cd /news/ai-agents/show-hn-bough-a-coding-agent-that-wr… · home topics ai-agents article
[ARTICLE · art-93822] src=github.com ↗ pub= topic=ai-agents verified=true sentiment=· neutral

Show HN: Bough – a coding agent that writes a program per turn, not tool calls

Bough, a new open-source coding agent from developer Andrey Lukin, lets AI models write one JavaScript program per turn with real loops and branching instead of emitting individual tool calls, executing code directly on the user's machine with no sandbox or isolation. The harness, which runs on macOS or Linux and supports Anthropic, OpenAI, OpenRouter, and Cloudflare Workers AI models, edits the user's real checkout and delivers changes via git diff, commit, and push. Bough is positioned as an alternative harness design rather than a better coding agent, with history stored as a tree and all state managed by a headless server.

read6 min views1 publishedAug 12, 2026
Show HN: Bough – a coding agent that writes a program per turn, not tool calls
Image: source

A coding agent that acts by writing programs.

One JavaScript program per round, with real loops and branching, run against your real checkout.

bough rhymes with now, not with dough: /baʊ/. It is the word for a branch of a tree, which is what a conversation is here: you fork a turn and the old line goes on living as a branch.

Most harnesses let the model emit one tool call and wait. bough gives it a single tool that takes a program: the model writes JavaScript with real control flow, and a harness executes it on your machine. A headless server owns all state and execution; the terminal UI is a view over it.

bough is an alternative harness design, not a better coding agent. That distinction is the point of the project, and this README tries not to blur it.

Warning

There is no isolation boundary. Programs run as you, with your full authority: filesystem, network, subprocesses, npm:

imports. No sandbox, no egress proxy, no credential gating. Host functions are convenience and session integration, never a wall.

This is a deliberate choice, not an unfinished one (spec §2): the harness edits your real files because reviewing git diff

and pushing with your own git is the delivery mechanism. Run it only on a machine where you would be comfortable running the code it writes, because that is exactly what happens.

One program per round. The model's only action isrun_steps(code)

. Control flow lives in the program, not in a chain of round-trips.In place. The agent edits your own checkout. No copy, no overlay. The Changes rail isgit diff

against the sha the session started from; you deliver withgit commit

/git push

.History is a tree. Fork any turn, compact a span onto a new branch, lift messages into a fresh root. Nothing is destructively rewritten; every operation produces a new branch.The server is the system. State, execution, and orchestration are server-side. A client can crash or detach without affecting a running turn.Delegation is core. Subagents and workflows are primary capabilities with real persistence, lifecycle control, and observability.

Here is a round. It is one program where another harness would spend five round-trips:

// Which crates still pin the old ratatui, and do they still pass?
const pinned = (await bash("rg -l 'ratatui = \"0.29\"' crates", "repo:scan:ratatui"))
  .trim().split("\n").filter(Boolean);

const names = pinned.map(p => p.split("/")[1]);

// sh() runs them concurrently; a non-zero exit is data, not an exception.
const runs = await sh(names.map(n => ({
  cmd: `cargo test -p ${n} 2>&1 | tail -3`,
  tag: `cargo:test:${n}`,
})));

const broken = names.filter((_, i) => runs[i].code !== 0);
console.log(broken.length ? `failed: ${broken.join(", ")}` : "all green");

The loop, the fan-out and the branch are the model's own code. console.log

is what streams to you and what comes back as the round's result, so the program decides what is worth your context: here, the names that failed rather than four test logs.

macOS or Linux. Builds from source, so the first run takes a few minutes.

brew tap andreylukin/bough https://github.com/andreylukin/bough
brew install bough
$EDITOR ~/.bough/env      # ANTHROPIC_API_KEY=…
bough start               # background service
bough                     # the TUI

Without Homebrew, the same install as a script. It clones into ~/bough

and builds there:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/andreylukin/bough/main/install.sh)"

Models. Four providers, and a model routes to one by the shape of its id alone: claude-opus-5

is Anthropic, openai:gpt-5

is OpenAI's Responses API, vendor/model

is OpenRouter, @cf/vendor/model

is Cloudflare Workers AI. OpenRouter is the wide door: if it carries a model, bough can run a turn on it. Every provider's base URL is overridable, and the OpenRouter path speaks /v1/chat/completions

, so pointing OPENROUTER_API_BASE

at Ollama, vLLM, LM Studio or a gateway runs turns against that instead. The picker (^o

) lists what your keys actually reach rather than a compiled-in catalog, and any one key is enough to start.

Full instructions, keys, and updating: docs/install.md.

Point a session at a repo and ask in plain language. bough writes a small program, runs it, and answers. Folded reasoning, the code that ran, and live cost and context all sit in one view. Unfold a step (^e

) and you see the actual program and its output:

Everything that is not the conversation lives in one panel with nine tabs, each on a direct-jump chord: the conversation tree (^f

), changes (^d

), workflows (^w

), model (^o

), MCP (^p

), skills (^k

), hooks (^x

), context (⌥c

), theme (^y

). Press ?

for the full keymap.

Review with ^d

: the Changes rail is git diff

against the sha the session started from, per file and revertable per path. You commit and push with your own git.

Rewind to any turn and send something else, and the old line survives as a branch.

docs/tui.md for panels and every chord · docs/cli.md for exec

, acp

, mcp

, tags

and the rest

Programs. Eighteen host functions in scope, plus the full JS runtime. One editing idiom: view

gives numbered lines with a version tag, patch

names lines instead of quoting them, so code being edited never has to survive the model's own string escaping, and a stale edit reports a conflict instead of clobbering. → docs/programs.md

Delegation. agent

and spawn

run subagents in the same checkout; a workflow is a detached orchestration script with parallel

/ pipeline

primitives, schema-validated results, and a journal that replays unchanged work on rerun instead of paying for it twice. → docs/delegation.md

Memory across sessions. Every shell command carries tags naming what it is for, written at the moment the command is written. A session opens primed with its project's own vocabulary, and bough tags

answers what was tried here, what worked, and what it printed. → docs/tags.md

Extending it. Skills, Lua hooks that can start work rather than only veto it, JavaScript extensions bound into every program's scope, and MCP as a command rather than a verb. Reads the AGENTS.md

, CLAUDE.md

and .claude/skills

your other harnesses already wrote. → docs/extending.md

docs/ is the map. Start at

install.md, then

tui.md.

how-it-works.mdis the architecture in one page;

spec.mdand

specs/are authoritative for behavior.

These are decisions, not gaps:

  • No confinement of any kind, and no credential gating.
  • No acceptance gate. The model reports what it did and you verify it. The harness does not re-run a committed command or block a turn from finishing.
  • No local inference in the turn loop; the cheap tier is a hosted model. The one exception is the embedding layer, which runs a small model inside SQLite.
  • No embeddings over transcripts; cross-session transcript search is SQLite FTS. The two vector indexes cover the tagged command memory and note sections; both live in a separate embeddings.db

that is derived state and can be deleted at any time. - No per-agent worktrees or file leases. One shared checkout.

  • No remote access, no auth layer, no web UI.

The most useful contributions sharpen or falsify the design. Read CONTRIBUTING.md for setup, the bar for a pull request, and the verification you are expected to have done.

Bugs and features go through the issue templates; questions and design debates belong in Discussions. Security issues go through SECURITY.md, never the public tracker. Participation is governed by the Code of Conduct.

Apache License 2.0. By contributing you agree your contributions are licensed under it; there is no CLA.

── more in #ai-agents 4 stories · sorted by recency
── more on @bough 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/show-hn-bough-a-codi…] indexed:0 read:6min 2026-08-12 ·