Skip to content

feat(ipc): add history query method and CLI subcommand#136

Merged
eitsupi merged 9 commits intomainfrom
feat/ipc-history
Mar 29, 2026
Merged

feat(ipc): add history query method and CLI subcommand#136
eitsupi merged 9 commits intomainfrom
feat/ipc-history

Conversation

@eitsupi
Copy link
Copy Markdown
Owner

@eitsupi eitsupi commented Mar 29, 2026

Summary

  • Add history JSON-RPC method and arf ipc history CLI subcommand for querying command history from a running session
  • Default to current session's history only (--all-sessions to include all)
  • Uses read-only rusqlite connection to avoid WAL/DDL conflicts with the main history connection
  • Works even when R is busy or in alternate mode (shell/history/help browser)
  • Fix headless history entries missing session_id in the database
  • Handle missing/null params gracefully (treat as empty object with defaults)
  • Document that only completed commands appear in history

Details

CLI usage

arf ipc history                          # current session, last 50 entries
arf ipc history --limit 10               # last 10
arf ipc history --all-sessions           # include all sessions
arf ipc history --grep dplyr             # search commands (exact substring via instr())
arf ipc history --cwd /path/to/project   # filter by directory
arf ipc history --since 2026-03-29       # entries after date (RFC 3339 or YYYY-MM-DD)
arf ipc history | jq '.entries[].command' # pipe-friendly compact JSON

JSON-RPC protocol

{
  "method": "history",
  "params": {
    "limit": 50,            // max entries (default 50, must be positive)
    "all_sessions": false,   // false = current session only (default)
    "cwd": null,            // filter by exact working directory
    "grep": null,           // substring search on command line
    "since": null           // ISO 8601 / YYYY-MM-DD timestamp filter
  }
}

Architecture

  • History DB path and session ID stored in a global OnceLock at startup (both REPL and headless)
  • Query opens a read-only rusqlite::Connection (same pattern as pager/history_browser.rs) to avoid WAL/DDL conflicts
  • No ExternalBreak needed — handled on the server thread, like the session method
  • Allowed through the alternate mode guard (shell/history/help browser)
  • Validation errors return INVALID_PARAMS (-32602), DB errors return INTERNAL_ERROR (-32603)

Test plan

  • test_ipc_history_basic — basic query returns evaluated commands
  • test_ipc_history_limit--limit restricts entry count
  • test_ipc_history_grep--grep filters by command substring
  • test_ipc_history_default_session_scoped — default query scoped to current session
  • test_ipc_history_metadata — entries include timestamp, cwd, exit_status
  • test_ipc_history_disabled — error when history is disabled
  • cargo clippy clean
  • Shell completion snapshots updated
  • docs/ipc.md updated

🤖 Generated with Claude Code

eitsupi and others added 4 commits March 29, 2026 08:15
Add a new `history` JSON-RPC method that queries the SQLite history
database and returns matching entries as JSON. The method is handled
directly on the server thread (no R interaction needed), making it
available even when R is busy.

CLI: `arf ipc history` with --limit, --session-only, --cwd, --grep,
--since filters. Output is pretty-printed on terminal, compact when
piped.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Add 6 tests covering: basic query, --limit, --grep, --session-only,
metadata (timestamp/cwd/exit_status), and --no-history error.

Also fix headless history entries missing session_id — the
save_to_headless_history function was not setting session_id on the
HistoryItem, causing NULL in the database.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
- Validate limit > 0 in query_history() and restrict CLI --limit to
  positive values via clap value_parser range
- Replace serde_json::to_value().unwrap() with proper error handling
  in the history dispatch path
- Add comment explaining why set_history_db_info is called before the
  DB file exists in REPL mode (with_file creates it on open)

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Add arf ipc history CLI section with parameter table and examples.
Update Available Methods table to include history method.
Note that history and session methods work when R is busy.
Also add missing --history-dir and --no-history to headless options.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new IPC surface for querying command history from a running arf session, plus a corresponding arf ipc history CLI subcommand and end-to-end tests.

Changes:

  • Introduces history JSON-RPC method + client CLI plumbing (arf ipc history) with filtering options.
  • Stores history DB path/session ID in-process and uses it to query history and to populate headless session_id on saved entries.
  • Adds headless integration tests and updates shell completion snapshots.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
crates/arf-console/src/ipc/protocol.rs Adds HistoryParams, HistoryEntry, HistoryResult types for the new JSON-RPC method.
crates/arf-console/src/ipc/server.rs Routes "history" requests and handles them on the server thread.
crates/arf-console/src/ipc/mod.rs Adds global history DB info + implements query_history; sets headless history item session_id.
crates/arf-console/src/ipc/client.rs Implements cmd_history client request + terminal-aware JSON formatting.
crates/arf-console/src/cli.rs Adds arf ipc history subcommand and flags/help text.
crates/arf-console/src/main.rs Registers history DB info at startup (REPL + headless) and wires new IPC action.
crates/arf-console/tests/headless_tests.rs Adds IPC history integration tests and a helper to invoke arf ipc history.
crates/arf-console/src/snapshots/arf__cli__tests__completions_*.snap Updates completion snapshots for the new subcommand/options.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

eitsupi and others added 2 commits March 29, 2026 08:29
…ssions

The primary value of querying history via IPC is accessing the current
session's entries. Querying all sessions can be done by reading the
SQLite DB directly.

- Default to current session only (was all sessions)
- Replace --session-only with --all-sessions opt-in flag
- Rename JSON-RPC param from session_only to all_sessions
- Update docs, tests, and shell completion snapshots

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
- Use read-only rusqlite connection instead of SqliteBackedHistory::with_file
  to avoid WAL/DDL conflicts with the main history connection (same pattern
  as pager/history_browser.rs)
- Allow history method through alternate mode guard (like session)
- Return INVALID_PARAMS for validation errors (limit, since format),
  INTERNAL_ERROR only for DB/serialization failures
- Return error when session_id is unavailable and all_sessions=false
- Log warning on duplicate set_history_db_info calls
- Fix since doc comment to mention YYYY-MM-DD format

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@eitsupi eitsupi requested a review from Copilot March 29, 2026 08:37
LIKE interprets % and _ as wildcards even in parameterized queries,
so user input containing those characters would match more rows than
intended. Switch to instr() for exact substring matching, which is
the same approach reedline uses for its Substring search.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Treat missing/null params as empty object in history method so
  callers can omit params and rely on defaults
- Correct "always succeeds" wording for history in mutual exclusion
  section — history may fail if disabled or DB inaccessible
- Document that only completed commands appear in history results
  (in both CLI help and IPC docs)

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@eitsupi eitsupi requested a review from Copilot March 29, 2026 08:57
@eitsupi eitsupi merged commit c6040e7 into main Mar 29, 2026
10 checks passed
@eitsupi eitsupi deleted the feat/ipc-history branch March 29, 2026 09:19
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