Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
b98107f
An Agent container, and a picker that does not lie about what can run
ThyFriendlyFox Aug 14, 2026
c3c0a7c
A thinking orb, and the gateway Hermes already speaks
ThyFriendlyFox Aug 14, 2026
34d1832
The orb is the microphone, and the picker drops its caret
ThyFriendlyFox Aug 14, 2026
37aaac3
The brief for the agent run, and a loop that can end
ThyFriendlyFox Aug 14, 2026
8bc2b29
What the agents actually do when you ask them, measured
ThyFriendlyFox Aug 14, 2026
bad361d
No scoped package's command has ever existed
ThyFriendlyFox Aug 14, 2026
aebcc50
A bounded wait, because an agent that hangs is the normal case
ThyFriendlyFox Aug 14, 2026
a1685ed
Setup the container remembers
ThyFriendlyFox Aug 14, 2026
2c844b9
The brief carries the answers, not the questions
ThyFriendlyFox Aug 14, 2026
3773f9b
A blocked agent stops asking to be configured
ThyFriendlyFox Aug 14, 2026
4471cff
The empty container is empty
ThyFriendlyFox Aug 14, 2026
febaaca
The gateway client, proven — and the hang was `.waiting`
ThyFriendlyFox Aug 14, 2026
40ec32c
The container holds a conversation over the gateway
ThyFriendlyFox Aug 14, 2026
3b142a5
The line protocol was right, the socket was not
ThyFriendlyFox Aug 14, 2026
9a3bdbf
Read the docs first: it is an API server, not the TUI gateway
ThyFriendlyFox Aug 14, 2026
7ec156c
The API, read rather than inferred
ThyFriendlyFox Aug 14, 2026
d057699
The documented endpoint, and the container talks to it
ThyFriendlyFox Aug 14, 2026
b7160d3
A gate for the client that replaced the one I deleted
ThyFriendlyFox Aug 14, 2026
86241e1
The address asks on its own terms
ThyFriendlyFox Aug 14, 2026
7f8cf2a
Claude Code does not hang for want of a key
ThyFriendlyFox Aug 14, 2026
39a1272
Claude Code works; our launch path was the bug
ThyFriendlyFox Aug 14, 2026
d18641b
A caller with no screen stops being handed one
ThyFriendlyFox Aug 14, 2026
bc95fd6
It is not the compound; it is having a key at all
ThyFriendlyFox Aug 14, 2026
3f9babe
The network is not it
ThyFriendlyFox Aug 14, 2026
57c6fd8
Startup and stdin are not it either; streaming is the last suspect
ThyFriendlyFox Aug 14, 2026
fbc821f
Streaming works; the process just never ends
ThyFriendlyFox Aug 14, 2026
ba6dcc0
My watchdog printed KILLED whether or not it killed anything
ThyFriendlyFox Aug 14, 2026
a05b155
It blocks before its first write
ThyFriendlyFox Aug 14, 2026
15dd644
Hermes runs inside Mouse; Mouse is its tool surface
ThyFriendlyFox Aug 14, 2026
ac4de9a
pip exists now, for the wheels this Python can honour
ThyFriendlyFox Aug 14, 2026
ebbb6dc
The bridge is files per step, because the engine's WASI says so
ThyFriendlyFox Aug 14, 2026
e5b0b3b
The embedded agent answers, with Python in the loop on the device
ThyFriendlyFox Aug 14, 2026
5ade7db
Hermes's real closure, measured to its first two walls
ThyFriendlyFox Aug 14, 2026
df4f332
A Python with zlib, and a closure that survives its compiled stragglers
ThyFriendlyFox Aug 14, 2026
778f26f
The yaml wall falls to a substitute; the next wall is a silent hang
ThyFriendlyFox Aug 14, 2026
5ad4391
import run_agent succeeds on the device
ThyFriendlyFox Aug 14, 2026
12147c2
The loop's front door is AIAgent.chat, and the bridge is record-and-r…
ThyFriendlyFox Aug 14, 2026
6c30f10
Hermes's own loop completes a turn on the device
ThyFriendlyFox Aug 14, 2026
fd59807
Hermes answers in the container, on the simulator, on screen
ThyFriendlyFox Aug 14, 2026
b10ebac
Nine eliminations, and the conclusion that the hunt needs a new tool
ThyFriendlyFox Aug 14, 2026
de12b35
The interrupt names its holdout, and it names statsig
ThyFriendlyFox Aug 14, 2026
dfbcca3
Not our bug: 1.0.128 hangs on real node too, and for the same reason
ThyFriendlyFox Aug 14, 2026
8a282bf
2.1.98: two seconds on real node, a silent spin on ours
ThyFriendlyFox Aug 14, 2026
e4f1dad
The spin was ours after all: ICU, fed a nine-megabyte line
ThyFriendlyFox Aug 14, 2026
7837908
2.1.98 after the fixes: runs clean, refuses print mode silently
ThyFriendlyFox Aug 14, 2026
5ba6b51
The silent death was our spawnSync guard refusing `timeout`
ThyFriendlyFox Aug 14, 2026
c1ab6cc
Claude Code 2.1.98 answers in the Agent container
ThyFriendlyFox Aug 14, 2026
382536f
Claude Code signs in the way it documents, inside the chat
ThyFriendlyFox Aug 14, 2026
9f19635
One home for every agent; the project stays the project
ThyFriendlyFox Aug 15, 2026
97f9c34
The answer streams, and the phone speaks it as it lands
ThyFriendlyFox Aug 22, 2026
0821acf
The orb tap trapped on the audio thread; the callbacks opt out of the…
ThyFriendlyFox Aug 22, 2026
8428743
A turn belongs to the agent it was sent to
ThyFriendlyFox Aug 23, 2026
471f5e4
Hermes sets itself up, in the container, as itself
ThyFriendlyFox Aug 23, 2026
c47b867
The Terminal container's keys, above an agent's own program; setup re…
ThyFriendlyFox Aug 23, 2026
12322e4
STATUS: the key row and re-run affordance, with the rest of the Herme…
ThyFriendlyFox Aug 23, 2026
9848cff
The program's menu, mirrored as chips the thumb can reach
ThyFriendlyFox Aug 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
624 changes: 624 additions & 0 deletions .claude/agent-brief.md

Large diffs are not rendered by default.

74 changes: 65 additions & 9 deletions STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ numbers some of the same ground differently; the mapping is noted per row.
| **D** — web toolchain | tsc, bundlers, dev servers | **Largely done**, as a byproduct of G | tsc + `tsc --watch`, webpack, esbuild-wasm, vite dev (HMR) and vite build (rollup-wasm) all gated (`verify/esbuild`, `devserver`, `hmr`, `firstrun`). A real SvelteKit project runs `npm run dev` on the device: starts once, pre-bundles its 20 dependencies, and answers a curl from the Mac with HTTP 200 and the rendered 33 kB page. Remaining piece is the Preview surface (phase C) |
| **B** — WebView JIT | Move JS/wasm execution into WKWebView for JIT speed | **Not started — optional** | Measured: everything runs interpreted; the JIT buys speed, not capability (system.md:2094). No longer a prerequisite for anything |
| **C** — Preview container | In-app viewing surface for what dev servers serve; LAN hosting | **Not started** | The server half works (vite serves clients outside the app — gated in `verify/devserver`); no in-app viewer exists |
| **E** — wasm runtime processes | Real processes: `$PATH`, executable bits, `ps`/`kill`/`&`, pipes between programs; other languages (Python first) as wasm32-wasi artifacts | **Runtime half done** | `pkg install python` downloads the official CPython wasm32-wasi build, hash-checks it, unpacks it (zip reader written here — iOS has no `unzip`) and `python hello.py` runs CPython 3.14.6. `swift/Mouse/Runtimes.swift` + mounts in `NodeEngine`. Gated: `verify/python`, `verify/pkgpython`. Written up in system.md §5b. Missing: `$PATH`, executable bits, background jobs (`&` is still refused by name in the lexer) |
| **E** — wasm runtime processes | Real processes: `$PATH`, executable bits, `ps`/`kill`/`&`, pipes between programs; other languages (Python first) as wasm32-wasi artifacts | **Runtime half done** | `pkg install python` downloads a CPython wasm32-wasi build (VMware Labs' 3.12.0, chosen because it compiles zlib in — the official 3.14 build does not, and no zlib kills `import openai` before any agent code runs), hash-checks it, unpacks it and `python hello.py` runs it. `swift/Mouse/Runtimes.swift` + mounts in `NodeEngine`. Gated: `verify/python`, `verify/pkgpython`. Written up in system.md §5b. Missing: `$PATH`, executable bits, background jobs (`&` is still refused by name in the lexer) |

## On the device

Expand All @@ -51,8 +51,8 @@ launches and is driven on the iPhone 16 Pro simulator
an opinion about how it prints was printing its raw fields instead.
Gated in `verify/inspectopts` and `verify/nodeprint`.
- **Python runs on the phone.** `pkg install python` prints `fetching
python 3.14.6 (14 MB)` / `installed python 3.14.6`; `python -c` prints
`python 3.14.6 on wasi` and `{"squares": [0, 1, 4, 9, 16, 25]}`; and
python ` / `installed python`; `python -c` prints
its version `on wasi` and `{"squares": [0, 1, 4, 9, 16, 25]}`; and
`python hello.py` prints what the script prints. Screenshots at 23:48 on
2026-07-31.
- **A node server runs on the phone and answers real requests from off the
Expand All @@ -70,17 +70,73 @@ launches and is driven on the iPhone 16 Pro simulator
only while a program runs; tapping it sends the interrupt the program
already knew how to handle. Verified: the server stopped, the prompt came
back, and the port stopped answering.
- **An agent CLI starts and renders its UI on the phone.** claude-code
1.0.128 installs through our own npm, reports `1.0.128 (Claude Code)`,
and its React/ink TUI draws its bordered `Welcome to Claude Code` frame
on the phase-T screen. Screenshot at 23:58.
- **An agent CLI answers a prompt on the phone.** claude-code 2.1.98
installs through our own npm, runs `-p` to completion on the engine, and
its answer renders in the Agent container's exchange on the simulator
(screenshot Aug 14, against an Anthropic-shaped stand-in; a real key and
an empty address point the same path at api.anthropic.com). The 1.0.x
line that first rendered its TUI here is dead UPSTREAM — it awaits
statsig.anthropic.com, which no longer resolves — and hangs identically
on real node. 2.1.98 is the newest release that is JavaScript the whole
way down.
- **The Agent container answers while the answer is still arriving, and speaks it.** A
top-level screenless Node run now streams stdout through the shell line by line
(`Context.liveOutput`; children spawned through the bridge still return theirs whole), and
Claude Code runs in `stream-json`: the agent message exists from the first delta and grows,
the `result` line replaces it with the whole. Measured on the simulator: **1.1 s to the first
word, 4.5 s to the whole** of a 29-word answer paced at 120 ms/word by the stand-in — the
status line shows both numbers after every turn. On-device speech reads each sentence the
moment it completes (`Speech`, AVSpeechSynthesizer; fenced and inline code stay on screen),
the microphone ends a turn on ~1.1 s of silence and reopens after the answer is spoken, and a
tap on the orb while it speaks is a barge-in. Spoken turns only: a typed prompt stays silent.
`verify/voice` gates the sentence-boundary and code-stripping rules headlessly; the audio
path itself needs a device.
- **Hermes's own `hermes setup` runs inside the Agent container, as itself.** The
Hermes `set up` row hosts `python -m hermes_cli.main setup` on the terminal grid:
its banner, its three setup modes, its 35-entry provider menu, its custom-endpoint
questions, terminal backend, messaging and tools checklists, through to "🚀 Ready
to go!" — answered from the chat field (type-ahead works: stdin is line-buffered),
writing hermes's own `/home/.hermes/config.yaml` (`model: {provider: custom,
base_url, api_key, default}`), app-wide. A turn then resolves its endpoint through
hermes's `resolve_runtime_provider()` and the `llm.complete → <host>` note names who
answered. What it took, all measured: WASI programs can now READ stdin — a native
line buffer the JS thread blocks on, fed by keystrokes, with a cooked-mode line
discipline (echo, backspace, Enter, ^D) since this Python has no termios; the
standard streams report as a tty (wasi-libc wants a character device WITHOUT
seek/tell rights — all-rights made `isatty()` false for every program that asked);
and two more wasi-gap shims, `ctypes` (hermes imports it unguarded for a process
title) and `fcntl` (its gateway status file locks). Gated: `verify/pystdin`. The Terminal container's key row (up/down/left/right/
esc/tab/canc) sits above the program here too, and the picker carries each agent's
`set up` / `sign in` so a setup can be re-run once it has gone through. When the
screen shows a numbered menu (or a [Y/n] question), the visible options are
mirrored as tappable chips in a rail under the key row — read from the grid, so
they are whatever the program presented; tapping one types that number and Enter,
the program's marked default renders brighter, and the chip matching the number
in the input field lights up. The rail's slot is fixed-height: it appearing and
vanishing must not resize the grid mid-program. Known
limits, hermes's own words on screen: no curses (numbered menus), `getpass` echoes
(no termios), and no network from this Python yet, so the Nous Portal login inside
the wizard cannot complete — bring-your-own-key providers and custom endpoints do.
- **Claude Code's own sign-in runs inside the Agent container.** The `sign
in` row hosts `claude setup-token` — its real ink screen — on an embedded
terminal grid: the OAuth URL renders, an `open claude.com` chip
reassembles it from the wrapped rows and opens Safari on Anthropic's
login page, the chat input feeds the program (bogus code → claude's own
"OAuth error: Invalid code", Enter → fresh retry), and `stop` reclaims
the terminal in one tap. A finished sign-in stores claude's credential in
the SHARED home — the container exports HOME=/home, a mount every shell
carries, so one sign-in covers every project while cwd stays the ring's
workspace — and both auth rows (sign-in and ANTHROPIC_API_KEY) disappear.
Verified on the simulator Aug 15: a sign-in run wrote its config only to
the shared home; the per-workspace copies kept the previous day's
timestamps.
- **claude-code's CURRENT releases cannot run here, and that is a change in
the package, not a regression in the engine.** `@anthropic-ai/claude-code`
now ships `bin/claude.exe` — a per-platform NATIVE binary — with
`cli-wrapper.cjs` as a fallback that spawns it. iOS will not execute
unsigned native code, so this is the platform wall the wasm strategy
exists for, reached from a new direction. The JS-bundle versions (1.0.128
and its era) still run. Any claim here about "claude-code" means those.
exists for, reached from a new direction. The JS-bundle versions (through
2.1.9x) still run. Any claim here about "claude-code" means those.
- **Interactive TUIs work.** `npx create-vite` walks its whole flow on the
phone: text prompt, framework menu, variant menu, install confirmation —
every transition painting live, colours intact, selections tracking.
Expand Down
Loading
Loading