sagasu is a local hybrid search CLI for source repositories.
It indexes text-based project files into a SQLite database, then searches them with a hybrid lexical and semantic workflow. By default, indexes are stored in a managed global cache directory so you can search a repository from anywhere.
brew install shinyonogi/tap/sagasuRequires Go 1.25.0.
git clone https://github.com/shinyonogi/sagasu.git
cd sagasu
go install ./cmd/sagasuIf GOBIN or $(go env GOPATH)/bin is on your PATH, the CLI is available as:
sagasu --help- SQLite-backed local index with managed global storage
- Incremental reindexing based on file modification time
- Search by token, phrase, and extension filter
- Optional local semantic search via Ollama embeddings
- Context lines around matches
- Human-friendly CLI output
- Machine-readable JSON and count modes
- Status, rebuild, and doctor commands
- Config-based include / exclude filtering
- Shell completion generation
Build an index for a repository:
sagasu index .
sagasu index /path/to/repoBy default the index is stored in a managed global cache path:
~/.cache/sagasu/indexes/<name>-<hash>.sqlite
Override the storage path explicitly:
sagasu index /path/to/repo --index-path /tmp/sagasu.sqlitePrint the indexing summary as JSON:
sagasu index /path/to/repo --jsonRebuild the index from scratch:
sagasu rebuild /path/to/repoBuild semantic embeddings with local Ollama:
sagasu index /path/to/repo --semanticUse a different local embedding model:
sagasu index /path/to/repo --semantic --embedding-model all-minilmSearch from the repository root:
sagasu search sqlcSearch a repository from anywhere:
sagasu search sqlc --root /path/to/repoPhrase search:
sagasu search '"hello world"' --root /path/to/repoLimit results:
sagasu search sqlc --limit 5Filter by extension:
sagasu search sqlc --ext go
sagasu search sqlc --ext .go --ext mdShow context lines:
sagasu search sqlc -C 2
sagasu search sqlc --context 3Output modes:
sagasu search sqlc --count
sagasu search sqlc --json
sagasu search sqlc --path-only
sagasu search sqlc --files-with-matches--json, --count, --path-only, and --files-with-matches are mutually exclusive.
Semantic search is optional and uses a local Ollama server.
Start Ollama and pull an embedding model:
ollama pull embeddinggemmaIndex the repository with semantic embeddings:
sagasu index /path/to/repo --semanticRun hybrid search:
sagasu search "database connection pool" --semantic --root /path/to/repoTune semantic influence:
sagasu search "database connection pool" --semantic --semantic-weight 3.0 --root /path/to/repoUse a custom Ollama endpoint:
sagasu search "storage layer" --semantic --ollama-url http://localhost:11434 --root /path/to/repoShow index metadata:
sagasu status --root /path/to/repo
sagasu info --root /path/to/repo
sagasu status --root /path/to/repo --jsonThis includes:
- index file path
- file size
- document count
- chunk count
- posting count
- last indexed update time
- extension breakdown
Check whether the stored index is still in sync with the working tree:
sagasu doctor --root /path/to/repo
sagasu doctor --root /path/to/repo --jsondoctor reports:
- missing files still referenced by the index
- stale files whose current mtime no longer matches the indexed value
- unreadable files
If the index is stale or broken:
sagasu rebuild /path/to/reposagasu can load include / exclude settings from a JSON config file.
By default it looks for:
.sagasu.json
Example:
{
"include": ["internal/**/*.go", "cmd/**/*.go"],
"exclude": ["**/*_test.go"],
"ignore_dirs": ["tmp", "coverage"]
}Use a custom config:
sagasu index /path/to/repo --config /path/to/sagasu.json
sagasu rebuild /path/to/repo --config /path/to/sagasu.jsonGenerate shell completion scripts:
sagasu completion bash
sagasu completion zsh
sagasu completion fish
sagasu completion powershellThe indexer currently includes:
.txt.md.go.ts.tsx.js.jsx.json.yaml.yml.tf.proto
The crawler skips these directories by default:
.gitnode_modulesdistbuildvendor
- Semantic search requires a local Ollama server and a pulled embedding model
- Hybrid ranking is still heuristic and not yet benchmark-tuned
- Phrase search is available, but query language is still minimal
- No advanced boolean query syntax yet
- No machine-readable output for
doctorexit codes yet - Config format is JSON only