@scriptgun/workerc 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 workerc contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # workerc
2
+
3
+ Claude Code session management — commands, hooks, and progress tracking.
4
+
5
+ workerc adds structured session workflows to any project using [Claude Code](https://docs.anthropic.com/en/docs/claude-code). It installs slash commands for managing work sessions, hooks that enforce progress tracking and code quality, and a progress file system that persists context across sessions.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npx @scriptgun/workerc init
11
+ ```
12
+
13
+ This interactively sets up:
14
+
15
+ - **10 slash commands** in `.claude/commands/workerc/`
16
+ - **Hooks** in `.claude/hooks/` (tracker + optional lint/type check)
17
+ - **Settings** in `.claude/settings.local.json`
18
+ - **Progress directory** at `.claude/progress/`
19
+
20
+ ## Commands
21
+
22
+ | Command | Description |
23
+ |---------|-------------|
24
+ | `/workerc:new` | Start a new work session with optional spec |
25
+ | `/workerc:resume` | Resume an unclaimed session |
26
+ | `/workerc:status` | Show current session progress |
27
+ | `/workerc:list` | List all progress files with status |
28
+ | `/workerc:scope` | Update spec scope mid-session |
29
+ | `/workerc:commit` | Stage and commit with auto-generated message |
30
+ | `/workerc:review` | Review work against spec |
31
+ | `/workerc:handoff` | Pause session with handoff notes |
32
+ | `/workerc:done` | Mark session complete |
33
+ | `/workerc:abort` | Abandon session |
34
+
35
+ ## Hooks
36
+
37
+ ### Always installed
38
+
39
+ - **post-edit-tracker.sh** — Blocks edits if no progress file is active. Auto-claims pending sessions on first edit. Auto-tracks edited files. Enforces 15s freshness (agent must update progress regularly).
40
+ - **session-start-compact.sh** — Re-injects session context after Claude compacts the conversation. Restores progress file, spec, and file list so the agent can continue seamlessly.
41
+
42
+ ### Optional (auto-detected)
43
+
44
+ - **post-edit-lint.sh** — Runs linter on every file edit. Detected tools: Biome, ESLint.
45
+ - **post-edit-types.sh** — Runs type checker on every file edit. Detected tools: TypeScript (`tsc`).
46
+
47
+ ## How it works
48
+
49
+ 1. Run `/workerc:new` to start a session — creates a progress file in `.claude/progress/`
50
+ 2. The tracker hook auto-claims the session on your first file edit
51
+ 3. As you work, the tracker logs edited files and enforces regular progress updates
52
+ 4. Use `/workerc:commit` to commit, `/workerc:review` to check against spec
53
+ 5. Use `/workerc:handoff` to pause or `/workerc:done` to complete
54
+
55
+ Progress files persist across sessions — use `/workerc:resume` to pick up where you left off.
56
+
57
+ ## Re-running init
58
+
59
+ `workerc init` is idempotent. Running it again updates all commands and hooks without duplicating settings entries.
60
+
61
+ ## License
62
+
63
+ MIT
package/dist/bin.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/bin.js ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+ import { resolve } from "node:path";
3
+ import { init } from "./init.js";
4
+ const args = process.argv.slice(2);
5
+ const command = args[0];
6
+ if (command === "init") {
7
+ const projectDir = resolve(args[1] ?? ".");
8
+ init(projectDir);
9
+ }
10
+ else {
11
+ console.log(`workerc — Claude Code session management
12
+
13
+ Usage:
14
+ workerc init [dir] Install commands, hooks, and settings
15
+
16
+ Options:
17
+ dir Project directory (default: current)
18
+
19
+ Examples:
20
+ npx workerc init
21
+ npx workerc init ./my-project`);
22
+ if (command && command !== "--help" && command !== "-h") {
23
+ process.exit(1);
24
+ }
25
+ }
@@ -0,0 +1,10 @@
1
+ export interface DetectedTool {
2
+ name: string;
3
+ command: string;
4
+ extensions: string;
5
+ }
6
+ export interface DetectionResult {
7
+ linter: DetectedTool | undefined;
8
+ typeChecker: DetectedTool | undefined;
9
+ }
10
+ export declare function detect(projectDir: string): DetectionResult;
package/dist/detect.js ADDED
@@ -0,0 +1,59 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ const LINTER_CONFIGS = [
4
+ {
5
+ patterns: ["biome.json", "biome.jsonc"],
6
+ tool: {
7
+ name: "biome",
8
+ command: "npx biome check --write",
9
+ extensions: "ts|tsx|js|jsx|json|css",
10
+ },
11
+ },
12
+ {
13
+ patterns: [
14
+ "eslint.config.js",
15
+ "eslint.config.mjs",
16
+ "eslint.config.cjs",
17
+ "eslint.config.ts",
18
+ ".eslintrc",
19
+ ".eslintrc.js",
20
+ ".eslintrc.json",
21
+ ".eslintrc.yml",
22
+ ],
23
+ tool: {
24
+ name: "eslint",
25
+ command: "npx eslint --fix",
26
+ extensions: "ts|tsx|js|jsx",
27
+ },
28
+ },
29
+ ];
30
+ const TYPE_CHECKER_CONFIGS = [
31
+ {
32
+ patterns: ["tsconfig.json"],
33
+ tool: {
34
+ name: "tsc",
35
+ command: "npx tsc --noEmit",
36
+ extensions: "ts|tsx",
37
+ },
38
+ },
39
+ ];
40
+ function findConfig(projectDir, patterns) {
41
+ return patterns.some((p) => existsSync(join(projectDir, p)));
42
+ }
43
+ export function detect(projectDir) {
44
+ let linter;
45
+ for (const config of LINTER_CONFIGS) {
46
+ if (findConfig(projectDir, config.patterns)) {
47
+ linter = config.tool;
48
+ break;
49
+ }
50
+ }
51
+ let typeChecker;
52
+ for (const config of TYPE_CHECKER_CONFIGS) {
53
+ if (findConfig(projectDir, config.patterns)) {
54
+ typeChecker = config.tool;
55
+ break;
56
+ }
57
+ }
58
+ return { linter, typeChecker };
59
+ }
package/dist/init.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function init(projectDir: string): Promise<void>;
package/dist/init.js ADDED
@@ -0,0 +1,144 @@
1
+ import * as p from "@clack/prompts";
2
+ import { detect } from "./detect.js";
3
+ import { mergeSettings } from "./merge-settings.js";
4
+ import { writeFiles } from "./write-files.js";
5
+ export async function init(projectDir) {
6
+ p.intro("workerc init");
7
+ /* Step 1: Detect tools */
8
+ const spinner = p.spinner();
9
+ spinner.start("Detecting project tools");
10
+ const detected = detect(projectDir);
11
+ spinner.stop("Detection complete");
12
+ if (detected.linter) {
13
+ p.log.info(`Found linter: ${detected.linter.name}`);
14
+ }
15
+ if (detected.typeChecker) {
16
+ p.log.info(`Found type checker: ${detected.typeChecker.name}`);
17
+ }
18
+ if (!detected.linter && !detected.typeChecker) {
19
+ p.log.info("No linter or type checker detected");
20
+ }
21
+ /* Step 2: Lint hook */
22
+ let enableLint = false;
23
+ let lintCommand = "";
24
+ let lintExtensions = "";
25
+ const lintHookFilename = "post-edit-lint.sh";
26
+ if (detected.linter) {
27
+ const lintAnswer = await p.confirm({
28
+ message: `Enable lint hook? (${detected.linter.name}: ${detected.linter.command})`,
29
+ initialValue: true,
30
+ });
31
+ if (p.isCancel(lintAnswer)) {
32
+ p.cancel("Cancelled");
33
+ process.exit(0);
34
+ }
35
+ enableLint = lintAnswer;
36
+ if (enableLint) {
37
+ const cmdAnswer = await p.text({
38
+ message: "Lint command (file path appended automatically):",
39
+ initialValue: detected.linter.command,
40
+ });
41
+ if (p.isCancel(cmdAnswer)) {
42
+ p.cancel("Cancelled");
43
+ process.exit(0);
44
+ }
45
+ lintCommand = cmdAnswer;
46
+ const extAnswer = await p.text({
47
+ message: "File extensions to check (pipe-separated):",
48
+ initialValue: detected.linter.extensions,
49
+ });
50
+ if (p.isCancel(extAnswer)) {
51
+ p.cancel("Cancelled");
52
+ process.exit(0);
53
+ }
54
+ lintExtensions = extAnswer;
55
+ }
56
+ }
57
+ /* Step 3: Type check hook */
58
+ let enableTypes = false;
59
+ let typeCommand = "";
60
+ let typeExtensions = "";
61
+ const typesHookFilename = "post-edit-types.sh";
62
+ if (detected.typeChecker) {
63
+ const typesAnswer = await p.confirm({
64
+ message: `Enable type check hook? (${detected.typeChecker.name}: ${detected.typeChecker.command})`,
65
+ initialValue: true,
66
+ });
67
+ if (p.isCancel(typesAnswer)) {
68
+ p.cancel("Cancelled");
69
+ process.exit(0);
70
+ }
71
+ enableTypes = typesAnswer;
72
+ if (enableTypes) {
73
+ const cmdAnswer = await p.text({
74
+ message: "Type check command:",
75
+ initialValue: detected.typeChecker.command,
76
+ });
77
+ if (p.isCancel(cmdAnswer)) {
78
+ p.cancel("Cancelled");
79
+ process.exit(0);
80
+ }
81
+ typeCommand = cmdAnswer;
82
+ const extAnswer = await p.text({
83
+ message: "File extensions to check (pipe-separated):",
84
+ initialValue: detected.typeChecker.extensions,
85
+ });
86
+ if (p.isCancel(extAnswer)) {
87
+ p.cancel("Cancelled");
88
+ process.exit(0);
89
+ }
90
+ typeExtensions = extAnswer;
91
+ }
92
+ }
93
+ /* Step 4: Build active hooks description for compact hook */
94
+ const hookDescriptions = [];
95
+ if (enableLint) {
96
+ hookDescriptions.push(`- ${lintHookFilename} (blocks on lint/format errors)`);
97
+ }
98
+ if (enableTypes) {
99
+ hookDescriptions.push(`- ${typesHookFilename} (blocks on type errors)`);
100
+ }
101
+ hookDescriptions.push("- post-edit-tracker.sh (blocks if progress not updated within 15s)");
102
+ const activeHooksDescription = hookDescriptions.join("\n");
103
+ /* Step 5: Write files */
104
+ spinner.start("Writing files");
105
+ const result = writeFiles({
106
+ projectDir,
107
+ enableLint,
108
+ lintCommand,
109
+ lintExtensions,
110
+ lintHookFilename,
111
+ enableTypes,
112
+ typeCommand,
113
+ typeExtensions,
114
+ typesHookFilename,
115
+ activeHooksDescription,
116
+ });
117
+ spinner.stop("Files written");
118
+ /* Step 6: Merge settings */
119
+ spinner.start("Updating settings");
120
+ mergeSettings({
121
+ projectDir,
122
+ enableLint,
123
+ lintHookFilename,
124
+ enableTypes,
125
+ typesHookFilename,
126
+ });
127
+ spinner.stop("Settings updated");
128
+ /* Step 7: Summary */
129
+ p.log.success("workerc installed");
130
+ p.log.message([
131
+ "",
132
+ "Commands (10):",
133
+ ...result.commands.map((f) => ` .claude/commands/workerc/${f}`),
134
+ "",
135
+ "Hooks:",
136
+ ...result.hooks.map((f) => ` .claude/hooks/${f}`),
137
+ "",
138
+ "Settings: .claude/settings.local.json",
139
+ "Progress: .claude/progress/",
140
+ "",
141
+ "Get started: run /workerc:new in Claude Code",
142
+ ].join("\n"));
143
+ p.outro("done");
144
+ }
@@ -0,0 +1,8 @@
1
+ export interface MergeOptions {
2
+ projectDir: string;
3
+ enableLint: boolean;
4
+ lintHookFilename: string;
5
+ enableTypes: boolean;
6
+ typesHookFilename: string;
7
+ }
8
+ export declare function mergeSettings(options: MergeOptions): void;
@@ -0,0 +1,82 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ /**
4
+ * Identifies workerc-managed hooks by checking if the command path
5
+ * contains ".claude/hooks/" and one of our known script names.
6
+ */
7
+ const WORKERC_HOOK_NAMES = [
8
+ "session-start-compact.sh",
9
+ "post-edit-tracker.sh",
10
+ "post-edit-lint.sh",
11
+ "post-edit-types.sh",
12
+ ];
13
+ function isWorkercHook(hook) {
14
+ return WORKERC_HOOK_NAMES.some((name) => hook.command.includes(name));
15
+ }
16
+ function isWorkercGroup(group) {
17
+ return group.hooks.every(isWorkercHook);
18
+ }
19
+ export function mergeSettings(options) {
20
+ const settingsPath = join(options.projectDir, ".claude", "settings.local.json");
21
+ const settingsDir = dirname(settingsPath);
22
+ if (!existsSync(settingsDir)) {
23
+ mkdirSync(settingsDir, { recursive: true });
24
+ }
25
+ let settings = {};
26
+ if (existsSync(settingsPath)) {
27
+ const raw = readFileSync(settingsPath, "utf-8");
28
+ settings = JSON.parse(raw);
29
+ }
30
+ if (!settings.hooks) {
31
+ settings.hooks = {};
32
+ }
33
+ /* SessionStart: remove old workerc hooks, add compact */
34
+ const existingSessionStart = (settings.hooks.SessionStart ?? []).filter((g) => !isWorkercGroup(g));
35
+ const compactHook = {
36
+ matcher: "compact",
37
+ hooks: [
38
+ {
39
+ type: "command",
40
+ command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/session-start-compact.sh',
41
+ },
42
+ ],
43
+ };
44
+ settings.hooks.SessionStart = [...existingSessionStart, compactHook];
45
+ /* PostToolUse: remove old workerc hooks, add new ones */
46
+ const existingPostToolUse = (settings.hooks.PostToolUse ?? []).filter((g) => !isWorkercGroup(g));
47
+ const newPostToolUse = [];
48
+ if (options.enableLint) {
49
+ newPostToolUse.push({
50
+ matcher: "Write|Edit",
51
+ hooks: [
52
+ {
53
+ type: "command",
54
+ command: `"$CLAUDE_PROJECT_DIR"/.claude/hooks/${options.lintHookFilename}`,
55
+ },
56
+ ],
57
+ });
58
+ }
59
+ if (options.enableTypes) {
60
+ newPostToolUse.push({
61
+ matcher: "Write|Edit",
62
+ hooks: [
63
+ {
64
+ type: "command",
65
+ command: `"$CLAUDE_PROJECT_DIR"/.claude/hooks/${options.typesHookFilename}`,
66
+ },
67
+ ],
68
+ });
69
+ }
70
+ /* Tracker always goes last */
71
+ newPostToolUse.push({
72
+ matcher: "Write|Edit",
73
+ hooks: [
74
+ {
75
+ type: "command",
76
+ command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/post-edit-tracker.sh',
77
+ },
78
+ ],
79
+ });
80
+ settings.hooks.PostToolUse = [...existingPostToolUse, ...newPostToolUse];
81
+ writeFileSync(settingsPath, JSON.stringify(settings, null, "\t") + "\n");
82
+ }
@@ -0,0 +1,63 @@
1
+ ---
2
+ name: workerc:abort
3
+ description: Abandon current work and mark progress as aborted
4
+ allowed-tools:
5
+ - Read
6
+ - Edit
7
+ - Glob
8
+ - AskUserQuestion
9
+ ---
10
+
11
+ <objective>
12
+ Mark the current session's work as abandoned. Different from done (finished) and handoff (paused).
13
+ Use when: wrong approach, spec changed, work no longer needed.
14
+ </objective>
15
+
16
+ <process>
17
+
18
+ **Step 1: Find session progress file**
19
+
20
+ Read all `.claude/progress/*.md`. Find the one with `<!-- session: CURRENT_SESSION_ID -->` on line 2.
21
+
22
+ If none found: print "No active progress file for this session." and STOP.
23
+
24
+ **Step 2: Get reason**
25
+
26
+ Ask user:
27
+ ```
28
+ AskUserQuestion(
29
+ header: "Reason",
30
+ question: "Why is this work being abandoned?",
31
+ options: [
32
+ { label: "Wrong approach", description: "The approach didn't work out" },
33
+ { label: "No longer needed", description: "Requirements changed or feature dropped" },
34
+ { label: "Blocked", description: "Can't proceed due to external dependency" }
35
+ ],
36
+ multiSelect: false
37
+ )
38
+ ```
39
+
40
+ **Step 3: Update progress file**
41
+
42
+ - Update line 1: append " [ABORTED]"
43
+ - Update line 2: change session ID to empty `<!-- session: -->`
44
+ - Add log entry: `- [ ] ({YYYY-MM-DD HH:MM}) (abort) Abandoned: {reason}`
45
+
46
+ **Step 4: Update spec if exists**
47
+
48
+ Read line 3 for spec path. If spec exists (not "None"):
49
+ - Read the spec file
50
+ - Append to `## Rejected` section: `- {YYYY-MM-DD}: Aborted — {reason}`
51
+
52
+ **Step 5: Confirm**
53
+
54
+ Print:
55
+ ```
56
+ Aborted: {filename}
57
+ Reason: {reason}
58
+ Session unclaimed. Progress kept as historical record.
59
+ ```
60
+
61
+ STOP.
62
+
63
+ </process>
@@ -0,0 +1,145 @@
1
+ ---
2
+ name: workerc:commit
3
+ description: Commit tracked files with auto-generated conventional commit message
4
+ allowed-tools:
5
+ - Read
6
+ - Glob
7
+ - Bash
8
+ - AskUserQuestion
9
+ ---
10
+
11
+ <objective>
12
+ Stage and commit files from the current session's progress file.
13
+ Auto-generates conventional commit message from progress context.
14
+ NEVER add Co-Authored-By, AI attribution, or any footer to the commit message.
15
+ </objective>
16
+
17
+ <process>
18
+
19
+ **Step 1: Find session progress file**
20
+
21
+ Read all `.claude/progress/*.md`. Find the one with `<!-- session: CURRENT_SESSION_ID -->` on line 2.
22
+
23
+ If none found: print "No active progress file for this session." and STOP.
24
+
25
+ **Step 2: Read progress and spec**
26
+
27
+ Read the full progress file.
28
+ Read spec if one exists (line 3, not "None").
29
+
30
+ **Step 3: Check git status**
31
+
32
+ Run `git status --short` and `git diff --stat`.
33
+
34
+ Get the list of files from `## Files` section.
35
+
36
+ For each file in ## Files, check if it has uncommitted changes (modified, untracked, or staged).
37
+ Collect only files that actually have changes — skip files already committed or unchanged.
38
+
39
+ If no files have changes:
40
+ - Print: "No uncommitted changes in tracked files."
41
+ - STOP
42
+
43
+ **Step 4: Ask what to stage**
44
+
45
+ ```
46
+ AskUserQuestion(
47
+ header: "Stage",
48
+ question: "Which files to commit?",
49
+ options: [
50
+ { label: "Tracked files", description: "Only files listed in ## Files that have changes" },
51
+ { label: "Let me pick", description: "I'll tell you which files" }
52
+ ],
53
+ multiSelect: false
54
+ )
55
+ ```
56
+
57
+ **If "Tracked files":** stage all changed files from ## Files.
58
+ **If "Let me pick":** wait for user input, stage only those files.
59
+
60
+ Run `git add` for the selected files. Do NOT use `git add -A` or `git add .`.
61
+
62
+ **Step 5: Generate commit message**
63
+
64
+ **Prefix** — infer from log entries and file types:
65
+ - `fix` if log contains: fix, bug, broken, patch, repair, resolve
66
+ - `feat` if log contains: add, create, implement, new, feature
67
+ - `refactor` if log contains: refactor, move, rename, extract, reorganize
68
+ - `test` if log contains: test
69
+ - `docs` if only .md files changed
70
+ - `chore` if only config/tooling files changed
71
+ - `style` if log contains: style, css, theme, layout
72
+ - fallback: `feat`
73
+
74
+ **Scope** — infer from file paths:
75
+ - If spec exists: use spec filename slug (e.g. `auth-refactor` from `auth-refactor.md`)
76
+ - Else if all files share a common parent dir: use that dir name
77
+ - Else: use first meaningful directory from ## Files
78
+ - Keep scope short (1-2 words, no path separators)
79
+
80
+ **Message** — from progress file line 1:
81
+ - Take the work name, lowercase it
82
+ - Remove "Progress for" prefix and date suffix
83
+ - Keep it under 50 chars total (with prefix and scope)
84
+
85
+ **Body** — from last 5 log entries:
86
+ - Extract the description part (after the timestamp and scope)
87
+ - Format as bullet points with `-`
88
+ - NEVER add Co-Authored-By lines
89
+ - NEVER add AI attribution or generated-by footers
90
+ - NEVER add any trailer lines
91
+ - Body is ONLY the bullet points from the log
92
+
93
+ Full format:
94
+ ```
95
+ {prefix}({scope}): {message}
96
+
97
+ {body bullet points}
98
+ ```
99
+
100
+ **Step 6: Preview and confirm**
101
+
102
+ Print the full draft commit message in a code block.
103
+ Print the list of files that will be committed.
104
+
105
+ ```
106
+ AskUserQuestion(
107
+ header: "Commit",
108
+ question: "How does this look?",
109
+ options: [
110
+ { label: "Commit as-is", description: "Use this exact message" },
111
+ { label: "Edit", description: "I'll adjust the message" }
112
+ ],
113
+ multiSelect: false
114
+ )
115
+ ```
116
+
117
+ **If "Edit":** wait for user to provide corrected message, use that instead.
118
+ **If "Commit as-is":** proceed with the generated message.
119
+
120
+ **Step 7: Commit**
121
+
122
+ Run `git commit` with the final message. Use HEREDOC format:
123
+ ```bash
124
+ git commit -m "$(cat <<'EOF'
125
+ {final message here — NO Co-Authored-By, NO trailers}
126
+ EOF
127
+ )"
128
+ ```
129
+
130
+ IMPORTANT: The commit message must contain ONLY the prefix/scope/message and body bullets. Nothing else. No signatures, no attribution, no footers.
131
+
132
+ **Step 8: Log the commit**
133
+
134
+ Get the short hash with `git rev-parse --short HEAD`.
135
+ Add to progress log: `- [x] ({YYYY-MM-DD HH:MM}) (commit) {short_hash}: {prefix}({scope}): {message}`
136
+
137
+ Print:
138
+ ```
139
+ Committed: {short_hash}
140
+ {prefix}({scope}): {message}
141
+ ```
142
+
143
+ STOP.
144
+
145
+ </process>
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: workerc:done
3
+ description: Mark current session progress as complete and unclaim
4
+ allowed-tools:
5
+ - Read
6
+ - Write
7
+ - Edit
8
+ - Glob
9
+ ---
10
+
11
+ <objective>
12
+ Mark the current session's progress file as complete. Unclaim it so it becomes a historical record.
13
+ </objective>
14
+
15
+ <process>
16
+
17
+ **Step 1: Find session progress file**
18
+
19
+ Read all `.claude/progress/*.md`. Find the one with `<!-- session: CURRENT_SESSION_ID -->` on line 2.
20
+
21
+ If none found: print "No active progress file for this session." and STOP.
22
+
23
+ **Step 2: Pre-done suggestions**
24
+
25
+ Check progress log and git status:
26
+ - If spec exists (line 3, not "None") and no `(review)` log entry: print "Tip: run /workerc:review first to verify spec coverage."
27
+ - If no `(commit)` log entry and tracked files have uncommitted changes: print "Tip: run /workerc:commit first to commit your changes."
28
+ - Continue anyway — these are suggestions, not blocks.
29
+
30
+ **Step 3: Mark complete**
31
+
32
+ - Update line 1: append " [DONE]" to the description
33
+ - Update line 2: change session ID to empty `<!-- session: -->`
34
+ - Add final log entry: `- [x] ({YYYY-MM-DD HH:MM}) (done) Session complete`
35
+
36
+ **Step 4: Confirm**
37
+
38
+ Print:
39
+ ```
40
+ Complete: {filename}
41
+ Session unclaimed. This is now a historical record.
42
+ ```
43
+
44
+ STOP.
45
+
46
+ </process>