Skip to content

Latest commit

 

History

26 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Brainer

Your docs and your landing page are nodes in your code graph.

Change a function → know which paragraph of marketing copy just became a lie. Start a task → get the files that matter, without the search loop.

no API key · no network · no telemetry · 24MB · works offline


Two problems, one graph

1. Prose rots silently

Every code-intelligence tool can tell you what calls what. None can tell you that yoursite.com/product/ still advertises the feature you renamed last Tuesday.

$ brainer surfaces getSession

  getSession()  src/lib/auth/helpers.ts

  3 surfaces describe this:
    docs/architecture.md › Server vs client         98%  declared
    docs/auth.md › Authentication › File Layout     98%  declared
    docs/security.md › Cookie hardening             90%  semantic

2. Agents search blind, and you pay for it

An agent starting a task greps, globs, reads, discards, greps again. Every round costs tokens and latency, and it still misses things.

$ brainer context "add rate limiting to the login flow"

  src/lib/auth/server.ts        91%  semantic + imported by login
  docs/auth.md › Auth Flow      88%  prose match
  src/app/auth-form.tsx         84%  imports auth/server
  src/lib/auth/actions.ts       81%  semantic
  ...
  Nothing matched: "throttle" — search for this directly.

Measured against a keyword-grep baseline on four real tasks:

grep Brainer
recall of the files that mattered 48% 94%
tokens spent 21.1k 12.8k

Twice the recall, ~60% of the cost, one call instead of a loop.


Quick start

npm install -g @stack256org/brainer
brainer install       # detect your agent, wire everything up
brainer init          # build the index

Installed from GitHub, not npm — the name brainer on npm belongs to an unrelated package. The @stack256org scope is registered; @stack256org/brainer publishes there when it is ready.

After that it is on by default — nobody has to remember Brainer exists or ask for it each session.

brainer install --global   # wire up every session, not just this project
brainer serve              # the whole graph in a browser

init downloads a 24MB model once. After that Brainer never touches the network.

On by default, including cold sessions

Host How it becomes default
Claude Code SessionStart + UserPromptSubmit + PostToolUse hooks
Codex, Copilot CLI, Gemini CLI skill in ~/.agents/skills/ + AGENTS.md
Cursor, Windsurf, Continue, Aider AGENTS.md / .cursorrules + MCP instructions
Any other MCP client MCP instructions sent on connect

A cloud session starts with no index — a fresh clone, an ephemeral container. SessionStart detects that, builds the index in the background, and says so. The query hooks stay quiet until it is ready, so a cold session degrades to no Brainer, never to Brainer but wrong.

Always-on costs 36 tokens per turn, measured across a realistic mix of task openers, follow-ups and off-topic prompts. One grep round-trip in an agent loop is 800–2000.


Works with your agent

Built in tiers, so it degrades instead of breaking.

Tier Surface Works with Automatic
1 CLI anything, including CI no
2 MCP every MCP client on request
3 Skills Claude Code, Codex, Copilot CLI, Gemini CLI model decides
4 Hooks Claude Code every time

The CLI is the substrate — MCP, skills and hooks are thin wrappers over it, so a host Brainer has never heard of still works at tier 1.

MCP config is identical everywhere; only the key differs (mcpServers, servers for VS Code, context_servers for Zed). brainer install writes the right one. Full matrix, plus an AGENTS.md snippet for hosts without skills: integrations/README.md.

Three hooks, three jobs

Event When Job Tuned for
SessionStart session opens build/refresh index, warm the model availability
UserPromptSubmit before work seed context with relevant files recall
PostToolUse after an edit report prose describing the change precision

The recall/precision split is deliberate. A missed file makes an agent do incomplete work confidently — worse than searching slowly. A false surface cries wolf, and a noisy hook gets muted within a week. Same graph, opposite tuning.

Both fail silent: no index, tool missing, timeout or stale data prints nothing and leaves your session untouched.


How it works

     PROSE                                          CODE
  ┌──────────────────────┐                 ┌──────────────────────┐
  │ landing page copy    │───── describes ─│ runMigrations()      │
  │ docs/architecture.md │═════ declared ══│ getSession()         │
  │ README › Themes      │───── semantic ──│ ThemeProvider        │
  └──────────────────────┘                 └──────────────────────┘
        ═══ corroborated          ─── guess, awaiting confirmation

Prose is a node type. A heading and its body, a JSX text run, a doc comment — indexed, linked to the symbols it describes, traversed like any other edge.

Three properties keep it honest:

Provenance is never blended. An edge from a resolved import and an edge guessed from similarity are different kinds of thing. Structural and semantic results come back in separate buckets; a guess never renders as a fact.

Confidence is calibrated, not raw. Embedding similarity is compressed — a cosine of 0.50 means the link is right ~98% of the time. Reporting the raw number would say "coin flip" about a near-certainty. Brainer stores the score and reports the measured probability.

Guesses become facts. brainer confirm writes a marker into the file, so a link you approved once is never guessed again. Precision climbs with use instead of being frozen at whatever the model gives you.


Commands

brainer context "<task>"      # files a task touches — recall-tuned seed set
brainer surfaces <symbol>     # what prose describes this?
brainer impact <file>         # blast radius, bucketed by provenance
brainer trace <from> <to>     # how does A reach B?
brainer review                # walk unconfirmed links, y/n/skip
brainer doctor                # stale index, orphaned links, hubs
brainer serve                 # the graph, in a browser

Every command takes --json.


Measured, not asserted

Verified against a 103-file TypeScript repo and a separate marketing site, with a hand-labelled golden set.

Link recall@30 0.885
Link precision@3 0.677 (hand-adjudicated)
Agent context recall 94% shipped (100% in the spike) vs grep's 48%
Import resolution 100% (162/162, incl. tsconfig aliases)
impact() query 0.05ms worst case
Incremental reindex 15× faster than full
Always-on overhead 36 tokens/turn

Two probes failed before they passed, and a cross-encoder reranker was cut for making precision worse (0.391 → 0.198). Full methodology, including what we got wrong: docs/VERIFICATION.md.


Honest limitations

  • Renames break confirmed links. doctor reports them; automatic rename detection is deferred.
  • 59% of real links have no corroborating identifier and stay labelled guesses until reviewed. The review flow is load-bearing, not a nicety.
  • Some prose has no code referent. ~1/6 of a landing page describes the project as a whole. Returning nothing is correct, and Brainer returns nothing rather than inventing a link.
  • Cross-file call resolution is heuristic without a type checker, and labelled as such.
  • The context seed set is not exhaustive. It is a starting point.

Language support

TypeScript, TSX, JavaScript, JSX. Markdown, MDX and HTML for prose. Grammars sit behind a registry, so more languages are a contribution, not a fork.

Brainer deliberately does not chase a 60-language count. Breadth is the competition's differentiator. Prose is ours.


Releasing

Publishing runs on npm trusted publishing (OIDC), so there is no NPM_TOKEN secret to leak or rotate. GitHub Actions requests a short-lived identity token, npm checks it against the trusted-publisher rule for this repository, and publishes if it matches.

npm version patch          # or minor / major
git push

That is the whole release. release.yml sees a version with no matching tag on main, runs the tests, tags it, cuts a GitHub release, and publishes.

Release and publish are one workflow, publish.yml, because npm trusted publishing validates the entry-point workflow filename. Splitting them cannot work: a release cut with GITHUB_TOKEN raises no event for another workflow to catch, and a reusable workflow presents the caller's filename in the OIDC claim. One file, named what npm trusts, is the only arrangement where a merge publishes by itself.

A merge whose version is unchanged releases nothing, on purpose — a typo fix should not burn a version number, and npm versions cannot meaningfully be unpublished.

First publish is manual. npm cannot create a new package over OIDC: a trusted-publisher rule can only attach to a package that already exists. So the first version goes up by hand, and everything after it is automatic.

With a passkey (WebAuthn) as your second factor there is no six-digit code to pass to --otp. Use a current npm, which falls back to a browser flow:

npx npm@latest publish --access public

It prints a npmjs.com/auth/cli/… URL, waits while you authenticate with the passkey, and then completes. This needs a real terminal — npm redacts that URL when stdout is not a TTY, so it cannot be driven from a script. npm 10 does not offer the fallback at all and only accepts --otp.

Then, on npmjs.com: the package → Settings → Trusted Publisher → repository stack256org/brainer, workflow publish.yml. After that, releases publish themselves and no token is ever stored.

workflow_dispatch runs the same job with --dry-run by default, so the whole path can be exercised without shipping anything.

Status

v0.1.0 — working. Indexes, links, queries, serves and installs. Verified against a real 127-file corpus: 281 symbols, 209 prose blocks, 2684 edges in 7.7s.

The confirmation ratchet is live: review, confirm and reject are built and tested, so a guess you approve is written into the file as a marker and read back as ground truth — precision now climbs with use rather than sitting wherever the model left it. trace and doctor are built too.

Still outstanding: true per-file incremental reindex. reindex rebuilds.

Usage · Design · Verification · Integrations

Part of Stack256 — 256 open-source applications you can host yourself.

About

Your docs and landing page are nodes in your code graph. Change a function, know which paragraph of marketing copy just became a lie.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages