Maxxwell by Rindler
Writing

Wiring Coding Agents Across Repos and Monorepos

2026-09-08

Most people hit the same ceiling the moment they run agents on more than one repo: the models are fine, but you are now the scheduler for ten terminals.


Most people hit the same ceiling the moment they run agents on more than one repo: the models are fine, but you are now the scheduler for ten terminals.

This tutorial shows how to use Maxxwell to run coding agents across many small repos and large monorepos, with concrete patterns for dependency mapping and cross-repo coordination.

If you want the bigger picture of what “agent-native development” looks like, see the pillar piece Agent-native development: a working definition; this one is the hands-on wiring guide.


1. Prerequisites and mental model

You’ll get more out of this if you already:

Maxxwell basics you need to know:

The rest of this tutorial is how to wire that across repos.


2. Choose a topology: many small repos vs monorepo

You need to decide where coordination lives.

Many small repos

Pattern: each repo has its own worker(s), and you run a control seat over them.

Works well when:

Typical stack:

Large monorepo

Pattern: everything is in one repo, but you isolate work by worktree + path.

This mirrors Claude Code’s guidance for large codebases:

Typical stack:

Both patterns rely on the same primitives: isolated worktrees, a visible control plane, and a human being the last click before anything lands.


3. Set up Maxxwell for a polyrepo fleet

This section assumes:

Step 3.1 - Define a simple repo manifest

Create a small manifest that the orchestrator and you both treat as ground truth.

~/dev/agent-fleet/repos.yml:

repos:
  - name: service-a
    path: ~/dev/service-a
    kind: service
    depends_on: [shared-lib]

  - name: service-b
    path: ~/dev/service-b
    kind: service
    depends_on: [shared-lib]

  - name: shared-lib
    path: ~/dev/shared-lib
    kind: library
    depends_on: []

This is intentionally simple. The orchestrator doesn’t parse it on its own, but you will:

Step 3.2 - Start workers per repo

From Maxxwell’s CLI (or the in-app terminal), start one worker per repo.

Example with a Claude Code CLI placeholder claude-code:

# service A worker
cd ~/dev/service-a
claude-code # or your actual agent command

# service B worker
cd ~/dev/service-b
claude-code

# shared lib worker
cd ~/dev/shared-lib
claude-code

Maxxwell lists three sessions, each with a state. Name them clearly in the UI (e.g. svc-a/feature-x, svc-b/bug-123, shared-lib/refactor).

Step 3.3 - Create an orchestrator seat

In Maxxwell, start a new agent session and brief it as the orchestrator.

Example initial prompt (edit for your stack):

You are an orchestration agent managing several coding agents that each work in a different git repository.

Repos and dependencies:
- service-a (~/dev/service-a) depends on shared-lib
- service-b (~/dev/service-b) depends on shared-lib
- shared-lib (~/dev/shared-lib) has no dependencies

Your job:
- Plan work that may span multiple repos.
- Decide which worker should do each task.
- Draft clear, copy-pastable instructions TO A SPECIFIC WORKER.
- Track what landed (merged) vs what is waiting on reviews or my decisions.

Rules:
- Never run git or shell commands yourself; draft them for ME to run.
- When cross-repo changes are needed, plan them in dependency order.
- When unsure about repo state, ask me which branch/commit we are on.

Now you talk to this orchestrator instead of juggling three agent chats.

Step 3.4 - Run a cross-repo change

Say you need to change shared-lib and then update both services.

  1. Tell the orchestrator:
    We need to change the Foo API in shared-lib and update both services to call the new API.
    Assume feature branches per repo and that I will run all git commands.
    Plan the sequence and draft instructions for each worker.
  1. The orchestrator responds with an ordered plan, and messages like:
    • For shared-lib worker: “Refactor Foo API, add tests, expose a backward-compatible shim.”
    • For service-a worker: “Update callers, adjust tests, and note dependency on shared-lib@feature/foo-api.”
  1. You paste each drafted message into the target worker session.
  1. As states change (workingwaiting on youdone), you can ask the orchestrator:
    Summarize the status of the Foo API rollout across repos. What landed, what is waiting on me?

The orchestrator replies with a return report instead of you skimming three terminals.


4. Configure dependency mapping for polyrepos

Maxxwell doesn’t magically know your dependency graph; you have to expose it.

A workable pattern:

  1. Machine-readable graph in a side repo (like GitHub’s MultiRepoOps control plane):
    • repos.yml from above
    • Optionally a script that answers questions, e.g. ./what-depends-on shared-lib
  1. Brief the orchestrator with:
    • The dependency rules
    • How to think about rollouts and breaking changes
  1. Use GitHub governance to guard landing:
    • CODEOWNERS per repo
    • Branch protection & merge queue so agent changes serialize safely

Example snippet you can paste into the orchestrator when you change the graph:

Dependency rules:
- shared-lib is a library; service-* repos depend on it.
- Changes to shared-lib that break the public API MUST:
  - Update all dependent services in the same feature wave.
  - Keep a deprecation shim in shared-lib when feasible.
  - Land in shared-lib main LAST, after dependent changes are merged.

When planning changes, schedule cross-repo work in this order: library -> dependents -> final library cleanup.

You are building, in text, what GitHub’s MultiRepoOps docs describe as a side-repo control plane, but with a conversational interface.


5. Running agents safely in a monorepo

Now the other side of the world: one big repo instead of many.

Google’s engineers have written about their monorepo holding billions of lines of code and absorbing a large volume of daily changes; the challenge is scope, not raw editing. Claude Code’s monorepo docs say the same: nested config, path-scoped rules, and graphs.

Step 5.1 - Create isolated worktrees

You want “many repos” semantics inside one repo.

From the monorepo root:

# feature for payments service
git worktree add ../monorepo-payments-feature -b feat/payments-new-flow

# infra refactor
git worktree add ../monorepo-infra-cleanup -b chore/infra-cleanup

Now you have two directories that behave like separate repos.

Start workers in each worktree:

cd ../monorepo-payments-feature
claude-code

cd ../monorepo-infra-cleanup
claude-code

Maxxwell shows two workers; sessions outlive the app, so you can quit and reattach without killing work.

Step 5.2 - Add layered configuration files

Borrowing from Claude Code’s CLAUDE.md pattern, place guidance in directories.

Example services/payments/AGENT.md:

# Agent scope for payments service

- Only modify code under `services/payments/` and its tests.
- Do not change shared libraries in `libs/` without explicit instruction.
- Prefer adding new modules over editing core routing logic.
- Use existing test helpers from `services/payments/tests/helpers/`.

For a shared library:

libs/billing/AGENT.md:

# Agent scope for billing library

- Only modify code under `libs/billing/`.
- Any breaking API change must:
  - Update all known callers listed in `libs/billing/CALLERS.md`.
  - Add or update migration notes in `libs/billing/MIGRATIONS.md`.

Brief each worker to read and respect the nearest AGENT.md.

Step 5.3 - Expose a dependency graph

Agents need to understand the monorepo as a graph, not as one giant text blob.

If you use Bazel:

bazel query "allrdeps(//libs/billing:all)" > libs/billing/CALLERS.md

If you use Nx:

nx graph --file=project-graph.json

Then add to libs/billing/AGENT.md:

Known callers are documented in CALLERS.md, generated from the build graph.
Consult this list before changing public APIs.

Now brief the orchestrator:

This monorepo uses Bazel/Nx. Dependency information lives in:
- libs/billing/CALLERS.md (Bazel-generated reverse deps)
- project-graph.json (Nx project graph)

When planning API changes, always:
- Ask me to regenerate CALLERS.md if it may be stale.
- Use the list of callers to enumerate all affected packages.

You have effectively given an agent the same inputs that Nx and Bazel use for task graphs.


6. Using Maxxwell’s session states as your coordination signal

Past a few sessions, the main job is knowing where attention is needed.

In Maxxwell, every worker has a state derived from facts, not guesses - similar to Agent Orchestrator’s “display status from facts” design.

A practical pattern:

  1. Glance at the fleet pane:
    • working: leave it alone.
    • waiting on you: this is where to click next.
    • blocked / needs sign-in: unblock or kill.
    • possibly stalled: read the last few turns and decide whether to re-aim.
  1. Ask the orchestrator for a summary instead of manually checking every tab:
    For all active workers, summarize:
    - What they are working on
    - Whether they are waiting on me
    - Whether any look stalled or off-target
  1. When you want to change the fleet (stop a worker, start another), use the controls, then review the drafted message/command before hitting Enter.

This respects the principle: the person presses Enter. Agents draft, you decide.


7. Example: cross-repo rollout vs monorepo-wide change

To make this concrete, here are two parallel workflows.

Polyrepo: shared library breaking change

  1. Orchestrator plans:
    • Update shared-lib with new API + shim
    • Update service-a and service-b to use new API
    • Remove shim in a later wave
  1. Workers:
    • shared-lib worker implements the new API
    • service-* workers update callers and tests
  1. GitHub control plane:
    • Each repo raises PRs with CODEOWNERS and branch protection
    • Merge queue ensures landing order
  1. Orchestrator return report describes:
    • PR URLs
    • What’s merged vs waiting review

Monorepo: billing API breaking change

  1. Orchestrator asks you to regenerate callers:
    bazel query "allrdeps(//libs/billing:all)" > libs/billing/CALLERS.md
  1. Worktrees:
    • ../monorepo-billing-api worker changes libs/billing and updates CALLERS.md
    • Another worker in a different worktree updates a big consumer like services/payments
  1. CI:
    • Single monorepo CI picks up all changes on one branch
  1. Maxxwell keeps all sessions visible; you can reattach after a restart and continue the rollout.

The underlying coordination problem is the same. The difference is whether your graph edges are repo-level or path-level.


FAQ

How many workers should I run per repo or worktree?

Start with one worker per active branch that actually needs parallelism.

If you’re not running into context or queueing limits, adding more workers often just adds cognitive load. Use Maxxwell’s working/idle states as a sanity check before spinning up more.

How do I keep agents from trampling each other in a monorepo?

Use separate worktrees and path-scoped config:

This is the same pattern Claude Code, Alera, and others recommend for large monorepos.

Where should I put my dependency graph so agents can use it?

For polyrepos, keep it in a control repo or a small manifest file like repos.yml.

For monorepos, use your build system or task runner:

Make the location and meaning of these files part of the orchestrator’s brief.

How does Maxxwell compare to just using tmux and shell aliases?

Tmux gives you panes; Maxxwell adds:

You can still attach to any worker as a real terminal session; nothing is hidden.

Can Maxxwell automatically detect when a worker has drifted off-goal and fix it?

No. Maxxwell conducts; it doesn’t fly on autopilot.

You get honest visibility (including “not heard from”) and a context-pressure readout with one-click compaction, but you re-aim sessions and decide what to stop or restart. That’s deliberate.