Architecture
devgrep is a local-first CLI built around four small layers — indexers, storage, search, and commands/TUI.
┌─────────────────────────────────────────────────────────────┐
│ Cobra CLI (cmd/) │
│ search · index · stats · sources · doctor · version │
└───────────────────────────┬─────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Indexers │ │ Search Engine │ │ Bubble Tea │
│ shell-history │ │ fuzzy + rank │ │ TUI │
│ logs · notes │ │ typo fallback │ │ (internal/ │
│ (Indexer IF) │ │ │ │ tui) │
└───────┬───────┘ └───────┬───────┘ └───────────────┘
│ │
└─────────┬─────────┘
▼
┌─────────────────────┐
│ SQLite (WAL) │
│ ~/.local/share/ │
│ devgrep/devgrep.db│
│ documents · states │
│ watched_paths · … │
└─────────────────────┘
▲
│ fsnotify (watch mode)
┌─────────┴─────────┐
│ Local files only │
│ history · logs · md │
└─────────────────────┘Command layer
cmd/ defines the Cobra tree: search, index, stats, sources, doctor, version. The root command applies direct-search fallback — if the first non-flag argument is not a known subcommand, args are rewritten to search.
Package layout mirrors responsibilities:
internal/history— bash and zsh history parsinginternal/logs— log indexing and tail modeinternal/indexer— pluggable Indexer interface and markdown indexerinternal/storage— SQLite migrations and prepared statementsinternal/search— fuzzy search and plain formattinginternal/ranking— scoring modelinternal/tui— Bubble Tea interfaceinternal/doctor— health checks
Indexers
Phase 1 sources are shell history, .log files, and markdown notes. Each source implements the Indexer interface so future sources (Docker logs, Git history, CI logs) can be added without changing command code.
File discovery uses centralized ignore logic in internal/utils, shared by normal indexing, dry-run, and watch re-indexing. The policy skips configured directories, huge files, media, binaries, and archives before parsers run.
SQLite storage
Default path: ~/.local/share/devgrep/devgrep.db
WAL mode, busy timeout, prepared statements, and source state for incremental indexing.
Tables
documents— indexed commands, log lines, notessource_states— file offsets and modification metadatasearch_stats— local query frequencyindex_runs— indexing performance historyschema_migrations— applied schema versionswatched_paths— directories restored by watch mode
The sources command reads document metadata and groups locations without duplicating paths.
Ranking
Ranking blends configurable weights:
ranking:
fuzzy: 0.38
recency: 0.26
frequency: 0.10
exact: 0.16
command_length: 0.02
directory_relevance: 0.08Fuzzy match quality drives primary scoring; typo-tolerant fallback ranking handles near matches. Recency and usage frequency come from document metadata and search_stats.
Watch mode
Explicit index paths are persisted in watched_paths. Foreground watch uses fsnotify with 500ms debounced re-indexing, reuses the same indexers, and deletes documents when files are removed.
Shell history files are always added to the watcher set alongside configured directories.
Parser system
Each indexer owns parsing logic:
- History indexers read bash/zsh formats with deduplication
- Log indexer detects severity levels and respects max file size
- Note indexer walks markdown files under configured paths
Normalized documents share a common schema in storage regardless of source type.
Privacy
No telemetry, background network calls, accounts, or cloud API. All indexing and search operate on local files only. See the FAQ for database size and offline behavior.