{"id":50780710,"url":"https://github.com/kylefoxaustin/claude-connect","last_synced_at":"2026-06-12T03:02:39.349Z","repository":{"id":359001828,"uuid":"1242946574","full_name":"kylefoxaustin/claude-connect","owner":"kylefoxaustin","description":"A simple way to view claude code sessions in a browser window and pipe data between them","archived":false,"fork":false,"pushed_at":"2026-06-05T17:52:51.000Z","size":408,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-05T18:39:40.772Z","etag":null,"topics":["claude","claude-code","dashboard","developer-tools","python","session-management"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kylefoxaustin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-18T23:02:01.000Z","updated_at":"2026-06-05T17:52:37.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/kylefoxaustin/claude-connect","commit_stats":null,"previous_names":["kylefoxaustin/claude-connect"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/kylefoxaustin/claude-connect","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kylefoxaustin%2Fclaude-connect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kylefoxaustin%2Fclaude-connect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kylefoxaustin%2Fclaude-connect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kylefoxaustin%2Fclaude-connect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kylefoxaustin","download_url":"https://codeload.github.com/kylefoxaustin/claude-connect/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kylefoxaustin%2Fclaude-connect/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34226630,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["claude","claude-code","dashboard","developer-tools","python","session-management"],"created_at":"2026-06-12T03:02:38.458Z","updated_at":"2026-06-12T03:02:39.342Z","avatar_url":"https://github.com/kylefoxaustin.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Claude Connect\n\n**A local dashboard for watching all your Claude Code sessions at once — in your browser or as a standalone desktop app — plus an optional message bus that lets them talk to each other.**\n\n[![version: 2.2](https://img.shields.io/badge/version-2.2-blue)](https://github.com/kylefoxaustin/claude-connect/releases)\n[![platform: linux](https://img.shields.io/badge/platform-linux-orange)](#requirements)\n[![safety: read--only](https://img.shields.io/badge/safety-read--only-green)](#how-it-works)\n\n```\n┌─ ●  api-server ────────────────┐  ┌─ ●  web-app ───────────────────┐\n│ ~/code/api                 📬3 │  │ ~/code/web                     │\n│ ┌──────────────────────────┐   │  │ ┌──────────────────────────┐   │\n│ │ ...running test suite    │   │  │ │ ...waiting on user input │   │\n│ └──────────────────────────┘   │  │ └──────────────────────────┘   │\n│  msgs: 47   ⏱ 2s ago           │  │  msgs: 12   ⏱ 1m ago           │\n└────────────────────────────────┘  └────────────────────────────────┘\n```\n\n\u003e 💡 **Heads up on names:** the repo is `claude-connect`; the dashboard binary is `conductor`. Same project — you'll see both names throughout.\n\n![The 2D dashboard — one tile per Claude session, a central Bus tile, and animated wires showing cross-session traffic (solid = active, dashed = passive).](assets/screenshot-2d.png)\n\n\u003csub\u003eThe classic 2D board: live tiles, status dots, the orange **backend** group, the central **Bus** tile, and connection wires (solid = active, dashed = passive). *Sample data shown.*\u003c/sub\u003e\n\n### …or flip to 3D\n\nNew in **2.2**: a **🧊 3D** button swaps the board into a WebGL scene where your sessions float around a glowing bus core, grouped sessions cluster together, and you orbit/zoom the whole thing. Three layouts — pick by feel:\n\n| Carousel *(default)* | Orbital | Gallery |\n| :---: | :---: | :---: |\n| ![3D carousel layout](assets/screenshot-3d-carousel.png) | ![3D orbital layout](assets/screenshot-3d-orbital.png) | ![3D gallery layout](assets/screenshot-3d-gallery.png) |\n| Spin through sessions; the front card is focused and fully readable. | Sessions orbit the bus core on a sphere; groups share an arc. | Your saved 2D positions, lifted into depth; groups clump together. |\n\n\u003csub\u003eCards always face the camera, so text stays readable at any angle. 2D stays the default — 3D is one click away. *Sample data shown.*\u003c/sub\u003e\n\n---\n\n## Why?\n\nIf you're like us, you're running 3, 4, or 8 Claude Code sessions at once across different projects. You forget which terminal is doing what. You miss when one finishes and goes quiet. You wish they could *coordinate* — \"hey, the API change is in, you can start on the frontend.\"\n\n**Claude Connect solves both problems:**\n\n- **See everything at a glance.** One tile per live Claude session — status dot, live preview of what it's saying, time since last activity. Click a tile to jump to that terminal.\n- **Let your Claudes talk.** Wire up the optional message bus and your sessions can `/msg-send` each other across projects. The dashboard shows the traffic with animated connection lines.\n\nIt's **read-only and local**. It watches Claude's `~/.claude/projects/*.jsonl` logs and process state — it never modifies Claude itself, and it only binds to `127.0.0.1`.\n\n---\n\n## Features\n\n- 🪟 **Live tiles** for every running Claude session — auto-discovered, no config\n- 🎯 **Click-to-focus** — clicking a tile raises the actual terminal window\n- 📬 **Cross-session messaging** with an animated bus tile showing live traffic\n- ✉️ **Compose from the dashboard** — send your own bus message to all sessions or a chosen few, with an optional \"ping\" that makes them read it now\n- 🟢 **Status indicators** — `active` / `warm` / `idle` / `dormant` / `waiting` / `ended`\n- 💾 **Persistent layout** — drag tiles to rearrange and **resize** them (corner grip); both stick\n- 🗕 **Minimize to dock** — tuck rarely-touched sessions into a bottom dock (still live), restore with a click\n- ▦ **Groups** — color-code sessions into named groups; minimize a whole group to one dock chip with a rollup badge\n- 🧊 **3D view** *(new in 2.2)* — flip the whole board into a WebGL scene (Carousel / Orbital / Gallery); grouped sessions cluster in space, cards stay readable, 2D remains the default\n- 🔀 **Active/Passive bus control** — click a tile's tag chip to toggle whether it's auto-notified of bus traffic\n- 🎨 **Themeable** — dark/light, animations, connection-line styling\n- 🔒 **Local only** — `127.0.0.1`, in-memory, restart-clean\n\n---\n\n## Requirements\n\n- **Linux with X11** (Wayland is best-effort)\n- **Python 3.10+**\n- **`wmctrl` and `xdotool`** for terminal focus and `/msg-check` injection\n  - Both optional — without them, the focus and 📬 buttons just no-op\n  - **Tilix users** also get exact-tile focus via `gdbus` (ships with GLib, already present on any GTK desktop) — see [Reliable Terminal Focus](#reliable-terminal-focus)\n- **Native App Edition only:** system WebKitGTK (`python3-gi`, `gir1.2-webkit2-4.0`, `libwebkit2gtk-4.0-37`) — see [Native App Edition](#native-app-edition-ubuntu). The Web Browser Edition needs none of this.\n\n---\n\n## Quick Start\n\n```bash\n# 1. Clone and install\ngit clone https://github.com/kylefoxaustin/claude-connect\ncd claude-connect\npip install -e \".[dev]\"\n\n# 2. Install the OS helpers (recommended)\nsudo apt install wmctrl xdotool\n\n# 3. Copy the example settings\ncp settings.example.toml settings.toml\n\n# 4. Run it\nmake dev    # http://127.0.0.1:8765, auto-reload\n```\n\nOpen the URL in a browser. Start a Claude Code session in another terminal — a tile appears within seconds. **No per-session registration. No config to get started.**\n\nOther targets:\n\n```bash\nmake run     # production-style, no reload\nmake test    # run the pytest suite\n```\n\n---\n\n## Editions\n\nConductor ships in two editions from the same codebase:\n\n| Edition | What it is | Run |\n|---|---|---|\n| **Web Browser** | The dashboard served at `http://127.0.0.1:8765`, opened in any browser. | `make dev` / `make run` |\n| **Native App** | The *same* dashboard wrapped in a native desktop window (pywebview → WebKitGTK), with its own app-menu launcher and dock icon. | `make native` |\n\nBoth editions ship in a **single release per version** (`vX.Y.Z`) — it's one\ncodebase at one commit, the edition is just how you run it. New features land\nonce and both editions get them.\n\n### Native App Edition (Ubuntu)\n\nThe native edition runs the identical FastAPI + JS app inside a WebKitGTK window.\nThe uvicorn server runs in a background thread; **closing the window stops the\nserver** (nothing is left running). If a Conductor is already serving the port\n(e.g. a `make dev` instance, or a second launch), the app *attaches* to it\ninstead of starting a duplicate.\n\n```bash\n# 1. System WebKitGTK (not pip-installable — provides PyGObject + the WebKit2 typelib)\nsudo apt install python3-gi gir1.2-webkit2-4.0 libwebkit2gtk-4.0-37\n\n# 2. Build the native venv (--system-site-packages, so it can see system gi/WebKit) + pywebview\nmake install-native\n\n# 3. Launch the native window\nmake native\n\n# 4. (Optional) Add a launcher to your app menu / dock, with this checkout's paths baked in\nmake install-desktop\n```\n\n`make install-native` creates a **separate** `.venv-native` so the Web edition's\n`.venv` stays untouched. `make install-desktop` writes\n`~/.local/share/applications/conductor.desktop` (icon: `assets/conductor.svg`,\n`StartupWMClass=conductor` for dock grouping) — re-run it if you move the repo.\n\n\u003e Tested against WebKit2 **4.0** (Ubuntu 22.04). The SVG connection-line overlays\n\u003e and tile drag render correctly under WebKitGTK.\n\n---\n\n## Using the Dashboard\n\n### Tiles\n\nEach tile is one live Claude session. It shows:\n\n- **Status dot** — `active` (writing now), `warm` (recent), `idle`, `dormant`, `waiting` (on user input), `ended`\n- **Squashed live preview** of the latest message\n- **Message count + time since last activity**\n- **📬 bubble** — appears when this session has unread bus messages (only if the [bus](#cross-session-bus) is wired up)\n- **Tag chip** (e.g. `[backend]`) — its bus identity, and a click-toggle for [Active/Passive](#active--passive) membership\n\n**Drag** a tile to move it; **drag the bottom-right corner** to resize it; the **`–`** button minimizes it to the bottom dock. Hover a truncated title to see it in full. Position, size, and minimized state persist across restarts.\n\n### Minimize / dock\n\nClick a tile's **`–`** to tuck it into a thin **dock** along the bottom — a tiny chip with its status dot, name, and 📬 badge. It's still monitored (the dot keeps updating; a new message still lights the badge), just out of the way. Hover for the full name; **click the chip to restore** it to its previous position and size. Minimized tiles' bus wires are hidden to keep the board clean.\n\n### Groups\n\nFor a crowded board, organize sessions into **named, color-coded groups**. Each tile has a **▦** button that opens a small menu:\n\n- **▦ → New group from this** (prompts for a name) — or **Add to ▸ {group}** to join an existing one. A tile belongs to one group; members get a colored top accent.\n- On a grouped tile: **Rename group**, **Move to ▸ {other}**, **Remove from group**, or **Minimize group** — which folds the *whole* group into a single dock chip (swatch + name + member count + active dot + total 📬). Click the chip to expand it back.\n- The **▦ Groups** panel (top bar) lists every group to rename, recolor, minimize/restore, or ungroup.\n\nGroups are *logical* (members keep their own positions — they aren't auto-arranged) and persist across restarts.\n\n### 🧊 3D view\n\nClick **🧊 3D** in the top bar to lift the board into a 3D scene; click **🗔 2D** to come back. **2D is the default** and stays untouched — 3D is an optional view, and your choice (plus the last layout) is remembered.\n\n- **Navigate** — *drag* to orbit the camera, *scroll* to zoom. Click a card's **▶** to focus its terminal, or its tag chip to toggle Active/Passive, just like 2D.\n- **Cards always face you.** No matter how you orbit, every card is billboarded toward the camera so the text stays readable — depth and motion live in the *space between* sessions, never in the angle of the content.\n- **Groups become places.** Cards carry their group color (border + glow), and group members physically **cluster together** in the scene. The glowing **bus core** sits at the center with wires fanning out (solid = active, dashed = passive), pulsing on each message.\n- **Three layouts** (switcher floats at the bottom):\n  - **Carousel** *(default)* — sessions on a ring you spin through; the front card is enlarged and in focus.\n  - **Orbital** — sessions orbit the bus core on a sphere; each group shares an arc.\n  - **Gallery** — your saved 2D positions lifted into depth (active sessions float forward, idle recede), with groups pulled into tight clumps.\n\n\u003e The 3D view loads Three.js from a CDN the first time you open it (no build step). Offline or CDN blocked? It cleanly falls back to 2D with a notice — the 2D board never depends on it. Assign/rename/recolor groups from the 2D **▦** menu; 3D visualizes whatever's set.\n\n### Click a tile\n\nRaises that session's terminal window. See [Reliable terminal focus](#reliable-terminal-focus) for the trick that makes this work cleanly when you have many sessions in one terminal app.\n\n### Click the 📬 bubble\n\nRuns `/msg-check` *inside that live Claude* — it raises the window and types the command for you. Behavior is configurable so you don't clobber a Claude mid-task (see below).\n\n### Bus tile\n\nA central tile shows recent cross-session traffic. SVG lines fan out to every session that's on the bus and animate on each message. The line style tells you *how* a session is on the bus (see the legend, bottom-left):\n\n- **Active** (solid) — wired to the bus hooks, so it's **auto-notified** of new messages and receives broadcasts.\n- **Passive** (dashed, dim) — has used the bus manually (`/msg-send` / `/msg-check`) but isn't auto-notified, so it **won't see broadcasts** unless you Ping it. (These are sessions outside `bus.sh`'s hook whitelist — a deliberate scoping so the bus doesn't pester unrelated sessions.)\n\n### Active / Passive\n\nClick a tile's **tag chip** to toggle that session between **Active** (auto-notified) and **Passive** (manual only) right from the dashboard. Conductor writes the membership to `~/.claude/bus-state/active-tags`, and `bus.sh` reads it — so the change takes effect on that session's **next prompt** (promote a throwaway session into the team, or stop pestering one). The list seeds from your existing active set on first toggle, so nothing changes until you click.\n\n\u003e Requires the data-file-aware `bus.sh` (the shipped [`bus/bus.sh`](bus/bus.sh) reads `active-tags`, falling back to its built-in `BUS_WHITELIST` when the file is absent). If you wired up the bus before this, re-copy `bus/bus.sh`.\n\n### ✉ Compose\n\nClick **Compose** in the top bar to send your own message on the bus — like email for your sessions. You're a first-class sender (tagged `[operator]` by default; set `bus.sender_tag` in `settings.toml` to your name).\n\n- **All sessions** (default) — a broadcast everyone sees.\n- **Specific sessions** — uncheck \"All\" and pick recipients. The message is soft-addressed with a leading `@to [tag] …` line, so receivers (and the dashboard's connection-line animation) know who it's for. It's still on the shared log; addressing is advisory, not private.\n- **Ping recipients** — also injects `/msg-check` into the chosen sessions so they read it immediately (specific recipients only — broadcast-ping would steal focus across every window). `Ctrl/⌘+Enter` sends.\n\n\u003e Sending makes Claude Connect a *writer* on the bus (it still never touches Claude's own state). Requires the markdown bus adapter.\n\n### ⚙ Settings\n\nTheme, connection lines (incl. **Lines behind tiles** to drop the wires behind the tiles for a cleaner board — each wire still stays anchored to its own tile via a plug + stub drawn on top), animations, rescan cadence, and the **bus-bubble click policy**:\n\n| Policy                                      | Behavior                                                                                      |\n| ------------------------------------------- | --------------------------------------------------------------------------------------------- |\n| **Confirm if busy, inject if idle** *(default)* | Inject silently when idle; confirm first if the session looks busy (writing in the last 30s). |\n| **Always inject**                           | Type `/msg-check` immediately, regardless of state.                                           |\n| **Block while busy**                        | Badge is dimmed/non-clickable while busy; injects only when idle.                             |\n| **Always confirm**                          | Ask before every injection.                                                                   |\n\n\u003e ⚠️ \"Busy\" is inferred from `jsonl` activity + CPU. A Claude blocked on a long, quiet tool call can still look idle, so this guard *shrinks* the risk of clobbering rather than eliminating it. Use *Always confirm* if you want a prompt every time.\n\n---\n\n## Cross-Session Bus\n\n\u003e *Optional, but the killer feature.*\n\nThe 📬 features ride on a **shared markdown message log**. Claude sessions append to it with `/msg-send` and read it with `/msg-check`; hooks make each session aware of new messages. Claude Connect tails the same log to drive the bus tile.\n\n### Setup\n\n```bash\ninstall -Dm755 bus/bus.sh ~/.claude/bin/bus.sh\ncp bus/commands/*.md ~/.claude/commands/\n\n# Then merge bus/settings.hooks.example.json into ~/.claude/settings.json\n```\n\nPoint Claude Connect at the log in the `[bus]` section of `settings.toml`. Full setup docs and format spec:\n\n- 📖 [`bus/README.md`](bus/README.md) — install + slash commands\n- 📖 [`docs/claude-bus.md`](docs/claude-bus.md) — message format spec\n\n### What if a session isn't on the bus?\n\nClaude Connect works fully without it. Session discovery comes from OS process state, not from the bus, so:\n\n- ✅ An un-wired Claude still appears as a normal tile — status, preview, message count, click-to-focus all work\n- ❌ It just won't show a 📬 badge or a connection line to the Bus tile\n\nThis is actually useful — if you wire up some sessions and leave others out, the dashboard shows at a glance which ones are on the tunnel and which are silent.\n\n---\n\n## Reliable Terminal Focus\n\nA single terminal server (Tilix, `gnome-terminal-server`) owns all its windows, so they share one PID — and a tiled window shows only the *active* tile's title at a time. So matching purely on **window title** is ambiguous: a backgrounded tile has no title of its own on the window, and a stray same-named terminal (e.g. a shell `cd`'d into the project dir) can win the match.\n\n**Tilix gets an exact path.** Each tilix tile stamps its shell with a `TILIX_ID` env var, so Claude Connect reads that UUID from the Claude process and tells tilix (over its `com.gexperts.Tilix` D-Bus interface) to focus that precise tile — **raising the window *and* switching to the exact tile**, even inside a combined/tiled window where several Claudes share one window. No wrapper, no setup; it just works if you run Claude inside tilix.\n\n\u003e Scope: this exact-tile path is **tilix-only** and only tested on tilix. Other terminals fall through to the title-matching path below — no regression, just less precise.\n\nFor non-tilix terminals, focus falls back to **window-title matching**, and the optional `claude-tracked` wrapper in [`scripts/`](scripts/) gives each Claude its own window with a unique X11 title so focus and 📬 injection target precisely:\n\n```bash\nsudo install -m755 scripts/claude-tracked /usr/local/bin/\nclaude-tracked api-server --resume\n```\n\nWithout either the tilix path or the wrapper, focus is best-effort: Claude Connect raises the terminal window owning the Claude PID, but can't switch between tabs packed into one window.\n\n---\n\n## Configuration\n\nEdit `settings.toml` (copied from `settings.example.toml`). Key knobs:\n\n| Setting                       | What it does                                                  | Default |\n| ----------------------------- | ------------------------------------------------------------- | ------- |\n| `scanner.interval_seconds`    | Full rescan cadence                                           | `3`     |\n| `bus.adapter`                 | `markdown` (the reference bus), `jsonl` (generic), or `fake`  | —       |\n| `bus.markdown_path`           | Path to the bus log                                           | —       |\n| `bus.state_dir`               | Where unread state lives                                      | —       |\n| `bus.script_path`             | Path to `bus.sh`                                              | —       |\n| `ui.end_fadeout_seconds`      | How long ended-session tiles linger after exit                | `30`    |\n\n---\n\n## What's stored, and where\n\nConductor keeps **no central database** — state lives in two clearly separated places:\n\n**Your browser (localStorage, per-origin `127.0.0.1:8765`)** — all the visual/layout customization. Written to disk by the browser, so it survives closing the tab, restarting the browser, restarting the server, and rebooting:\n\n| Key | Holds |\n| --- | --- |\n| `conductor.prefs.v1` | theme, connection-line visibility, lines-behind, flow animation, bus-bubble click policy |\n| `conductor.positions.v2` | tile positions **and sizes** |\n| `conductor.minimized.v2` | which tiles are minimized to the dock |\n| `conductor.groups.v2` | your groups (names, colors, members, collapsed state) |\n\nLayout/minimize/group state is keyed by **project directory**, so a session re-attaches to its saved spot, size, and group whenever it runs in the same directory — across reboots and even fresh (non-resumed) sessions. Conductor doesn't prune offline tiles' layout, so it waits for them to return. Clear it with **Reset layout**, **Ungroup**, or your browser's site-data tools.\n\n**On your machine (the bus), not the browser:** the cross-session bus log (`~/Documents/claude-bus/messages.md`), unread state (`~/.claude/bus-state/`), and the active/passive whitelist (`~/.claude/bus-state/active-tags`). The Conductor server itself is **in-memory and restart-clean** — it holds no persistent state of its own.\n\n---\n\n## How It Works\n\nFor the curious:\n\n1. **SessionScanner** enumerates Claude Code processes via `psutil`, resolves `/proc/\u003cpid\u003e/cwd`, and walks `~/.claude/projects/\u003cencoded\u003e/` to find each session's `*.jsonl`.\n2. **ActivityWatcher** uses `watchdog` (inotify on Linux) to react to jsonl writes without polling.\n3. A **WebSocket hub** at `/ws` fans updates out to the browser: a full session + bus snapshot every `scanner.interval_seconds` (3 s by default), plus an immediate per-session push whenever a jsonl write fires (inotify), and a bus event as each message arrives.\n4. The **frontend** renders one tile per session — plain JS, no build step.\n5. **BusAdapter** tails the message-bus log; the Bus tile shows recent traffic and SVG lines fan out to sessions on the bus.\n6. **WindowMapper** raises the right terminal window on click and types `/msg-check` into a session when you click its 📬 — focusing the exact tilix tile via `gdbus` + `TILIX_ID` when available, else falling back to `wmctrl`/`xdotool` title matching.\n\nFull design doc: [`CONDUCTOR_SPEC.md`](CONDUCTOR_SPEC.md)\n\n---\n\n## Design Notes\n\n- **Single-host only.** Binds to `127.0.0.1`.\n- **No persistence.** State is in-memory and restart-clean.\n- **No build step on the frontend.** Edit `frontend/*.js` and reload.\n\n---\n\n## Troubleshooting\n\n**Tiles aren't appearing.**\nCheck that `claude` is actually running and that `~/.claude/projects/` has recent jsonl files. Drop `scanner.interval_seconds` to `1` temporarily to confirm discovery is happening.\n\n**Clicking a tile doesn't focus the terminal.**\nOn **Tilix**, focus is exact out of the box (via `gdbus` + `TILIX_ID`) — make sure `gdbus` is on PATH (it ships with GLib). On other terminals, make sure `wmctrl` is installed; for tabbed/tiled non-tilix terminals, install the `claude-tracked` wrapper so each session gets a unique window title. See [Reliable Terminal Focus](#reliable-terminal-focus).\n\n**📬 bubbles never appear.**\nThe bus isn't wired up. See [Cross-Session Bus](#cross-session-bus). Sessions work fine without it — they just won't have bubbles or connection lines.\n\n**`/msg-check` doesn't inject when I click 📬.**\nCheck that `xdotool` is installed and the session's terminal window is on the current desktop/workspace.\n\n---\n\n## Maintainer\n\nBuilt and maintained by **Kyle Fox** ([@kylefoxaustin](https://github.com/kylefoxaustin)).\n\nGot an idea, found a bug, or want to share how you're using it? Open an [issue](https://github.com/kylefoxaustin/claude-connect/issues) or ping me on GitHub.\n\n## Contributing\n\nIssues and PRs welcome. See [`CLAUDE.md`](CLAUDE.md) for the agent-friendly contributor guide.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkylefoxaustin%2Fclaude-connect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkylefoxaustin%2Fclaude-connect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkylefoxaustin%2Fclaude-connect/lists"}