mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
* feat(web): add workspace browser for multi-directory navigation Add /browse route with a folder browser that lets users navigate filesystem directories on connected machines and launch sessions from any folder. Supports saved workspace paths and direct path input. The "Start Session" action pre-fills the NewSession form. - CLI: register machine-level `list-directory` RPC handler - Hub: add POST /machines/:id/list-directory route - Web: add WorkspaceBrowser component with git repo detection - Web: add /browse route with navigation from sessions sidebar - Web: support initialDirectory/initialMachineId in NewSession Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add --workspace-root opt-in scoping for /browse and session spawn Adds a single new flag, \`--workspace-root <path>\` (with \`~\` / \`~/foo\` expansion), on \`hapi runner start\` and \`hapi runner start-sync\`. When set: - The runner reports the path in machine metadata. - The list-directory and spawn-session RPC handlers reject paths outside the root, so the web UI can't escape the configured tree even if someone crafts a request manually. - The /browse page in the web UI auto-opens that root, restricts the breadcrumb / go-up to its subtree, and shows directory entries with git-repo annotations. - The /sessions/new form keeps its existing free-text directory input plus autocomplete + recent-paths chips, and gains a small "Browse" button (next to the input) that opens /browse for picking a folder. - Reconnect-time metadata sync ensures stale records get the field filled in (or cleared when the flag is dropped on a later restart), so the hub state matches the CLI's intent. When unset: - Runner behaves like the legacy hapi (no scoping, no browse feature). - /browse renders an informative state pointing at the flag instead of blocking the user. - The /sessions/new form looks identical to the pre-change behavior; the "Browse" button is hidden. Includes a startup banner so \`runner start-sync\` no longer looks like it hung, and surfaces the workspace-root sync result on stdout. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(hub): preserve workspaceRoot when rehydrating machines from store MachineCache.refreshMachine() rebuilt the metadata object from an explicit field allowlist, so any field not in the list (including the new workspaceRoot) was silently dropped on every read — even though it was correctly written to the store. Add workspaceRoot to the zod schema, the Machine interface, and the hand-rolled projection. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(web): friendlier empty state on /sessions When there are zero sessions the page used to be a vast blank rectangle with just the "0 sessions in 0 projects" caption. Render a centered empty state instead: a calendar/agenda icon, a short heading and hint, and two buttons — "Start a session" (→ /sessions/new) and "Browse workspace" (→ /browse). SessionList gains an optional onBrowse prop. Router wires it on the sessions page so the secondary button resolves; other callers can leave it unset to hide that button. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: document --workspace-root flag in cli/README and root README Add a short paragraph under "Runner management" in cli/README.md explaining what \`--workspace-root\` enables (scoped /browse tree, list/spawn enforcement, tilde expansion) and that omitting it keeps the legacy behavior. Mention the workspace browser in the top-level README's Features list. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: address PR #526 review feedback Three findings from the review bot: 1. [Major] Workspace-scope check was lexical only. With workspaceRoot = /safe, a symlink such as /safe/out -> /etc would pass the relative- path test and let list-directory / spawn-happy-session reach paths outside the configured root. realpath the workspaceRoot at construction time, and resolve every incoming path through realpath (walking up to the nearest existing parent for spawn targets that haven't been created yet) before the containment check. 2. [Minor] \`hapi runner start --workspace-root\` with no value used to drop the flag silently and start the runner unscoped. Now treats a missing or flag-shaped next argument as an error. 3. [Minor] /sessions/new's "Browse" button always opened /browse using localStorage's last-used machine, ignoring the user's current selection. NewSession already passes machineId in its callback; forward it through the /browse search params and seed WorkspaceBrowser with it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(cli): gate list-directory RPC behind --workspace-root opt-in Without a configured workspaceRoot, isWithinWorkspaceRoot() returns true unconditionally, leaving the new list-directory RPC able to enumerate any path on the runner. The Web UI already hides Browse for these machines, but the backend should enforce the opt-in too. Refuse the RPC up front when no workspace root is configured. --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
hapi CLI
Run Claude Code, Codex, Cursor Agent, Gemini, or OpenCode sessions from your terminal and control them remotely through the hapi hub.
What it does
- Starts Claude Code sessions and registers them with hapi-hub.
- Starts Codex mode for OpenAI-based sessions.
- Starts Cursor Agent mode for Cursor CLI sessions.
- Starts Gemini mode via ACP (Anthropic Code Plugins).
- Starts OpenCode mode via ACP and its plugin hook system.
- Provides an MCP stdio bridge for external tools.
- Manages a background runner for long-running sessions.
- Includes diagnostics and auth helpers.
Typical flow
- Start the hub and set env vars (see ../hub/README.md).
- Set the same CLI_API_TOKEN on this machine or run
hapi auth login. - Run
hapito start a session. - Use the web app or Telegram Mini App to monitor and control.
Commands
Session commands
hapi- Start a Claude Code session (passes through Claude CLI flags). Seesrc/index.ts.hapi codex- Start Codex mode. Seesrc/codex/runCodex.ts.hapi codex resume <sessionId>- Resume existing Codex session.hapi cursor- Start Cursor Agent mode. Seesrc/cursor/runCursor.ts. Supportshapi cursor resume <chatId>,hapi cursor --continue,--mode plan|ask,--yolo,--model. Local and remote modes supported; remote usesagent -pwith stream-json.hapi gemini- Start Gemini mode via ACP. Seesrc/agent/runners/runAgentSession.ts. Note: Gemini runs in remote mode only; it waits for messages from the hub UI/Telegram.hapi opencode- Start OpenCode mode via ACP. Seesrc/opencode/runOpencode.ts. Note: OpenCode supports local and remote modes; local mode streams via OpenCode plugins.
Authentication
hapi auth status- Show authentication configuration and token source.hapi auth login- Interactively enter and save CLI_API_TOKEN.hapi auth logout- Clear saved credentials.
See src/commands/auth.ts.
Runner management
hapi runner start- Start runner as detached process.hapi runner stop- Stop runner gracefully.hapi runner status- Show runner diagnostics.hapi runner list- List active sessions managed by runner.hapi runner stop-session <sessionId>- Terminate specific session.hapi runner logs- Print path to latest runner log file.
Both start and start-sync accept --workspace-root <path> (or --workspace-root=<path>). When set:
- The web
/browsepage surfaces a scoped file tree rooted at that path. - The runner refuses
list-directoryandspawn-sessionrequests for paths outside the root. ~and~/fooare expanded.
Omitting the flag keeps the legacy behavior: no scoping, no /browse feature.
See src/runner/run.ts.
Diagnostics
hapi doctor- Show full diagnostics (version, runner status, logs, processes).hapi doctor clean- Kill runaway HAPI processes.
See src/ui/doctor.ts.
Other
hapi mcp- Start MCP stdio bridge. Seesrc/codex/happyMcpStdioBridge.ts.hapi hub- Start the bundled hub (single binary workflow).hapi server- Alias forhapi hub.
Configuration
See src/configuration.ts for all options.
Required
CLI_API_TOKEN- Shared secret; must match the hub. Can be set via env or~/.hapi/settings.json(env wins).HAPI_API_URL- Hub base URL (default: http://localhost:3006).
Optional
HAPI_HOME- Config/data directory (default: ~/.hapi).HAPI_EXPERIMENTAL- Enable experimental features (true/1/yes).HAPI_EXTRA_HEADERS_JSON- JSON object of extra headers to send on CLI → hub requests, e.g.{"Cookie":"CF_Authorization=..."}.HAPI_CLAUDE_PATH- Path to a specificclaudeexecutable.HAPI_HTTP_MCP_URL- Default MCP target forhapi mcp.
Runner
HAPI_RUNNER_HEARTBEAT_INTERVAL- Heartbeat interval in ms (default: 60000).HAPI_RUNNER_HTTP_TIMEOUT- HTTP timeout for runner control in ms (default: 10000).
Worktree (set by runner)
HAPI_WORKTREE_BASE_PATH- Base repository path.HAPI_WORKTREE_BRANCH- Current branch name.HAPI_WORKTREE_NAME- Worktree name.HAPI_WORKTREE_PATH- Full worktree path.HAPI_WORKTREE_CREATED_AT- Creation timestamp (ms).
Storage
Data is stored in ~/.hapi/ (or $HAPI_HOME):
settings.json- User settings (machineId, token, onboarding flag). Seesrc/persistence.ts.runner.state.json- Runner state (pid, port, version, heartbeat).logs/- Log files.
Requirements
- Claude CLI installed and logged in (
claudeon PATH). - Cursor Agent CLI installed (
agenton PATH) forhapi cursor. Install:curl https://cursor.com/install -fsS | bash(macOS/Linux),irm 'https://cursor.com/install?win32=true' | iex(Windows). - OpenCode CLI installed (
opencodeon PATH). - Bun for building from source.
Build from source
From the repo root:
bun install
bun run build:cli
bun run build:cli:exe
For an all-in-one binary that also embeds the web app:
bun run build:single-exe
Source structure
src/api/- Bot communication (Socket.IO + REST).src/claude/- Claude Code integration.src/codex/- Codex mode integration.src/cursor/- Cursor Agent integration.src/agent/- Multi-agent support (Gemini via ACP).src/opencode/- OpenCode ACP + hook integration.src/runner/- Background service.src/commands/- CLI command handlers.src/ui/- User interface and diagnostics.src/modules/- Tool implementations (ripgrep, difftastic, git).
Related docs
../hub/README.md../web/README.md