Skip to main content

Re-indexing

shaktiman reindex purges every indexed artifact for a project and rebuilds from scratch. You rarely need it — the file watcher handles ordinary edits incrementally. This page covers the handful of cases where you do, and what happens under the hood.

When to reindex​

TriggerWhy
Shaktiman upgrade with parser / schema changesNew parser fixes or schema migrations should apply across the whole corpus, not just edited files.
You changed [embedding].model or [embedding].dimsExisting vectors are incompatible with a new model; reindex regenerates them.
.shaktiman/ looks corruptedImpossible counts from enrichment_status, queries returning gibberish, SQLite errors in the log.
You want to switch vector backendsE.g. brute_force → hnsw — the new store starts empty and needs repopulating.

You don't need to reindex after routine code edits — incremental indexing covers those. You also don't need to reindex after upgrading Ollama unless the model itself changed.

How to run it​

shaktiman reindex /path/to/project

On a TTY you'll be prompted to confirm:

This will delete ALL indexed data and reindex from scratch. Continue? [y/N]

In CI or any non-interactive context, pass --force to skip the prompt. Without --force, reindex aborts on non-TTYs rather than hanging on stdin.

Optional flags (same as index):

FlagPurpose
--embedAlso generate embeddings (requires Ollama).
--vector <backend>Switch to a different vector backend for the rebuild.
--db <backend>Switch metadata backend.
--postgres-url <url>Override the Postgres connection string.
--qdrant-url <url>Override the Qdrant URL.

What gets purged vs. preserved​

Purged (rebuilt from scratch)Preserved
.shaktiman/index.db (all metadata, chunks, symbols, edges, FTS5).shaktiman/shaktiman.toml
.shaktiman/embeddings.bin (local vectors).shaktiman/.shaktimanignore (if present)
Qdrant collection contents (when configured)Your source files (obviously)
pgvector table rows (when configured)
diff history
Session / access history

Configuration is preserved on purpose — reindexing shouldn't require you to reconfigure the project.

Daemon must be stopped first​

reindex refuses to run while shaktimand is holding the project lock. If the daemon is running:

Error: a shaktimand daemon is running for this project; stop it before running reindex

Stop the daemon first (close the Claude Code window, or kill the shaktimand process), then run reindex.

This matches index's behaviour — both are writer operations, and having the daemon's writer and the CLI's writer touch the same database would race.

Two-phase purge​

Under the hood reindex runs in phases:

  1. Open server-based backends and purge them. For Postgres / Qdrant / pgvector, this issues explicit delete statements scoped to the current project. EnsureProject is used to resolve the project ID without creating spurious rows.
  2. Delete local files. .shaktiman/index.db, .shaktiman/embeddings.bin, and the HNSW on-disk index are unlinked.
  3. Rebuild. A fresh daemon is opened and IndexProject runs as normal, followed by EmbedProject when --embed is set.

Crucially, phase 1 runs before phase 2, so if your Postgres credentials are wrong or Qdrant is unreachable, you'll fail out with local files intact — you haven't dropped the useful part of the index before hitting the broken dependency.

Implementation: cmd/shaktiman/main.go → reindexCmd.

Ctrl-C during reindex​

Safe at any point. SQLite transactions won't commit unless they complete. The embedding worker flushes progress to disk periodically; on the next run only the un-embedded chunks are processed.

What to do after an interrupted run​

The worst case is Ctrl-C between phase 1 (backend purge) and phase 2 (local file purge). Your server-side vector store and Postgres rows are empty, but local .shaktiman/index.db still reflects the old corpus — a plain shaktiman index will not reconcile this mismatch and will produce stale results.

How to detect it: after a Ctrl-C during reindex, run shaktiman enrichment-status .. If Total chunks is non-zero but Embeddings % is 0 (or you see dimension errors when you query), you're in the split state.

How to recover: re-run shaktiman reindex /path/to/project (add your original --embed / --vector / --db flags). It starts over and will converge. Don't run shaktiman index expecting it to fix this — it won't.

See also​