← Commit history

Delete skills/hd-claude-management/SKILL.md

John Lauer ·32ec43700f ·2mo ago ·parent 70f943c
1 file changed −214
skills/hd-claude-management/SKILL.mddeleted−214
@@ -1,214 +0,0 @@-----name: hd-claude-management-description: >-  First-class API for managing the Claude Code conversations inside Hydrogen Desktop:-  list/open/close/switch conversation tabs, read each conversation's full state (title,-  message count, compose box, and the on-disk session GUID), type messages into a SPECIFIC-  conversation (instant or with a human typing animation) and submit them, and turn on-  Remote Control to get a claude.ai cloud URL so the user can view+drive that exact-  conversation from claude.ai or the Claude mobile app. Every conversation is addressed by a-  stable execution-context id (deterministic, background, no foreground/focus needed). Also-  explains how a live conversation is matched to its ~/.claude/projects/*.jsonl log.-  Trigger words: claude tabs, claude conversations, list conversations, open claude tab,-  close claude tab, switch claude tab, new conversation, type into claude, inject prompt,-  remote control, claude.ai url, view on mobile, session id, conversation guid, jsonl,-  claude session, context_id, multi-tab claude, conversation management.------# HD Claude Conversation Management--Hydrogen Desktop runs Claude Code as webview tabs inside VS Code. This skill is the-**first-class API** for managing those conversations programmatically — from HD's control-API, from the user's AI inside the WSL2 workspace, or from setup steps.--All endpoints are on the **HD control API** (a dynamic localhost port). From inside the-workspace, examples below use `$HD` for `http://127.0.0.1:<port>` (find the port in the HD-log / port discovery). From an **external** context (a cloud container), call the same-endpoints with the AD verb `adom-desktop hd_api '{"path":"/claude/…","method":"POST","body":{…}}'`-— it auto-discovers the port. Everything here works in the **background** — no window focus,-no foreground, no keystroke stealing.--## The core idea: address conversations by CONTEXT ID, list from the TAB BAR--Each Claude conversation is its own webview **execution context** with a **stable integer id**.-That id — not the tab index, not the title, not visibility — is how you reliably *target* one-conversation (type into it, remote-control it). VS Code keeps multiple webviews "visible" at-once, so visibility/tab-index are NOT reliable addresses; the context id is.--But VS Code also **disposes the webview of a background tab**, so a context id only exists for-*loaded* tabs. That's why `GET /claude/conversations` **merges three sources** into one view:-the **tab bar** (every open conversation + which is active — what you see), the **live webview-contexts** (rich data for loaded tabs), and the **on-disk session logs** (the GUIDs). Each row-carries a `loaded` flag; `loaded:false` means activate the tab first to read its live details.--## GET /claude/conversations — everything in one call--```bash-curl -s $HD/claude/conversations-```-```jsonc-{-  "ok": true,-  "count": 4,-  "conversations": [-    {-      "ordinal": 3,                 // its position in the tab bar-      "active": true,               // the currently-focused tab-      "loaded": true,               // webview is live → rich fields are populated-      "context_id": 7,              // STABLE address for inject/remote-control (null if not loaded)-      "title": "Calculate 10 times 10",   // authoritative title (from the session log when matched)-      "tab_label": "Calculate 10 times 10", // raw tab label (may be ellipsis-truncated)-      "compose_text": "",           // what's typed but not yet sent (null if not loaded)-      "msg_count": 16,              // null if not loaded-      "session_id": "566cec21-…",   // on-disk log GUID (read ~/.claude/projects/*/<id>.jsonl)-      "rc_active": false,           // Remote Control on? (null if not loaded)-      "remote_control_url": null    // claude.ai cloud URL when rc_active-    },-    { "ordinal": 1, "active": false, "loaded": false, "context_id": null,-      "title": "Find the capital of France", "tab_label": "Find the capital of Fran…",-      "compose_text": null, "msg_count": null, "session_id": "b352055b-…", "rc_active": null, "remote_control_url": null }-  ]-}-```-- **Merged view:** every tab is listed (from the tab bar). `loaded:true` rows have live fields-  (`context_id`, `compose_text`, `msg_count`, `rc_active`); `loaded:false` rows are background tabs-  VS Code disposed — **activate them** (`/claude/tabs/activate`) to read those. Even a disposed tab-  resolves its `session_id` when its title matches the on-disk log.-- A conversation is **`Untitled`** with **`session_id: null`** until its first message is submitted —-  then Claude names it and writes the session log.-- `?with_session=false` skips the disk read (faster; omits `session_id`).--`GET /claude/contexts` is the lighter version (just the *loaded* contexts: `context_id` + `compose_text`).--## Open / close / switch tabs--```bash-# Open a fresh conversation (new tab)-curl -s -X POST $HD/claude/new-conversation--# Open the Claude panel if it isn't open-curl -s -X POST $HD/claude/open--# List raw editor tabs (label/active/dirty)-curl -s $HD/claude/tabs--# Close ALL conversation tabs (also removes the leftover empty editor group)-curl -s -X POST $HD/claude/tabs/close-all--# Switch the visible tab by index or label substring (background)-curl -s -X POST $HD/claude/tabs/activate -d '{"index":1}'-curl -s -X POST $HD/claude/tabs/activate -d '{"label":"Eiffel"}'--# Remove a stale EMPTY editor group (the dead blank panel) WITHOUT collapsing a-# real 2-group left/right layout. (merge-groups is a back-compat alias.)-curl -s -X POST $HD/claude/tabs/close-empty-groups-```--## Type a message into a SPECIFIC conversation--`POST /claude/inject` types into the conversation you name with `context_index`. Two speeds:--```bash-# INSTANT paste (fast) — no typing animation. Best for slash commands and scripted input.-curl -s -X POST $HD/claude/inject -d '{"text":"summarize this repo","context_index":16,"typed":false,"submit":true}'--# SLOW human typing animation (the "watch the AI type" effect), then submit.-curl -s -X POST $HD/claude/inject -d '{"text":"hello there","context_index":16,"typed":true,"delay_ms":50,"submit":true}'--# Type but DON'T send (leave it sitting in the compose box):-curl -s -X POST $HD/claude/inject -d '{"text":"draft…","context_index":16,"typed":false,"submit":false}'-```-- `typed`: `true` = char-by-char with ±50% jitter (avg `delay_ms`); `false` = instant paste.-- `submit`: `true` = press Enter; `false` = leave in the box.-- Omit `context_index` ONLY when a single conversation is open. With **more than one** conversation-  open, omitting it can type your text into **several compose boxes at once** (it falls back to a-  visibility heuristic that isn't reliable when the window isn't foreground). When in doubt, pass it.-- Targeting by `context_index` is deterministic — it lands in exactly that tab even when it's-  not the foreground one and even with many tabs open (no fan-out into other tabs). **This is the-  safe default: list `/claude/conversations`, take the row with `active:true` (or the tab you want),-  use its `context_id`, then inject.**--Typical "open a new tab and ask a question":-```bash-curl -s -X POST $HD/claude/new-conversation-CTX=$(curl -s $HD/claude/contexts | jq '.contexts[-1].context_id')-curl -s -X POST $HD/claude/inject -d "{\"text\":\"what does this project do?\",\"context_index\":$CTX,\"typed\":true,\"submit\":true}"-```--## ⭐ Remote Control → view the conversation on claude.ai / mobile--This is the big one. Turn on Remote Control for a conversation and HD returns a **claude.ai-cloud URL**. Open it on claude.ai in any browser or in the Claude **mobile app** to see and-drive that exact conversation in the cloud — not tied to HD. The user can be on their phone-editing the same conversation.--```bash-curl -s -X POST $HD/claude/remote-control -d '{"context_index":7}'-```-```jsonc-{-  "ok": true,-  "rc_active": true,-  "toggled": true,                 // false + already_in_desired_state:true if it was already on-  "context_id": 7,-  "remote_control_url": "https://claude.ai/code/session_014koKPJxmjYpnX2SjRRqrD3"-}-```-- ⚠️ **`/remote-control` is a TOGGLE.** This endpoint **detects** the current state first and only-  toggles when needed — re-calling it on an already-on session is a **no-op** that returns the-  existing URL (it will NOT turn it off; doing that blindly archives the cloud session).-- `{enable:false}` turns Remote Control **off**.-- The `session_…` id in the URL is the **cloud** session id — distinct from the local on-disk-  `session_id` GUID. The cloud URL is the shareable one for claude.ai / mobile.-- `{name}` → `/remote-control <name>` to label the remote session.-- Each conversation's current state is also reported as `rc_active` in `/claude/conversations`.-- **Opening it on the user's machine (external/cloud agent):** get the URL, then open it in their-  Chrome and screenshot to confirm — all via AD verbs (no synthetic keystrokes):-  `desktop_find_window {titleContains:"Claude Code - Google Chrome"}` → `desktop_screenshot_window-  {hwnd}`. To type INTO the claude.ai page, use the native-browser bridge `nbrowser_eval-  {tabId, expression}` (the composer is shadow-DOM; do NOT blind-type with SendInput). See the-  `driving-hd-remotely` guide on the Hydrogen Desktop wiki page.--## How a live conversation maps to its on-disk log (JSONL)--Claude Code stores each conversation as `~/.claude/projects/<cwd>/<uuid>.jsonl` containing-`sessionId`, `aiTitle` (the generated title), and every message. **The session GUID is NOT-exposed in the conversation's webview DOM**, so HD correlates a live conversation to its log by-matching the **first user message** (exact + unique; present in both the DOM and the JSONL).-On a match, `/claude/conversations` fills in `session_id` and uses the log's `aiTitle` as the-authoritative `title`. (Matching on the title alone is unreliable — the rendered title and the-persisted `aiTitle` can differ.)--Read a conversation's full transcript from the workspace:-```bash-cat ~/.claude/projects/*/<session_id>.jsonl-```--## Why this is valuable--- **Multi-conversation orchestration:** open N conversations, drive each independently by-  context id, read each one's state — all from a script or an agent, in the background.-- **Cloud + mobile continuity:** Remote Control hands you a claude.ai URL so a conversation-  started in HD continues on the phone / web. Huge for working away from the desk.-- **Deterministic + safe:** context-id addressing never types into the wrong tab; the empty-  blank panel is cleaned up automatically; a real 2-group left/right layout is preserved.-- **Auditable:** every conversation maps to an on-disk JSONL you can read, diff, or archive.--## Endpoint quick reference--| Endpoint | Method | What it does |-|---|---|---|-| `/claude/conversations` | GET | Full per-conversation data incl. `session_id` (the canonical list) |-| `/claude/contexts` | GET | Light list: `context_id` + `compose_text` |-| `/claude/tabs` | GET | Raw editor tabs (label/active/dirty) |-| `/claude/new-conversation` | POST | Open a fresh conversation tab |-| `/claude/open` | POST | Open the Claude panel if closed |-| `/claude/tabs/close-all` | POST | Close all tabs + remove the leftover empty group |-| `/claude/tabs/activate` | POST | Switch visible tab by `{index}` or `{label}` |-| `/claude/tabs/close-empty-groups` | POST | Remove stale empty editor groups (preserves populated) |-| `/claude/inject` | POST | Type into `{context_index}` — `{typed,submit,delay_ms}` |-| `/claude/remote-control` | POST | Turn on RC for `{context_index}` → returns `remote_control_url` |-| `/claude/cross-eval` | POST | (Diagnostic) run JS across all workbench/webview contexts |--These are the same endpoints HD's own setup steps use to open Claude and inject the first-prompt — so behavior is identical whether a human, setup, or the workspace AI drives them.