* feat(web): show subagent's executed model in Task/Agent card header Task/Agent trace cards previously gave no indication of which model a subagent actually ran under, even though the model can differ from the calling session's (e.g. main session on opus, subagent on haiku) and can even change mid-run when --fallback-model kicks in under overload. The data already reaches the frontend: each child block produced from a subagent's own sidechain carries the model of the assistant message it came from. Derive it in getSubagentModel() from the tool call's own children (not the parent ToolCallBlock.model, which reflects the calling session and would misattribute the model), collecting distinct raw values in first-seen order and joining them the same way aggregateResponseGroups already does for top-level multi-turn message metadata. Full SDK model ids (e.g. claude-sonnet-4-5-20250929) are long and not great for a compact label, so formatSubagentModelLabel() extends this repo's existing "friendly label, else raw fallback" idiom (getClaudeModelLabel(model) ?? model in claudeModelOptions.ts, which only covers the short preset aliases) with a narrow second fallback that extracts just the name and version from the SDK id shape and drops the date suffix (-> "Sonnet 4.5"). Anything else is left as-is. Renders the result as a small chip in the header's existing right-side meta cluster (next to ElapsedView/status icon), always visible without opening the detail dialog. * fix(web): cap subagent model badge width to avoid squeezing the card header Addresses HAPI Bot review on #1045: formatSubagentModelLabel() returns unrecognized model ids (Gemini, Codex, future formats) unchanged, and those can be long. Bound the chip with max-w + truncate so it can't push the title/status area off narrow cards, with a title attribute so the full value is still reachable on hover.
HAPI
Run official Claude Code / Codex / Cursor Agent / Grok Build / OpenCode sessions locally and control them remotely through a Web / PWA / Telegram Mini App.
Why HAPI? HAPI is a local-first alternative to Happy. See Why Not Happy? for the key differences.
Features
- Seamless Handoff - Work locally, switch to remote when needed, switch back anytime. No context loss, no session restart.
- Native First - HAPI wraps your AI agent instead of replacing it. Same terminal, same experience, same muscle memory.
- AFK Without Stopping - Step away from your desk? Approve AI requests from your phone with one tap.
- Your AI, Your Choice - Claude Code, Codex, Cursor Agent, Grok Build, OpenCode—different agents, one unified workflow.
- Terminal Anywhere - Run commands from your phone or browser, directly connected to the working machine.
- Voice Control - Talk to your AI agent hands-free using the built-in voice assistant.
- Workspace Browser - Opt-in via one or more
hapi runner start --workspace-root <path>flags: browse scoped file trees from the web and start sessions in allowed subdirectories.
Demo
https://github.com/user-attachments/assets/38230353-94c6-4dbe-9c29-b2a2cc457546
Getting Started
npx @twsxtd/hapi hub --relay # start hub with E2E encrypted relay
npx @twsxtd/hapi # run claude code
hapi server remains supported as an alias.
The terminal will display a URL and QR code. Scan the QR code with your phone or open the URL to access.
The relay uses WireGuard + TLS for end-to-end encryption. Your data is encrypted from your device to your machine.
For self-hosted options (Cloudflare Tunnel, Tailscale), see Installation
Docs
Build from source
bun install
bun run build:single-exe
Credits
HAPI means "哈皮" a Chinese transliteration of Happy. Great credit to the original project.