mirror of
https://github.com/openai/codex.git
synced 2026-04-26 23:55:25 +00:00
feat: add command history persistence (#152)
This PR adds a command history persistence feature to Codex CLI that: 1. **Stores command history**: Commands are saved to `~/.codex/history.json` and persist between CLI sessions. 2. **Navigates history**: Users can use the up/down arrow keys to navigate through command history, similar to a traditional shell. 3. **Filters sensitive data**: Built-in regex patterns prevent commands containing API keys, passwords, or tokens from being saved. 4. **Configurable**: Added configuration options for history size, enabling/disabling history, and custom regex patterns for sensitive content. 5. **New command**: Added `/clearhistory` command to clear command history. ## Code Changes - Added `src/utils/storage/command-history.ts` with functions for history management - Extended config system to support history settings - Updated terminal input components to use persistent history - Added help text for the new `/clearhistory` command - Added CLAUDE.md file for guidance when working with the codebase ## Testing - All tests are passing - Core functionality works with both input components (standard and multiline) - History navigation behaves correctly at line boundaries with the multiline editor
This commit is contained in:
@@ -49,6 +49,11 @@ export type StoredConfig = {
|
||||
approvalMode?: AutoApprovalMode;
|
||||
fullAutoErrorMode?: FullAutoErrorMode;
|
||||
memory?: MemoryConfig;
|
||||
history?: {
|
||||
maxSize?: number;
|
||||
saveHistory?: boolean;
|
||||
sensitivePatterns?: Array<string>;
|
||||
};
|
||||
};
|
||||
|
||||
// Minimal config written on first run. An *empty* model string ensures that
|
||||
@@ -70,6 +75,11 @@ export type AppConfig = {
|
||||
instructions: string;
|
||||
fullAutoErrorMode?: FullAutoErrorMode;
|
||||
memory?: MemoryConfig;
|
||||
history?: {
|
||||
maxSize: number;
|
||||
saveHistory: boolean;
|
||||
sensitivePatterns: Array<string>;
|
||||
};
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -313,6 +323,21 @@ export const loadConfig = (
|
||||
config.fullAutoErrorMode = storedConfig.fullAutoErrorMode;
|
||||
}
|
||||
|
||||
// Add default history config if not provided
|
||||
if (storedConfig.history !== undefined) {
|
||||
config.history = {
|
||||
maxSize: storedConfig.history.maxSize ?? 1000,
|
||||
saveHistory: storedConfig.history.saveHistory ?? true,
|
||||
sensitivePatterns: storedConfig.history.sensitivePatterns ?? [],
|
||||
};
|
||||
} else {
|
||||
config.history = {
|
||||
maxSize: 1000,
|
||||
saveHistory: true,
|
||||
sensitivePatterns: [],
|
||||
};
|
||||
}
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
@@ -341,14 +366,24 @@ export const saveConfig = (
|
||||
}
|
||||
|
||||
const ext = extname(targetPath).toLowerCase();
|
||||
// Create the config object to save
|
||||
const configToSave: StoredConfig = {
|
||||
model: config.model,
|
||||
};
|
||||
|
||||
// Add history settings if they exist
|
||||
if (config.history) {
|
||||
configToSave.history = {
|
||||
maxSize: config.history.maxSize,
|
||||
saveHistory: config.history.saveHistory,
|
||||
sensitivePatterns: config.history.sensitivePatterns,
|
||||
};
|
||||
}
|
||||
|
||||
if (ext === ".yaml" || ext === ".yml") {
|
||||
writeFileSync(targetPath, dumpYaml({ model: config.model }), "utf-8");
|
||||
writeFileSync(targetPath, dumpYaml(configToSave), "utf-8");
|
||||
} else {
|
||||
writeFileSync(
|
||||
targetPath,
|
||||
JSON.stringify({ model: config.model }, null, 2),
|
||||
"utf-8",
|
||||
);
|
||||
writeFileSync(targetPath, JSON.stringify(configToSave, null, 2), "utf-8");
|
||||
}
|
||||
|
||||
writeFileSync(instructionsPath, config.instructions, "utf-8");
|
||||
|
||||
Reference in New Issue
Block a user