$npx -y skills add pandazki/pneuma-skills --skill pneuma-sessionRewrite the active Pneuma session's UI title + one-line summary so the launcher and ProjectPanel rows reflect what the session is actually about. Use this skill whenever the user asks to "整理 / 概括 / refresh / re-title / summarize this session", whenever the conversation has produc
| 1 | # Refining your session's identity |
| 2 | |
| 3 | Every Pneuma session has a row in the launcher (Recent Sessions) and inside its project (ProjectPanel). The row has two slots: |
| 4 | |
| 5 | - **Title** — defaults to `"<Mode> session"` (e.g. "WebCraft session"). Mode-only. |
| 6 | - **Description / preview** — defaults to the first user prompt. For project sessions, the first prompt is the server-emitted `<pneuma:env reason="opened" />` synthetic tag — which carries zero information for a human scanning the list. |
| 7 | |
| 8 | Until you refine, both fields are placeholders. Three "WebCraft session" rows look identical except for their thumbnails. The user has to remember by time, which they won't. |
| 9 | |
| 10 | This skill is how you fix that. You write a meaningful title + one-sentence summary into `<sessionDir>/session.json`, and the launcher row updates in place. The data persists across reopens; the launcher's own listing always reads from your last refine. |
| 11 | |
| 12 | ## The mechanism |
| 13 | |
| 14 | ```bash |
| 15 | $PNEUMA_CLI session refine --json '{"displayName": "<≤40 chars>", "description": "<≤280 chars>"}' |
| 16 | ``` |
| 17 | |
| 18 | Always call through the `$PNEUMA_CLI` env var, not the literal `pneuma` binary. The env var resolves to the right invocation regardless of how Pneuma was installed (npm-global, dev worktree, desktop bundle); writing the literal `pneuma session refine` only works when the binary happens to be on `PATH`, which it usually isn't inside the agent's sandbox. The Bash tool word-splits unquoted `$PNEUMA_CLI` correctly, so `$PNEUMA_CLI session refine ...` invokes as one command — don't quote it. |
| 19 | |
| 20 | The command POSTs to the running Pneuma server (via `$PNEUMA_SERVER_URL`), which atomically rewrites `<sessionDir>/session.json`, syncs the global registry at `~/.pneuma/sessions.json`, and broadcasts an event so any open browsers refresh the row without a reload. |
| 21 | |
| 22 | Both fields are optional. Sending just `displayName` rewrites only the title; just `description` rewrites only the summary. Send both when the session has changed enough to warrant a fresh pair. The server validates lengths and rejects empties. |
| 23 | |
| 24 | Run it from your default Bash tool. It's a one-shot HTTP call — no background process, no follow-up needed. On success the command prints `Session meta refined.` and exits 0; on failure it prints the server's error to stderr and exits non-zero. |
| 25 | |
| 26 | ## What goes in each field |
| 27 | |
| 28 | The goal is to make the row useful to a human scanning a list a week from now. Two principles: |
| 29 | |
| 30 | **Describe the session, not the work.** The row is a session identifier, not a worklog. Write what the session is *about*, the user-facing concern, not the sequence of edits you made. |
| 31 | |
| 32 | | Don't | Do | |
| 33 | |---|---| |
| 34 | | "Implemented three React hooks" | "加载状态卡片调研" | |
| 35 | | "Edited hero.html 7 times" | "Hero section landing-page iteration" | |
| 36 | | "Created file pricing.html and modified manifest.json" | "Pricing page draft for the launch site" | |
| 37 | |
| 38 | **Match the user's register.** If the user has been writing in Chinese, the refined title should be in Chinese too — they're scanning their own list. If the project's `displayName` in `project.json` is English, English is fine. Read the room. |
| 39 | |
| 40 | ### displayName (≤40 chars) |
| 41 | |
| 42 | The new title. Short. A scannable label, not a sentence. Capitalize as you would a headline. No trailing period. |
| 43 | |
| 44 | Replacement, not augmentation — the mode is shown via the row's icon (and a hover tooltip), so don't prefix with "WebCraft · ". Just the topic. |
| 45 | |
| 46 | Good shapes: |
| 47 | |
| 48 | - `加载状态卡片调研` |
| 49 | - `Hero section iteration` |
| 50 | - `Pricing page · v3 layout` |
| 51 | - `负熵痕迹 · 写作框架` |
| 52 | |
| 53 | If the user has explicitly renamed the session (via `--session-name` or a future rename UI), your `displayName` is recorded but the explicit name still wins in the listing — user intent beats inference. You don't need to detect this; the server handles precedence. |
| 54 | |
| 55 | ### description (≤280 chars) |
| 56 | |
| 57 | The new summary. One or two sentences. Should fit on one line in the row, with the second sentence as overflow on hover. Plain prose, no markdown. |
| 58 | |
| 59 | Tell a user re-encountering this row in a week: "what was I doing here?" and "should I open it?". Concrete enough to disambiguate from sibling sessions, abstract enough to survive minor reshuffles. |
| 60 | |
| 61 | Good shapes: |
| 62 | |
| 63 | - `Iterating on three loading-state card variants for the dashboard's data-fetching screens. Picked a skeleton + shimmer combo; still tuning the timing curve.` |
| 64 | - `Drafting the hero section for the launch site. Brand voice: "calm and clinical |