macOS 15+ · Apple Silicon · FSL-1.1-MIT

Graph Engineering, simplified —
with GraphCode.

A loop is an agent session that runs on repeat. GraphCode connects loops on a canvas — they run unattended, bounded, and still live, so you can attach to any one of them mid-run and steer.

$brew install --cask scgopi/graphcode/graphcode
LOCAL PROJECTS
Monetization NEEDS YOU
Check how we improve conversion on the pricing page…
Goal · 7d 6h entry
Marketing SCHEDULED
/loop 6h Sales and marketing…
Timed · 7d
permissions RUNNING
editing GraphStore.swift
Goal · 8h 17m
granularity Nothing runs it yet
GUARD
≤5×
pass 2 of 5
An  Issue orchestration  loop on a 15-minute cadence, fanning out a child loop per GitHub issue.
10+
parallel live sessions, one canvas
0
files written inside your project folder
3
backends: Claude Code, Copilot, Codex
reboots survived — sessions outlive the app
01 — FOUR LOOP TYPES

Pick by what you're ready to let go of.

Put an agent on repeat and you hand off exactly one thing: the check, the stop condition, the trigger, or the prompt itself. That's the whole space.

Turn-based
hands off: the check

Pauses each turn until you say go. For a refactor you eyeball step by step.

make test
exit 0 → resolved
Goal-based
hands off: the stop condition

Runs until the goal is met — optionally proven by a shell command exiting 0.

Time-based
hands off: the trigger

A cadence in the prompt: /loop 1h triage new bug reports.

Composite
hands off: the prompt

A pipeline that plans its own steps and runs a sub-graph end to end.

A working graph mixes them — a time-based triage loop hands findings to a goal-based fixer, which hands the fix to a turn-based reviewer.
02 — LOOP-TO-LOOP MESSAGING

No IDs. No plumbing. You just say the name.

A loop finishes its fix, you tell it "merge and ask Release for the next beta" — and it messages the Release loop, running in a different repo's graph. Delivered live if the peer is awake, staged into its memory if it isn't.

LIVE Loop messaging · across graphs, across repos
03 — SESSIONS OUTLIVE EVERYTHING

The daemon starts it at 3 a.m. You're in that same session at 9.

Every loop is a zmx session — a PTY that survives quitting the app, restarting the daemon, or rebooting. Click a node and you attach to the terminal that did the work, live, with one scrollback.

Drag between nodes for hand-off, message, or spawn edges.
Each edge carries a condition: always, on success, on failure.
A message to a sleeping loop is staged, not lost.
loop-a4f2 · attached RUNNING
[graphcode] Cycle re-entry 2 of 5 — the stop condition
is not yet met. Continue toward your goal.
Reading wake digest… 40 lines
  • approach A failed
  • metric 41 → 38
  • try B next
editing GraphStore.swift
04 — THE SELF-IMPROVING LOOP

Try → get judged → remember → try again smarter → stop honestly.

A maker, a reviewer, and a guarded back-edge closing the cycle. The feature that lets a loop repeat is the same feature that bounds it — so "loop forever, spending tokens" can't be said by accident.

FORGE
Make change
pass 2 · running
CRITIC
Verify change
idle · judges only
GUARD · ≤5 passes · stop after 2 idle
A loop may not change its own stop condition. The verifier stays outside the verified — the same reason maker and reviewer are separate sessions.
Measured by
lower is better

The orchestrator runs your metric command once per pass, so recorded numbers come from the measurement — never the loop's self-report.

41
38
27
27
STALLEDstopped after 2 passes without improvement
Every loop keeps a diary

The daemon records facts, the agent records lessons. A relaunched session opens by reading the digest — round two starts smarter, not from scratch.

14:24 tried A, failed
14:31 metric: 38
14:42 pass 3 started
↳ read wake digest
05 — THE GRAPH, LIVE

A canvas you design, not a pile of terminals you babysit.

graphcode · 6 worktrees
GraphCode graph canvas with live loop nodes
LIVE Issue orchestration · fan-out per GitHub issue
Hand-off

Fires when the source resolves, unblocking the target.

Message

Injects text into a running peer. Staged if it's asleep.

Spawn

Instantiates a copy from a template. Children die with their parent.

06 — UNDER THE HOOD

Four pieces, one socket.

App and CLI are both clients speaking length-framed JSON over ~/.graphcode/graphcoded.sock. Validation lives in the daemon — a rule only one client enforces isn't a rule.

Reported, never estimated. Presence, current tool call and token usage come from the backend's own hooks. Without hooks the UI says "not reported" rather than a zero nobody measured.
graphcode.app
SwiftUI app — sidebar, canvas, per-loop terminal rendered with GhosttyKit.
graphcoded
The orchestrator daemon, kept alive by launchd — owns every graph and all automation.
graphcode
CLI on the same socket: status, node create, send, memo, update, delete.
GraphcodeKit
The shared framework, so app and daemon can never disagree about what a loop is.
~/.graphcode/
Graphs, memory logs, layouts, socket — plain JSON. Nothing is ever written inside a project folder you open.

Draw your first graph in a minute.

Add a folder, write a goal — GraphCode names the loop for you. Connect a second with an edge. Then close the app; the loops won't notice.

$brew install --cask scgopi/graphcode/graphcode
Developer ID signed & notarized · requires Claude Code on your PATH