Files

2.0 KiB

CC Sidepanel

A Brave/Chrome MV3 side-panel extension that puts a live Claude Code seat in your browser sidebar — type in the sidebar, it lands in the real terminal pane. Two-way.

Built by Monica (bridge + extension skeleton), parser and styling pass by Selene, 2026-09-11.

Pieces

  • bridge.py — a localhost HTTP shim on :8988. Browser extensions can't reach a unix socket, so this proxies JSON to injectd.py's socket at /tmp/injectd.sock (ops: seats, screen, inject). CORS is locked to one chrome-extension:// origin — no wildcard.
  • extension/ — MV3 side panel. Polls /screen every 1.5s, parses the raw kitty pane into typed blocks (user / assistant / tool / thinking / live-heartbeat / meta), and sends text back via /inject.

Dependencies / pre-reqs

  • injectd.py is house infrastructure, not part of this repo. The bridge expects the socket /tmp/injectd.sock to already exist (created by injectd, which runs separately and is shared by every seat).
  • The extension ID is deliberately not in the code. bridge.py reads CCSIDEPANEL_EXT_ID from the environment and refuses to start if it's unset (no silent fallback).

Setup

  1. Load the extension unpacked from extension/ at brave://extensions.

  2. Copy its ID from the brave://extensions page.

  3. Create the env file:

    cp cc-sidepanel.env.example /etc/cc-sidepanel.env
    # fill in CCSIDEPANEL_EXT_ID=<your-id>
    
  4. Start/restart the bridge:

    systemctl restart cc-sidepanel-bridge   # unit: /etc/systemd/system/cc-sidepanel-bridge.service
    

    The systemd unit runs as juxtapo and reads config via EnvironmentFile=/etc/cc-sidepanel.env — both files live outside the repo (documented here, not committed).

Gotcha: reloading = new ID

Reloading the extension from a different path gives it a new ID, and the panel gets CORS-blocked with no visible error. If the panel stops working after a reload, copy the new ID, update /etc/cc-sidepanel.env, and restart the unit.

License

House project — MIT.