Skip to content

vighriday/Pulse

⚡ Pulse

Remote Orchestration & Mobile Command Center for Claude Code

A lightweight orchestration layer that turns any phone into a remote command & control surface for long-running Claude Code sessions — built to accelerate multi-agent development workflows.

Works with both Claude Code surfaces: the claude CLI (stream-json mode) and the Claude Code VS Code extension (hook-based ingress). A single mobile app drives either, or both at once.

License: MIT Node Python Claude Code MCP PRs Welcome


The Problem

While architecting a 460K+ LOC trading infrastructure, I was leaning heavily on Anthropic's Claude Code CLI for long-running, multi-step engineering tasks. Before first-party remote execution support landed, the workflow had a real bottleneck:

  • Tasks ran for 10+ minutes; you had to sit at the terminal.
  • No programmatic way to nudge an in-flight session from elsewhere.
  • SSH/VNC is a poor mobile UX. Cloud sandboxes move code off-machine.
  • "Approve this tool call?" prompts blocked everything if you stepped away.

I wanted to step away from the laptop — to the gym, a call, or another screen — without either babysitting the agent or giving up steering control.

The Solution

Pulse is an opinionated orchestration layer that wraps Claude Code and fans its lifecycle events out to a mobile-first control surface in real time. It splits the workload across three tiers:

Tier Role Stack
Observer Hooks into Claude Code, parses events, streams output. Python 3.10+ · pexpect · pyte
Relay Stateless WebSocket bus. Buffers on disconnect, gates approvals. Node.js 18+ · Express · Socket.IO
Commander Mobile PWA. Heatmap, decision cards, voice input, config panel. React 18 · Three.js · Framer Motion
MCP Bridge MCP server the Claude Code IDE calls to check a mobile inbox. Node.js 18+ · @modelcontextprotocol/sdk

Concretely, Pulse gives you:

  • Automated remote execution — start, steer, and resume sessions from any device on the same relay.
  • Environment & session state tracking — cost, turns, tokens, model, approvals, and file activity captured per session.
  • Structured conversation mirror — human prompts, tool use, tool results, and assistant text replayed on reconnect (5-minute buffer).
  • Hook-mediated approvalsPreToolUse blocks the CLI until mobile approves/denies, driven entirely by Claude Code's native hook system.
  • Bidirectional messaging — the MCP bridge exposes a tool surface for Claude to read mobile-sent messages mid-session.

Architecture

┌──────────────────────────────────────────────────────────────┐
│                        LAPTOP (local)                        │
│  ┌──────────────┐   ┌──────────────────┐   ┌──────────────┐  │
│  │  Claude Code │──▶│  Observer (CLI)  │   │ MCP Bridge   │  │
│  │     CLI      │   │  + Hook Handler  │   │  (stdio)     │  │
│  └──────────────┘   └────────┬─────────┘   └──────┬───────┘  │
└─────────────────────────────┬┴─────────────────────┴─────────┘
                              │ HTTP + WebSocket (Socket.IO)
                              ▼
┌──────────────────────────────────────────────────────────────┐
│                     RELAY (any host)                         │
│   Stateless pipe · Session registry · 5-min replay buffer    │
│   REST: /api/sessions · /api/hook · /api/inbox · /api/approval
│   WS:   observer:* · commander:* · approval:* · conversation │
└──────────────────────────────────────────────────────────────┘
                              ▲
                              │ HTTPS + WebSocket
                              │
┌──────────────────────────────────────────────────────────────┐
│                  COMMANDER (mobile PWA)                      │
│  Heatmap · Decision Cards · Voice Input · Config · E-Stop    │
└──────────────────────────────────────────────────────────────┘

Two ingestion paths feed the same session model — pick whichever matches your surface; the commander treats both identically:

  1. CLI Observer — for the claude CLI. A Python process spawns claude --output-format stream-json, parses the stream, and forwards structured events to the relay over WebSocket. Best for headless runs, full cost tracking, and --resume follow-up tasks.
  2. Hook-Observed IDE Session — for the Claude Code VS Code extension (and any other Claude Code surface that fires hooks). Claude Code's lifecycle hooks (SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, Notification, Stop, SessionEnd) POST to /api/hook; Pulse auto-creates a session keyed on claudeSessionId. The MCP bridge gives Claude a first-class tool surface to drain the mobile inbox mid-turn. No CLI wrapping required.

Quick Start

Prerequisites

  • Node.js 18+, Python 3.10+
  • At least one of:
    • claude CLI — npm i -g @anthropic-ai/claude-code (or invoke via npx)
    • Claude Code VS Code extension — install from the VS Code Marketplace and sign in (hooks fire automatically once Pulse is registered)
  • A host reachable by both your laptop and your phone (localhost on the same Wi-Fi works; see Deployment for remote setups)

1 · Start the Relay

cd relay
npm install
cp .env.example .env        # adjust PORT / AUTH_TOKEN if needed
npm start
# → http://localhost:3001

2 · Install Hooks + MCP Bridge

python setup.py             # registers hooks + MCP server in ~/.claude/settings.json

Inspect with python setup.py --verify. Uninstall cleanly with python setup.py --remove.

3 · Launch the Commander PWA

cd commander
npm install
cp .env.example .env        # point REACT_APP_RELAY_URL at your relay
npm start                   # http://localhost:3000

On your phone, navigate to http://<laptop-ip>:3000 and Add to Home Screen to install the PWA.

4 · Run a Session

Pulse supports both Claude Code surfaces. Pick whichever you use.

A. VS Code extension (recommended for most users)

Open any project in VS Code, open the Claude Code panel, and start a turn. The SessionStart hook fires automatically and the session appears on the commander within a second. No additional commands — just code.

B. claude CLI (headless / scripted runs)

cd observer
pip install -r requirements.txt
python sidecar.py start "Refactor the authentication module"

The relay ID prints to the terminal. Tap it on your phone to take over.

You can mix both: a long-running CLI refactor and an ad-hoc VS Code session will appear side-by-side on the commander's session list.


Configuration

All components read from environment variables. See each component's .env.example for the full list.

Variable Component Default Purpose
PORT relay 3001 HTTP/WS port
ALLOWED_ORIGINS relay * CORS allowlist (comma-separated)
REQUIRE_AUTH relay false Gate connections with AUTH_TOKEN
AUTH_TOKEN relay Shared secret (observer ↔ relay)
SIDECAR_RELAY_URL observer http://localhost:3001 Where the observer/hooks send events
SIDECAR_AUTH_TOKEN observer Must match relay AUTH_TOKEN when auth is on
SIDECAR_APPROVAL_TIMEOUT observer 300 Seconds a PreToolUse hook waits for mobile
REACT_APP_RELAY_URL commander http://localhost:3001 Relay URL consumed by the PWA

Note on env var names. SIDECAR_* prefixes are preserved for backward compatibility with existing settings.json hook installations. They refer to the same Pulse relay — renaming is a planned breaking change for v2.


Mobile UX

The Commander PWA ships with four distinct surfaces:

  • Heatmap — live file-tree with activity coloring (green = created, amber = edited, red = deleted), access count badges, and a cool-to-hot recency gradient.
  • Decision Cards — one card per pending approval. Swipe right to approve, left to deny, long-press to attach a voice note. State-version checks prevent stale approvals if the laptop has moved on.
  • Conversation — structured thread mirroring the Claude session: human prompts, tool calls with collapsible previews, tool results, assistant text, and end-of-task summary cards with cost/turns/files/commands.
  • Config Panel — model (Opus/Sonnet/Haiku), permission mode, max turns, max budget, per-tool allow/deny, system prompt append — all applied on the next task without killing the session.

A single large red Emergency Stop is pinned across every screen; tapping it SIGINTs the active process and flips the session to stopped.


API Surface

The relay exposes a REST + WebSocket API that is stable for the lifetime of a session. Full reference: docs/API.md.

REST (selected)

GET  /health                         server health
GET  /api/sessions                   list active sessions
POST /api/sessions                   create session
POST /api/sessions/:id/approve       approve/deny a pending tool
POST /api/sessions/:id/config        push config patch to observer
POST /api/sessions/:id/stop          emergency stop
POST /api/hook                       unified hook ingress
GET  /api/approval/:id               poll approval (used by hook)
GET  /api/inbox/:sessionId           MCP reads & drains mobile inbox
POST /api/inbox/:sessionId           queue message for MCP pickup

WebSocket (selected)

Direction Event Purpose
Observer → Relay observer:register Bind a CLI observer to a session
Observer → Relay observer:event File/tool lifecycle event
Observer → Relay observer:conversation_message Structured chat message
Observer → Relay observer:heartbeat Liveness + cost/turns snapshot
Commander → Relay commander:connect Join session (with replay cursor)
Commander → Relay commander:approve Decide a pending approval
Commander → Relay commander:new_task Follow-up task (uses --resume)
Commander → Relay commander:emergency_stop Kill the active process
Relay → Commander approval:request New decision card
Relay → Commander conversation:message Append to thread
Relay → Commander session:state Full snapshot on (re)connect
Relay → Commander session:replay Buffered catch-up after reconnect

Repository Layout

Pulse/
├── commander/         React PWA (mobile command center)
├── relay/             Node/Express + Socket.IO relay server
├── observer/          Python CLI wrapper + Claude Code hook handler
│   └── hooks/         `sidecar_hook.py` — dispatched by Claude Code hooks
├── mcp-bridge/        MCP stdio server bridging Claude Code ↔ relay inbox
├── docs/              Architecture, deployment, API reference
├── docker-compose.yml Single-command relay + commander stack
└── setup.py           Idempotent installer for hooks + MCP registration

Deployment

For production, run the relay behind TLS and set REQUIRE_AUTH=true. A single-command stack is provided:

docker compose up -d        # relay :3001 + commander :3000

See docs/DEPLOYMENT.md for hardening notes, reverse-proxy recipes, and the mobile-PWA install checklist.


Roadmap

  • End-to-end encryption between observer and commander
  • Biometric auth gate for destructive tool calls
  • Time-travel scrubber across buffered state
  • First-class multi-agent fan-out (N sessions, one commander)
  • Optional local-LLM summarizer to compress bandwidth

Contributing

Issues and pull requests are welcome. Please read CONTRIBUTING.md and CODE_OF_CONDUCT.md before opening a PR. Security disclosures: see SECURITY.md.

License

MIT © 2026 Hriday.


Note. Pulse was built internally to accelerate my own architectural workflows on a large trading-infrastructure codebase. It is open-sourced here as a reference for high-velocity prototyping with Claude Code — not as a hosted product. Expect sharp edges on non-happy paths and please file issues when you find them.

About

Pulse is a lightweight mobile command center and remote orchestration layer for Claude Code, built to help developers monitor live sessions, steer tasks, and approve AI tool calls remotely. Development of the original version is currently paused following Claude’s native remote control launch, while an expanded V2 is actively in development.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors