Claude
Skills
Sign in
Back

swain-session

Included with Lifetime
$97 forever

Session management and project status dashboard. Owns the full session lifecycle (start/work/close/resume), focus lane, bookmarks, worktree detection, and tab naming. Also serves as the project status dashboard — shows active epics, progress, actionable next steps, blocked items, tasks, GitHub issues, and recommendations. Worktree creation is deferred to swain-do task dispatch (SPEC-195). Triggers on: 'session', 'status', 'what's next', 'dashboard', 'overview', 'where are we', 'what should I work on', 'show me priorities', 'bookmark', 'focus on', 'session info'.

Productivityscripts

What this skill does

<!-- swain-model-hint: haiku, effort: low -->

# Session

Manages session identity, preferences, and context continuity across agent sessions. This skill is agent-agnostic — it relies on AGENTS.md for auto-invocation.

## Auto-run behavior

This skill is invoked automatically at session start (see AGENTS.md). When auto-invoked:

1. **Restore tab name** — run the tab-naming script
2. **Load preferences** — read session.json and apply any stored preferences
3. **Show context bookmark** — if a previous session left a context note, display it

When invoked manually, the user can change preferences or bookmark context.

## Session purpose text

When the operator launches with free text (e.g., `swain new bug about timestamps`), the launcher exports `SWAIN_PURPOSE` and — for runtimes that accept an initial prompt — also passes it inline as `/swain-session Session purpose: new bug about timestamps`.

The launcher is responsible for choosing the checkout that will own that bookmark:
- If the operator starts from the main checkout, the launcher opens a new worktree first and only then passes the session purpose.
- If the operator starts inside a linked worktree that already has a bookmark, the launcher should steer them to resume/finish that worktree or open a different worktree before reusing the purpose text.

The greeting script (`swain-session-greeting.sh`) reads `$SWAIN_PURPOSE` and writes the bookmark deterministically (SPEC-297). The greeting JSON exposes the captured text as the `purpose` field.

When the greeting JSON's `purpose` field is non-null:
- Display it to the operator: `**Session purpose:** <text>`.

Do not re-parse the initial prompt or call `swain-bookmark.sh` yourself — the greeting already did both. The inline prompt text is for display context only; the env var is the source of truth.

## Preflight

Before any step, run the preflight script to gather all session state in a single pass. This replaces the old subprocess chain (greeting → bootstrap → tab-name) with one read-only script.

```bash
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
PREFLIGHT_SCRIPT="$(find "$REPO_ROOT" -path '*/swain-session/scripts/swain-session-preflight.sh' -print -quit 2>/dev/null)"
PREFLIGHT_JSON=$( bash "$PREFLIGHT_SCRIPT" --repo-root "$REPO_ROOT" 2>/dev/null )
echo "$PREFLIGHT_JSON"
```

Store `PREFLIGHT_JSON` for use in all steps below. Every decision references a field from this JSON — do not run additional check commands unless performing a mutation.

## Step 1 — Fast Greeting (SPEC-194)

Run the greeting script. It calls the preflight internally and applies lightweight mutations (tab naming, lock cleanup, .agents dir creation). It does **not** invoke specgraph, GitHub API, or the full status dashboard.

```bash
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
bash "$REPO_ROOT/.agents/bin/swain-session-greeting.sh" --json
```

The greeting emits structured JSON:

```json
{
  "greeting": true,
  "branch": "trunk",
  "dirty": false,
  "isolated": false,
  "bookmark": "Left off implementing the bootstrap script",
  "focus": "VISION-001",
  "tab": "project @ branch",
  "warnings": []
}
```

The preflight JSON also includes previous session state under `prev_session`, which eliminates the need for a separate `swain-session-state.sh resume` call:

```json
{
  "prev_session": {
    "exists": true,
    "status": "closed",
    "session_id": "session-20260404-215204-9576",
    "focus_lane": "INITIATIVE-002",
    "phase": "closed",
    "start_time": "2026-04-05T01:52:04Z",
    "end_time": "2026-04-06T04:10:09Z",
    "decisions_made": 0,
    "walkaway": "Reviewed and fixed SPIKE-058"
  }
}
```

**After receiving the greeting JSON:**

1. Present the greeting to the operator — branch, dirty state, bookmark (if any), focus lane (if any), and warnings.

2. If `prev_session.exists` is true, display the previous session context (from the preflight JSON) so the operator can decide whether to continue or start fresh.

3. If `isolated` is `false` and the operator has not started work yet, **do not create a worktree now** — worktree creation is handled by bin/swain pre-launch (SPEC-245). If a worktree name is needed for reference, generate it:
   ```bash
   bash "$REPO_ROOT/.agents/bin/swain-worktree-name.sh" "context"
   ```
   Then re-run the greeting with `--path` to refresh tab name and context:
   ```bash
   bash "$REPO_ROOT/.agents/bin/swain-session-greeting.sh" --path "$(pwd)" --json
   ```

3. If `bookmark` is not null, display it:
   > **Resuming session** — Last time: {bookmark}

4. The session is now ready for work. The full status dashboard is available on-demand (see [Status Dashboard](#status-dashboard-spec-122)).

**If `$TMUX` is NOT set** (detected by absence of `tab` in the JSON), check whether tmux is installed:
- **tmux not installed:** Offer to install it (`brew install tmux`).
- **tmux installed but not in a session:** Show: `[note] Not in a tmux session — session tab and pane features unavailable`

The operator can say "exit worktree" or "back to main" at any time — this ends the session. bin/swain handles worktree cleanup after the runtime exits (SPEC-245).

### Worktree / branch changes (agent-agnostic)

When an agent enters a worktree or switches branches, re-run the bootstrap with `--path` to update the tab name:

```bash
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
bash "$REPO_ROOT/.agents/bin/swain-session-bootstrap.sh" --path "$NEW_WORKDIR" --skip-worktree --auto
```

This is agent-agnostic — works in Claude Code, opencode, gemini cli, codex, copilot, or any agent that reads AGENTS.md and can run bash commands.

### Session.json schema

```json
{
  "lastBranch": "trunk",
  "lastContext": "Working on swain-session skill",
  "preferences": {
    "verbosity": "concise"
  },
  "bookmark": {
    "note": "Left off implementing the bootstrap script",
    "files": ["SKILL.md"],
    "timestamp": "2026-03-10T14:32:00Z"
  }
}
```

**Migration:** If `.agents/session.json` does not exist but the old global location (`~/.claude/projects/<project-path-slug>/memory/session.json`) does, the bootstrap script copies it automatically.

## README Reconciliation Checkpoint (SPEC-209)

After the greeting and before work begins, compare README.md against the artifact tree. This runs once per session, at focus lane selection time.

### Trigger

When a focus lane is set (either restored from a previous session or newly selected), and README.md exists:

```bash
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
[ -f "$REPO_ROOT/README.md" ] && echo "has_readme" || echo "no_readme"
```

If no README exists, skip reconciliation silently — swain-doctor will flag the missing README.

### Process

1. Read README.md and extract claims — any statement about what the project does, who it's for, how it works, what it supports, or what behavior it exhibits. Read the entire README as prose; no markers or section conventions required.
2. Compare claims against current Active Visions, Designs, Journeys, and Persona artifacts. Look for:
   - **Stale promises** — README claims a feature or behavior that an artifact explicitly dropped or superseded.
   - **Missing coverage** — an artifact describes a capability the README doesn't mention.
   - **Contradictions** — README and artifact disagree on behavior, audience, or scope.
3. For each mismatch, surface a specific question to the operator:
   > "README says '{claim}' but {artifact-id} {describes the conflict}. Which is right?"

### Reconciliation direction

Bidirectional. Drift does not assume artifacts are right:
- A new Vision may mean the README needs updating.
- The README may be right and the Vision needs reshaping.
- A promise may have been intentionally dropped and needs removing from both.

### Deferral tracking

The operator can defer any mismatch. Deferrals are tracked in `.agents/session.json` under a `readme_deferrals` key:

```json
{
  "readme_deferrals": [
   
Files: 26
Size: 206.3 KB
Complexity: 90/100
Category: Productivity

Related in Productivity