@metyatech/workspace-agent-hub
v0.2.1
Published
Windows + WSL tmux session fabric with a mobile-friendly web UI for AI agent CLI handoff
Downloads
184
Readme
Workspace Agent Hub
Workspace Agent Hub is the Windows + WSL tmux session fabric for running and resuming multiple AI agent CLI sessions across PC and smartphone. It now includes a mobile-friendly browser UI/PWA for starting sessions, reopening them, and sending follow-up prompts without dropping into raw terminal flows.
It provides:
- A Windows launcher for starting, reopening, renaming, archiving, closing, and deleting agent sessions
- A WSL mobile menu that opens automatically after SSH login from tools such as Termius
- A browser UI/PWA for smartphone and desktop session management, transcript viewing, prompt sending, and browser-local resume cues
- Regression tests for the primary PC/mobile handoff paths
- An
Open Managerpath that opens Hub's native Manager inbox on the same authenticated origin for both PC and smartphone
Supported environments
- Windows 11 host
- PowerShell 7 or Windows PowerShell
- Node.js 22+
- WSL2 with an Ubuntu distro
tmuxinstalled inside WSL- Optional: Android emulator for the ConnectBot coverage path
Install / setup
Configure git hooks:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/setup-hooks.ps1Refresh agent rules for this repository:
compose-agentsmdInstall Node dependencies:
npm ciInstall the WSL mobile-login hook from inside WSL:
./scripts/install-wsl-mobile-menu-hook.shOptionally create Windows shortcuts for the launcher:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/install-agent-session-launcher-shortcuts.ps1
Usage
Windows launcher
Open the GUI:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/agent-session-launcher.ps1Open one profile directly:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/agent-session-launcher.ps1 -Mode codexList all sessions, including archived or closed entries:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/agent-session-launcher.ps1 -Mode list -Json -IncludeArchivedRename an existing session:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/agent-session-launcher.ps1 -Mode rename -SessionName shell-example -Title "Current debugging task"Archive a session without killing it:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/agent-session-launcher.ps1 -Mode archive -SessionName shell-exampleClose a running session while keeping its catalog entry:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/agent-session-launcher.ps1 -Mode close -SessionName shell-exampleDelete a session entry entirely:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/agent-session-launcher.ps1 -Mode delete -SessionName shell-exampleWSL mobile menu
Show archived and closed entries from the WSL-side CLI:
./scripts/wsl-agent-mobile-menu.sh list-allOpen the mobile management flow for rename/archive/close/delete:
./scripts/wsl-agent-mobile-menu.sh manageBrowser UI / PWA
Start the local browser UI with an auto-generated access code:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/start-web-ui.ps1Start it in the recommended smartphone-ready mode so the script configures Tailscale Serve and emits an installable HTTPS tailnet URL. If automatic HTTPS setup does not complete on this machine, it falls back to a Tailscale-direct URL instead of hanging. The opened PC page is preloaded so the smartphone QR is ready immediately. If Tailscale Serve has not been enabled on the tailnet yet, the command now points you at the stable Tailscale DNS settings page and keeps the direct tailnet URL available until you enable HTTPS Certificates there and rerun the same command:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/start-web-ui.ps1 -PhoneReadyStart it without automatically opening a desktop browser:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/start-web-ui.ps1 -NoOpenBrowserStart it with a fixed access code so a phone can reconnect later:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/start-web-ui.ps1 -ListenHost 0.0.0.0 -Port 3360 -AuthToken "replace-with-your-code"Start it with a phone-facing HTTPS/Tailscale URL so the browser app can render a reconnect QR and copyable one-tap link:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/start-web-ui.ps1 -ListenHost 0.0.0.0 -Port 3360 -PublicUrl "https://agent-hub.example.ts.net"Start it with an explicit Tailscale Serve-backed HTTPS URL by using the CLI flag directly:
workspace-agent-hub web-ui --tailscale-serve --auth-token auto --no-open-browserStart it through the CLI directly:
workspace-agent-hub web-ui --host 127.0.0.1 --port 3360 --auth-token autoPrint one JSON object with the listening URL, preferred connect URL, access code, and one-tap pairing link for automation or launcher integration:
workspace-agent-hub web-ui --host 127.0.0.1 --port 3360 --auth-token auto --json --no-open-browserThe PowerShell wrapper exposes the same behavior with -JsonOutput:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/start-web-ui.ps1 -JsonOutput -NoOpenBrowserWrapper-specific parameters that differ from the CLI:
| Parameter | Description | Example |
| -------------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| -ListenHost <host> | PowerShell-safe equivalent of the CLI --host option. | powershell -NoProfile -ExecutionPolicy Bypass -File scripts/start-web-ui.ps1 -ListenHost 0.0.0.0 |
| -PhoneReady | PowerShell shortcut for --tailscale-serve plus the normal wrapper defaults. | powershell -NoProfile -ExecutionPolicy Bypass -File scripts/start-web-ui.ps1 -PhoneReady -NoOpenBrowser |
| -JsonOutput | PowerShell wrapper switch for CLI --json. | powershell -NoProfile -ExecutionPolicy Bypass -File scripts/start-web-ui.ps1 -JsonOutput -NoOpenBrowser |
| -NoOpenBrowser | PowerShell wrapper switch for CLI --no-open-browser. | powershell -NoProfile -ExecutionPolicy Bypass -File scripts/start-web-ui.ps1 -NoOpenBrowser |
CLI parameters
workspace-agent-hub web-ui supports these parameters:
| Parameter | Description | Example |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| --host <host> | Host/IP to bind. Use 127.0.0.1 for local-only access or 0.0.0.0 when another device reaches the PC through Tailscale or another trusted network path. | workspace-agent-hub web-ui --host 0.0.0.0 |
| --port <port> | Preferred port. If already taken, the server walks upward to the next free port. | workspace-agent-hub web-ui --port 3360 |
| --public-url <url> | Phone-facing URL used for reconnect links and QR pairing. Point this at Tailscale Serve or another trusted HTTPS reverse proxy when using the PWA from a phone. | workspace-agent-hub web-ui --public-url https://agent-hub.example.ts.net |
| --tailscale-serve | Configure Tailscale Serve for this run and prefer the resulting HTTPS tailnet URL. Useful for the normal smartphone/PWA path when the PC is already on Tailscale. | workspace-agent-hub web-ui --tailscale-serve |
| --auth-token <token> | Access code for API/browser auth. Use auto to generate one, or none only on a trusted local machine. | workspace-agent-hub web-ui --auth-token auto |
| --json | Print a single JSON object describing the live web UI endpoint, connect URL, access code, and pairing link. | workspace-agent-hub web-ui --json --no-open-browser |
| --no-open-browser | Start the server without opening the default desktop browser. | workspace-agent-hub web-ui --no-open-browser |
End-to-end example:
workspace-agent-hub web-ui --host 0.0.0.0 --port 3360 --auth-token auto --no-open-browserFirst-use flow:
- Start the web UI on the PC.
- Let the local PC page open and show the pairing card.
- Scan the pairing QR from the phone. Treat the printed link and copy/share controls as fallback only when scanning is not available.
- If the terminal or secure-launch card tells you to open the Tailscale DNS settings page, open it once on the PC, enable HTTPS Certificates there, and rerun the same
-PhoneReadycommand to upgrade the path to HTTPS. - If the page is served over HTTPS, use the install card to add it to the home screen.
- Start or reopen a session, then use the transcript and prompt box from the same page.
- If needed, enable browser notifications or use the device-lock button to clear the saved access code on that browser.
- Use the session search box, browser-local favorites, the remembered last-session card, and saved prompt drafts to jump back into the same work quickly on that device.
Browser/mobile handoff state matrix
The browser app carries auth state in localStorage. The claimed primary paths
and their token-source precedence rules are:
| State | localStorage token | URL hash #accessCode= | Auth source | QR / app result |
| ------------------- | ------------------------ | ------------------------ | --------------------------------- | -------------------------------------------------- |
| Fresh | absent | present | URL hash → stored to localStorage | Token stored, QR rendered |
| Fresh | absent | absent | none | Auth overlay shown; user must enter code |
| Resumed | present and valid | absent | localStorage | QR rendered; no re-auth needed |
| Stale + hash | present (old server run) | present (new server run) | URL hash overrides localStorage | New token stored, old token discarded, QR rendered |
| Stale (no hash) | present (old server run) | absent | localStorage (rejected by server) | API returns 401 → auth overlay shown |
The server embeds the current access code in the browser-open URL on every start, so the URL hash always takes precedence over any cached localStorage value. This ensures that a phone opening the browser-open URL after a server restart always gets the correct token, even if an older token is still cached in that browser.
Automated tests in src/__tests__/web-app-dom.test.ts cover all five rows of
this matrix.
Installable/PWA note:
- The browser app registers a service worker on normal HTTP for local caching, but installable PWA mode requires a secure context.
- The intended secure path is to front the local web UI with Tailscale Serve or another HTTPS-capable reverse proxy.
- When the network drops, the app keeps showing the last cached session list and transcript until connectivity returns.
- The browser UI can optionally notify on selected-session output while the page is hidden, and it can clear the saved browser-side access code/cache with the device-lock control.
- When Tailscale is available, the launcher can emit a tailnet-direct reconnect
URL automatically, and
--tailscale-serve/-PhoneReadyupgrades that path to an installable HTTPS tailnet URL in the same run. - The session list supports browser-local favorites plus title/folder/preview search, so a phone can pin the sessions it reopens most often without changing the shared backend catalog.
- The browser remembers the last reopened session on that device, preserves unsent prompt drafts per session, and marks sessions with unseen output based on browser-local seen activity.
- When
--public-urlis provided, the browser app treats the QR as the primary smartphone entry path, while the share action and one-tap reconnect link stay available as fallback. - When
--tailscale-serveor-PhoneReadyhits a tailnet where Serve is not enabled yet, the launcher points you at the stable Tailscale DNS settings page and the browser UI shows the same next step so you can finish HTTPS approval without guessing why the upgrade did not happen.
Open Manager
Workspace Agent Hub now provides the official Open Manager entrypoint in the
browser UI.
How it works:
- Open the normal Hub page from the PC or smartphone.
- Use
Manager を開く. - The browser opens Hub's native
/manager/page on the same origin. - The Manager page reads and writes the workspace
.threads.jsonland.tasks.jsonlfiles directly through Hub's own API. - The built-in manager backend starts inside Hub when the user presses
起動するon the Manager page, then keeps handling inbox messages for that workspace.
Important behavior:
- The same Hub access code protects the smartphone/desktop Manager path.
- There is no separate
manager-guiprocess or second GUI server anymore. Open Manageris now a direct navigation path to Hub's own Manager page.- Thread storage remains compatible with
thread-inboxdata files, but the higher-level Manager GUI now belongs toworkspace-agent-hub.
Verification
Lint:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/lint.ps1Node-layer verify only:
npm run verifyReal-browser web UI verification only:
npm run test:e2eFull local test suite:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/test.ps1Add the Android emulator path:
$env:WORKSPACE_AGENT_HUB_RUN_ANDROID_MOBILE_E2E='1'; powershell -NoProfile -ExecutionPolicy Bypass -File scripts/test.ps1Regenerate agent rules:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/build.ps1Primary path matrix
This repository claims the following primary handoff paths.
| Path | Claimed behavior | Automated evidence |
| ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| P1 | PC-side launcher flow can create a session, surface it in the inventory, and resolve it again for reopening. | scripts/test-primary-path-matrix.ps1 |
| P2 | A session started from the PC side can be reopened from the mobile SSH menu. | scripts/test-mobile-ssh.py |
| P3 | A session started from the mobile SSH menu becomes visible and reopenable from the PC-side launcher flow. | scripts/test-mobile-ssh.py |
| P4 | When multiple sessions exist, the user can distinguish and reopen the intended one by title/folder. | scripts/test-primary-path-matrix.ps1 and scripts/test-mobile-ssh.py |
| P5 | The browser UI can authenticate, list sessions, start a session, restore the remembered last session plus saved prompt drafts, mark sessions with unseen output, display transcript output, search/prioritize browser-local favorite sessions, surface install/offline/notification guidance, expose Tailscale-aware secure-launch hints, render QR/copyable smartphone pairing links, locally lock the current browser, and manage archive/close/delete flows. | e2e/web-ui.spec.ts, src/__tests__/web-ui.test.ts, src/__tests__/web-app-dom.test.ts, scripts/test-web-session-bridge.ps1 |
| P6 | Open Manager opens Hub's native /manager/ page on the same authenticated origin, and that page can read/write workspace threads, show active tasks, and start/use the built-in manager backend for both desktop and smartphone-oriented browser entry paths. | src/__tests__/web-ui.test.ts, src/__tests__/web-app-dom.test.ts |
Environment variables
WORKSPACE_AGENT_HUB_RUN_ANDROID_MOBILE_E2E=1Runs the Android emulator + ConnectBot coverage path duringscripts/test.ps1.AI_AGENT_SESSION_CATALOG_PATHOverrides the session catalog file used by the mobile menu.WORKSPACE_AGENT_HUB_WEB_UI_AUTH_TOKENOptional environment override for the browser UI access code when a wrapper or service manager wants to inject one.WORKSPACE_AGENT_HUB_WEB_UI_PUBLIC_URLOptional phone-facing URL used for the reconnect QR and one-tap pairing link.AI_AGENT_SESSION_NO_ATTACH=1Keeps the mobile menu tests from attaching the current shell to the created session.AI_AGENT_MOBILE_BYPASS=1Prevents the login bootstrap from opening the mobile menu automatically.
Release / deploy
Release the package and create the matching GitHub release:
$version = '0.2.1'
npm version $version --no-git-tag-version
npm run verify
git push origin main
git tag v$version
git push origin v$version
gh release create v$version --repo metyatech/workspace-agent-hub --title v$version --notes "See CHANGELOG.md"
npm publishVerify the published package resolves and runs:
npm view @metyatech/workspace-agent-hub version
npm exec --yes --package @metyatech/workspace-agent-hub@latest workspace-agent-hub -- --version