{"id":50758962,"url":"https://github.com/simcubeltd/synapse","last_synced_at":"2026-06-11T08:01:45.841Z","repository":{"id":361841444,"uuid":"1256070488","full_name":"SimCubeLtd/synapse","owner":"SimCubeLtd","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-01T13:58:21.000Z","size":107,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-01T14:25:09.264Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SimCubeLtd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"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-06-01T12:39:25.000Z","updated_at":"2026-06-01T14:17:37.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/SimCubeLtd/synapse","commit_stats":null,"previous_names":["simcubeltd/synapse"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/SimCubeLtd/synapse","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimCubeLtd%2Fsynapse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimCubeLtd%2Fsynapse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimCubeLtd%2Fsynapse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimCubeLtd%2Fsynapse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SimCubeLtd","download_url":"https://codeload.github.com/SimCubeLtd/synapse/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimCubeLtd%2Fsynapse/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34188272,"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-11T02:00:06.485Z","response_time":57,"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":[],"created_at":"2026-06-11T08:01:44.906Z","updated_at":"2026-06-11T08:01:45.822Z","avatar_url":"https://github.com/SimCubeLtd.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SimCube Synapse\n\nA deterministic, **local**, **offline** repository context compiler.\n\n`synapse` indexes a source repository into a lightweight graph (files, symbols,\nprojects, packages, and their relationships), persists it in\n[LadybugDB](https://ladybugdb.com), and emits compact, LLM-ready Markdown\ncontext packs you can paste into ChatGPT, Claude, Codex, or any other LLM UI.\n\nIt is **not** an AI agent, **not** an MCP server, and requires **no daemon, no\nnetwork, and no AI API calls**. It is a pure local CLI built for large\nmono-repos and mixed-language engineering repositories.\n\n```text\nlocal repo\n  -\u003e indexed graph in LadybugDB\n  -\u003e selected relevant files/symbols/relationships\n  -\u003e compact LLM-ready Markdown context pack\n```\n\nThe core value is **selection**: it does not dump your whole repo. It picks\nfocused context based on changed files, paths, symbols, or queries, ranks it,\nfits it to an approximate token budget, and renders portable Markdown.\n\n## Install / build\n\nRequires a recent Rust toolchain and a C++ toolchain (LadybugDB statically\ncompiles its engine on first build).\n\n```bash\ncargo build --release          # binary at target/release/synapse\n```\n\nLadybugDB lives behind a default-on cargo feature (`ladybug`). Tests that only\nneed the in-memory store can run without it:\n\n```bash\ncargo test --no-default-features   # fast: no C++ build, no Ladybug\ncargo test                         # full suite incl. the Ladybug smoke test\n```\n\n## Usage\n\n```bash\nsynapse init --name my-repo                 # create .synapse/ + config\nsynapse index --stats                       # build the graph\nsynapse status                              # ready / stale / counts\nsynapse symbols GraphStore                  # search symbols\nsynapse symbols --kind component --language typescript\nsynapse related --symbol MyHandler --depth 2\nsynapse pack --symbol MyHandler --output context.md\nsynapse pack --changed --budget 40000 --output context.md --explain\nsynapse pack --symbol MyHandler --format json     # structured output for tools\nsynapse explore                                   # visualize the graph in a browser\nsynapse pull                                      # fetch a shared graph from an OCI registry\nsynapse push --yes                                # publish the graph (restricted; see below)\nsynapse clean --all\n```\n\n### Visualizing the graph\n\n`synapse explore` launches [Ladybug Explorer](https://docs.ladybugdb.com/visualization/)\n— a browser UI for the graph — from its Docker image, mounting the indexed\n`.lbug` file **read-only** by default on \u003chttp://localhost:8000\u003e:\n\n```bash\nsynapse explore                 # foreground, read-only, Ctrl-C to stop\nsynapse explore --read-write    # allow edits in the UI to persist\nsynapse explore --detach        # run in the background\nsynapse explore --print         # just print the `docker run` command\n```\n\nRequires Docker. If it isn't installed/running, `explore` prints the exact\n`docker run` command so you can run it yourself. Note: Explorer's storage format\nmust match this build's LadybugDB version — if you hit a storage-format error,\ntry `--tag dev` or a matching image tag.\n\n### Commands\n\n| Command | Purpose |\n|---|---|\n| `init` | Create `.synapse/{synapse.toml,graph,cache,packs}` (`--force`, `--name`). |\n| `index` | Index the repo into LadybugDB (`--force`, `--changed`, `--stats`). Incremental via blake3 content hashes. |\n| `status` | Show index readiness, counts (including `referenceEdges`), stale + untracked files (`--json`, `--stale`). The `--json` output lists `referenceLanguages` so reference-edge coverage is explicit. |\n| `symbols \u003cquery\u003e` | Search symbols (`--kind`, `--file`, `--language`, `--json`). |\n| `related` | Find related files for a `--symbol` or `--file` (`--depth`, `--json`). Traverses the graph — project membership (`CONTAINS_FILE`) for same-project siblings, type relations (`INHERITS`/`IMPLEMENTS`) for base types, interfaces/traits, subtypes and implementors, and usage references (`REFERENCES`) for callers / instantiation sites — alongside same-directory / test / name heuristics. |\n| `packages` | List indexed package dependencies (or `--projects`), with versions resolved via .NET Central Package Management (`--ecosystem`, `--json`). Use `--importers \u003cpkg\u003e` for impact analysis: the files that import a package. |\n| `explore` | Launch [Ladybug Explorer](https://docs.ladybugdb.com/visualization/) (Docker) to visualize the indexed graph in a browser (`--port`, `--read-write`, `--detach`, `--in-memory`, `--tag`, `--print`). Mounts the index read-only by default; `--print` shows the `docker run` command without executing it. |\n| `pack` | Emit a context pack (`--changed`/`--path`/`--symbol`/`--query`, `--budget`, `--include-tests`, `--include-config`, `--include-diff`, `--dry-run`, `--explain`, `--output`). `--format markdown` (default) or `--format json` for programmatic callers. Writes to stdout unless `--output` is given; diagnostics go to stderr. |\n| `pull` | Fetch a shared graph from the configured OCI registry (`--tag`, `--registry`, `--repository`). Verifies integrity (blake3), writes the graph atomically, and warns if its indexed commit differs from local `HEAD`. |\n| `push` | Publish the indexed graph to the configured OCI registry (`--tag`, `--registry`, `--repository`, `--yes`, `--allow-dirty`). Restricted — see [Sharing the graph](#sharing-the-graph-oci-registry). |\n| `clean` | Remove `--cache` / `--index` / `--packs` / `--all`. |\n\n## Sharing the graph (OCI registry)\n\nThe indexed graph (`synapse.lbug`) is a multi-MB binary — too heavy for git. Instead, share it with your team via any OCI registry (GHCR, ECR, ACR, Harbor, …): CI (or a maintainer) `push`es the graph, teammates `pull` it instead of re-indexing.\n\n```bash\n# One-time: point the [share] section at your registry (in .synapse/synapse.toml)\n#   [share]\n#   registry = \"ghcr.io\"\n#   repository = \"myorg/myrepo-synapse-graph\"\n#   push_enabled = true        # required to allow `push` at all (default false)\n\nsynapse pull                   # fetch the current shared graph (tag \"latest\")\nsynapse pull --tag a1b2c3d     # fetch the graph for a specific commit\nsynapse push --yes             # publish (CI-friendly; skips the confirm prompt)\n```\n\n- **Credentials are auto-discovered** from your existing `docker login` (`~/.docker/config.json` + OS credential helpers). You do **not** put a token in synapse's config. Public registries pull anonymously with no setup. For headless setups without a docker config, set `SYNAPSE_REGISTRY_USER` + `SYNAPSE_REGISTRY_PASS` (or `SYNAPSE_REGISTRY_TOKEN`).\n- **Push is heavily guarded** (a fresh clone / CI can never push by accident): it requires `push_enabled = true` in config **and** a clean working tree (or `--allow-dirty`) **and** interactive type-to-confirm (or `--yes`). The graph is tagged by commit (a per-commit tag plus the moving `latest`), so a tag always describes a known state.\n- **Staleness is surfaced, never hidden.** `pull` warns loudly when the graph's indexed commit differs from your `HEAD`, and `synapse status` shows the pulled graph's `Origin:` commit on every run. If it's stale, `synapse index` rebuilds locally.\n- **Visibility = the registry's visibility.** The graph encodes file paths, symbol names and dependencies — treat a public registry accordingly.\n- Sharing is the `share` Cargo feature (on by default); a `--no-default-features` build without it drops the networking/TLS stack and the `push`/`pull` commands.\n\n## Languages\n\nSymbol extraction (via tree-sitter) covers **C#, Rust, Python, Go, JavaScript,\nTypeScript/TSX, Svelte (Svelte 5 / SvelteKit), Bash/sh, YAML, JSON, and\nMarkdown**:\n\n- **JS/TS**: functions, classes, interfaces, type aliases, enums, exported\n  declarations, and obvious React components.\n- **Svelte**: each `.svelte` file is a `component` symbol named after its file\n  stem, plus the functions/classes/types declared in its `\u003cscript\u003e` block\n  (parsed as TS by default, `lang=\"js\"` honoured). SvelteKit route files\n  (`+page`, `+layout`, `+server`, `+error`) are recognised and tagged with their\n  route role.\n- **Bash/sh**: function definitions from `.sh`/`.bash`/`.zsh` files.\n- **YAML / JSON**: top-level mapping keys (and YAML anchors) as `key` symbols, so\n  config sections are searchable and packable by name.\n- **Markdown**: every heading (ATX and setext) as a `key` symbol named after the\n  heading text, with its level recorded — so docs repos are ingestible and you\n  can pack a specific section by name (`pack --query \"Installation\"`). Covers\n  `.md`/`.markdown`/`.mdx`.\n\n`.csproj` files contribute project/package references; `package.json` files\ncontribute dependencies, dev/peer dependencies, and scripts. Per-language\nextraction can be toggled in `[index.languages]` in `synapse.toml`.\n\n**Type relationships** (`INHERITS` / `IMPLEMENTS`) are extracted from explicit\ndeclarations — C# base lists, Rust `impl Trait for Type` and supertrait bounds,\nTS `extends`/`implements`, Python class bases, Go embedding — and resolved to\nsymbols by name (preferring same-file/same-project matches). For C#, where the\nsyntax doesn't separate a base class from interfaces, the edge kind is decided\nfrom the target symbol's kind. This is deterministic name-based resolution, not\nfull type inference.\n\n**Usage references** (`REFERENCES`) connect the symbol a usage sits inside to the\nsymbol it points at — `new Foo(...)` instantiations, calls, and type uses. So\n`related --symbol Foo` and `pack --symbol Foo` now surface the callers and\ninstantiation sites of `Foo`, not just its declaration. Resolution is the same\ndeterministic, name-based scheme as type relationships (same-file/same-project\npreference; ambiguous names link every candidate rather than guessing; a name\nthat matches no declared symbol — e.g. a local variable — produces no edge).\nReference extraction currently covers **C#, Rust, and JS/TS**; `status --json`\nreports `referenceLanguages` and a `referenceEdges` count so coverage is explicit\nrather than silently partial. (Python, Go and Svelte resolve type relationships\nand imports but not yet usage references.)\n\n**File → package imports** (`IMPORTS_PACKAGE`) are extracted for JS/TS (`import`/\n`require`, reduced to the npm package root) and C# (`using` namespace, matched to\nthe NuGet package by longest dotted prefix). Edges are only created when an\nimport resolves to a package the manifests already declared, so\n`synapse packages --importers \u003cpkg\u003e` answers \"which files use this dependency?\".\n\n**.NET Central Package Management** is handled: a `PackageReference` without an\ninline version is resolved against the `\u003cPackageVersion\u003e` pins in the nearest\n`Directory.Packages.props` (and shared `PackageReference`s in\n`Directory.Build.props`) up the directory tree. Projects governed by CPM are\nflagged accordingly. Files are also linked to their nearest owning project\n(`.csproj`/`package.json`) in the graph.\n\n## Architecture\n\n```text\nsrc/\n  main.rs        cli.rs        config.rs     repo.rs      git.rs    errors.rs\n  indexer/       { languages, tree_sitter, dotnet, node }\n  graph/         { model, store (GraphStore trait), ladybug_store, memory_store }\n  pack/          { selector, budget, markdown }\n  output/        { table, json }\n```\n\nAll LadybugDB-specific code is isolated in `src/graph/ladybug_store.rs` behind\nthe `GraphStore` trait, so the storage backend stays replaceable and testable.\nA `MemoryGraphStore` backs unit tests; the production CLI always uses LadybugDB.\n\n## Claude\n\nGet claude to create a memory, that prefers the tool usage over raw grep.\n\n```markdown\nSave this as a memory called reference_synapse_cli.md in this project's memory directory, and add a one-line entry for it to MEMORY.md so it shows up in the index. Here's the content:\n\n---\nname: reference-synapse-cli\ndescription: \"synapse CLI — local offline graph index of the repo; use BEFORE grep/glob/Explore to pull focused, token-budgeted context.\"\nmetadata:\n  node_type: memory\n  type: reference\n---\n\n`synapse` is a deterministic, offline Rust CLI that indexes a repo into a local graph (LadybugDB at `.synapse/`) and emits focused, token-budgeted context packs. No network, no AI, no daemon. **Prefer it over reading whole files or running multi-file grep sweeps** when you need to understand or modify code.\n\n## Setup (once per repo)\n\\```bash\nsynapse init            # creates .synapse/\nsynapse index           # build the graph (incremental, blake3-hashed, safe to repeat)\nsynapse status --json   # confirm: filesIndexed, symbolsIndexed, referenceEdges, referenceLanguages\n\\```\n\nRe-run `synapse index` after code changes; `status` reports `staleFiles`.\n\n## When to reach for it\n- Before editing a known file: **`synapse pack --path \u003cfile\u003e --format json --budget 20000`** is the killer move — gives the file + same-directory siblings (events, exceptions, supporting types) in one call. Replaces 5–7 sequential Reads when working in a domain slice.\n- \"Who emits/calls/instantiates X\" — **`synapse related --symbol X --json`** returns true reference sites via the REFERENCES edge (C#/Rust/JS/TS). **Replaces grep for symbol impact analysis on supported languages.**\n- Before editing a symbol: `synapse pack --symbol \u003cName\u003e --format json --budget 20000` pulls the declaration + all reference sites at tier 1, ahead of same-directory noise.\n- Before editing the working tree: `synapse pack --changed --format json` to see exactly what's about to be touched plus related context.\n- Symbol lookup faster than grep: `synapse symbols \u003cquery\u003e --kind class --json` — fast, precise.\n- Dependency impact analysis: `synapse packages --importers \u003cpkg\u003e --json` — beats grep for \"what would a library upgrade touch?\".\n- Skip when: you already know the exact file path AND need the full contents (just Read it); you need full-text content search inside strings/comments/log messages (synapse correctly ignores comments — grep for those); the target language is Python/Go/Svelte (no REFERENCES yet — check `status` `referenceLanguages`).\n\n## Contract\n- **stdout = data, stderr = diagnostics.** Capture stdout, ignore stderr. Exit 0 = ok, 1 = error.\n- Pass `--json` (or `pack --format json`) for machine-parseable output — always prefer this when consuming programmatically.\n- Deterministic; all paths repo-relative with forward slashes.\n- If a command errors \"no Synapse workspace\" / \"run `synapse index` first\" → run `synapse index`. Use `synapse index --changed` on big repos.\n\n## `pack` — the main tool\nPick exactly ONE selection mode: `--symbol \u003cName\u003e`, `--changed`, `--path \u003cdir|file\u003e`, or `--query \u003ctext\u003e`. Useful flags:\n- `--format json` (structured: `{request, repository, selection[], symbols[], files[{path,language,contents}], diff?}`)\n- `--budget \u003cN\u003e` token cap (default 40000; over-budget files listed as `included:false`)\n- `--depth \u003cN\u003e` graph expansion (default 1)\n- `--dry-run` selection + symbols only, no contents (cheap preview)\n- `--explain` print ranking tier/reason (to stderr)\n- `--include-tests` / `--include-config` / `--include-diff` / `--output \u003cfile\u003e`\n\nSelection ranking (high→low): changed / exact-symbol / exact-path → graph relations (same project, base types, implementors, imports, **references**) → tests/config/same-dir → docs. Generated files, lockfiles, minified bundles excluded.\n\n## Other commands\n- `synapse symbols \u003cquery\u003e [--kind \u003ck\u003e] [--language \u003cl\u003e] [--file \u003cpath\u003e] [--json]` — kinds: class struct record interface trait enum function method module type component constructor key. Languages: csharp rust python go javascript typescript svelte bash yaml json markdown.\n- `synapse related --symbol \u003cName\u003e` or `--file \u003cpath\u003e` `[--depth N] [--json]`\n- `synapse packages [--json] [--projects] [--importers \u003cpkg\u003e]` — last form is impact analysis: which files import a package. CPM-resolved for .NET.\n- `synapse explore` — Ladybug Explorer UI on :8000 (needs Docker); `--print` to just print the docker command.\n\n## Graph contents\nNodes: Repository, Project, Package, File, Symbol. Populated edges: DECLARES, CONTAINS_FILE, REFERENCES_PROJECT, USES_PACKAGE, IMPORTS_PACKAGE (JS/TS + C#), INHERITS, IMPLEMENTS, **REFERENCES (symbol→symbol: `new`/call/type use; C#/Rust/JS/TS only as of v0.1.5 — check `status.referenceLanguages`).** CALLS is folded into REFERENCES; the legacy edge is empty, don't rely on it. Edge resolution is name-based (no type inference): ambiguous names may link to multiple symbols (prefers same-file/project). `related --symbol`/`pack --symbol` need exact (case-insensitive) name match to seed. **REFERENCES are anchored to the enclosing declaration** — a usage at file/module top-level (outside any function/type) is not captured.\n\n## Symbol extraction by language\nC#, Rust, Python, Go, JS/TS (+JSX/TSX), Svelte (component + script symbols + SvelteKit route roles), Bash (functions), YAML/JSON (top-level keys), Markdown (headings as `key` symbols).\n\n## Gotchas (learned from real use)\n- **`related --symbol` can explode on overloaded names at depth 1.** A name declared in many files makes \"same project\" at depth 1 pull the entire enclosing project. The REFERENCES results come first (good) but the same-project noise still bloats the JSON — filter on `reason` containing `\"references\"` or `\"declares\"` when you only care about real call sites, or use `--path \u003cfile\u003e` for narrow scope.\n- **Always budget-cap `pack`.** Output is huge by default (40k token budget). For most domain-slice work, `--budget 20000` is plenty. Use `--dry-run` first when unsure — it shows selection + estimated tokens without the contents.\n- **REFERENCES only covers C#/Rust/JS/TS** (v0.1.5). Python, Go, Svelte declarations index fine but their call sites won't show up via `related`. Confirm coverage with `synapse status --json` → `referenceLanguages`.\n- **REFERENCES needs an enclosing declaration.** A `new Foo()` at module top-level (outside any function/method/class) is not captured. Rare in C#/Rust, more common in TS/JS init code — grep if you suspect a top-level call site.\n- **`symbols`/`--query` match names+paths, not file bodies.** For text inside files (string literals, comments, log messages), use grep. **Comments are correctly ignored** by REFERENCES — a \"see `UserRegistered` in XYZ\" doc comment is NOT a reference and won't show up.\n- **Pipe big JSON through `python3 -c`/`jq`** instead of `head` — the file list is what you want, raw JSON dumps blow up context.\n\n## Verdict (measured head-to-head vs grep)\n- **Find related classes**: synapse finds ~4× more relevant classes than naive `grep \"class X\"` (catches names *containing* X, not just prefix matches).\n- **Find usages**: filtered `related --symbol` returns the actionable list; raw `grep -l` returns ~6× more files (substring matches in unrelated names, comment hits, doc references).\n- **Get a domain slice**: `pack --path` is 1 call + automatic budget enforcement; the grep equivalent is 1 `ls` + N `Read` calls with no ranking.\n\nUse synapse first. Reach for grep only when (a) you need text inside strings/comments/log messages, (b) the language isn't in `referenceLanguages` yet, or (c) you're hunting a top-level usage outside any declaration.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimcubeltd%2Fsynapse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimcubeltd%2Fsynapse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimcubeltd%2Fsynapse/lists"}