juxtapoandClaude Opus 5 f8ef6e6981 cc-sidepanel: emoji picker, 475 glyphs from celest-chat's table
The panel had no picker before this. 8 category tabs plus a recents tab, table
lifted verbatim from celest-chat's 07-emoji.js so the house row (💜🌙🐝🔫)
carries over. Offline by construction: no library, no fetch, the panel's CSP
would block a set anyway.

Inserts at the caret rather than appending, and the pad stays open so glyphs can
be stacked. Recents (last 24) live in localStorage under
`ccsidepanel-emoji-recent`; the pad opens on that tab once it has entries.

`#emoji-pad[hidden] { display: none }` is spelled out because an ID selector
outranks the UA's `[hidden]` rule — without it the pad never closes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-13 02:02:25 +08:00

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.

S
Description
No description provided
Readme
3 MiB
Languages
JavaScript 60.1%
HTML 22.8%
Python 17.1%