shy turns a task into tool calls — bash, read, write, edit, grep, glob, web_fetch — runs them in parallel, compacts its own context when it gets long, and verifies its own fix before calling it done. Built from scratch to understand how coding agents actually work, not just to use one.
Pulls the harness, tools, and eval runner.
Or skip this and paste a key straight into the web demo.
Same loop, same tools, straight from the terminal.
Deterministic where it can be — parallel execution, retry, compaction — adaptive where it has to be: what the model decides to call.
System prompt + task go in as the first two messages. Tool schemas ride along with every model call.
The model either answers directly, or returns one or more tool calls — retried with backoff on transient errors.
Independent tool calls run concurrently via Promise.all, not one at a time. Every command is checked against a guardrail list first.
Once the conversation crosses ~70% of the token budget, older turns get summarized into one message by an extra model call.
Before declaring a fix done, the model is told to actually run it and read the output — not assume it's correct because the diff looks right.
Results feed back in, and the loop continues until the model stops, or a hard iteration ceiling is hit.
Each one is a plain object — name, description, JSON-schema parameters, an execute function. The loop doesn't know or care what's inside. Grown from five to eight as real tasks exposed what was missing.
Runs shell commands. Blocks destructive patterns (rm -rf /, fork bombs, curl | sh) before they execute.
Reads a file's contents, truncated to a safe output length.
Creates a file or fully overwrites one — never used on files with content worth keeping.
Replaces one exact string match inside a file. Refuses ambiguous matches instead of guessing.
Searches text across files with line numbers, instead of the model hand-rolling a search command.
Finds files by pattern (**/*.py) across the whole tree — no manual recursion, node_modules/.git skipped automatically.
Fetches a URL and returns its text. Refuses local/internal addresses; its output is flagged as untrusted to the model.
Delegates a sub-task to a fresh agent with clean context. Capped at 5 spawns per run.
Once a demo takes real API keys from real people, "the model probably won't do anything destructive" stops being an acceptable answer.
SWE-bench Lite, verified through the official Docker-based evaluation harness — real GitHub issues, real repos, real test suites. Not a self-graded number.
| Iteration | Resolved | What changed |
|---|---|---|
| Baseline | 8/18 · 44% | first working agent loop |
| + compaction, parallel calls, retry | 10/18 · 56% | context & reliability |
| + glob, web_fetch | 12/18 · 67% | codebase navigation |
| + verify-before-done | 12/18 · 67% | wrong fixes 4 → 2 |
Same 18 instances, re-run after each round of harness changes — no task-specific tuning. glob mostly fixed give-ups (agent could finally find the right file in big repos); verify-before-done then cut wrong fixes from 4 to 2 without changing the resolved count.
$ bun run src/index.ts "count .ts files in src/tools and src/core, delegate each to a sub-agent" spawn_subagent → "count .ts files in src/tools" → 7 spawn_subagent → "count .ts files in src/core" → 5 Both counts are in: - src/tools: 7 .ts files - src/core: 5 .ts files stopReason: stop · iterations: 2
Every model call and tool call streams to the browser over SSE, in real time. Bring your own DeepSeek key — it never touches our server.