{"id":50711066,"url":"https://github.com/mopanc/saga","last_synced_at":"2026-06-09T15:04:25.636Z","repository":{"id":356752437,"uuid":"1229101886","full_name":"mopanc/saga","owner":"mopanc","description":"Topic-grained, layered memory layer for AI coding agents — local-first, MCP, single binary. Plug Claude Code / Cursor / Windsurf / Antigravity into persistent memory across sessions and machines.","archived":false,"fork":false,"pushed_at":"2026-05-09T14:59:37.000Z","size":287,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-09T16:40:51.256Z","etag":null,"topics":["ai","ai-agents","claude-code","cli","cursor","developer-tools","golang","knowledge-base","llm","mcp","memory","model-context-protocol","rag","sqlite","windsurf"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mopanc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":"docs/ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-04T17:46:23.000Z","updated_at":"2026-05-09T14:59:41.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mopanc/saga","commit_stats":null,"previous_names":["mopanc/saga"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/mopanc/saga","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mopanc%2Fsaga","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mopanc%2Fsaga/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mopanc%2Fsaga/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mopanc%2Fsaga/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mopanc","download_url":"https://codeload.github.com/mopanc/saga/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mopanc%2Fsaga/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34112225,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","ai-agents","claude-code","cli","cursor","developer-tools","golang","knowledge-base","llm","mcp","memory","model-context-protocol","rag","sqlite","windsurf"],"created_at":"2026-06-09T15:04:24.586Z","updated_at":"2026-06-09T15:04:25.631Z","avatar_url":"https://github.com/mopanc.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Saga — persistent memory for AI coding agents\n\n[![CI](https://github.com/mopanc/saga/actions/workflows/ci.yml/badge.svg)](https://github.com/mopanc/saga/actions/workflows/ci.yml)\n[![Latest release](https://img.shields.io/github/v/release/mopanc/saga?include_prereleases\u0026sort=semver)](https://github.com/mopanc/saga/releases)\n[![Go Reference](https://pkg.go.dev/badge/github.com/mopanc/saga.svg)](https://pkg.go.dev/github.com/mopanc/saga)\n[![Go Report Card](https://goreportcard.com/badge/github.com/mopanc/saga)](https://goreportcard.com/report/github.com/mopanc/saga)\n[![License: Apache-2.0](https://img.shields.io/github/license/mopanc/saga)](LICENSE)\n[![CodeQL](https://github.com/mopanc/saga/actions/workflows/codeql.yml/badge.svg)](https://github.com/mopanc/saga/actions/workflows/codeql.yml)\n\n\u003e **Stop re-explaining your codebase to AI every session.** Saga is a topic-grained, layered memory layer for AI coding agents. It lets Claude Code, Cursor, Windsurf, Antigravity and any other [Model Context Protocol](https://modelcontextprotocol.io) (MCP) client remember what they learned across sessions — your codebase, your decisions, your preferences — so the next conversation starts where the last one ended.\n\nLocal-first. Single static binary. Markdown notes in git, indexed by SQLite. Cross-IDE, cross-machine.\n\n## Why Saga\n\nAI coding agents have no memory between sessions. Every conversation starts blank — you re-explain your stack, your conventions, the bug you fixed last week. For solo developers and small teams working on real codebases, this re-explanation costs hours every week.\n\nSaga gives the agent a place to **write durable notes** after an investigation, and a fast retrieval path to **read them back** on the next session. The unit of memory is a curated *topic note* (~500 words, self-contained markdown), not a chunked sentence corpus — because investigation work needs coherent context, not scattered phrases.\n\nThink of it as **git for cognition**: notes are versioned by markdown, related by typed operators (`@supersedes`, `@refines`, `@conflicts_with`), surfaced by ranking that respects what the AI has actually used. The retrieval layer doesn't just *search* relevant memories — it tracks which ones are still canonical, which evolved, and which are superseded.\n\n### What happens on every prompt\n\n```mermaid\nsequenceDiagram\n    autonumber\n    actor U as You\n    participant CC as Claude Code\n    participant H as saga hook\n    participant DB as ~/.saga\u003cbr/\u003eSQLite + markdown\n    participant AI as Claude\n\n    U-\u003e\u003eCC: prompt\n    CC-\u003e\u003eH: UserPromptSubmit\n    H-\u003e\u003eDB: FTS5 + BM25 recall (relation-aware)\n    DB--\u003e\u003eH: top-K topics\n    H--\u003e\u003eCC: \u003csaga-context\u003e block\n    CC-\u003e\u003eAI: prompt + injected memory\n    AI--\u003e\u003eU: response\n    AI-\u003e\u003eCC: tool_use (e.g. topic_write)\n    CC-\u003e\u003eDB: persist new topic\n    Note over DB: next session reads it back automatically\n```\n\nEvery step is in code: the hook lives in `cmd/saga/cmd_hook.go`, recall and ranking in `internal/saga/service.go`, the MCP tool surface in `internal/mcp/`. The diagram above is the literal call path — not an abstract intention.\n\n## Highlights\n\n- **Topic-grained, not chunk-grained.** ~500-word self-contained notes beat sentence-level chunking for code-investigation workloads.\n- **Typed relations between memories.** Six pure-metadata operators — `@supersedes`, `@refines`, `@deprecated`, `@derived_from`, `@conflicts_with`, `@relates_to` — let the corpus evolve over time without becoming a dumpster.\n- **Layered scopes.** `personal | project | dept | org` — each layer has an independent owner, sync remote, and sensitivity. Personal travels with you; project travels with the repo.\n- **Cross-IDE via MCP.** Six tools (`recall`, `topic_read`, `topic_list`, `topic_write`, `lembranca_log`, `saga_capabilities`) exposed over JSON-RPC 2.0 stdio to any MCP client.\n- **Auto-injection on Claude Code.** A `UserPromptSubmit` hook surfaces the relevant topic notes on every prompt so the agent never forgets to look.\n- **Multi-machine sync.** `saga sync` keeps your personal layer in step across Mac / Linux / Windows over your own private git remote.\n- **Versioned, open spec.** [Saga Topic Spec v1.0](docs/spec/saga-topic-v1.md) is published Apache-2.0 and defines the on-disk contract independent of any engine — V8 / ECMAScript model.\n- **Local-first, no telemetry.** SQLite index regenerable from markdown. No cloud, no auth, no vendor lock-in.\n- **Single static binary.** No runtime, no dependencies. macOS / Linux / Windows × amd64 / arm64.\n- **Hardened by default.** Secret-pattern detection at write time (AWS keys, SSH private keys, JWTs, etc.), similarity warnings on near-duplicates, `sensitivity: confidential` opt-out from sync. `gosec`, `govulncheck`, `gitleaks`, `golangci-lint`, CodeQL — all green in CI.\n\n## How memory is organised\n\n```\n~/go/bin/saga                    BINARY    one install, used everywhere\n~/.saga/personal/                DATA      your private notes (your own git remote)\n\u003cproject\u003e/.saga/                 DATA      project notes (commits with the project)\n```\n\n- **Personal layer** (`~/.saga/personal/`) — identity, preferences, policies, personal topics. Auto-created on first invocation. Sync to *your own* private git repo. Visible from any directory.\n- **Project layer** (`\u003cproject\u003e/.saga/`) — topics about this codebase. Created with `saga init`. Lives inside the project's git repo and travels with it. Active only when you `cd` into the project.\n- **Automatic resolution.** Saga walks up from `cwd` looking for `.saga/meta.yml`, merges with personal. Switch projects, project layer changes; personal stays.\n\n## Install\n\nPick whichever fits.\n\n### Option A — `go install` (any OS, needs Go ≥ 1.25)\n\n```bash\ngo install github.com/mopanc/saga/cmd/saga@latest\n```\n\nMake sure `$(go env GOPATH)/bin` is on `PATH` (usually `~/go/bin`).\n\n### Option B — prebuilt binary (no Go required)\n\nEvery release ships static binaries for all six common platforms. Pick your asset from the [latest release](https://github.com/mopanc/saga/releases/latest):\n\n| OS | Architecture | Asset |\n|---|---|---|\n| macOS | Intel | `saga_\u003cversion\u003e_macos_amd64.tar.gz` |\n| macOS | Apple Silicon (M1/M2/M3/M4) | `saga_\u003cversion\u003e_macos_arm64.tar.gz` |\n| Linux | amd64 (most x86_64 servers/desktops) | `saga_\u003cversion\u003e_linux_amd64.tar.gz` |\n| Linux | arm64 (Raspberry Pi 4/5, IMX8, AWS Graviton) | `saga_\u003cversion\u003e_linux_arm64.tar.gz` |\n| Windows | amd64 | `saga_\u003cversion\u003e_windows_amd64.zip` |\n| Windows | arm64 | `saga_\u003cversion\u003e_windows_arm64.zip` |\n\n`checksums.txt` (SHA-256) is published alongside for verification.\n\n#### One-line install — macOS / Linux\n\n```bash\nTAG=$(curl -sL https://api.github.com/repos/mopanc/saga/releases/latest | grep -o '\"tag_name\":\\s*\"[^\"]*\"' | cut -d'\"' -f4)\nOS=$(uname -s | tr '[:upper:]' '[:lower:]' | sed 's/darwin/macos/')\nARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')\ncurl -L \"https://github.com/mopanc/saga/releases/download/${TAG}/saga_${TAG#v}_${OS}_${ARCH}.tar.gz\" | tar -xz -C /tmp saga\nsudo mv /tmp/saga /usr/local/bin/saga\nsaga version\n```\n\n#### One-line install — Windows (PowerShell)\n\n```powershell\n$tag = (Invoke-RestMethod https://api.github.com/repos/mopanc/saga/releases/latest).tag_name\n$ver = $tag.TrimStart('v')\n$arch = if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') { 'arm64' } else { 'amd64' }\n$url = \"https://github.com/mopanc/saga/releases/download/$tag/saga_${ver}_windows_$arch.zip\"\nInvoke-WebRequest $url -OutFile $env:TEMP\\saga.zip\nExpand-Archive -Force $env:TEMP\\saga.zip -DestinationPath $HOME\\bin\n$env:Path = \"$HOME\\bin;$env:Path\"     # add to PATH for the session\nsaga version\n```\n\n### Option C — Homebrew / Scoop\n\nComing with `v1.0.0` stable. Watch the repo for the announcement.\n\n### Verify\n\n```bash\nsaga doctor                       # diagnoses everything that is missing\n```\n\n`saga doctor` is your compass — run it on any machine and it tells you exactly what is wired, what is missing, and a copy-paste fix for each gap.\n\n## Quick start\n\nPrerequisite: `saga` on your `PATH` (see [Install](#install)).\n\n### 1. Wire into Claude Code\n\n```bash\nsaga setup-claude --apply         # registers the MCP server and prints the hook snippet\n```\n\nSaga has two integration points and they live in different files:\n\n- **MCP server** → `~/.claude.json` (managed by `claude mcp add`). Without this, the `mcp__saga__*` tools never appear in any session.\n- **`UserPromptSubmit` hook** → `~/.claude/settings.json`. Without this, Saga does not auto-inject context into prompts.\n\n`--apply` runs `claude mcp add saga -s user -- $(which saga) mcp` for you. The hook snippet must be merged into `settings.json` by hand (automatic edits to that file would risk clobbering other hooks/MCPs).\n\n**Restart Claude Code completely (`Cmd+Q` and reopen)** — MCP servers and settings are read at startup.\n\n### 2. Initialise a project layer (optional)\n\nFor each project where you want shared, team-visible notes:\n\n```bash\ncd ~/code/acme-platform\nsaga init                         # creates .saga/meta.yml + .saga/topics/\ngit add .saga/ \u0026\u0026 git commit -m \"init saga layer\"\ngit push                          # ships with the project\n```\n\n`saga init` derives the scope name from `git rev-parse --show-toplevel`. The personal layer is auto-created on first invocation — no manual init needed.\n\n### 3. Validate\n\n```bash\nsaga doctor                       # everything should be ✓\n```\n\nFrom here, any MCP-configured AI gets the five tools listed below. On Claude Code, the hook injects on every prompt:\n\n- `\u003csaga-meta\u003e` — always, even when the index is empty. Tells the agent that Saga is wired in, lists the tools, and explains when to call `topic_write`. Without this, a fresh session has no way to discover Saga.\n- `\u003csaga-identity\u003e` — when profile / preference notes exist (personal baseline).\n- `\u003csaga-context\u003e` — when topic notes match the prompt's recall query.\n\n## Multi-machine sync\n\nSaga is built to follow you between PCs. The personal layer is a directory you control — make it a git repo backed by your own private remote, and `saga sync` does the rest.\n\n### One-time setup (first machine)\n\n```bash\ncd ~/.saga/personal\ngit init \u0026\u0026 git add -A \u0026\u0026 git commit -m \"init\"\ngit branch -M main\ngit remote add origin git@github.com:\u003cyour-user\u003e/saga-personal.git    # private repo\ngit push -u origin main\n```\n\n### Each new machine\n\n```bash\ngit clone git@github.com:\u003cyour-user\u003e/saga-personal.git ~/.saga/personal\nsaga reindex\n```\n\n### Day-to-day\n\n```bash\nsaga sync             # pull --rebase + push (auto-commits pending changes)\nsaga sync --status    # report state without changing anything\nsaga sync --pull      # pull only (useful at session start)\nsaga sync --push      # push only (useful after a burst of topic_writes)\n```\n\nOn conflict, `saga sync` stops with clear instructions: resolve manually, `git rebase --continue`, then re-run `saga sync --push`.\n\n`saga doctor` reports the sync state (remote, branch, ahead/behind, uncommitted files).\n\n## CLI\n\n| Command | What it does |\n|---|---|\n| `saga init` | Create `.saga/meta.yml` and `.saga/topics/` for a project layer in `cwd` |\n| `saga reindex` | Rebuild the SQLite index from markdown across active layers |\n| `saga sync` | Pull/push the personal layer between machines (`--pull`, `--push`, `--status`, `--no-auto-commit`) |\n| `saga lembrancas` | List recent recall events (filters: `--since`, `--kind`, `--topic`) |\n| `saga conflicts` | List unresolved `@conflicts_with` topic pairs in active layers |\n| `saga show` | Display a topic plus its incoming and outgoing relations |\n| `saga capabilities` | Print engine capability declaration (spec version, conformance level, types, operators) |\n| `saga lint` | Validate topics against [Saga Topic Spec v1.0](docs/spec/saga-topic-v1.md) — required fields, trait enums, slug ↔ title coherence, relation target resolution, supersedes / derived_from cycles, duplicate ids (`--scope`, `--fix`, `--format json`) |\n| `saga doctor` | Diagnose installation, configuration, content, and sync state |\n| `saga mcp` | Run as MCP stdio server (invoked by AI clients, not directly) |\n| `saga hook` | `UserPromptSubmit` hook for Claude Code (reads event JSON from stdin) |\n| `saga setup-claude` | Wire saga into Claude Code (`--apply` registers MCP automatically) |\n| `saga version` | Print version |\n| `saga help` | Help text |\n\n## MCP tools (every compatible AI client)\n\n| Tool | Purpose |\n|---|---|\n| `recall` | Retrieve topic notes (FTS5 + BM25 + recency + relation-aware ranking) across active scopes |\n| `topic_read` | Read a single topic note in full by name (slug or title) |\n| `topic_list` | List topic notes visible in the current scope |\n| `topic_write` | Create or update a topic note (default scope=personal; modes: `create` / `append` / `replace`). Blocks credential-shaped content by default; warns on near-duplicate titles |\n| `lembranca_log` | Inspect the recall history (filters: `since`, `kind`, `topic`, `limit`) |\n| `saga_capabilities` | Engine capability declaration for capability-negotiation (spec §10) |\n\n## Performance \u0026 limits\n\nSaga is designed so per-prompt token cost stays **constant** as your memory grows. The size of the corpus does not change how much context is injected — only retrieval ranking does.\n\n### Per-prompt injection — hard caps in code\n\n| Block | Cap | Source of truth |\n|---|---|---|\n| `\u003csaga-meta\u003e` | ~80 tokens (always-on) | `cmd/saga/cmd_hook.go::emitMetaBlock` |\n| `\u003csaga-identity\u003e` | **400 tokens** (env-overridable via `SAGA_BASELINE_MAX_TOKENS`) | `internal/saga/baseline.go::DefaultBaselineMaxTokens` |\n| `\u003csaga-context\u003e` | top-3 topics × 1000 chars each (~750 tokens), with **8 KB total ceiling** | `cmd/saga/cmd_hook.go::hookTopK / maxTopicBodyChars / maxHookOutputBytes` |\n| **Total per prompt** | **≈ 2000 tokens, hard ceiling** | — |\n\nTopics longer than the per-snippet cap are truncated with a `[truncated — call mcp__saga__topic_read for full body]` marker; the AI fetches the rest only when worth it.\n\n### Per-write cap — `topic_write` body\n\n| Limit | Value | Source |\n|---|---|---|\n| Per-topic body | **8000 chars (~2000 tokens, ~3000 words)** | `internal/saga/service.go::MaxTopicBodyChars` |\n\nWrites above the cap are rejected with an actionable error (split into narrower topics, or `mode=append` for evolving knowledge with dated sections). This keeps `topic_read` results bounded too — no surprise 13 KB tool result.\n\n### What grows with the corpus\n\n| Metric | Growth | Practical bound |\n|---|---|---|\n| Tokens injected per prompt | **constant (≈ 2000)** | n/a — by design |\n| Reindex time (full) | ~30 ms / topic | 10k topics ≈ 5 min, run on demand |\n| Recall latency (FTS5 + BM25) | sub-linear | well under 200 ms for 100k topics in measurements |\n| Index DB size | ~30 % overhead over markdown | 10k notes × 2 KB ≈ 26 MB total |\n| `git pull/push` of personal layer | linear in history | use `--depth=1` clone for very large layers |\n\n### What can degrade — and the recovery path\n\n1. **Hook timeout.** Claude Code allows ~30 s for `UserPromptSubmit`. Recall on extreme corpora can flirt with this limit. Mitigation in roadmap: `sqlite-vec` extension + Ollama embeddings (Phase 1.5).\n2. **Reindex failure.** The index is fully regenerable from markdown. `rm $SAGA_HOME/index.db \u0026\u0026 saga reindex` recovers 100 % of state.\n3. **Sync conflict.** Surfaced by `saga sync` with the conflicting file paths and exit-non-zero. Resolve with `git rebase --continue` and `saga sync --push`.\n4. **Wide recall query.** Top-K is bounded; ranking still applies. Worst case is irrelevant snippets, never an injection blow-up.\n\n### Token budget visibility (planned)\n\n`saga doctor` will surface a 7-day token-budget summary (avg/p99 injected, hook truncation count, `topic_read` average size). Backed by the existing `lembrança` log; landing in a future release.\n\n## Security model\n\nSaga is local-first and runs as your user. The short version of who it protects against, and who it does not:\n\n- **Protects.** Recall accidentally leaking across project layers · plaintext credentials drifting into topic bodies (`topic_write` runs a secret-pattern scanner) · sync of topics flagged `sensitivity: confidential` (never staged, never pushed) · common Go supply-chain issues (CI runs `gosec`, `govulncheck`, `gitleaks`, `golangci-lint`, CodeQL on every PR; releases are Cosign-keyless signed and ship a CycloneDX SBOM).\n- **Does not protect.** A compromised local user account · a compromised AI agent (whatever writes via `topic_write` is the authoriser) · disk theft without OS-level encryption (Saga does not encrypt at rest in v1 — that is on the v2 roadmap as opt-in) · compromise of the sync remote · prompt injection embedded in topic content · PII redaction beyond the credential scanner.\n\nUse **OS-level full-disk encryption** (FileVault / BitLocker / LUKS), keep your sync remote **private**, and mark anything truly sensitive `sensitivity: confidential` so it never leaves the machine.\n\nFull threat model, trust boundaries, and `sensitivity: confidential` semantics: [SECURITY.md](SECURITY.md).\n\n## Configuration\n\n| Variable | Default | Meaning |\n|---|---|---|\n| `SAGA_HOME` | `~/.saga` | Personal layer + index.db location |\n| `SAGA_DB_PATH` | `$SAGA_HOME/index.db` | Override the index path |\n| `SAGA_BASELINE_MAX_TOKENS` | `400` | Token budget for `\u003csaga-identity\u003e` injection per prompt |\n\n## Tested clients\n\n| Client | MCP | Auto-injection hook |\n|---|---|---|\n| [Claude Code](https://claude.com/claude-code) | ✓ | ✓ (`UserPromptSubmit`) |\n| [Cursor](https://cursor.com) | ✓ | — (manual `recall` / `topic_read` calls) |\n| [Windsurf](https://windsurf.com) | ✓ | — |\n| [Antigravity](https://antigravity.google.com) | ✓ | — |\n\nEvery MCP-conformant client should work; auto-injection on each prompt is Claude Code-only because no other client exposes a comparable hook.\n\n## Troubleshooting\n\n**`saga: command not found` in one terminal but works in another.**\nOften an IDE (Cursor / VS Code / Antigravity) opens a login shell that reads `.zprofile` but not `.zshrc`. Add the `PATH` export to both files.\n\n**Hook does not fire after editing `settings.json`.**\nClaude Code does not reload settings at runtime. `Cmd+Q` and reopen.\n\n**`saga doctor` reports \"saga MCP server not registered\".**\nClaude Code reads MCP servers from `~/.claude.json` (not `~/.claude/settings.json`). Run `saga setup-claude --apply`, or manually `claude mcp add saga -s user -- $(which saga) mcp`. If the `claude` CLI is missing, install / repair Claude Code first.\n\n**`saga doctor` reports \"UserPromptSubmit hook not wired\".**\nYou did not merge the hook snippet into `~/.claude/settings.json`. Re-run `saga setup-claude` and add the `hooks` block without removing any existing entries.\n\n**`saga reindex` reports `failed=N`.**\nInvalid YAML frontmatter in some `.md` files. Run `saga reindex` to see exact paths; open and validate the YAML.\n\n## Architecture\n\n| Layer | Choice |\n|---|---|\n| Language | Go 1.25+ |\n| MCP transport | JSON-RPC 2.0 stdio (in-tree, ~200 LOC, no third-party MCP SDK) |\n| Index | SQLite via [`modernc.org/sqlite`](https://modernc.org/sqlite) (pure Go, no CGO, cross-compiles trivially) |\n| Search | FTS5 + BM25 + custom recency boost; `sanitizeFTSQuery` against keyword injection |\n| Vector (Phase 1.5) | `sqlite-vec` (lazy-loaded; `embedding BLOB` column reserved from day one) |\n| Embeddings (Phase 1.5) | Ollama local, `nomic-embed-text` |\n\n```\nsaga/\n├── cmd/saga/                  single binary, subcommands in cmd_*.go\n├── internal/\n│   ├── saga/                  core: parser, indexer, layers, service, baseline, lembrança, sync\n│   │   └── migrations/*.sql   schema embedded in the binary\n│   └── mcp/                   JSON-RPC 2.0 stdio server\n└── docs/                      design notes\n```\n\n### Data flow\n\n```mermaid\nflowchart LR\n    subgraph disk[On disk]\n        MD[(markdown\u003cbr/\u003etopics/*.md)]\n        IDX[(SQLite\u003cbr/\u003eindex.db)]\n    end\n    subgraph runtime[saga binary]\n        H[saga hook\u003cbr/\u003eUserPromptSubmit]\n        M[saga mcp\u003cbr/\u003eJSON-RPC 2.0 stdio]\n        CLI[saga lint / sync /\u003cbr/\u003edoctor / show]\n    end\n    AI((AI agent))\n    CC((Claude Code /\u003cbr/\u003eCursor / Windsurf))\n\n    MD -. reindex .-\u003e IDX\n    H  -- FTS5 + BM25 + relations --\u003e IDX\n    M  -- topic_write atomic --\u003e MD\n    M  -- recall --\u003e IDX\n    AI \u003c==\u003e|MCP tools| M\n    CC -- spawns on every prompt --\u003e H\n    CLI -- read --\u003e IDX\n    CLI -- read --\u003e MD\n```\n\nMarkdown is the source of truth. The SQLite index is a regenerable cache — `rm ~/.saga/index.db \u0026\u0026 saga reindex` restores it from disk. The hook is fire-and-forget per prompt; the MCP server is the long-lived process the agent talks to.\n\n## Saga Topic Spec\n\nSaga is a **cognitive substrate over markdown**, not just a memory tool. The on-disk contract — primitives, relations, operators, conformance levels — is published as a versioned specification, separate from any particular engine.\n\n- [`docs/spec/saga-topic-v1.md`](docs/spec/saga-topic-v1.md) — Saga Topic Specification v1.0 (draft).\n- [`docs/spec/README.md`](docs/spec/README.md) — spec/engine separation, versioning, contribution process.\n\nThe model is ECMAScript / V8: an open spec that anyone can implement, plus a canonical reference engine (this repository) that catches up to the spec over time. Other engines — IDE lint extensions, cognitive runtimes, hosted services — are welcome and conform by implementing the level (§10) that fits their surface.\n\n## Documentation\n\n- [docs/spec/saga-topic-v1.md](docs/spec/saga-topic-v1.md) — **Saga Topic Spec v1.0** (normative on-disk contract).\n- [docs/DESIGN_v2.md](docs/DESIGN_v2.md) — technical architecture (storage, MCP, SQL).\n- [docs/COGNITIVE_MODEL.md](docs/COGNITIVE_MODEL.md) — cognitive model (5 layers + 2 cross-cutting); failure modes, anti-creep.\n- [docs/PLAN.md](docs/PLAN.md) — iterations and utility tests.\n- [docs/ROADMAP_v2.md](docs/ROADMAP_v2.md) — granular tasks with acceptance criteria.\n\n## Building from source\n\n```bash\ngo build ./...      # compiles all packages\ngo test ./...       # runs the test suite\ngo run ./cmd/saga version\n```\n\nMain branch: `main`.\n\n## Contributing\n\nIssues and pull requests are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for the conventions, [SECURITY.md](SECURITY.md) for vulnerability reporting, and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for community expectations.\n\n## License\n\n[Apache-2.0](LICENSE) © 2026 Jorge Morais\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmopanc%2Fsaga","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmopanc%2Fsaga","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmopanc%2Fsaga/lists"}