Skip to content

feat(cli): add indexing and search commands#721

Merged
mksglu merged 1 commit into
mksglu:nextfrom
dennesneumann:feature/index-search-cli
May 31, 2026
Merged

feat(cli): add indexing and search commands#721
mksglu merged 1 commit into
mksglu:nextfrom
dennesneumann:feature/index-search-cli

Conversation

@dennesneumann

Copy link
Copy Markdown
Contributor

Summary

Adds terminal and slash-style entry points for pre-warming and querying context-mode's persistent FTS5 knowledge base.

  • add context-mode index <path> for indexing local files/directories into the per-project content DB
  • add context-mode search <query...> for querying indexed content from the terminal
  • add user-invocable /context-mode:ctx-index and /context-mode:ctx-search skills
  • document the new slash, chat utility, and terminal commands
  • add focused CLI surface regression tests

Why

ctx_index(path) already supports indexing file and directory content through MCP, but there was no deterministic terminal entry point for pre-filling the SQLite/FTS5 store before or outside an agent session. This makes the workflow discoverable and automatable while keeping raw project bytes out of chat context.

Validation

  • pnpm exec tsc --noEmit --pretty false
  • pnpm exec vitest run tests/core/cli.test.ts --reporter=dot
  • smoke test: context-mode index README.md --project . --source smoke:readme, then context-mode search "context savings" --project . --source smoke:readme --limit 1
  • git diff --check

@mksglu mksglu changed the base branch from main to next May 31, 2026 11:09
@mksglu mksglu force-pushed the feature/index-search-cli branch 2 times, most recently from 2965d24 to d25b7a7 Compare May 31, 2026 12:38
@mksglu

mksglu commented May 31, 2026

Copy link
Copy Markdown
Owner

Thanks @dennesneumann. Conflicting on next after #716 modified src/cli.ts. Please rebase — the index and search subcommands shouldn't overlap textually with #716's swap-loop hardening, but the file header / command-registration block likely needs a clean replay.

Optional follow-up nit: pass attribution: { tool: "cli-index" } to store.index() so Insight analytics can distinguish CLI-pre-warmed chunks from agent-indexed ones. Not blocking.

Verdict was MERGE_WITH_NITS — re-ping after rebase.

Add terminal commands for indexing local files or directories into the persistent FTS5 content store and searching that store by project/source.

Expose slash-style ctx-index and ctx-search skill triggers, update README utility command docs, and cover the new CLI/skill surface in focused tests.

Validation: pnpm exec tsc --noEmit --pretty false; pnpm exec vitest run tests/core/cli.test.ts --reporter=dot; CLI smoke index/search with temporary CONTEXT_MODE_DIR; git diff --check.
@mksglu mksglu force-pushed the feature/index-search-cli branch from d25b7a7 to c863044 Compare May 31, 2026 13:39
@mksglu mksglu merged commit b51873f into mksglu:next May 31, 2026
mksglu added a commit that referenced this pull request May 31, 2026
Adds an opt-in `project` parameter to `ctx_search` that scopes the FTS5
ContentStore to a single project directory when the user runs in shared-
DB mode (`CONTEXT_MODE_PROJECT_DIR` set at launch). The field is
registered conditionally on the schema — it physically does not exist
on the tool surface when shared mode is off — so the LLM cannot pass an
inactionable parameter. This is a stronger guarantee than runtime
validation that depends on the model honouring the description.

`src/search/ctx-search-schema.ts` factors the schema builder out of
`server.ts` to keep the conditional field path testable in isolation:

- `buildCtxSearchInputSchema(isSharedMode)` composes the Zod object.
  When `isSharedMode === false`, `Object.keys(schema.shape)` does NOT
  include `project`; when true, it does. The base fields and their
  `z.coerce.number()` / `z.preprocess(coerceJsonArray, ...)` semantics
  match the previous inline definition byte-for-byte, including the
  bare-string lift behaviour relied on by the OpenCode native plugin
  bridge (regression coverage in tests/opencode-plugin.test.ts).
- `resolveProjectScope(raw, isSharedMode, getProjectDirFn)` normalises
  the param into the three-state contract that `searchAllSources`
  consumes: `undefined` (no filter), `null` (cross-project recall),
  `string` (restrict to that path).
- `CTX_SEARCH_SHARED_MODE` snapshots `process.env.CONTEXT_MODE_PROJECT_DIR`
  at module load. The tool surface registered with
  `server.registerTool` should never flip mid-session, so the env read
  happens once.

The ctx_search handler in `src/server.ts` opens SessionDB whenever a
string `projectScope` is in play (not only in timeline mode) so the
relevance-mode path can resolve the same allow-set that searchAllSources
resolves internally for timeline mode. Both paths now agree on
filtering, and an absent / `null` scope preserves today's behaviour.

Test coverage in `tests/core/search-project-filter.test.ts` covers:

  - Slice 1 — ContentStore.searchWithFallback with the allow-set,
    including legacy session_id='' visibility and a no-op undefined
    pass.
  - Slice 2 — SessionDB.getSessionIdsForProject with multi-project
    fixtures and a 1000-session perf sanity bound.
  - Slice 3 — searchAllSources.projectScope wired end-to-end
    (string, null, undefined).
  - Slice 4 — Conditional schema registration.
  - Slice 5 — resolveProjectScope helper truth table.

Closes #737. Refs e7dbf58 (#363 — unified persistent memory baseline),
ead9177 (#367 — searchAllSources unification), PR #698 (query_scope
precedent for parameter shape), PR #721 (CLI --project naming parity).
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