The Paper Compute platform spans 25 member repositories across 6 layers — OS, Platform, Telemetry, Tooling, Ecosystem, and Sites. At this scale, the question of where work happens matters as much as how it happens. An engineer touching the agent session lifecycle might need changes in paper the CLI (Go), stereOS (Nix), the paper cloud (Go), and console (TypeScript) — four repositories, four separate git histories, four separate pull requests.
Human engineers can hold that shape in their heads. Coding agents can’t. Give Claude Code a task like “add telemetry to the sandbox boot sequence” and it will reliably get lost somewhere between the repos — editing files in a fresh clone, missing cross-repo imports, or worse, inventing files in a non-existent unified tree. The individual repository is the unit of Git. The thing an agent is actually working on is almost never just one repository. Paper Forest is a piece of agent infrastructure — one of the missing primitives the field is still working out — built specifically to close the gap between what an agent can see and what the task actually spans.
Paper Forest is how we closed that gap. This post walks through the design: what the forest is, what a grove is, why we built it on git worktree instead of submodules or monorepos, and how we made an agent working inside a grove feel like it’s working inside a single project even when it’s touching 25 of them.
We evaluated three conventional options first.
Option 1: Collapse everything into a monorepo. Go pushes against this before team size even enters the conversation. Look at kubernetes/kubernetes — dependency management in a large Go monorepo gets nasty fast, and the failure modes are well documented. go work exists, but workspace tooling support is rough enough that adoption has been slow. Most of the Paper Compute platform is Go, and Go’s module system aligns naturally with one-module-per-repo rather than a single tree. The monorepo path would have meant fighting the language. Beyond that, the tooling investment (Bazel, Buck, Nx, Turborepo) is prohibitive for a 6-person team, and migrating 25 repos with independent release cadences is a one-quarter project we couldn’t afford.
Option 2: Git submodules. Submodules require every contributor to understand detached HEAD, --recurse-submodules, and the commit-pinning semantics that cause half of Git’s footgun reputation. More critically, submodules would force contributors working in one repo to either ignore the others or sync-commit across all of them. Agents don’t gracefully handle either.
Option 3: No coordination — agents get a path and figure it out. This was our starting point. It failed on any task larger than a single repo. Agents invoked in ~/projects/tapes/ could not see ~/projects/paper/. You can write glue scripts only to have the agents ignore them, or add path conventions to have agents hallucinate around them.
The human workflow isn’t much better. When you’re working across multiple projects at once, every new task starts with the same setup task: clone the right repos, put them in the right place, remember which repo belongs to which project, then hope the agent understands the same layout.
Even when an engineer glued together a setup script, the agent’s context still fractures across directories, scripts, assumptions, and repo boundaries. The root problem is that the agent’s working context was smaller than the task’s.
This is one face of the missing harness. Until you give agents a coherent runtime, every cross-cutting task fails the same way.
The challenge is that agents need a single navigable working directory where cross-repository code is immediately visible, but each repository must retain its independent git identity, release cadence, and PR workflow.
We had pattern-matched this problem before we hit it. Bottlerocket — the Linux distribution for containers — broke its monorepo into many repositories to scale, then ran into the same coherence problem when agents started working across the split. Sean Kelly (cbgbt) had prototyped a Bottlerocket-specific fix: synthesize a monorepo back together from git worktrees so agents could see the whole system. It worked for Bottlerocket. The open question was whether the pattern generalized beyond that one project. When we hit the same shape of problem at Paper Compute, we already had a known-good direction to reach for — and Paper Forest is what we built when we generalized it for any agent-driven team running 10+ repositories.
Paper Forest introduces two primitives.
A forest is a parent repository containing a forester.toml manifest listing every member repository, its remote, its local path, and its default branch. The paper-forest manifest has 25 members organized under os/, platform/, telemetry/, tooling/, ecosystem/, sites/, and demos/. There is exactly one forest per organization.
A grove is an isolated working directory containing a git worktree for every member repo. Each grove lives under groves/<name>/ at the forest root. An engineer or agent cds into a grove and works as if it were a monorepo — all 25 repos are present, organized, and navigable — but each directory inside is a real git worktree that commits, pushes, and reviews independently.
The name “forest” isn’t ornamental. It’s the mental model we wanted engineers and agents to adopt: many trees (repos) grow together (the forest), and you walk through them in specific clearings (groves) rather than chopping them all down to the ground floor of a monorepo.
forester seed Bootstraps the ForestThe first time you set up paper-forest, forester seed clones every member repository as a bare Git repo into .forest/bare/<member>.git. Bare repos are faster to clone from (no working tree) and serve as the local source of truth for every grove. Upstream fetches go to the bare repos; groves pull from them.
The seed runs a post-seed hook defined in forester.toml: crumbly build-cache. Crumbly — our semantic search tool, described below — builds its embedding index against the bare repos at seed time so that new groves inherit a warm index instead of rebuilding from scratch.
forester grove create Produces a Working Monorepo Viewforester grove create develop creates a directory at groves/develop/ and, for every member repo in the manifest, runs git worktree add against the bare repo at the member’s configured default_branch. After the command completes, the grove contains 25 working trees at their declared paths:
groves/develop/
├── os/stereOS/ # worktree of stereOS at main
├── os/agentd/ # worktree of agentd at main
├── platform/paper/ # worktree of paper at main
├── platform/console/ # worktree of console at staging
├── telemetry/tapes/ # worktree of paper cli at main
├── ... # 20 more
└── .crumbly/ # semantic search index
From the agent’s perspective, groves/develop/ is a single navigable project. From Git’s perspective, each subdirectory is a fully independent worktree with its own HEAD, branch, and remote tracking.
A grove-create also triggers crumbly update-context, which updates the semantic search index to reflect the grove’s current state.
Agents need the same steering documents regardless of which grove they’re working in. Re-copying AGENTS.md, README.md, and the skills catalog into every grove would let them drift and rot. Paper Forest solves this with declarative symlinks defined in forester.toml:
[grove]
[[grove.symlink]]
source = "inner-docs/AGENTS.md"
target = "AGENTS.md"
[[grove.symlink]]
source = "skills"
target = ".claude/skills"
[[grove.symlink]]
source = "docs"
target = "docs"
Every grove gets a symlinked AGENTS.md that points to the forest’s canonical version. When we update agent steering, we update it once in inner-docs/AGENTS.md and every grove inherits the change. Skills work the same way — .claude/skills in every grove is a symlink to the forest’s skills/ directory. Thirteen skills (ad-hoc-implementation-plan, deep-research, fact-find, and others) are maintained in one place and available everywhere.
Having 25 repos navigable at once is only useful if an agent can find things across them. Grep works for keywords; it falls apart for concepts. An agent asking “where is the sandbox lifecycle handled?” needs semantic search, not pattern matching.
Crumbly is our semantic search tool. It currently lives in the forest workspace, built as a set of Rust crates (crates/crumbly-core and crates/crumbly-cli) that compile to a binary on the PATH like any other CLI tool — intentionally available to every agent on the system, not gated behind a grove. It uses the candle ML stack to generate embeddings locally via HuggingFace models, stores them in SQLite with sqlite-vec for vector search, and chunks source files using tree-sitter parsers for Go, Rust, Java, Kotlin, C, JavaScript, and TypeScript — matching the actual language distribution of Paper Compute’s repos. The index is stored at .crumbly/ in the forest root and reused across groves.
A typical cross-repo query from inside a grove looks like this:
crumbly search "agent sandbox lifecycle"
The output cites specific files and line numbers across repos, giving the agent enough context to make the next read accurate instead of speculative.
We measure Paper Forest on two axes: agent coherence on multi-repo tasks, and human ergonomics for engineers doing the same work.
On coherence: the share of cross-repo changes an agent can execute without a human having to redirect it between repositories improved materially after forest adoption. Before forest, asking an agent to “add a new sandbox provider to stereOS and wire it through masterblaster to tapes” required manual repo-to-repo orchestration — the agent would complete the stereOS change, then need to be re-invoked in masterblaster, then in tapes, with human-provided context bridging each step. Inside a grove, the same task is executed in a single agent session with all three repositories visible.
On ergonomics: grove creation is a single command. forester grove create feature-x produces a 25-repo working environment in under a minute on a warm seed. Removing a grove is forester grove remove feature-x — the worktrees are detached, the directory is cleaned, and the bare repos are untouched. Spinning up parallel groves for parallel work is as cheap as spinning up a new directory.
There are trade-offs. Disk usage is linear in the number of groves (each grove has its own worktree for every repo). We’ve capped grove count in practice and rely on forester grove list plus manual cleanup. Groves are not fully isolated at the filesystem level — they share the bare repos — so simultaneous force-operations across repos can race. We haven’t needed to solve this yet because our workflow is single-engineer-per-grove.
The forest/grove model does not eliminate multi-repo complexity — it relocates it. Pull requests still land in 25 separate places. CI still fires per-repo. Cross-repo API changes still require coordination across repos. What changed is who holds the whole picture. Before the forest, an engineer in tapes could not see what was happening in stereOS, and neither could an agent. Inside a grove, the agent has the full system in view: it can guide the engineer on order of operations, suggest review order across the related PRs, and reason about whether a deployment will be safe to roll out because it can read the parts that have to land together. Engineers used to be the only people who knew how the system fit together in production. They aren’t anymore — the agent can carry that load with them.
The multi-grove design is intentional rather than a workaround. Each engineer typically keeps a develop grove for general work and spins up ad-hoc groves for specific features. Multiple agents can run in parallel, each in its own grove, working on different changes without colliding — and the git worktree underneath is the mechanism that makes this safe. Two agents that don’t know about each other can’t step on the same branch in the same repo, because each grove has its own worktree pinned to its own branch. The “many directories” that look like a downside on first read are how we get parallel agent work without unruly clobbering.
Paper Forest is deliberately unopinionated beyond the forest/grove model — it doesn’t prescribe how repos are organized, how CI runs, or how releases coordinate. Those are still per-repo decisions. The next thing we’re working on is forest-wide operations that can’t be expressed as “run this in every repo”: automated cross-repo import verification at grove-create time, and a forest-wide PR creation workflow that groups related changes across member repositories without manual copy-paste.
We also expect crumbly to grow into the primary research surface for agents inside a grove. The current implementation handles semantic search over code and docs. The next step is intersecting crumbly with tapes — our agent session recorder — so that an agent asking “why was this built this way?” can get both the current code and the prior discussion that shaped it.
The broader pattern — a faux-monorepo built from git worktrees, with declarative manifests and symlinked agent-steering — is not specific to Paper Compute. Any team running 10+ repositories that need to be touched together by agents can apply it.
We are launching soon, subscribe for early access.