-
Notifications
You must be signed in to change notification settings - Fork 0
Your First Index and Search
A guided tour using a tiny sample project, with the real output Columbus produces and what each result means. The sample is three TypeScript files plus a README:
src/config.ts # type Config + parseConfig()
src/server.ts # class Server + newServer(), imports ./config
src/index.ts # imports ./server, starts it
README.md
$ columbus install
Installed columbus project proj_2fd171eebe922fad
config: /tmp/cbsample/.columbus.json
data dir: /tmp/cbdata
indexed: 4 files, 7 symbols, 7 embeddedOutcome: a stable project id, a git-excluded .columbus.json, a data dir for
the database outside your repo, and a first index where every symbol/file is
embedded on-device for semantic search.
After edits, reindex updates only what changed:
$ columbus reindex --status
index now: 4 files (unchanged: 4)$ columbus search "how do we read configuration"
1. parseConfig [function] (score 0.71, semantic match)
src/config.ts:4
function parseConfig(env: Record<string, string>): Config {
2. Config [type] (score 0.66, semantic match)
src/config.ts:1
type Config = { port: number; host: string };
3. config.ts [file] (score 0.48, semantic match)
src/config.ts
...Outcome: the query never says "parseConfig", yet it ranks first — search
embedded the question and matched by meaning, then re-ranked with heuristics.
Each hit has a score and a why (semantic match, or a heuristic reason like
exact name match). Run it twice — same model, same order.
$ columbus graphs --in src
{ nodes: [src/config.ts, src/server.ts, src/index.ts, …],
edges: [src/index.ts → src/server.ts (import), src/server.ts → src/config.ts (import)] }Outcome: the file dependency graph as nodes + edges — here, that index.ts
imports server.ts, which imports config.ts. Great for "what depends on this?"
reasoning. See graphs.
$ columbus show symbol parseConfig
1 definition(s) of "parseConfig"
1. parseConfig [function] src/config.ts:4-6
| export type Config = { port: number; host: string };
|
| // parseConfig reads raw env values into a typed Config.
| export function parseConfig(env: Record<string, string>): Config {
| return { port: Number(env.PORT ?? 8080), host: env.HOST ?? "localhost" };
| }$ columbus show file src/server.ts
src/server.ts [typescript, package , impl]
outline (4 symbols):
3 class Server
4 method Server.constructor
5 method Server.start
8 function newServer
imports: src/config.ts
imported by: src/index.tsOutcome: full bodies with exact line ranges, file outlines, and import edges — without you ever opening the file. See Navigating Code.
Insert two blank lines at the top of src/config.ts and do not reindex:
# before edit
1. parseConfig [function] src/config.ts:4-6
# after inserting 2 blank lines, with NO reindex
1. parseConfig [function] src/config.ts:6-8Outcome: the line range tracked the live file (4-6 → 6-8) because the
snippet is reconstructed from the working tree at query time. The index didn't
even need updating. This is the core invariant — see
Never Stale: Live Reconstruction.
$ columbus memory add context --type decision \
--title "Default port is 8080" \
--body "parseConfig falls back to 8080 when PORT is unset" \
--evidence src/config.ts:4-6 --ref symbol:parseConfig --tag config
mem_001 [decision] Default port is 8080
parseConfig falls back to 8080 when PORT is unset
tags: config
evidence: src/config.ts:4-6
ref: symbol:parseConfigOutcome: durable, queryable project knowledge tied to evidence in the code. See Project Memory.
Columbus — the navigator your coding agent has been missing · local-only, deterministic code context · Repository · Issues · MIT License
Getting started
Concepts
Guides
- Using Columbus with Your Agent
- Searching Effectively
- Navigating Code
- Project Memory
- Tracking Work: Epics, Stories & Tasks
- Keeping the Index Fresh
Command reference
Reference
- Output Modes
- JSON Contract & Errors
- Exit Codes
- Configuration
- Supported Languages
- Color & Environment
Project