A Cursor-shaped coding harness you can read.
Local Electron desk. Python LangGraph worker. Human Accept on every skill and every diff.
Most “coding agents” hide the loop. Patchline puts the loop on screen, the way Cursor does, and keeps the model frozen.
| You see | The harness does |
|---|---|
| Agent / Plan / Chat | Mode prompt + tool set, no silent writes in Chat or Plan |
| Todos, tool rows, streaming text | JSONL from harness_worker |
| Accept / Undo on a diff | Keep the patch, or restore and record a trace |
| Accept / Reject on a skill | Skill Box only after you say yes |
| Fullscreen graph | Import, call, and co-edit edges the retriever walks |
| “This model does not accept images.” | Text models never pretend they saw a screenshot |
The desk is Patchline. The worker is python -m adaptive_agent.harness_worker run. Together they are adaptive-coding-ai-agent.
Patchline (Electron)
apps/web React 19 · Vite 6 · Monaco · vis-network
apps/desktop IPC · ConPTY · spawn python -B -m adaptive_agent.harness_worker
│ stdin: start_run JSON stdout: JSONL events
▼
adaptive_agent/harness_worker.py
router → adapter patch
code graph retrieve (anchors + PageRank)
LangGraph tools (read, grep, patch, todos, plan, skills)
plan_gate.json · skill review poll · Memory SQLite
│
▼
OpenCode Go https://opencode.ai/zen/go/v1
default model: deepseek-flash
vision only if OPENCODE_VISION_MODEL is set
Crops are from the running Electron window.
| Mode | Writes files? | What you get |
|---|---|---|
| Agent | Yes | Todos, tools, patches |
| Plan | No, until Build | Questions, research, editable markdown |
| Chat | No | Answers from the workspace |
Shift+Tab cycles modes. Send sits at the right edge and becomes Stop while a turn is running.
Clarifying chips, Continue planning, sticky Build, skill Reject / Accept, todos, and read_file in one column. Chats are tabs.
Paste is refused unless OPENCODE_MODEL or OPENCODE_VISION_MODEL is a vision id (deepseek-v4-flash-vision-exp).
Muted green and red. Accept (Ctrl+Shift+Y) keeps the file. Undo (Ctrl+N) restores it and writes a trace.
Title-bar Graph. Legend: files, imports, calls, co-edits. Retrieval uses this walk so the next prompt names real symbols.
Plan mode does not invent a todo list and call it a plan. A real exchange:
You
Add skip for muted clips. I am not sure if it belongs in the ranker or the player.
Patchline
Where should skip happen?
ranker·player
You pick ranker, then Continue planning.
Patchline writes a markdown plan you can edit:
# Skip muted clips
## Files
- feed/ranker.py
Filter clips with audio_gain 0 before scoring.You press Build. Only then does Agent mode patch the file. The diff waits for Accept.
If the same failure shows up again, the harness drafts a skill. It does not install it:
skip_muted_clips v3 — two Undo traces, muted clips still ranked first.
Reject skill · Accept skill
Accept puts it in the Skill Box. The next system prompt can retrieve it. Reject throws the draft away.
| Layer | Choice | Why |
|---|---|---|
| Desk | Electron 29 | One window, real OS terminal, file IPC |
| UI | React 19, Vite 6, Tailwind 4 | Fast desk, Monaco theme, no extra app server |
| Editor | Monaco | Diff review, TS path hints, Preview / Source |
| Graph view | vis-network | Fullscreen import / call / co-edit |
| Terminal | ConPTY (node-pty) |
A shell, not a log |
| Harness | LangChain + LangGraph | Tools, streaming messages, mode prompts |
| Model | OpenCode Go, DeepSeek Flash | Frozen base; adapters are instruction patches |
| Memory | SQLite (data/agent.db) |
Episodes, pending skills, Skill Box |
| Graph store | SQLite + JSON | Import, call, contains, git co-edit, PageRank |
| Tests | pytest, node:test, Playwright | Worker, path safety, Electron smoke |
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
copy .env.example .env
npm install
npm run devPut OPENCODE_API_KEY in .env. Keys come from opencode.ai/auth after a Go subscription.
Vite listens on 127.0.0.1:5173. Electron opens Patchline. Point it at a folder or set WORKSPACE_ROOT.
Installer: npm run dist → apps/desktop/release.
| Variable | Default | |
|---|---|---|
OPENCODE_API_KEY |
— | Required |
OPENCODE_BASE_URL |
https://opencode.ai/zen/go/v1 |
Chat completions |
OPENCODE_MODEL |
deepseek-flash |
Coding default |
OPENCODE_VISION_MODEL |
unset | Set to allow image paste |
WORKSPACE_ROOT |
repo root | Folder the desk opens |
adaptive_agent/ harness, graph, memory, skills, router, plan gate
apps/web/ Patchline UI
apps/desktop/ Electron main, preload, PTY
lessons/ L2 skills, L3 graph, L4 retrieval
tests/ pytest, no live model required
docs/screenshots/ Electron crops
docs/architecture/ system, turn, skill loop
python -m adaptive_agent.router "implement the hash function" --run
python -m adaptive_agent.code_graph --repo C:\path\to\project --out data\graphs\example.json
python -m adaptive_agent.graph_viz --query "where do we verify a token?"
python lessons/l2_skill_induction.py --decision reject --reason "not ready"
python -m pytest -q
npm run test:desktop- Auto-activate a skill.
- Send pixels to a text model and hope.
- Let Plan mode write files before Build.
- Commit
.env,data/agent.db, ordata/eval/.
Windows JSONL is UTF-8. The worker replaces lone surrogates so a pasted character cannot crash the pipe.















