Skip to content

Conversation

jmmoser
Copy link
Contributor

@jmmoser jmmoser commented Aug 18, 2025

Issue #, if available:
#2633

Description of changes:

Implements persistent chat history that survives CLI restarts and is isolated by working directory.

Features:

  • Chat history persists across CLI sessions using SQLite database
  • History is isolated per working directory (/project/a vs /project/b)
  • Up arrow navigation works with persistent history
  • Dual cleanup limits: max 100 entries per directory, 1000 total
  • Silent failure: history issues don't break CLI functionality
  • Filters out empty/whitespace-only and confirmation inputs

Implementation:

  • Database table: chat_readline_history(input TEXT, cwd TEXT, timestamp INTEGER) with index on cwd and timestamp
  • Uses existing database infrastructure and Os abstraction
  • Transactional insert+cleanup for data consistency
  • Early return for empty inputs to avoid unnecessary DB operations

Files modified:

  • crates/chat-cli/src/database/mod.rs: Added add_chat_readline_history_entry() and get_chat_readline_history()
  • crates/chat-cli/src/cli/chat/input_source.rs: Load history on startup, save on input

Edge cases handled:

  • Database failures (silent)
  • Empty/whitespace and confirmation inputs (filtered)
  • Working directory access failures (fallback to default)
  • Unicode/special characters (parameterized queries)

Interaction with other features:

  • Does not conflict with --resume. It enhances it.
  • Does not conflict with /load.

Questions:

  • Should the max history size be configurable?
  • Should confirmations (y/n/t) be ignored?
  • Should bash commands, e.g. !ls, be ignored?

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@jmmoser jmmoser force-pushed the main branch 6 times, most recently from 298852a to 26bce5e Compare August 24, 2025 14:00
Copy link
Contributor

@brandonskiser brandonskiser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused by the intention of this PR, we do support persistent chat history per working directory already (try it q chat --resume!).

If the intention is to store readline history, then it should be stored directly with the conversation state as part of the serialization process (see the conversations table under the database module) instead of being handled separately.

@@ -62,6 +62,10 @@ const IDC_REGION_KEY: &str = "auth.idc.region";
const CUSTOMIZATION_STATE_KEY: &str = "api.selectedCustomization";
const PROFILE_MIGRATION_KEY: &str = "profile.Migrated";

// Chat history limits
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't make any new SQLite tables or migrations for this without a very necessary reason

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

The SQLite database will enable many more powerful features so being very clear here will help future contributors.

@jmmoser
Copy link
Contributor Author

jmmoser commented Aug 29, 2025

@brandonskiser thank you for the review! I disagree with you. This feature should be included regardless of --resume. Customers should be able to access the prompt history without having to resume the context because context and prompt history are not the same.

By coupling prompt history and context, you make prompt history less flexible. If a customer inputs a complex prompt, exits q, then restarts q, they should have access to their previous prompts without requiring resuming the previous context. Customers may want a fresh context while still having access to previous prompts.

If customers want the previous context then they can use --resume. And with this PR they also have the added benefit of having access to the previous prompts.

Your suggestion forces customers to resume the context to be able to have access to their previous prompts. Customers should not be forced to use --resume to have access to their previous prompts. There is no reason to have this limitation.

@jmmoser
Copy link
Contributor Author

jmmoser commented Aug 29, 2025

If we want previous prompt history to be related to conversation and when using --resume (or /load) the readline is preloaded with chat history from that conversation first then that can be a secondary improvement but not a blocker for this PR.

@jmmoser
Copy link
Contributor Author

jmmoser commented Aug 29, 2025

@brandonskiser My main point is this feature should work by default. I'm totally onboard with changing the behavior if the customer uses --resume or /load. But prompt history and context are fundamentally different features and must be treated separate to maximize flexibility.

@brandonskiser
Copy link
Contributor

@jmmoser got it, that explanation makes a lot more sense now! In which case you should create a new migration for "chat_readline_history" table that includes a timestamp field (it's the array of migrations in that same database file you're updating). Then, we can create an index on cwd and timestamp, so we'd just delete all entries after the latest 100 entries per cwd whenever we insert a new entry. Shouldn't have any references to rowid here - instead I'd actually prefer an explicit id INTEGER PRIMARY KEY

Should the max history size be configurable?

Don't think this is necessary. For now let's just set it to 100.

Should confirmations (y/n/t) be ignored?

Yes - let's just filter out "y/n/t" when saving the history entry.

Should bash commands, e.g. !ls, be ignored?

I would say no

@jmmoser jmmoser force-pushed the main branch 8 times, most recently from 21bb7c0 to 0b15d59 Compare September 3, 2025 16:52
Implements persistent chat history that survives CLI restarts and is isolated by working directory.

Features:
- Chat history persists across CLI sessions using SQLite database
- History is isolated per working directory (/project/a vs /project/b)
- Up arrow navigation works with persistent history
- Dual cleanup limits: max 100 entries per directory, 1000 total
- Silent failure: history issues don't break CLI functionality
- Filters out empty/whitespace-only and confirmation inputs

Implementation:
- Database table: chat_readline_history(input TEXT, cwd TEXT, timestamp INTEGER) with index on cwd and timestamp
- Uses existing database infrastructure and Os abstraction
- Transactional insert+cleanup for data consistency
- Early return for empty inputs to avoid unnecessary DB operations

Files modified:
- crates/chat-cli/src/database/mod.rs: Added add_chat_readline_history_entry() and get_chat_readline_history()
- crates/chat-cli/src/cli/chat/input_source.rs: Load history on startup, save on input

Edge cases handled:
- Database failures (silent)
- Empty/whitespace and confirmation inputs (filtered)
- Working directory access failures (fallback to default)
- Unicode/special characters (parameterized queries)
@jmmoser
Copy link
Contributor Author

jmmoser commented Sep 3, 2025

@brandonskiser Updated based on your feedback!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants