@act0r/cxs
v0.3.3
Published
Progressive search CLI for local Codex session logs
Maintainers
Readme
cxs
cxs is a local-first CLI for searching Codex session logs. It is designed for
progressive retrieval: find the right session first, then read only the relevant
range or page.
Core workflow:
status -> ensure selector coverage -> find/list -> read-range/read-pageWhat It Is
- A CLI for indexed search over local Codex JSONL sessions.
- A retrieval backend for agents, sidecars, and local tools that need session recall.
- A manual-sync tool:
syncis the only command that writes the SQLite index.
What It Is Not
- Not a GUI.
- Not a watcher, daemon, or realtime sync service.
- Not a live in-flight thread attachment layer.
- Not a default full-transcript dumper.
Install
Requirements:
- macOS or Linux. Windows users should use WSL.
- Node.js
>= 22. - Read access to
~/.codex/sessions.
Install the CLI globally:
npm i -g @act0r/cxs
cxs --helpThe installed command is cxs. The package is scoped because the unscoped
cxs package name is already taken on npm. The current distribution is the npm
package only; no standalone binary is published.
For one-off usage:
npx @act0r/cxs@latest --help
npx @act0r/cxs@latest status --jsonQuick Start
Inspect available sources and index coverage:
cxs status --jsonCheck coverage for a project:
cxs status --cwd /Users/you/work/project --jsonIf requestedCoverage.recommendedAction is "sync", build or refresh coverage:
cxs sync --cwd /Users/you/work/projectReplace the example paths with your own absolute paths.
Search and read progressively:
cxs find "health check"
cxs read-range <sessionUuid> --seq <matchSeq>
cxs read-page <sessionUuid> --offset 0 --limit 20You can run the same flow without global installation:
npx @act0r/cxs@latest sync --root /Users/you/.codex/sessions
npx @act0r/cxs@latest find "health check" --root /Users/you/.codex/sessionsCommands
| Command | Purpose |
| --- | --- |
| cxs status | Show execution context, source inventory, index state, and coverage. --selector checks whether a target range is fresh. Does not write the index. |
| cxs sync --root <dir>\|--cwd <path>\|--selector <json> | Scan selected Codex sessions and update the SQLite index. This is the only write command. |
| cxs find <query> | Search indexed sessions and return ranked session candidates with minimal snippets. Use --root, --cwd, and --sort ended for scoped "latest + keyword" queries. |
| cxs read-range <sessionUuid> | Read a small message window around a matched sequence or in-session query. |
| cxs read-page <sessionUuid> | Read a session page by offset and limit. |
| cxs list | List indexed sessions without full-text search. |
| cxs stats | Show index statistics. |
All commands that read indexed content support --json. Read commands fail
cleanly if the index has not been created yet.
Selectors
sync requires an explicit scope, but it no longer requires handwritten
root inside selector JSON. Prefer these CLI shortcuts:
cxs sync --root /Users/you/.codex/sessions
cxs sync --cwd /Users/you/work/project
cxs find "health check" --cwd /Users/you/work/project --sort ended
cxs list --root /Users/you/.codex/sessions --sort ended -n 10Use full selector JSON for date ranges or advanced scopes. If you pass
--root, the selector JSON may omit root; without --root, cxs uses the
default Codex sessions root.
{"kind":"all","root":"/Users/you/.codex/sessions"}
{"kind":"date_range","root":"/Users/you/.codex/sessions","fromDate":"2026-04-01","toDate":"2026-04-30"}
{"kind":"cwd","root":"/Users/you/.codex/sessions","cwd":"/Users/you/work/project"}
{"kind":"cwd_date_range","root":"/Users/you/.codex/sessions","cwd":"/Users/you/work/project","fromDate":"2026-04-01","toDate":"2026-04-30"}Example list query scoped to one project:
cxs list --selector '{"kind":"cwd","root":"/Users/you/.codex/sessions","cwd":"/Users/you/work/project"}' --sort ended -n 10
cxs list --selector '{"kind":"cwd","cwd":"/Users/you/work/project"}' --sort ended -n 10Example latest keyword query, excluding the current self-hit:
cxs find "xsearch" --cwd /Users/you/work/project --sort ended --exclude-session <current_session_uuid> -n 5 --jsonfind defaults to relevance sorting. Do not treat default find order as time
order.
Sync And Storage
By default, cxs reads Codex sessions from ~/.codex/sessions and stores its
index at:
~/.local/state/cxs/index.sqlite$XDG_STATE_HOME is respected, and CXS_DATA_DIR has the highest priority:
export CXS_DATA_DIR="$HOME/.config/cxs"Sync is strict by default. If any selected file fails to parse or write, sync
exits non-zero with per-file diagnostics and does not commit partial coverage.
On success, strict sync updates the selected index slice for files that are
currently visible in the source snapshot and writes complete coverage for that
snapshot. Previously indexed sessions whose source JSONL later disappears are
retained by default, so raw log maintenance does not make historical cxs find
or read-* results disappear.
Pass --prune only when you explicitly want to delete indexed sessions that are
no longer present in the selected source snapshot.
Pass --best-effort only when you explicitly want successful files written
despite failures; best-effort sync does not record complete coverage.
sync is not required before every query. Use status --cwd or
status --selector to check coverage first. A fresh {"kind":"all", ...}
coverage record covers narrower
selectors under the same root; a high stats.sessionCount only means rows exist
and is not itself a freshness proof.
Indexes created before cxs-v6-selector-provenance should be refreshed with
sync --root, sync --cwd, or sync --selector so date selectors and read coverage use the current
path_date and source-root provenance fields.
Older cxs <= 0.2.0 indexes stored under ~/.cache/cxs/ are migrated
automatically on first run when the new state directory is empty. If the new
directory already has data, migration is skipped and the old cache is left in
place.
Retrieval Model
The current retrieval chain is:
message/session recall -> session heuristic rerank -> read-range/read-pageImplemented recall surfaces:
messages_ftsover real user and assistant messages.sessions_ftsovertitle + summary_text + compact_text + reasoning_summary_text.- Session-level FTS weights: title
8.0, compact4.0, summary3.0, reasoning summary1.2. - A small LIKE fallback for rare zero-token CJK message queries.
find returns enough context to choose the next read step. If a result only
matches session-level fields, it is marked with matchSource = "session" and
has no message anchor; use read-page for those results.
Not implemented yet:
- Resource-level reranking.
- Richer projection or event replay.
- Range cache.
- Duplicate-family collapse or diversity control.
- Strong gold-set acceptance suite.
More detail: docs/ARCHITECTURE.md. Roadmap: docs/ROADMAP.md.
Development
Run from source:
git clone https://github.com/catoncat/cxs.git
cd cxs
npm install
npm run cxs -- --versionCommon checks:
npm run check
npm run eval:manual
npm run eval:compare -- data/cxs-eval/<before-batch> data/cxs-eval/<after-batch>npm run check runs TypeScript and Vitest. eval:manual exports manual eval
results; eval:compare compares two eval batches.
Project rules and contribution notes:
Agent Skill Package
This repository also publishes an installable agent skill package:
skill-packages/cxsInstall or update it with:
npx skills add catoncat/cxs --full-depth --skill cxs -g -a codex -yList available skills in the repository:
npx skills add catoncat/cxs --full-depth --listImportant boundaries:
npx skills addinstalls the agent skill only; it does not install thecxsCLI.- Install the CLI with
npm i -g @act0r/cxs, usenpx @act0r/cxs@latest, or setCXS_BINfor the skill. - Restart Codex or open a new session after installing or updating the skill.
