B4.run
Menu

Site

$ npm create b4-app@latest my-agent

The TypeScript framework for agents.

Ridiculous speed.
Readable code.

Write the agent. Give it tools. Set the limits.
Ship code you can actually read.

The whole application

One project.
A working agent.

Repair a broken CLI. Verify the patch. Ask for approval.

Follow the files.

01Declare the agent

This code runs this agent.

Choose a model and a task. B4 runs the tool-call loop.

Agents ↗
src/app/fix/index.tsFull source
import { agent } from "@b4run/sdk" export default agent({  model: process.env.B4_CODE_FIXER_MODEL ?? "gpt-5-mini",  recursionLimit: 60,  description: "Repairs a failing test and verifies the change.",  tools: { approve: ["exportForReview"] }, systemPrompt · instructions folded})

02Workspaces + sandboxes

Give it somewhere to work.

Declare the files. B4 manages their lifecycle in an isolated Docker workspace.

Workspaces + sandboxes ↗
src/project/workspace.ts · excerptFull source
export function projectWorkspace(id: string): WorkspaceDefinition {  const manifest = projectManifest(id)  return {    source: {      directory: "sample/project",      include: [...manifest.allowedSourcePaths, ...manifest.immutablePaths],      files: [        { path: "TASK.md", file: "sample/task.md" },        { path: ".gitignore", text: "node_modules/\n" },        { path: "project.json", text: JSON.stringify({ id: manifest.id }) },      ],    },    environmentLinks: [      { path: "node_modules", target: `/opt/fixtures/${manifest.id}/node_modules` },    ],    baseline: "git",  }}
Run it in Docker.
b4.config.ts · excerptFull source
  sandbox: {    ...sandboxPolicy,    provider: dockerSandbox({ scope: "code-fixer-local", image: sandboxImage }),    workspace: projectWorkspace(task),  },

03Typed tools

Your functions. Its tools.

Export a function. B4 derives its schema from your types and supplies ctx.

Tools ↗
src/app/fix/tools/prepareReview.tsFull source
import type { B4ToolContext } from "@b4run/sdk"import { inspectCandidate } from "../../../review/inspect.js"import { renderReviewDiff } from "../../../review/patch.js"import { verifyChanges } from "../../../review/verifier.js" /** Verify the source repair independently and return the exact candidate for review. */export default async function prepareReview(_input: Record<string, never>, ctx: B4ToolContext) {  // Compare the workspace with its captured source and reject edits outside the allowed files.  const { manifest, candidate, baseline, initial } = await inspectCandidate(ctx)   // Apply these exact changes in a fresh workspace and run both test suites.  const verification = await verifyChanges(manifest.id, candidate.changes, ctx.signal, initial)  if (!verification.passed) throw new Error("Independent verification failed")   // Give the agent a readable diff and the exact candidate it must submit for approval.  return {    task: manifest.id,    candidate,    diff: renderReviewDiff(baseline, candidate.changes),    verification,  }}

04Plans + skills

Give it a working method.

A plan seeds the checklist. Skills provide reusable instructions.

Plans + skills ↗
src/app/fix/plan.mdFull source
- [ ] Read the task and reproduce the failing test- [ ] Inspect the relevant source and identify the cause- [ ] Make a focused source repair- [ ] Run the test, check preservation requirements, and explain the verified result- [ ] Call prepareReview and inspect the independently verified candidate- [ ] Pass that exact candidate to exportForReview for runtime approval
skills/verify-change/SKILL.md

Reproduce. Repair. Verify. Request review.

05Independent verification

Define what “done” means.

Test the patch in a fresh workspace. Require every named check to pass.

Evaluate the workflow ↗
sample/checks.jsonFull source
{  "visible": {    "file": "test/cli.test.ts",    "assertions": [      "documented dry-run flag reaches the handler"    ]  },  "independent": {    "file": "checks/independent.test.ts",    "assertions": [      "forwards cap and memory-level cwd",      "rejects unknown and incomplete arguments",      "dry-run preserves memory state and creates no files"    ]  }}

06Human approval

The next action is your call.

B4 pauses before export. You approve the exact patch; the tool rechecks it.

Approval ↗
src/app/fix/index.ts · excerptFull source
  tools: { approve: ["exportForReview"] },
Recheck after approval.
src/app/fix/tools/exportForReview.ts · excerptFull source
  const candidate = validateCandidate(input.candidate)  const inspected = await inspectCandidate(ctx)  if (candidate.receiptDigest !== inspected.candidate.receiptDigest)    throw new Error("Workspace changed since review; prepare and approve a new candidate")  const verification = await verifyChanges(    inspected.manifest.id,    candidate.changes,    ctx.signal,    inspected.initial,  )  if (!verification.passed) throw new Error("Independent verification failed")

The pieces in motion

One request. The whole workflow.

  1. 01Request/fix#agent
  2. 02RepairIsolated workspace
  3. 03VerifyFresh workspace
  4. 04PauseB4 approval gate
  5. 05ApproveYour decision
  6. 06ExportRechecked patch

You write the task, tools, and acceptance rules.

B4 runs the agent loop, workspaces, streaming, and approval.

Current example source. Recording and installation use earlier versions.

See it in actionWatch the recorded repair.1m 53s · edited highlights

Historical defect, earlier implementation. Recorded timing applies to this run only.

This code runs this agent.

Recorded run · 1m 53s
Edited highlights · gpt-5

✓ Independent verification passed

Fixed. Verified.
Ready for your review.

A fresh sandbox checked the agent’s patch.

VISIBLE TESTS 1 / 1 passed
INDEPENDENT CHECKS 3 / 3 passed
  • documented dry-run flag reaches the handler
  • forwards cap and memory-level cwd
  • rejects unknown and incomplete arguments
  • dry-run preserves memory state and creates no files
Awaiting your approvalexportForReview paused. Nothing exported.

Recorded implementation

src/app/fix/index.tsFull source
import { agent } from "@b4run/sdk" export default agent({  model: process.env.B4_CODE_FIXER_MODEL ?? "gpt-5-mini",  recursionLimit: 60,  description: "Repairs a failing test and verifies the change.",  tools: { approve: ["exportForReview"] }, systemPrompt · instructions folded})

Your next commit starts here

Read it.
Run it.
Make it yours.

Start with this agent. Make it yours.

Open the installation guide

The B4 CLI prints the installation guide for your coding agent:

b4 add code-fixer

Qualified installation · B4 0.8.32 · Earlier source.
Node 24 · Git · Docker · API key for live runs.
Replay the sample without a model call.

Using the B4 CLI ↗
Read the code walkthrough ↗
See every attempt, including the failures ↗