--- name: trekendsession description: Mark the current session as complete and write session-state pointing at the next session. Helper for informal multi-session flows. argument-hint: " | --help" disable-model-invocation: true --- # Voyage End-Session Local v1.0 Tiny helper for **informal** multi-session flows (no formal plan with Execution Strategy). Writes a `.session-state.local.json` pointing at the next session so `/trekcontinue` can resume in a fresh Claude chat. For formal flows (a plan produced by `/trekplan --project`), `/trekexecute` Phase 8 already writes the state file — this helper is unnecessary there. Use this command for ad-hoc release runs, manual multi-session handovers, or any flow that does not run through `/trekexecute`. Pipeline position: ``` ... session N work ... /trekendsession "" → writes state ... session boundary, fresh chat ... /trekcontinue → reads state, starts session N+1 ``` See **Handover 7** in `docs/HANDOVER-CONTRACTS.md` for the schema. ## Phase 0 — `--help` handling Parse `$ARGUMENTS` with the arg parser. Run this via the Bash tool at runtime (NOT eager-exec): ```bash setopt nonomatch 2>/dev/null || true node ${CLAUDE_PLUGIN_ROOT}/lib/parsers/arg-parser.mjs --command trekendsession -- $ARGUMENTS ``` It prints the parse result as JSON. On exit 1, print its `errors` and stop. Print the usage block below and exit cleanly ONLY when one of these two conditions equals exactly true (no substring search, no "contains" check): - `flags['--help'] === true`, OR - `positional[0] === '-h'` (single-dash short form — the parser keeps it as positional because the schema declares no alias). Then do NOT proceed to any further phase. In every other case — a slug or a label that holds `-h` or `help` too — go on to Phase 1. ``` /trekendsession — Mark current session done; point at next session. Usage: /trekendsession /trekendsession --help Both arguments are REQUIRED. No interactive prompt — headless-safe. Writes /.session-state.local.json with: schema_version 1 project next_session_brief_path next_session_label status in_progress updated_at Then validates via lib/validators/session-state-validator.mjs and prints the same 3-line narration that /trekcontinue will show in the next session. Example: /trekendsession .claude/projects/2026-05-01-feature/brief.md "Session 2 of 3" ``` ## Phase 1 — Resolve project directory Resolve the nearest `.claude/projects/*/brief.md` from cwd (the current working directory). Use `node -e` enumeration (NOT shell glob — harness-mode safety): ```bash !`node --input-type=module -e "import {existsSync, readdirSync} from 'node:fs'; import {join} from 'node:path'; const root='.claude/projects'; if(!existsSync(root)) process.exit(0); readdirSync(root).filter(d=>existsSync(join(root,d,'brief.md'))).forEach(d=>process.stdout.write(join(root,d)+'\\n'));"` ``` Decision tree: - **0 candidates:** print error to stderr — "no `.claude/projects//brief.md` found under cwd; cannot determine project directory" — and exit 1. Do NOT fall back to a synthesized path. - **1 candidate:** use it as ``. Continue. - **>1 candidates:** print all paths and ask the operator to `cd` into the intended project directory before retrying. Exit 1. ## Phase 2 — Required args check (headless-safe) Read the parse result from Phase 0: `` is `positional[0]` and `` is `positional[1]`. Both are required. If either is missing or empty: ``` Error: missing required args. Usage: /trekendsession '' ``` Print to stderr and exit 1. **No interactive prompt** — this keeps the helper headless-safe (per brief NFR; addresses adversarial-review major #11). If you want an interactive flow, use `/trekcontinue --help` to see the full pipeline. ## Phase 3 — Atomically write `.session-state.local.json` + sibling NEXT-SESSION-PROMPT.local.md Write `{project_dir}/.session-state.local.json` with the schema-v1 object: ```json { "schema_version": 1, "project": "{project_dir}", "next_session_brief_path": "{arg 1}", "next_session_label": "{arg 2}", "status": "in_progress", "updated_at": "{now, ISO-8601}" } ``` Use the atomic-write util — write to `.tmp`, then `rename` into place — to avoid partial-state on crash. The util is ESM, so invoke via `node --input-type=module -e` with an `import` statement (a CommonJS shim would throw `ERR_REQUIRE_ESM` on Node 18+ since `atomic-write.mjs` is ESM). Under `node --input-type=module -e "