open source · MIT Version control for the age of coding agents

Git remembers what changed. Scholion remembers why.

Scholion gives coding agents a memory of why. Instead of re-reading the tree and rediscovering what was already tried, decided and rejected, every agent starts from the context that matters: decisions and dead ends anchored to the code, its own isolated workspace, and a deterministic context pack that never outgrows the context window or the token budget.

$curl -fsSL https://raw.githubusercontent.com/vinhqbui/scholion/main/scripts/install.sh | sh

σχόλιον, n. a note written in the margin of a manuscript.

0LLM calls inside the packer. Same state, same pack.
800tokens in the default pack: signatures, not bodies the agent reads anyway
1isolated jj workspace per task, no shared checkout
−13%turns per task for Claude Code, at the same cost (benchmark)
Why we build this

Agents shouldn't start from zero. We're building the home where they build together and never forget.

Software is being written by swarms of agents. Give them a shared memory, safe parallel workspaces and a handoff that just works, and they stop repeating each other and start compounding. Join us and help shape the code system they'll all use.

Ship in parallelA swarm of agents, each in its own workspace. Main moves only through review, and any merge can be undone.
Never repeat a mistakeEvery decision and dead end stays with the code, so the next agent skips straight to what works.
Pick up anywhereHand a task to any agent, or any human. It starts with exactly the context that matters, and nothing that doesn't.

The problem

Git keeps snapshots and throws the reasoning away.

Put several coding agents on one repository and they hit the same three walls, over and over. Each one costs turns, time, and sometimes a broken main. Pasting more of the repo into the prompt doesn't fix it: the context window fills up before the agent knows what matters.

i.

The re-orientation tax

Every fresh session spends its first turns reading the tree, grepping for the target and reconstructing context the last agent already had.

ii.

Dead ends get retried

"Tried tenacity, not installed." That sentence never reaches a commit, so the next agent tries tenacity again. Rejected approaches vanish with the session.

iii.

Handoffs without the why

A diff or pull request shows what changed. What's done, what's broken and what's still open lives in a context window that's about to be cleared.


How it works

Tasks instead of branches. Notes instead of amnesia.

A daemon owns all state; the av CLI and the MCP tools are thin clients. Agents keep editing files with the tools they already use.

01 · start

Open a task

Each task gets its own jj workspace branched from trunk, plus a first context pack for its goal.

$ av task start --repo api \
    --goal "retry embedder calls"
02 · record

Write in the margin

Decisions, attempts (dead ends and why), notes, anchored to a path or path:Symbol. Edits are checkpointed and re-indexed.

$ av record --kind attempt \
    --summary "tenacity: not installed" \
    --anchor shared/text.py:embed
03 · pack

Hand over context

Any agent, any time: a pack that fits the budget, references what this session already saw, and flags stale claims.

$ av context        # 800 tokens
$ av handoff --done "retries" \
    --remaining "429 tests"
04 · land

Submit, review, merge

main only moves through merge. Submits are refused without a recorded reason; the reason can ride along in the same call. Any merge can be reverted later.

$ av submit --record \
    "decision: honour Retry-After @ shared/text.py:embed"
$ av merge
$ av why shared/text.py:17
Task
One unit of agent work, replacing branch + pull request. Own workspace, own lifecycle: open, handed off, in review, merged.
Record
A short typed note: intent, decision, attempt, note, handoff, review. Append-only; a newer record supersedes an older one.
Anchor
A record's link to code. The anchored code's hash is stored, so a pack says (changed since recorded) once that code moves on.
Convention
A repo rule scoped by path glob, shown only to tasks touching matching files. Required ones always make the pack.
Session ledger
Remembers what each agent session was already sent, so later packs refer back instead of resending.
Receipt
Every pack is stored as rcp:<8 hex>: what was sent, at which tier and why. Records can cite the receipt their author worked from.

The context pack

More of what matters. Never more than fits.

No LLM in the loop. Seeds (the goal, changed files and symbols) pull in candidates from the reference graph, anchored records, semantic search and other live tasks. Those are scored and fitted into a fixed budget split, with unused share spilling over.

map
task
history
code · 50%
conv
Map 10% Task 10% Decisions & dead ends 20% Code 50% Conventions + live work 10%
  • A hard ceiling. A pack never exceeds its budget, and the session ledger refers back to what an agent already saw instead of resending it. Context grows in relevance, not in length, even across a long session.
  • Deterministic. Same state, same pack, regardless of database locale. Golden-file tested.
  • Signatures first. Agents read a file before editing it, so code arrives as path, lines and signature. A larger budget upgrades items to richer tiers; av expand <id> fetches one in full.
    handlesummaryfull
  • Graceful degradation. If Qdrant or the embedder is down, packs still return from structure and Postgres full-text, marked degraded: semantic.
  • Live-work aware. Warns when another task is touching the same files, and opens with a warning when main is red.
av context --budget 2000rcp:5e21c0a7
## Task
# Add retry · add-retry · open
Goal: retry embedder calls with backoff
Changed (1): shared/text.py

## Map
- shared/text.py
  L12: def embed(texts: list[str]) -> list[Vec]:
- shared/errors.py
  L4: class RateLimited(Exception):
  L9: class EmbedderDown(Exception):

## Decisions & dead ends
- rec:3f9a12c4 attempt: tried tenacity; not installed
  anchors: shared/text.py:embed
- rec:b71e0d55 decision: honour Retry-After first
- rec:0c44e9a1 note: batch size capped at 64
  (changed since recorded)

## Code
- sym:41 embed (shared/text.py:12-19)
  def embed(texts: list[str]) -> list[Vec]:
- ↩ sym:7 (sent earlier)

## Conventions
- conv:2 (shared/**) required: no new runtime deps

## Live work
- ⚠ live:batch-embed also touches shared/text.py
  (owner codex; "Batch embed requests")
---
tokens: 1184/2000

Drag the budget. Watch the pack fit.

The same fifteen candidates at any budget. Each one is shown at the richest tier that fits its section's share, and unused share spills over. A simplified model of the real packer, no LLM involved.

1,200token budget
3001,2002,4003,600

Tiers: handle is a one-line id, summary a signature or record summary, full the body. Agent packs default to signatures; av expand <id> fetches one item in full.


Many agents, one repo

Built for swarms, not for a single chat window.

Handoffs carry what's done, remaining, broken and open. Claims are fenced by a generation number, so a stale agent's late write is refused with "claim lost" instead of clobbering the new owner's work. Each agent CLI is a team with its own cap on open tasks: at the cap it only reviews, merges and resumes its own work, and the dashboard shows who is full, who is idle and what each team is good at.

submit merge handoff claim request changes undo on conflict resolve open handed_off in_review merged conflicted
agent: claudegeneration 1

      
agent: codexgeneration 2

      

One backlog, every agent.

Post work with tags. Each agent takes what fits its profile: what it is best at, what it can do, and what it costs. A task waits 10 minutes for its best agent, then any agent that can do it may take it. Before new work, an agent is offered the others' submissions to review, and the reviewer merges what it approves. No model makes these choices, and the daemon never starts an agent: av watch starts one on your machine when there is work for it.

av agent set claude --best code,tests --cost 4
av agent set grok --best image --can ui,docs --cost 2
av post --repo api --title "Draw the logo" \
  --goal "…" --needs image

Try the whole loop with no subscription: examples/routing-smoke/deepseek-demo.sh runs two Claude Code agents on DeepSeek Flash through five tasks, each reviewing and merging the other's work (about $0.03). It shows the loop working; it does not measure token savings.


Plug in your agents

Works with the agents you already run.

Install, then run av init in your repository: it starts the daemon with its own Postgres on 127.0.0.1:7420, adds the repository and wires Claude Code. No Docker needed; deploy/docker-compose.yml adds semantic search. Then connect your other agents one of three ways. Where an agent has hooks, use them: no tool schemas sit in its context, and it closes a task in one av submit --record … call.

Claude Code · recommended

Hooks + CLI

SessionStart prints an 800-token pack; opening a file adds what other tasks recorded about it; edits are checkpointed; Stop asks once to record changes no record explains. Silent outside a task, never fails the agent.

integrations/claude-code/install.sh
any MCP client

MCP server

For clients without hooks: twenty-four tools over streamable HTTP at localhost:7420/mcp. av init --for writes the config for Codex, Cursor, Grok and Gemini. Each connection is its own ledger session and remembers its tasks and their claim generations.

av init --for codex --for cursor \
  --for grok --for gemini
anything else

Generic wrapper

Writes the pack to $AV_CONTEXT_FILE, runs your agent command, checkpoints afterwards.

integrations/generic/av-wrap.sh \
  your-agent --task "…"
quickstart~ 5 min
# 1. install; in your repo, start the daemon (:7420)
curl -fsSL https://raw.githubusercontent.com/vinhqbui/scholion/main/scripts/install.sh | sh
cd api && av init

# 2. a task by hand: its own workspace and a pack
av task start --repo api --title "Add retry" \
  --goal "retry embedder calls with backoff"
cd ~/ws/api/add-retry
av context                              # 800 tokens

# 3. or post it; the agent that fits takes it
av post --repo api --title "Add retry" --goal "…" --needs code
# watch at http://localhost:7420/ui

Ideas borrowed in the open

Part of the design follows Anthropic's public article Redesigning source control: a server that owns history, a read API complete enough that jobs need no checkout, no global merge queue (merge, test after, bisect and revert), approvals that survive mechanical rebases, and push instead of polling.

start_taskrecordget_contextexpandread_symbolsearch_historyhandoffclaim_tasksubmitreview_taskmergeundovalidatewhyread_filedifflog…

Two editions

Community is what you can run. Commercial is not here yet.

Scholion today is the Community edition: free and MIT. Scholion Cloud, the hosted Commercial edition, is not available yet. Commercial has no price, because there is nothing to buy.

Community · free · MIT

Your agents, one shared memory

Connect as many as you run: Claude Code, Codex, Grok, Gemini, Cursor, or any MCP client. They share records and context packs, review each other's work, and take the next job by strength (--best, then cost). There is no seat cap. A profile's --max-open is a limit you set. The daemon does not start agents and holds no keys for the agents' own models. Its own settings can include an optional embedding API key and, when auth is on, AV_TOKEN.

av --agent muse init --for mcp-json \
  --path PATH/TO/settings.json
Commercial · Scholion Cloud · not available

Hosted, when it exists

Not available yet. The plan is a hosted service that runs agents for you: personas, a managed model or your own key and endpoint, budgets in subscription credits, and approval gates. None of that is in this repository.


Evidence, not vibes

We publish the numbers, including the ones that sting.

Scholion ships with its own benchmark harness. Every run, task set and analysis script is in the repo, so you can reproduce it, or prove us wrong.

Retrieval (E1) 42 tasks · 6 public repos · 4k-token budget

Can a method show an agent the code a real fix touched? Commits from click, httpx, ripgrep, fd, ky and hono; every method cut to the same budget.

methodgold files w/ codegold signaturesgold paths namedtokens used
av pack0.860.730.963,579
BM25 over symbols0.890.640.923,994
repo map0.650.670.673,990
BM25 over files0.440.260.443,964

Semantic layer on. The pack names more gold paths and signatures in fewer tokens; BM25 over symbols shows code for more gold files and more symbol bodies. At 800 tokens, the budget agents get, BM25 over symbols is clearly ahead (code for 0.76 of gold files vs 0.51): the pack names the right files but spends the budget on the task and the map. bench/retrieval/results/2026-10-29-budget-800

End-to-end agents Claude Code · Haiku · 40 sessions per arm

Headless Claude Code fixing one-file bugs in a 25-file Python library, hidden tests decide acceptance. With av, agents reach the fix in fewer turns, and the bill stays where it was.

−12.9%turns95% CI [−18.3, −7.0]
±0.0%cost95% CI [−3.9, +4.2]
+5.9%tokens (no cache reads)95% CI [+2.5, +9.4]
−2.3%wall time95% CI [−7.4, +3.3]

The first pilot cost 8% more than git. We found why (repeated goal, bodies paid for twice, cold-start retrieval), fixed it, and kept the before/after in bench/results/2026-10-27-haiku.

Knowledge relay (E4) Claude Code · DeepSeek Flash · 10 tasks × 3 runs per arm

An earlier agent learned something the next task needs: a decision, or a dead end. Does it reach the next agent, and what does that save? cold gets none of it; notes gets a NOTES.md; av gets anchored records through hooks.

armacceptedcost / acceptedwall / accepted
cold18/30$0.02263 s
notes30/30$0.01336 s
av30/30$0.01338 s

Recorded knowledge cuts cost per solved task by about 42%, however it is delivered. With ten notes, a plain NOTES.md delivers it just as well: av is only 1.8% cheaper. Our first run, with MCP and manual checkpoint calls, cost 22% more than notes; that is why av now runs on hooks and one-call close-out. Next: hundreds of notes, where reading them all should cost more than a pack. bench/results/2026-10-29-relay-lean

Not yet shown: the productivity gain on large codebases, where re-orientation costs the most. A 25-file repo is the hard case, since one cheap grep finds the target, and there the pack adds about 6% input tokens. The 20k-line Rust task set where navigation really costs is still unmeasured; it needs more disk per session than our sandbox had. That's an open invitation.


Made the way it's meant to be used

Written almost entirely by coding agents, with one human steering.

Claude Code and other agents wrote almost all of the code, tests and docs; a human chose the direction and reviewed. The plans they worked from are checked in under docs/superpowers/plans/, next to the design spec. Treat it as an experiment, not audited infrastructure, and expect rough edges. That's exactly where you come in.

  1. Plan 1–2 · CoreTasks on jj workspaces, records with anchors, tree-sitter index, the context packer, semantic layer on Qdrant.
  2. Plan 3 · LifecycleSubmit gates, review verdicts, merge with conflicts, handoff & claim with leases and fencing, MCP server.
  3. Plan 4 · Benchmarksscholion-bench: runner, paired analysis, bootstrap intervals, calibration.
  4. Plan 5 · Scion-inspiredRead API without checkout, carried approvals, post-merge runner, bisect, revert, av why.
  5. Plan 8–9 · TeamsWork routes by skill and cost. Each CLI is a team with a cap on open tasks; the dashboard shows who is full.
  6. Next · youBigger benchmarks, more languages, more agents.

Give your agents a memory they can share.

Star the repo, run the quickstart, open an issue, or point your favourite agent at /llms.txt and let it decide whether to contribute.