GraphCode
Run graphs of live, steerable CLI coding-agent sessions on macOS — connect them, leave them unattended, still attach and correct mid-run.
- Source repo
- scgopi/GraphCode
- Stars
- ★ 139
- Last updated
- 1d ago
- License
- NOASSERTION
- Primary language
- Swift
- FA score
- 48/100 · Major gaps
At a glance
- How it runs
- Works with
- Portable with changesChatGPT · Codex · Claude Code
- Cost
- Free software; you pay for model usage
- Setup effort
- Medium · a few setup steps
- You'll need
- Typical use
- You are pushing several independent lines of work in one repo (a refactor, a broken build, an issue queue) and want a canvas showing when one should hand off to another instead of ten terminal windows you babysit. You express each as a loop, connect them with edges and watch the graph.
- Not a fit if
- Teams on Windows or Intel Macs — the shipping build is macOS 15+ on Apple Silicon only
- Users expecting bundled models or agent CLIs — GraphCode installs none of them
- Anyone who needs to ship a competing commercial product built from it under FSL-1.1-MIT
- Source review
- 48/100 · Major gaps
What does this agent do, and when should you use it?
GraphCode is a macOS app that arranges real CLI coding-agent sessions into a graph: each node is a loop, a unit of work inside one session run by Claude Code, GitHub Copilot CLI, Codex, OpenCode or pi, chosen per loop; each edge is a hand-off, message or spawn between them, and an edge never needs to know which agent sits on either end. Loops come in four types — turn-based, goal-based, time-based and composite — differing in what you stop doing by hand: the check, the stop condition, the trigger, or the prompt. GraphCode schedules nothing itself: a time-based loop's cadence lives inside its session as the agent's own `/loop` skill, while the `graphcoded` daemon only fires hand-off edges, polls goal predicates and keeps sessions alive. Every loop's terminal is a `zmx` session, so it survives quitting the app and rebooting, and relaunching resumes the conversation with `--resume` rather than starting a duplicate — which is what keeps a running loop attachable and correctable instead of a job that already finished. State lives in `~/.graphcode/` and nothing is written inside a project folder you open; separate Workspaces under `~/.graphcode-<name>` are entirely isolated.
GraphCode ships as four moving parts. The UI, graphcode.app, gives you the project sidebar, the graph canvas and a per-loop terminal workspace with tabs, splits, ⌘K to jump to any loop and ⌘⇧R to walk the loops asking for you. The background daemon graphcoded (a launchd agent) owns every project's graph, fires hand-off edges, polls goal predicates and keeps unattended sessions alive whether or not the app is open. The graphcode CLI drives the same daemon — graphcode projects, graphcode status <project>, graphcode node create --backend claudeCode|copilotCLI|codex|openCode|pi, graphcode node send --follow-up, graphcode reap --dry-run. Underneath, the third-party zmx session daemon keeps each loop's PTY alive and GhosttyKit renders each surface. In practice: add a project (local folder, clone from URL, or a remote repository over SSH where loops run while this Mac steers them), create a loop on the canvas with its prompt and agent (Claude Code unless you change Settings ▸ New loops use), open the node to attach to that live session, then drag edges between nodes and set each edge as a hand-off (fires when the source resolves), a message or a spawn, optionally with a condition and cycle guard. A goal loop's done check can be a shell predicate, testable at creation time the way the daemon will run it. Copilot loops can be pinned to a published CLI version via Settings ▸ Preferred versions or "copilotPreferredVersion" in ~/.graphcode/settings.json, applied to new and resumed Copilot sessions plus title and summary requests.
- You are pushing several independent lines of work in one repo (a refactor, a broken build, an issue queue) and want a canvas showing when one should hand off to another instead of ten terminal windows you babysit. You express each as a loop, connect them with edges and watch the graph.
- You want 'fix the build' to run until it is actually fixed: create a goal-based loop whose done check is a shell predicate such as
make testexiting 0, leave it unattended, and attach when you want to intervene. Turn-based loops fit refactors you want to eyeball turn by turn. - You need recurring work such as hourly issue triage: a time-based loop puts the cadence in the prompt with
/loop 1h …, so the recurrence lives in the session rather than an external scheduler. - You are wiring a multi-step pipeline where steps depend on each other: a composite loop runs a sub-graph end to end, and one loop can spawn children that inherit its own agent unless they name another.
- You work across machines and want loops running on a remote host over SSH (key auth and zmx on the server) while you steer them from this Mac.
- You run unrelated lines of business side by side: separate Workspaces (⌥⌘1…⌥⌘9 to switch) keep their own graphs, loops and terminal sessions fully apart, each with its own Dock tile.
How do you install or deploy this agent?
Requirements: macOS 15+ on Apple Silicon (arm64), with at least one agent CLI on your PATH — claude, copilot, codex, opencode or pi. GraphCode bundles none of them.
Install with Homebrew:
brew install --cask scgopi/graphcode/graphcodeOr drag GraphCode into Applications from the latest .dmg (releases are Developer ID signed and notarized):
open https://github.com/scgopi/GraphCode/releases/latest/download/graphcode-macos-arm64.dmgBuilding from source needs mise (Xcode, tuist, swiftlint and zig come through it) plus the submodules:
git submodule update --init --recursive
make doctor
make third-party # builds zmx and GhosttyKit (zig)
make install-zmx install-cli daemon-install
make run-app
make test # unit tests
make check # swiftlint + swift-format, both strictTo run a local build beside an installed release, copy .env.example to .env.local and choose your own bundle-ID prefix:
make dev-run-appHow do you use this agent?
Start by adding a project, then create a loop, then open and connect it.
In the app: the sidebar's ⊕ menu adds a project (local folder, clone from a URL, or a remote repo over SSH); ⊕ on the canvas creates a loop where you write the prompt and pick the agent that runs it (Claude Code unless you change Settings ▸ New loops use); clicking a node opens that loop's terminal workspace, with ⌘K to jump to any loop and ⌘⇧R to walk the ones asking for you; dragging between nodes creates an edge.
The same daemon is drivable from a shell:
graphcode projects
graphcode --help
graphcode status <project>
graphcode node create --backend claudeCode
graphcode node send --follow-up
graphcode reap --dry-runTo pin a Copilot CLI version, first install that version on every machine that runs Copilot, including remote hosts:
npm install -g @github/[email protected]
copilot --prefer-version 1.0.84-5 --versionThen set Settings ▸ Preferred versions ▸ Copilot CLI, or write the settings file directly (read on each launch, so no daemon restart):
{
"copilotPreferredVersion": "1.0.84-5"
}Switch between workspaces with ⌥⌘1…⌥⌘9, step with ⌘ / ⌘⇧ and create one with ⌥⌘N; from the CLI, follow the same variable the app sets:
GRAPHCODE_SUPPORT_DIR=~/.graphcode-work graphcode status <project>What are this agent's strengths and limitations?
- Mixed-agent graphs are first-class: a Codex loop hands off to a Claude Code loop that messages a Copilot one, because an edge never asks which agent is on either end.
- Sessions outlive everything — each loop's PTY is a
zmxsession, so after quitting the app or rebooting it resumes with--resumeinstead of duplicating the conversation, keeping every running loop attachable and correctable. - The
graphcodeddaemon is independent of the UI: it fires hand-off edges, polls goal predicates and keeps sessions alive whether or not the app is open. - State is confined to
~/.graphcode/; the README states that nothing is ever written inside a project folder you open. - Workspaces are genuinely separate directories with their own graphs and their own
graphcoded, each with its own Dock tile, so unrelated work can be kept apart and even placed on a second screen.
- The shipping platform is macOS 15+ on Apple Silicon (arm64) only; the Windows port is explicitly a preview, not a shipping-platform claim.
- GraphCode bundles no agent CLI and installs nothing itself, so you must provision
claude,copilot,codex,opencodeorpion every host — local and remote — and pay their model or subscription costs. - Time-based loops on Codex, OpenCode and pi depend on the experimental Daemon heartbeat setting in Settings, since those CLIs have no
/loopskill. - Licensing is FSL-1.1-MIT: use, modification, self-hosting and redistribution are allowed, but shipping a competing commercial product built from it is not, and each release only converts to plain MIT two years after it goes out (GraphcodeKit/ and graphcode-cli/ are MIT).
- Some workflows carry manual prerequisites — for example, a version you have not installed on the host will not be there when a pinned Copilot loop launches.
How does this agent compare with similar options?
The README credits Supacode as the inspiration: both share the spine of daemon-kept terminal sessions, but Supacode's unit is the worktree while GraphCode's is the graph of loops. GraphCode is built on Ghostty for terminal rendering and zmx for session persistence, and is designed to drive the Claude Code, GitHub Copilot CLI, Codex, OpenCode and pi agent CLIs rather than replace them.
Key facts side by side with the most closely related agents.
| Agent | Source review | Form / cost | Stars | Updated | Language | Full support on |
|---|---|---|---|---|---|---|
| GraphCode This agent | 48 · Major gaps | Desktop appFree + model costs | ★ 139 | 1d ago | Swift | ChatGPT · Codex · Claude Code |
| hcom | 69 · Some gaps | CLIFree + model costs | ★ 566 | 1d ago | Rust | Codex · Claude Code |
| Vigil Multi-Agent Terminal Orchestrator | 69 · Some gaps | Desktop appFree + model costs | ★ 29 | 3d ago | Swift | Codex · Claude Code |
| Agent Skills Library | 67 · Some gaps | Agent plugin / skillFree + model costs | ★ 240 | 1mo ago | Python | Codex · Claude Code |
How does FollowAgents rate this agent?
Why each dimension lost points
Trust: README states state lives in ~/.graphcode/ and 'Nothing is ever written inside a project folder you open', a checkable least-privilege claim, but no sandbox or permission manifest is given, so least_privilege is 1. user_confirmation: README mentions a Test button for goal done checks and reap --dry-run, but lacks a unified confirmation flow for destructive actions, so 1. data_flow_transparency: only local state dir and remote SSH execution are described; data flow to third-party agent CLIs is not detailed, so 1. sensitive_data_handling: test evidence in agentRuntimes.test.ts shows only Nod's own Keychain items are read (app.graphcode.nod/anthropic-api-key, github-token) and inherited ANTHROPIC_AUTH_TOKEN, CLAUDE_CODE_OAUTH_TOKEN are stripped, a concrete implementation, so 2. dependency_security: CI pins actions/checkout by commit hash, but README requires users to install claude/copilot/codex CLIs with no version locking or vulnerability scanning, so 1. external_effects: README admits starting a daemon, creating zmx sessions, and remote SSH execution, but gives no impact inventory or rollback, so 1. rollback: only 'sessions outlive everything' and --resume are mentioned; no failure recovery or state rollback mechanism, so 1. source_attribution: README credits Supacode, Ghostty, zmx; LICENSE distinguishes MIT for GraphcodeKit/graphcode-cli and FSL-1.1-MIT for the rest, with ThirdParty retaining its own licenses, so 2.
Reliability: self_consistency: README's loop types, daemon, and CLI descriptions align with the protocol in tests (NodProtocol.swift, parseCommand); contract.test.ts validates the same event list against Swift decoding and TS parsing, so 2. dependency_availability: README requires macOS 15+ Apple Silicon, mise, submodules, zig to build zmx and GhosttyKit; heavy dependencies with no version locking or offline path, so 1. failure_messages: controlSocket.test.ts verifies malformed lines return {ok:false,error:"not JSON"}, handler errors return specific messages while keeping the connection, a checkable failure-message design, so 2.
Adaptability: audience_and_scenarios: README targets macOS developers with four loop types (turn-based, goal-based, time-based, composite) and examples, so 2. capability_boundaries: README states GraphCode schedules nothing, Codex/OpenCode/pi lack /loop skill and need Daemon heartbeat, Windows port is preview; boundaries are clear, so 2. trigger_precision: goal shell predicates, edge conditions, and cycle guards are described, but precise trigger semantics or test evidence are missing, so 1. environment_fit: macOS 15+ Apple Silicon only, Windows preview, Linux CI build only; narrow environment fit, so 1.
Convention: information_architecture: README has clear sections (How it works, Install, Using it, Parts, Workspaces, Building from source, Credits & license), so 2. install_notes: brew cask, dmg, and source build via make doctor are given, so 2. naming_stability: CLI verbs (node create, node send --follow-up, reap --dry-run) and settings are described, but no versioned naming policy or deprecation notes, so 1. examples_and_faq: loop-type examples and a Copilot version pinning example exist, but no FAQ, so 1. known_limitations: Windows preview, Codex/OpenCode/pi needing heartbeat, and 'GraphCode installs nothing itself' are mentioned, but not consolidated, so 1. license: LICENSE file provides full FSL-1.1-MIT text and per-directory licensing, so 2. versioning_changelog: README has a release badge and releases link, but no CHANGELOG file in the repo, so 1. maintenance_responsibility: LICENSE names Copyright 2026 scgopi and README covers DCO and contributions, but publisher identity is unverified and maintenance responsibility is unclear, so 1.
Effectiveness: output_usability: README describes per-loop terminal workspace, tabs/splits, ⌘K jump, ⌘⇧R walk, producing operable terminal output, so 2. marginal_value: versus a single terminal agent, GraphCode offers multi-loop orchestration, cross-agent hand-off, and session persistence; marginal value is clear, so 2. cost_benefit: requires macOS 15+ Apple Silicon, mise, zig-built third-party components, and self-installed agent CLIs; high cost with unquantified benefit, so 1.
Verifiability: claim_traceability: most README claims (sessions outlive everything, nothing written in project folder) lack code or test references; only a few are backed by tests, so 1. cross_source_corroboration: README protocol descriptions are corroborated by NodRuntime/test/contract.test.ts, controlSocket.test.ts, and agentRuntimes.test.ts, so 2. fact_inference_separation: README mixes factual descriptions with marketing phrasing (e.g., 'run ten') without clearly separating verified from unverified content, so 1.
- Publisher identity is unverified; maintenance responsibility and update path are unclear, so confirm the release channel and signing before adoption.
- Depends on multiple third-party agent CLIs (claude, copilot, codex, opencode, pi); GraphCode bundles none and locks no versions, creating supply-chain and version-drift risk.
- Supports only macOS 15+ Apple Silicon; Windows is preview and Linux is CI-build only, so environment fit is narrow.
- Most capability claims in README lack code or test references; static review cannot verify runtime behavior.
- The daemon and zmx sessions run persistently and may execute on remote hosts over SSH; assess impact scope and rollback yourself.
FAQ
Do I pay for models through GraphCode?
What happens to running loops when I quit the app or reboot?
zmx session, so it survives quitting and rebooting; relaunching resumes the conversation using the persisted backend session ID with --resume rather than starting a duplicate.Does it write anything into my repositories?
~/.graphcode/, and nothing is ever written inside a project folder you open.Can it run a loop on a fixed cadence?
/loop skill rather than in an external scheduler; Codex, OpenCode and pi lack that skill and need the experimental Daemon heartbeat in Settings.Can I keep multiple unrelated orchestrations apart?
~/.graphcode by default, otherwise ~/.graphcode-<name>) with its own graphs and its own graphcoded; nothing is shared between them, and the CLI follows GRAPHCODE_SUPPORT_DIR to match.