Skip to content

feat(web): add the web version, an assistant that manages your T3 Code work - #89

Merged
tnfssc merged 10 commits into
developfrom
feat/web-version
Oct 29, 2026
Merged

tnfssc merged 10 commits into
developfrom
feat/web-version

Conversation

@tnfssc

@tnfssc tnfssc commented Oct 28, 2026 •

Copy link
Copy Markdown
Owner

What this adds

pi --web turns a Pi session into your assistant for the work you run in T3 Code. You talk or type to it
(and paste pictures) from a page in the browser or on your phone; it starts, follows and messages T3 threads
for you, and tells you what needs you. It doesn't code itself.

The video below is one real session against a running T3: asking for work in plain words, the thread
starting, the assistant checking back on its own when it finished, a pasted screenshot, and voice. Waits
are sped up and labelled. The video has no sound: the spoken question was synthetic speech fed into a fake
microphone, and the spoken answer isn't captured.

How it works

  • One Pi session is the assistant. pi --web loads a lean set of bruv (no jobs, agents, goals,
    checks or finish, which serve coding) and gives the model only its workspace files, T3's tools and two
    of its own: overview (what's waiting, working, failed or newly finished, from memory, no T3 call) and
    approve.
  • T3 two ways. Acting goes through T3's MCP server; bruv signs in itself with t3 pair, no browser.
    Watching goes through T3's app websocket (live thread updates, resumed after a reconnect), and
    permission requests are answered there too, since MCP can't. All knowledge of T3's private protocol is in
    src/web/t3/.
  • Work, not threads. The assistant keeps tasks/<slug>.md in its workspace folder; the page shows them
    as your work, with T3's threads under them.
  • It checks back. A thread a task follows that finishes, fails or waits on you wakes the assistant
    (batched, held while it's busy or you're talking), and it takes a regular look while work is open. What
    it then says goes to the page, spoken if voice is on, or as a push notification if no page is in front.
  • The page is React, Vite, Tailwind and shadcn/ui, built into web/dist (committed: pi install
    skips dev dependencies and pi update deletes untracked files; a test fails when it's stale). What you
    send and approve shows at once (the server echoes your line under the page's id) and rolls back if the
    server doesn't confirm. TanStack DB was tried for this and left out: it doubled the page's JavaScript
    (91 → 177 KB gzip) and held back streaming replies while a send was pending; see the notes.
  • Voice reuses bruv's existing speech engine and models, lazily, in the same conversation.
  • Phone: /web tunnel serves it on your own domain through Cloudflare; it installs as an app and can
    send notifications (VAPID push, hand-written on node:crypto).

Showing files, pages and video

The assistant's show tool puts a file in the conversation: a picture, video or sound plays in place, an
HTML page runs in a sandboxed frame (it can't reach the page or its key), text and Markdown show in a
box, and a PDF opens in a tab. Files come from its folder, a T3 thread's folder, or a page a thread showed
in T3 with html_render.

T3 may run on another machine, so a thread's files are never read from disk: T3 makes a signed link for
each (assets.createUrl, projects.readFile for text) and bruv passes the bytes on, since a phone on the
tunnel may not reach T3. Links in the conversation are signed with the page's key and carry no key
themselves, and keep working after T3's hour-long links run out.

/web t3 <link> pairs with a T3 elsewhere from the link t3 pair --tailscale prints there. From then on
bruv signs in to MCP and renews its own key with tokens it mints, needing nothing else from that machine.

Below, a real run: a thread built a chart page (with a separate style.css) and a video, and the
assistant showed both after its check-in. On the phone, a page another thread had rendered in T3.

Chart page and video shown in the conversation

A page a thread rendered in T3, shown on a phone

What threads say reaches the assistant

The assistant manages threads like a parent agent its children: what a thread a task follows says
reaches it as the thread says it. A thread's last message comes with its "finished" (or failed, or
waiting) wake-up, and what it says while working is gathered and delivered every two minutes, so the
assistant acts on results without reading the thread. This rides on T3's per-thread subscription
(orchestration.subscribeThread), all followed threads on one socket, each resuming from its own
position; checked against T3's source. In a real run a scratch job finished and the assistant answered
from the thread's message alone.

In the activity panel, an opened task or thread has "Ask about this" (asks the assistant, as if typed)
and "Open in T3" (T3's own page for the thread; hidden when T3 is on 127.0.0.1 and the page isn't).

On the go

On a phone, the footprints button in the header swaps the keyboard for one big button to hold and talk
(tap it for hands-free), with what the assistant is doing in big words, big buttons for mute, quiet, stop
and back to typing, the first thread waiting on a yes or no as a card with big Approve and Deny, and bigger
text. Kept per device. Below, a real run at phone size with a fake mic: ready, hearing, thinking, speaking.

On the go: ready, hearing, thinking, speaking

Built to stay cheap

A conversation of any length costs a page 50 lines on connect and 50 more per scroll back; the server
walks back from the newest entry, and into earlier session files when the assistant moved to a fresh
session after its file grew past 20 MB. Replies stream as deltas, pictures are cached links, the page
virtualizes and caps what it keeps, the T3 feed resumes from its last position (a few KB instead of
1.8 MB), and the files it reads are read once and then only when they change.

Checked

  • bunx biome ci ., bun run check, bun test, bun run test:site.
  • Used for real against T3 (notes in .agents/notes/assistant/web.md): scratch jobs end to end with
    wake-ups, a vague ask (it asked), a risky ask (it confirmed), a pasted screenshot, a permission request
    approved by saying so, real speech through a fake microphone, phone size.
  • Showing files, run for real against T3: a thread's HTML page with its CSS, a video (plays and seeks), and an
    html_render page found from the thread's activity. Pairing from a link checked against the real T3
    with no local T3 to fall back on.
  • Not checked on a real phone: installing the app, push notifications, the tunnel. Not tried with T3 on a
    second real machine.

Notes: .agents/notes/assistant/ (plan, T3 access, web, voice, phone). Usage: docs/USAGE.md, "The web
version".

bruv-web.mp4

…e work

pi --web makes a Pi session your assistant: talk or type to it from the browser or your phone, and it starts, follows and messages T3 threads for you, checks back on its own, and passes on approvals. Built to stay cheap however long the conversation gets.
@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d429fcf2-fe7e-471e-8780-7ee179dfb177
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…h a T3 on another machine

The assistant's show tool puts a picture, video, sound, HTML page, PDF or text file in the conversation, from its folder or a T3 thread's. Thread files come through T3's signed links, never from disk, so T3 may run elsewhere; /web t3 <link> pairs with it from a t3 pair link.
…bout or open work from the activity panel

A thread's last message comes with its wake-up, and what it says while working comes gathered every two minutes, through T3's per-thread subscription on one socket. Opened tasks and threads get Ask about this and Open in T3.
…l and nothing it said is lost

Checked against T3's source: a thread's position is its own, and a shell position past it gets a whole snapshot. A new thread starts from a bounded snapshot; a snapshot replacing a resume passes on what was said meanwhile; a run's end passes on a last message left streaming.
…is not finished

T3's thread record says when a turn ended with work left going: a watched pull request, pending background tasks, a wait on another thread, or (for delegated tasks) live child threads. Such a thread counts as working, its turn's end is "stopped for now", and "finished" comes only when nothing holds it. A subagent waiting on the user wakes the assistant with its thread id.
registerWeb runs in every bruv session for /web, and registered overview, approve and show everywhere: three dead tools on every coding request, and a show that replaced terminal voice's. They are now registered only with --web.
…, scroll-back, snoozes, and smaller modules

A failing file transfer no longer ends the process, and long videos from T3 no longer stop at 30 s. A page's line is matched to Pi's echo by its words, not by order. /web tunnel off stops a tunnel still connecting; /web t3 local points T3's tools back. Lines a page saw live link to their saved entries for scroll-back and pictures. A snooze that ends brings its thread back. Files from T3 are always sandboxed. The web module is split into history, tools, commands and steps.
@tnfssc
tnfssc merged commit f04fbd0 into develop Oct 29, 2026
2 checks passed
@tnfssc
tnfssc deleted the feat/web-version branch October 29, 2026 09:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant