本文へ移動
cccskills
無料GitHub で公開

end-session

This skill should be used when the user explicitly types "/end-session": the mandatory final step of any session started or resumed with /start-project or /resume-project, which the agent prints alone in its own block as the session's last line for the user to type, never invoking it directly. It updates the active project's PLAN.md (Status, kickoff, log), checks the PLAN against itself, and commits+pushes. Do not auto-invoke on vague phrases mid-session.

日本語の概要は準備中です。原文の説明を表示しています。

jellyrock/jellyrockスター 46(GitHub 46 + cccskills 0)

実行スコア 未検証

インストール方法を見る

含まれるファイル(3)

  • SKILL.md22.4 KB
  • move-old-decisions.sh8.4 KB
  • replace-section.sh7.7 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

End Session

This repo

  • Journal writes are not committed here (commit=no): a tail /log writes rides the next code PR, and a journal-only change gets no PR of its own (No standalone journal PR). When the project is paused and no code PR is coming, keep the tail in the PLAN.

Contract

Goal. Close out the current session on the active project and hand off cleanly, so the next session can resume cold. This is the mandatory final step of any project-tracked session, the soft enforcement point of the whole lifecycle. It updates the project's PLAN.md (Status as live state, dated decisions, open questions and waits, a kickoff rewritten in the template's skeleton, an appended Session-log line), sweeps the session for deferred tails and routes the cross-cutting ones to /log, sets the project's end-of-session status, checks the PLAN against itself with a script before committing, commits and pushes, proves the handoff loads cold, and releases the session's claim on the project. The work is judgment-heavy synthesis (distilling a whole session into an accurate status delta and a kickoff a memoryless reader can act on, plus careful commit hygiene in a possibly-shared working tree), so the skill runs at the judgment-grade tier; the mechanical checks are scripts.

Inputs. Any arguments are ignored. The skill identifies the project from the session: whatever was loaded via /start-project or /resume-project, else the single active project (ask if several are). It expects the project's PLAN.md to be readable and the session's actual work to be verifiable against git log / git status.

Outputs.

  • An updated PLAN.md: Status holding live state only (the current phase with its id first, one line per phase, today's dated decisions prepended with the ones past the list's size moved (never deleted) to DECISIONS.md beside the PLAN, open questions still open, waits-on: current, last-updated: today), detail moved to its ## Reference section, a kickoff rewritten in the template's skeleton, and one appended Session-log line.
  • Cross-cutting deferred tails routed through /log (written to the journal and committed on their own, or left to ride with the change that prompted them where this repo commits journal writes that way), and a Cross-cutting tails routed: {{N}} line. Project-scoped tails stay in the PLAN, never double-booked.
  • The project's end-of-session status set (active by default; paused / completed / abandoned only on a real signal, with archival for the terminal states).
  • A PLAN that passes resume-state.sh --check, committed and pushed by explicit pathspec in the repo that holds the projects folder (through projects-write.sh when that is a projects home, a repo of its own; nothing to commit where that folder is gitignored), a clean cold load, and the claim released. A push to a projects home that fails never stops the close: the PLAN stays written there, and the next resume shows it as a pending sync.

Success criteria.

  • Status reflects what actually shipped, verified against git log, never aspirational. Invented progress is the cardinal sin here.
  • The kickoff and Status cannot contradict each other: the kickoff's Starts at names Status's current phase, that phase is in Phase progress and not ✅, and the check that says so ran and passed before the commit.
  • The kickoff is self-contained and in the skeleton: a reader with no memory of this session can act on it cold, each fact written once in its owner's place (phase state in Status, the plan for next time in the kickoff).
  • Every landmine the last kickoff carried is still there, or the Session log says why it stopped being true.
  • Deferred tails are sorted by scope, and every cross-cutting one is actually written to the journal, never claimed-captured in the PLAN narrative but lost at the boundary.
  • The commit lands on the intended branch, staged by explicit pathspec, with no foreign files swept in; a terminal close moves the project directory into _archive/ inside that same commit, both paths staged.
  • The end-of-session status is correct and low-friction: active is inferred silently when obvious; the choice is asked in chat only on a genuine ending or pausing signal.
  • The next /resume-project would load with no banner: this skill ran the reader itself and fixed what it named.

Failure modes to avoid.

  • Inventing progress. Status records what shipped, confirmed against git log, not what was hoped or intended. If it didn't land, it isn't done.
  • Committing a PLAN that contradicts itself. A kickoff that still starts at a phase Status marks done sends the next session off the stale half. The check is a script, run before the commit; a failure is fixed in the PLAN, never committed as is.
  • A kickoff that assumes session memory. Write it for a cold reader. "Continue where we left off" is useless; "Phase D is next; templates are missing at X; read Y first" is actionable.
  • A kickoff check the next session can't actually run. When the kickoff asks the reader to verify something ("did the plan land?", "did the backfill finish?"), key it on the artifact (a symbol in the source, a row in the data, a file on disk), never on a branch name, a commit subject or trailer, or a git log -N window. Branches get deleted or squashed, subjects get reworded, and a log window slides past the commit, so those checks answer "not done" about work that shipped and send the next session back at it.
  • A stated count that rots. A value that can change after the close (a count, a queue, a state) is written as the command that measures it and the value it showed, never as a bare number.
  • Dropping a landmine silently. Each one was learned by getting it wrong once; drop one and the next session relearns it the expensive way.
  • Letting Status grow into a history. Every resume prints Status in full. The session's story belongs in the Session log, findings and finished-phase detail in Reference: moved, never deleted, since a gitignored PLAN has no history to recover them from.
  • Deleting a decision to make room. The decisions list keeps the newest few; every older one moves to DECISIONS.md. The move is scripted, and the script refuses to write when its count of decisions would change. A decision /log already added this session is not added again.
  • Double-booking a tail, or letting a cross-cutting one die at the boundary. Project-scoped tails belong in the PLAN; cross-cutting ones in the journal, written through /log and confirmed landed. A missing journal or /log is a defect to fix, never a reason to record "no tails".
  • Sweeping foreign files into the commit. In a shared working tree a parallel agent can switch the branch or stage its own files. Verify branch + staging first; commit by explicit pathspec; re-check the branch after.
  • The pathspec-commit footguns. In git commit -m "msg" -- {{paths}}, -m must come before --; new files must be git add'd first (the -- {{paths}} form commits only tracked paths); an archive move needs both the old and the new path in the pathspec, or the deletion silently drops out of the commit.
  • Prompting for the status every session. Default to active silently; ask only on a real ending or pausing signal. A question every session is friction that erodes the skill.
  • Running it yourself, or never printing it. There is no Stop hook: the close happens only when the agent prints /end-session alone in its own block as the session's last line and the user types it. Started by the agent, it runs at the session's model and effort instead of its own pins; never printed, it never runs, and the PLAN is left stale and the next session blind.

When not to use.

  • The session never loaded a tracked project (pure ad-hoc work). Capture any tail via /log followup and commit normally: there's no PLAN to close.
  • You want to capture a single followup mid-session without closing. That's /log, not /end-session.
  • You're pausing for a coffee break, not ending the session. Don't churn the PLAN for a non-gap.
  • Do not auto-invoke, on vague mid-session phrases or at a project session's end. This runs when the user types /end-session; a project-tracked session prints it as its last line for them to type.

Implementation

Every read of the PLAN goes through bash .claude/skills/resume-project/resume-state.sh (the reader /resume-project uses, so the close sees what the next resume will see); the projects folder is whatever bash .claude/skills/start-project/projects-dir.sh prints. Repo facts this skill reads: this repo's capture types and its public posture; anything else this repo needs at a close (a hook that regenerates a file, a check before a push that deploys, a harvest before archiving) is in this skill's ## This repo, when it has one.

Step 1: Identify the project

If this session loaded one via /start-project or /resume-project, use that slug. Otherwise run bash .claude/skills/resume-project/resume-state.sh --check with no slug: it picks the single active project, or lists the active ones (exit 2) so you can ask in chat which.

Step 2: Read what you will rewrite

Run bash .claude/skills/resume-project/resume-state.sh {{slug}}. It prints Status, the kickoff, the last Session-log line, what the project waits on, and the commits made since the PLAN was saved (this session's work, for the log line); read any other section by its heading. Never read the whole PLAN: it can pass 100KB, and a part read is enough to edit it. A sed, awk or head slice of the PLAN, or a git log range you picked, is no substitute: it skips what the reader adds (the save commit, what the project waits on, the size flag), and a Status rewritten from memory instead of from this output drifts from the PLAN.

Step 3: Update Status: live state only

  • Current phase starts with the phase's id (D: the build), the one the kickoff will start at.
  • Rewriting Status whole: put it in place with replace-section.sh (Step 4 shows the call; the section name is "Status"), and before running move-old-decisions.sh below, since a later rewrite could undo its move. The body keeps every existing decision (copy them from the resume output), and the script refuses a body that drops one.
  • Phase progress: one line per phase, ✅ / 🚧 / ⬜ first after the id. A finished phase is one line: - C ✅ done (commits a1b2..c3d4): {{outcome in a clause}}, its range (first and last commit) taken from git log --oneline, never from memory; as a git range a1b2..c3d4 leaves out a1b2, so a command built from it (a revert, a diff) says a1b2^..c3d4 (a phase that made no commits says no commits and where its result lives); its detail moves to ## Reference under a heading naming the phase.
  • Decisions: prepend today's, dated, a few lines each (the full reasoning lives in the commit message), skipping any /log decision already added this session. Then run bash .claude/skills/end-session/move-old-decisions.sh {{project-dir}}/PLAN.md: it keeps the newest few and moves the rest to DECISIONS.md, never deleting one. If it refuses (a duplicate, no decisions heading), fix what it names and run it again; never trim the list by hand.
  • Open questions / blockers: delete the ones this session answered. A blocker only a person or an outside event can clear is tagged [external-gate: {{reason}}], and after:{{date}} goes in waits-on: as the day to check on it again (ask in chat for the date when this session does not know one). Remove both when it clears; when the date passes and the gate still holds, set a later date.
  • waits-on: in the frontmatter lists what another project or a followup must finish first, comma-separated, in the values waits.md lists (another followup, a project or one of its phases, a time, or another repo's project). Add one when this session found such a wait; remove each reference the reader showed as met.
  • Punch-list: tick off the items this session cleared (- [x]), add the ones it surfaced.
  • last-updated: in the frontmatter is today, from date +%F.

Step 4: Rewrite the kickoff in the skeleton

Write the whole section in the template's shape (its <…> fill-ins stay the PLAN template's own, which the scripts read as unfilled text), for a reader with no memory of this session, then put it in place with the script below (the body only: the script keeps the heading):

**Starts at:** <Current phase's id>: <the step to start with>

**Last session stopped:** <where it stopped and why, in a sentence or two>

**Unanswered:** <questions put to the operator that got no reply, or "none">

### Verify first

- `<command>` prints `<the one line it printed at the close>` <what its numbers mean, when the line does not say>

### Next, in order

1. <step>

### Required reading

- <file or section, and why>

### Landmines

- <a trap that bites inside this project, and how to avoid it>
bash .claude/skills/end-session/replace-section.sh {{project-dir}}/PLAN.md "Next-session kickoff" {{body file, or - for a quoted heredoc}}

It replaces exactly one ## section and leaves the rest of the PLAN byte for byte; it refuses, writing nothing, a name that matches no section or several, an empty body, and a body with a # or ## heading outside a code block. If it refuses, fix what it names and run it again; never splice a section by hand.

  • Each fact has one owner. What this session did is stated in Status and the log with its evidence (a commit, an artifact), not re-described here. A value that can change after the close goes in Verify first as `command` prints `the line it printed`. Only the ones the next work depends on go there. The command prints one line (a value whose text holds a backtick is written in double backticks), and a note after the backticked value may say what each number in it means; a command cut down with | tail or | grep keeps that meaning in the note, since the next session cannot read a column whose header was cut off. Run each command first and copy what it printed: Step 8 runs every one again and fails a value that differs.
  • Landmines carry forward. Keep every one the last kickoff had unless it has stopped being true, and add the ones this session found. A trap that bites outside this project is not a landmine here: Step 6 routes it.
  • A part with nothing in it holds the single line none (no bullet): the check reads every bullet under Verify first as a command and its value.
  • Cite a followup by its fid ([fid: …]), never by its position in the journal.

Step 5: Append one line to the Session log

Add it at the bottom: the log is oldest first, and a resume shows its last entry. Dated; a second session the same day is (s2), and so on. A session that began with /start-project already wrote its line: extend that line rather than adding a second. Say what shipped (with its commit range), what was found, and what went wrong or had to be redone: a log that records only successes is useless for a cold read. Name any landmine you dropped and why it stopped being true.

Step 6: Route the deferred tails

Sweep the session for loose ends that surfaced but won't be done here. Project-scoped ones already live in the PLAN (Steps 3–4); do not also route them through /log, which double-books them. Cross-cutting ones (a fix elsewhere in the repo, a "we should look at X" outside the phases, an audit item for later) go through /log followup; a trap that bites outside this project goes through /log with the type that fits from this repo's capture types. Confirm each landed. If the journal or /log is missing, that is a defect to fix before this step can pass, never a reason to route nothing. Close the step with the line, printed whatever the count:

Cross-cutting tails routed: {{N}}

Carry this line into the session's final summary too. A close whose Steps 3–5 went in as one scripted edit tends to jump from the PLAN to the commit, and a summary that lists what was logged without the count has skipped this step.

Step 7: Set the end-of-session status

Default to active: no change, and no question, while phases are still in progress or pending. Ask in chat only on a real signal that the project is ending or pausing (the final phase has shipped, every phase is ✅, or the user said "we're done" / "let's pause this" / "this isn't working"), with the options and a recommendation:

  • paused: status: paused in the frontmatter and on its row in the projects folder's README.md; it stays in the Active table (/resume-project won't auto-select it). No archival.
  • completed: status: completed; move the project directory into the projects folder's _archive/ (git mv where the folder is tracked, plain mv where it is gitignored); move its README row to the Archived list with a one-line closing summary and the date. Before completed, read each Charter success criterion against what shipped: one not met is written UNMET in the closing summary, never counted met through a substitute; one waiting on an event that may never come closes as a recorded defer, with a followup that tracks it.
  • abandoned: as completed, plus a one-line reason in Status and on the archived row.

For a terminal close, the kickoff becomes one line, Project closed {{date}}: {{why}}, put in place with replace-section.sh as in Step 4; its landmines drop with it, and the Step 5 log line says so, since Step 8's check skips its landmine review on a closed PLAN. After an archive move, search the whole repo (not only the docs) for the old path and re-point every hit in the same commit: a moved PLAN breaks links, registries and tests that name it. Decide this before Step 8 so every change lands in one commit.

Step 8: Check the PLAN

Run bash .claude/skills/resume-project/resume-state.sh --check {{slug}}. Every FAIL: line is a contradiction or a missing part: fix it in the PLAN and run the check again until it prints RESULT: ok. A Verify first: FAIL is a value that differs from what its command prints now: copy the printed line, never edit the command to match the value. The check runs each command (60 seconds each at most), so a Verify first command only reads. A REVIEW: line is answered as it says (a dropped landmine may instead be put back). A NOTE: line informs.

Step 9: Commit and push

The PLAN is committed in the repo that holds the projects folder. If git -C {{projects folder}} check-ignore -q . succeeds, the folder is gitignored: there is no PLAN commit, never git add -f it, and the PLAN must be the last thing written this session (after every other commit), because the next resume dates an untracked PLAN by its file time and reads any later commit as work the kickoff has not seen. Otherwise:

  1. git -C {{repo}} branch --show-current is the intended branch, and git -C {{repo}} status --short shows nothing staged that isn't yours (a parallel session may share the tree). Commit by explicit pathspec, never -a.
  2. git add any new file first (DECISIONS.md, an archive's new path). Stage the PLAN, DECISIONS.md, the README when Step 7 changed it, and for an archive move both the old and the new directory; git diff --cached --name-status must show the move as R (or a D for every old path).
  3. git commit -m "{{subject naming the project and the session's outcome}}" -- {{paths}} (-m before --). When this repo's public posture is public, re-read the subject and body first: no other repository or host, no person, email or home path, no secret. If a hook refuses, fix what it names and commit again, never --no-verify.
  4. Push, then re-check the branch. If the commit landed on the wrong branch, cherry-pick it onto the right one and move the stray branch back.

When the projects folder sits in another repo than this one (a projects home: git -C {{projects folder}} rev-parse --show-toplevel is not this repo's top), steps 1 to 4 do not apply. Run (cd {{projects folder}} && bash {{repo}}/.claude/skills/start-project/projects-write.sh --subject "{{subject}}" -- {{paths}}) with the same paths: for an archive move, the old and the new directory. It commits only those paths and pushes, and other sessions' files in that shared clone stay as they were. Exit 0 means pushed. On exit 3 (the change overlaps the remote) or 4 (not pushed) the PLAN stays written there, uncommitted: say so in the report, never push it another way, and go on; the next resume shows it as a pending sync. In a session whose machine will not last (a cloud session), also print the whole PLAN in chat, so the record outlives the machine.

Step 10: Prove it loads cold, then release the claim

Run bash .claude/skills/resume-project/resume-state.sh {{slug}} once more: it is what the next session will see. Every BANNER: line is something to fix now (a dirty tree, an unpushed commit, a commit after the PLAN's save, a PLAN check), not to hand on. After a push to a projects home that failed in Step 9, its pending-sync banner is expected: run its command once more, and if it still cannot push, leave it and say so in the report. After a terminal close its is closed (archived) banner is the cold load, the one BANNER: to leave, and the read stops before its own checks, so check them by hand: git status --short lists nothing of yours, and git status -sb shows no ahead. Then bash .claude/skills/resume-project/resume-state.sh --release {{slug}}, so the next session is not warned about this one.

Notes

  • Split planning and execution. When a planning session hands a plan to a separate executing session (a /focus plan picked up fresh), the planning session ends with /end-session right after the hand-off, printed for the user to type: the PLAN's log keeps the design narrative, git log the execution. The kickoff then checks the plan's landing by its artifact, never its branch or commit (Failure modes).

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

catchup

無料

Session-start briefing: where did I leave off, what is in flight, what needs attention. One tested script reads git, the journal (followups, running work, cadences) and tracked projects and prints every fixed-threshold check that fires; JellyRock's own aggregator adds open PRs, high-engagement bugs, recent bug reports, current-branch CI, pending handoffs, open upstream-watch issues (Jellyfin releases and release candidates, Roku OS), recent ADRs, tech debt and architecture-doc staleness. Ends with one Suggested next move that hands off to /log, /done, /issue-triage, /runtime-triage, /ci-triage or /server-upgrade. Mandated by AGENTS.md's catchup-discipline rule: run at the start of any genuine new session, after a multi-day gap, or whenever you ask what the state of the world is.

日本語の概要は準備中です。原文の説明を表示しています。

jellyrock/jellyrock462026年10月26日 更新

ci-triage

無料

Diagnose a failed CI workflow run and fix it the /snag way. A tested read-only script fetches the run, reports every failed job and step with the log region around its errors (not the post-job cleanup), and classifies each against this repo's gates.tsv, printing the banner a gate carries when its obvious fix is the wrong one. Then: re-run only what is transient, reproduce locally, find the root cause, and show one decision screen; the chosen fix is built test-first and committed on a fix branch, never pushed. Use when a CI run failed on a pull request or on the default branch.

日本語の概要は準備中です。原文の説明を表示しています。

jellyrock/jellyrock462026年10月26日 更新

DEPRECATED, replaced by the `enrich` phase built into /crash-report. The old flow filed crash issues first and enriched them one by one afterward. The new flow (stage, then enrich, then file) pulls the dashboard backtrace before filing, so issues are born complete and architectural-class crashes go to their epic instead of becoming standalone issues. Do not invoke it for new work: run /crash-report and paste the backtraces during its enrich step. It stays only as a redirect; the `enrich-issue` script subcommand still exists as a legacy escape hatch for a crash issue filed before the change.

日本語の概要は準備中です。原文の説明を表示しています。

jellyrock/jellyrock462026年10月26日 更新

Process a Roku weekly crash-report CSV (or a zip holding one or more CSVs) into tracked GitHub issues and architectural-epic evidence, enriching before filing (stage, then enrich, then file). STAGE parses and filters the CSV, groups by pkg-path signature, builds each cited app version in a temporary git worktree, maps the transpiled `.brs` line back to the source `.bs` line, runs the GitHub dedup search, and writes a local worksheet where every crash starts pending; a mechanism hint (task-launch, network, other) orders which to pull first but never authorizes a file. ENRICH folds in the per-crash backtraces you paste from Roku's dashboard (a 7-day window, one click per crash, no bulk export), extracts each `&hNN` exception code, and routes every crash to a disposition (nothing files or aggregates without a backtrace): `file` (a scoped bug becomes a new per-signature [crash] issue, born enriched), `aggregate` (a known architectural class: `&h29` big-library too-many-task-threads, `&h23` render-thread execution timeouts, the `&hec` init `m.global.constants` race; upserted as one flat record comment per `file·function·line·version` onto the class epic, never a standalone issue), or `watch` (accepted noise, a spike comment only). FILE performs the GitHub writes (create, comment or reopen for scoped bugs; the epic record upsert for architectural classes) and writes a run-summary handoff. Dedup-aware and idempotent. Use when a fresh Roku crash CSV arrives (weekly). A deep dive on one crash goes to `/issue-triage <N>` after filing.

日本語の概要は準備中です。原文の説明を表示しています。

jellyrock/jellyrock462026年10月26日 更新

Draft a GitHub issue body for the JellyRock repo from a Reddit/Discord post or free-form bug report and submit it via forge.sh. Reads the YAML form templates under .github/ISSUE_TEMPLATE/ to know which fields are required, fills them by extracting from the input, asks for any missing required fields, validates the body matches the chosen template's schema, then runs forge.sh issue create with the auto-labels the template defines. Use when you have a user report (paste from anywhere) and want to formalize it into a properly-structured GitHub issue.

日本語の概要は準備中です。原文の説明を表示しています。

jellyrock/jellyrock462026年10月26日 更新

dep-major

無料

Walk a major dependency-version bump (a Renovate major PR, possibly a grouped one carrying several deps, or a package you name) through JellyRock's major-bump SOP so the judgment steps run the same way every time. Resolves each package and its from and to versions, fetches the upstream changelog/migration guide for that range, classifies the breaking changes, greps the codebase for the call sites those breaks actually hit, runs the mechanical gate that fits the dependency's type (a runtime BrightScript lib: validate, build, lint:bs, then test:unit and test:rta on a device; JS or Node tooling: test:scripts, then run the affected script; GitHub Actions: the PR's own CI plus a trace of the conditional paths CI doesn't exercise), and returns a go/no-go with any required migration surfaced (and applied on request). Majors never automerge (the org Renovate config), so this is the human-review path. Use when a Renovate major PR appears, or before bumping a dependency's major version by hand. Not for patch or minor bumps (those automerge after a soak) or for Jellyfin server releases (use /server-upgrade).

日本語の概要は準備中です。原文の説明を表示しています。

jellyrock/jellyrock462026年10月26日 更新

jellyrock のスキルをすべて見る

このスキルの問題を報告する