Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
75db1e1
chore(main): release the-companion 0.96.0
github-actions[bot] Apr 2, 2026
e723252
fix(models): add claude opus-latest fallback option
edwinhu Apr 16, 2026
ee641fc
fix(models): replace invalid claude-opus-latest with claude-opus-4-7 …
edwinhu Apr 16, 2026
b8cb07d
fix(ui): hide empty thinking blocks instead of showing placeholder
edwinhu Apr 16, 2026
8a61ccc
fix(models): omit sampling params on opus-4-7 + bump legacy model fix…
edwinhu Apr 17, 2026
673db2f
chore: add .worktrees/ to gitignore
edwinhu Apr 17, 2026
d8b7139
feat(ide): add /ide slash command with live IDE binding
edwinhu Apr 17, 2026
51400d7
fix(ide): resolve post-PR runtime issues for /ide binding
edwinhu Apr 17, 2026
95666bd
fix(ide): harden bind/unbind for dynamic MCP merge + queue races
edwinhu Apr 17, 2026
e548024
fix(ide): address cubic-ai round-2 review + hardening
edwinhu Apr 17, 2026
928645e
fix(ide): address cubic round-3 review + CI coverage gaps
edwinhu Apr 17, 2026
4efaa62
fix(ide): reserve companion-ide-* MCP namespace + clear banner on rebind
edwinhu Apr 17, 2026
67140de
fix(ide): harden ide-discovery against transient/persistent read fail…
edwinhu Apr 17, 2026
777c4cd
fix(ide): reset readdirFailureStreak on discovery stop/start
edwinhu Apr 17, 2026
48b69d4
fix(ide): narrow /ide escape + defensive-clone listAvailableIdes
edwinhu Apr 17, 2026
6b7fae7
fix(ide): address codex + cubic adversarial review findings
edwinhu Apr 17, 2026
8ab4887
fix(ide): only reset ide_list_changed dedupe when no other sockets ac…
edwinhu Apr 17, 2026
1acf1ab
fix(ide): validate deleteKeys entries before MCP deletion
edwinhu Apr 17, 2026
bb4ce58
fix(ide): address cubic latest review — P1 MCP mirror + flaky test + …
edwinhu Apr 18, 2026
bf08bac
fix(ide): guard test-only exports with NODE_ENV check
edwinhu Apr 18, 2026
059262d
fix(ide): consolidate test-only guards with assertTestOnly helper
edwinhu Apr 18, 2026
5a33714
fix(recorder): redact IDE authToken before writing to recordings
edwinhu Apr 18, 2026
966db2b
fix(ide): await backend ack before committing bind/unbind state
edwinhu Apr 18, 2026
7c24679
fix(ide): unregister pending control-request on applyMcpSetServers ti…
edwinhu Apr 18, 2026
ec7b64f
fix(test): wait for directory load before testing manual input mode
edwinhu Apr 18, 2026
ed08578
fix(ide): close race between bind/unbind and concurrent mcp_set_servers
edwinhu Apr 18, 2026
db41f3b
fix(launcher): preserve bypassPermissions in containers + fix H2 queu…
edwinhu Apr 18, 2026
802d1b7
fix(ws-bridge): re-inject IDE entry in flush path after strip (C2)
edwinhu Apr 18, 2026
adcb543
fix(ide): address 5 cubic P2 findings across full PR
edwinhu Apr 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ docs/mocks/
docs/repo-only/
scripts/test-codex-*.ts
web/dev-dist/
.worktrees/
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.95.0"
".": "0.96.0"
}
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Changelog

## [0.96.0](https://github.com/The-Vibe-Company/companion/compare/the-companion-v0.95.0...the-companion-v0.96.0) (2026-04-02)


### Features

* **ui:** add ActivityTray floating component for background agents and tasks ([#638](https://github.com/The-Vibe-Company/companion/issues/638)) ([abdfb4b](https://github.com/The-Vibe-Company/companion/commit/abdfb4bc7e096e810bde30b3cac844ceb2d8f469))


### Bug Fixes

* **codex:** handle unhandled Codex notification methods to prevent protocol drift warnings ([#637](https://github.com/The-Vibe-Company/companion/issues/637)) ([e0c242d](https://github.com/The-Vibe-Company/companion/commit/e0c242dd1b0c94ff5ddbf3f8e7e706ce6d5cd506))
* **keepalive:** add Codex disconnect debounce and enable headless proactive keepalive ([#635](https://github.com/The-Vibe-Company/companion/issues/635)) ([a0d4e52](https://github.com/The-Vibe-Company/companion/commit/a0d4e5263820fefc2bb6beaf6aeb1903052b568d))
* **prompts:** expand prompt editor workspace ([#640](https://github.com/The-Vibe-Company/companion/issues/640)) ([5288314](https://github.com/The-Vibe-Company/companion/commit/52883144858f62d6f9b418c00432279f28d119d4))
* **ws-bridge:** broadcast permissionMode changes from CLI to browsers ([#639](https://github.com/The-Vibe-Company/companion/issues/639)) ([4c9dbab](https://github.com/The-Vibe-Company/companion/commit/4c9dbab91094d0d83a04c79681e6e153d7f17652))

## [0.95.0](https://github.com/The-Vibe-Company/companion/compare/the-companion-v0.94.0...the-companion-v0.95.0) (2026-04-01)


Expand Down
89 changes: 89 additions & 0 deletions WEBSOCKET_PROTOCOL_REVERSED.md
Original file line number Diff line number Diff line change
Expand Up @@ -1609,3 +1609,92 @@ type ContentBlock =
| { type: "tool_result"; tool_use_id: string; content: string | ContentBlock[]; is_error?: boolean }
| { type: "thinking"; thinking: string; budget_tokens?: number };
```

---

## IDE Channel

Claude Code integrates with running IDEs (Neovim, Visual Studio Code, Obsidian, Cursor, etc.) via a locally-discovered MCP server exposed by each IDE. Companion reuses the same mechanism the CLI's built-in `/ide` command relies on: a lockfile registry plus the existing `mcp_set_servers` control_request. No new protocol surface is introduced.

### Lockfile Registry (`~/.claude/ide/`)

Each IDE that supports the Claude Code integration writes a lockfile to `~/.claude/ide/`. The filename stem is typically the port the IDE's MCP server is listening on (e.g. `38630.lock`). The file contents are JSON:

```jsonc
{
"pid": 62243, // PID of the IDE process
"workspaceFolders": ["/Users/x/repo"], // one or more absolute paths
"ideName": "Neovim", // human-readable label
"transport": "ws", // newer IDEs: "ws" | "sse"
"useWebSocket": true, // VSCode-style IDEs: boolean
"running": true, // informational flag
"authToken": "ff3fedac-0efb-4608-a003-..." // bearer token for the MCP server
}
```

Either `transport` **or** `useWebSocket` is present (not both, in practice). Consumers should treat unknown fields as forward-compat and ignore them.

Entries whose `pid` is no longer alive are stale and must be pruned before use (a simple `process.kill(pid, 0)` succeeds for live PIDs; `ESRCH` means dead). The diagnostic script at `scripts/probe-ide.ts` demonstrates the full enumeration + prune + payload-preview flow.

### Bind via `mcp_set_servers`

Binding a session to an IDE is a **plain `mcp_set_servers` control_request** — the same message type Companion already uses to push user-configured MCP servers. The adapter at `web/server/claude-adapter.ts :: handleOutgoingMcpSetServers` carries the payload verbatim; the CLI treats the `ide` key as a dynamically-scoped MCP server and wires it up exactly as it does for the CLI's own `/ide` command.

Companion emits, browser-outgoing:

```json
{
"type": "mcp_set_servers",
"servers": {
"ide": {
"type": "ws-ide",
"url": "ws://127.0.0.1:38630",
"ideName": "Neovim",
"authToken": "ff3fedac-0efb-4608-a003-66530036024b",
"scope": "dynamic"
}
}
}
```

Which the adapter translates into a CLI `control_request`:

```json
{
"type": "control_request",
"request_id": "...",
"request": {
"subtype": "mcp_set_servers",
"servers": { "ide": { ... }, "...otherUserServers": { ... } }
}
}
```

### MCP Server Types

The CLI accepts two IDE-specific server types (discovered via probe against claude CLI v2.1.112):

| `type` | Derivation | URL scheme |
|--------|------------|------------|
| `ws-ide` | `useWebSocket === true` **or** `transport === "ws"` | `ws://127.0.0.1:<port>` |
| `sse-ide` | otherwise (falls back to SSE) | `http://127.0.0.1:<port>` |

These are peers of the standard `stdio` / `sse` / `ws` MCP types and are scoped with `scope: "dynamic"` so they don't persist across session restarts.

### Merge Semantics (Critical)

Companion must **not** overwrite the session's full MCP servers map when binding. The correct flow is:

1. Read the current `dynamicMcpConfig` from session state (includes any user-configured MCP servers).
2. Merge `servers.ide = {...}` into that map.
3. Send the full merged map via `mcp_set_servers`.

Unbinding removes only the `ide` key and re-sends the remainder. See `web/server/ws-bridge.ts :: bindIde / unbindIde`.

### Relationship to the CLI's `/ide` Command

The CLI ships its own `/ide` slash command that performs lockfile discovery and binding internally. Companion intercepts `/ide` client-side (in `Composer.tsx`) and renders a richer picker UI, but the underlying bind mechanism — a `mcp_set_servers` with a dynamically-scoped `ide` server — is identical. The CLI never sees the `/ide` text; it only receives the resulting `mcp_set_servers` control_request.

### Diagnostic

Run `bun scripts/probe-ide.ts` from the repo root to enumerate live lockfiles and preview the exact `mcp_set_servers` payload Companion would emit. Useful for bug reports and verifying that a given IDE is advertising itself correctly.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "the-companion",
"version": "0.95.0",
"version": "0.96.0",
"private": true,
"description": "Web UI for Claude Code agents",
"scripts": {
Expand Down
Loading
Loading