Skip to content
    ↑↓ select↵ openesc close
    lesquel

    Pilot

    @lesquel/opencode-pilot·v1.23.1·Notifications

    Remote control web dashboard for OpenCode — multi-project tabs, live SSE streaming, mobile-friendly, push/Telegram notifications, tunnel for phone access from anywhere.

    GitHub stars

    10

    +4 in 30 days

    Monthly installs

    399

    71 in 7 days

    Composite score

    49.0

    Multi-signal model

    Last commit

    20 hours ago

    2026-10-04

    Install and configure

    opencode.json

    Writes to this project's opencode.json — applies to this repository only.

    opencode.json

    {
      "$schema": "https://opencode.ai/config.json",
      "plugin": ["@lesquel/opencode-pilot@1.23.1"]
    }

    OpenCode loads npm dependencies through its embedded runtime on startup and caches them locally — no manual global install needed.

    Remote control plugin for OpenCode and Codex CLI — monitor sessions, send prompts, approve permissions, switch agents, and get notifications from your phone or any browser.

    npm version npm downloads License: MIT GitHub stars


    What it does

    Spin up OpenCode locally, get a web dashboard you can open on your laptop or phone. From the dashboard you can:

    • See all your sessions across all your projects (multi-project tabs)
    • Send prompts and watch responses stream live
    • Approve / deny tool permissions remotely
    • Switch agents (build / plan / general / explore) per session
    • Track cost per session, per day, per week
    • Get sound, browser, push, and Telegram notifications when an agent finishes
    • Pin TODOs that survive across sessions
    • Diff view of all files changed
    • File browser with live filter
    • Connect from your phone via QR code (LAN or public tunnel)
    • Monitor Codex CLI sessions too via the /codex/hooks/:event HTTP bridge — same dashboard, same notifications, same permission flow (see docs/CODEX-INTEGRATION.md)

    All from one keyboard shortcut (? opens the command palette).

    Pilot or OpenCode's built-in web UI?

    OpenCode already ships an excellent full browser client through opencode web. Use it when you want the complete OpenCode experience in a browser. Pilot is a local-first operations companion that loads alongside your normal TUI: it is optimized for quick phone control, permission approvals, attention and notifications, multi-project monitoring, and a shared command center for OpenCode plus Codex CLI. Both can be useful, and Pilot does not replace or disable the built-in UI.


    Install once, use everywhere

    opencode-pilot installs globally into your OpenCode config dir (~/.config/opencode on Linux/macOS, %APPDATA%\opencode on Windows). One install and the plugin auto-loads every time you run opencode from any project directory — no per-project setup, no .opencode/ folders to copy around, no duplicate configs.

    That's the whole point of running the installer: drop it in once, then just use opencode normally and the dashboard is always there.

    Quick Start

    One command (recommended)

    npx @lesquel/opencode-pilot init
    # or
    bunx @lesquel/opencode-pilot init
    

    That's it. The installer:

    1. Locates your OpenCode config dir (~/.config/opencode or your XDG path / %APPDATA%).
    2. Installs the plugin there (@lesquel/opencode-pilot@latest + @opencode-ai/plugin@latest).
    3. Adds "@lesquel/opencode-pilot@latest" to both opencode.json::plugin (for the dashboard server) and tui.json::plugin (for the slash commands). OpenCode uses two separate plugin loaders — one file each.
    4. Cleans up stale wrappers, cache entries, and legacy subpath specs left by earlier (<=1.12.x) installs.

    Fully close any running OpenCode sessions and reopen. A toast should appear:

    OpenCode Pilot — Remote control plugin loaded. Use /pilot or /pilot-token.

    The banner also prints in the terminal with URL + token + QR. If the toast doesn't appear, see Troubleshooting.

    Configuration is done from the dashboard (gear icon → Plugin configuration). You do NOT need to create a .env — though you still can if you prefer.

    Manual install (if you want to)

    # 1. Install in your OpenCode config dir
    cd ~/.config/opencode    # or your XDG_CONFIG_HOME path
    bun add @lesquel/opencode-pilot@latest @opencode-ai/plugin@latest
    
    # 2. Add the spec to BOTH config files:
    #
    #    opencode.json  — registers the dashboard server plugin:
    #    {
    #      "plugin": ["@lesquel/opencode-pilot@latest"]
    #    }
    #
    #    tui.json  — registers the slash commands (create this file if missing):
    #    {
    #      "$schema": "https://opencode.ai/tui.json",
    #      "plugin": ["@lesquel/opencode-pilot@latest"]
    #    }
    

    OpenCode runs two separate plugin loaders: the server loader reads opencode.json::plugin (for server() exports like the dashboard), and the TUI loader reads tui.json::plugin (for tui() exports like slash commands). A spec in only one of them gets you half the plugin. Do not add wrappers in <config>/plugins/ — they conflict with the server loader's strict validation.

    Run opencode from any project directory. Banner prints with URL + token + QR.

    Uninstall

    Fully quit OpenCode, then run:

    npx @lesquel/opencode-pilot uninstall
    # or: bunx @lesquel/opencode-pilot uninstall
    

    The uninstaller removes only Pilot's plugin registrations, installed package, cache entries, legacy wrappers, and local runtime state. Add --keep-config to preserve ~/.opencode-pilot/config.json for a future reinstall. It never edits your source projects. Browser-local tokens and the PWA service worker must be cleared separately from the browser's site-data settings; the command prints those final steps.


    Going deeper? docs/INSTALL.md explains OpenCode's two-loader plugin architecture, documents every gotcha we hit, and has a complete troubleshooting matrix. Read it if you're debugging, contributing, or publishing your own OpenCode plugin.

    How to use it day-to-day

    Once installed and OpenCode restarted, you have four entry points:

    1. Slash commands from inside OpenCode TUI

    Type any of these at the prompt:

    Command What it does
    /pilot Show the current dashboard URL + token
    /pilot-token Rotate the auth token (invalidates any open dashboards/phones)
    /dashboard Same as /pilot — alias
    /remote Print connection info (host, port, tunnel URL if active)
    /remote-control Full status block with all the above plus QR hint

    2. Terminal banner at startup

    Every opencode launch prints a banner with the dashboard URL, a token, and a QR code. Open the URL in any browser on the same machine, or scan the QR with your phone (requires PILOT_HOST=0.0.0.0 for LAN — see below).

    3. The web dashboard itself

    Open the URL. Then:

    • ? opens the command palette — every action is reachable from there.
    • Left sidebar: sessions grouped by folder. Click one to switch. + creates a new session.
    • Center pane: the live transcript — user messages appear instantly, the assistant's response streams token by token, tool calls animate pending → running → completed with their inputs and outputs expandable inline.
    • Right panel: context usage, MCP servers, LSP status, project path, pinned TODOs.
    • Tabs at the top: open multiple projects in parallel (v1.11+).
    • Gear icon (⚙): Settings UI — change port/host, enable tunnel, wire up Telegram bot, generate VAPID keys for Web Push. Everything is editable from here; you rarely need to touch .env files anymore.

    4. From your phone

    See Connect from your phone below. Either same-WiFi (LAN) with PILOT_HOST=0.0.0.0, or anywhere with a Cloudflare / ngrok tunnel. The dashboard is mobile-friendly — bottom-sheet modals, 44px tap targets, swipe-to-close. Permissions approvals, prompt sending, session switching all work from the phone.

    Troubleshooting — slash commands don't appear

    Other symptoms (port conflicts, /remote says "server not running", dashboard 401s, push/telegram silent, wrong tab opens) are covered in docs/TROUBLESHOOTING.md. This section is specifically about the "I installed it but slash commands are missing" case.

    If the plugin loads (you see the banner in the terminal) but typing /remo<Tab> in the TUI doesn't autocomplete /remote, /dashboard, /pilot, /pilot-token, or /remote-control:

    1. Check the canary toast. On startup the TUI should toast "OpenCode Pilot — Remote control plugin loaded". No toast → the TUI plugin didn't register, even if the dashboard server did.

    2. Inspect the latest log:

      tail -200 $(ls -t ~/.local/share/opencode/log/*.log | head -1) | grep -iE "pilot|tui.plugin|error"
      
      • Windows: %LOCALAPPDATA%\opencode\log\<timestamp>.log
      • macOS: ~/Library/Logs/opencode/<timestamp>.log
    3. Re-run init. It cleans up stale wrappers and stale subpath entries left behind by 1.11.x–1.12.x:

      npx @lesquel/opencode-pilot@latest init
      

      Then fully close all OpenCode sessions (the plugin loader is cached per running process) and reopen.

    4. Verify BOTH opencode.json::plugin AND tui.json::plugin each have exactly one entry for the pilot:

      "plugin": ["@lesquel/opencode-pilot@latest"]
      

      If tui.json is missing entirely, the TUI plugin was never registered and slash commands never appear — init in 1.13.1+ creates this file. If you see "@lesquel/opencode-pilot/tui" anywhere or wrapper paths in the array, the old install pattern got in — npx init in step 3 fixes that.

    5. Verify no stale wrappers in ~/.config/opencode/plugins/. Safe to delete: opencode-pilot.ts, opencode-pilot-tui.ts. These were auto-generated by 1.11.x–1.12.x and are no longer needed. init does this cleanup automatically.


    Connect from your phone

    Same WiFi (LAN access)

    1. Set PILOT_HOST=0.0.0.0 in .env
    2. Restart OpenCode
    3. Click the phone icon in the dashboard header (c shortcut)
    4. Scan the QR from the "Local network" tab with your phone camera
    5. Done — same dashboard, on your phone

    Anywhere (public tunnel)

    1. Install cloudflared (brew install cloudflared on Mac)
    2. Add PILOT_TUNNEL=cloudflared to your .env
    3. Restart OpenCode — it spawns the tunnel automatically
    4. Phone modal "Public tunnel" tab now has a QR with a public HTTPS URL
    5. Works from cellular, hotel WiFi, anywhere

    🔐 Security note: the tunnel URL contains your token. Treat it like a password. See docs/TUNNEL_TESTING.md for security checklist.


    Features

    Dashboard

    • Sessions sidebar with folder grouping and agent filter
    • Multi-view to watch multiple sessions side-by-side (desktop only)
    • Project tabs at the top — open multiple projects in parallel
    • Right info panel with Context, MCP servers, LSP clients, project path, instance version
    • Pinned TODOs survive across sessions and project switches
    • Cost panel with per-session, daily, and weekly totals + budget alerts
    • Diff tab showing all files changed in current session

    Notifications

    Type Trigger Setup
    Sound Page hidden + assistant turn complete Toggle in Settings
    Browser notification Page hidden + permission granted Toggle, allow when prompted
    Push (Web Push) Anywhere, even browser closed VAPID keys in .env (guide)
    Telegram Permission requests + completions Bot token in .env

    Mobile-friendly

    • Drawer sidebar with backdrop
    • Full-screen modals
    • Multi-view auto-hidden (use desktop for split view)
    • Right panel as bottom toggle
    • Live filter on file browser
    • 44×44 touch targets everywhere

    Keyboard shortcuts

    Single-key (when no input focused):

    Key Action
    ? Open command palette + show shortcuts
    n New session
    s Toggle sidebar
    m Toggle multi-view (desktop only)
    t Toggle theme
    c Connect from phone modal
    / Focus prompt input
    Esc Close modal/picker/palette

    Modifier:

    Key Action
    Cmd/Ctrl+K Command palette
    Cmd/Ctrl+Enter Send prompt
    Alt+I Toggle right info panel

    Configuration — two ways

    Since v1.12 you can configure the plugin two ways (or both):

    Easy: the Settings UI

    1. Open the dashboard
    2. Click the gear icon (⚙) in the header
    3. Go to Plugin configuration
    4. Edit port, host, tunnel, Telegram token, VAPID keys, permission timeout, and the glob opener toggle
    5. Click Save — values are written to ~/.opencode-pilot/config.json and survive restarts

    Some fields (port, host, tunnel, VAPID keys) require an OpenCode restart to take effect — the UI shows an inline warning for those. A Generate VAPID keys button calls the server to create a key pair in one click.

    Each field shows a small badge telling you where its current value comes from: saved (UI), .env, shell, or default. Fields set via shell env vars are locked from the UI — you must unset the shell var to override.

    Power user: .env file

    Full env-var reference with example .env files for common scenarios lives in docs/CONFIGURATION.md. Quick overview:

    Variable Default What
    PILOT_PORT 4097 HTTP server port
    PILOT_HOST 127.0.0.1 Bind address (0.0.0.0 for LAN)
    PILOT_TUNNEL (off) cloudflared or ngrok for public access
    PILOT_PERMISSION_TIMEOUT 300000 Permission-request timeout in ms
    PILOT_TELEGRAM_TOKEN (off) Telegram bot token from @BotFather
    PILOT_TELEGRAM_CHAT_ID (off) Your Telegram chat ID
    PILOT_VAPID_PUBLIC_KEY (off) Web Push public key (bunx web-push generate-vapid-keys)
    PILOT_VAPID_PRIVATE_KEY (off) Web Push private key
    PILOT_ENABLE_GLOB_OPENER false Enable /fs/glob for the dashboard's glob search
    PILOT_FETCH_TIMEOUT_MS 10000 Timeout for outbound HTTP calls (Telegram, push)

    Priority (highest wins)

    1. Shell env vars                         e.g. PILOT_PORT=5000 opencode
    2. ~/.opencode-pilot/config.json          written by the Settings UI
    3. .env file (process.cwd or plugin dir)  power-user file-based config
    4. Hardcoded defaults                     fallback
    

    The .env file is searched in: (1) process.cwd()/.env then (2) the plugin's install dir. Shell env vars always win over both .env and the Settings UI.


    Documentation

    Pilot is local-first and has no telemetry by default. Read where data goes and the threat model before exposing it through a LAN or tunnel.

    For users

    For contributors and AI agents


    Architecture (one line)

    The plugin runs ONE HTTP+SSE server inside your OpenCode process. The dashboard is a vanilla ES-modules SPA served from the same origin. All API calls go through the SDK with ?directory= for multi-project routing.

    If you want the deep version, see the docs/ folder.


    Tech stack

    • Server: Bun + TypeScript (strict)
    • Dashboard: vanilla ES modules, plain CSS, ~9000 LOC. No React, no build step.
    • Optional deps: cloudflared / ngrok (tunnel), @modelcontextprotocol/sdk (MCP), web-push (push notifications)
    • Tests: 228 (Bun test runner), all green

    Contributing

    Issues are welcome. Pull requests are welcome only after maintainer approval.

    Please start with an issue first: bug report, feature request, or discussion. The maintainer will triage it and either:

    • fix it directly and comment on the issue,
    • ask you to send a PR, or
    • close it as out of scope / duplicate / needs more information.

    Read CONTRIBUTING.md for the full issue-first workflow, PR rules, review expectations, contributor credit, and local development setup.

    Maintainer notes for contributors:

    • One PR per approved issue.
    • Keep PRs small and reviewable.
    • Add tests for behavior changes.
    • Do not bump versions, edit CHANGELOG.md, or publish releases.
    • Follow AGENTS.md for codebase conventions: no any, no server console.log, factory functions, release safety rules.

    Security reports are private: see SECURITY.md. Community expectations are in CODE_OF_CONDUCT.md.

    Shipping a new version is maintainer-only: follow docs/RELEASE.md. Pushing a vX.Y.Z tag is the only supported way to publish.


    License

    MIT © lesquel

    Similar plugins