@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 +21 -0
- package/README.md +63 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +25 -0
- package/dist/detect.d.ts +10 -0
- package/dist/detect.js +59 -0
- package/dist/init.d.ts +1 -0
- package/dist/init.js +144 -0
- package/dist/merge-settings.d.ts +8 -0
- package/dist/merge-settings.js +82 -0
- package/dist/templates/commands/abort.md +63 -0
- package/dist/templates/commands/commit.md +145 -0
- package/dist/templates/commands/done.md +46 -0
- package/dist/templates/commands/handoff.md +81 -0
- package/dist/templates/commands/list.md +32 -0
- package/dist/templates/commands/new.md +108 -0
- package/dist/templates/commands/resume.md +64 -0
- package/dist/templates/commands/review.md +86 -0
- package/dist/templates/commands/scope.md +74 -0
- package/dist/templates/commands/status.md +30 -0
- package/dist/templates/hooks/post-edit-lint.sh.tmpl +27 -0
- package/dist/templates/hooks/post-edit-tracker.sh +121 -0
- package/dist/templates/hooks/post-edit-types.sh.tmpl +25 -0
- package/dist/templates/hooks/session-start-compact.sh +88 -0
- package/dist/write-files.d.ts +16 -0
- package/dist/write-files.js +78 -0
- package/package.json +38 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# SessionStart hook: Re-inject tracker + spec context after compaction
|
|
3
|
+
# Fires on: compact (registered via matcher in settings.local.json)
|
|
4
|
+
# Output: additionalContext with tracker content, spec content, and action instructions
|
|
5
|
+
|
|
6
|
+
INPUT=$(cat)
|
|
7
|
+
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // empty')
|
|
8
|
+
|
|
9
|
+
[ -z "$SESSION_ID" ] && exit 0
|
|
10
|
+
|
|
11
|
+
TRACKER_DIR="$(cd "$(dirname "$0")/../progress" 2>/dev/null && pwd)"
|
|
12
|
+
[ -z "$TRACKER_DIR" ] || [ ! -d "$TRACKER_DIR" ] && exit 0
|
|
13
|
+
|
|
14
|
+
PROJECT_DIR="$(cd "$(dirname "$0")/../.." 2>/dev/null && pwd)"
|
|
15
|
+
|
|
16
|
+
# Find this session's active tracker
|
|
17
|
+
MY_TRACKER=""
|
|
18
|
+
for t in "$TRACKER_DIR"/*.md; do
|
|
19
|
+
[ -f "$t" ] || continue
|
|
20
|
+
LINE1=$(head -1 "$t")
|
|
21
|
+
echo "$LINE1" | grep -q "\[DONE\]" && continue
|
|
22
|
+
echo "$LINE1" | grep -q "\[ABORTED\]" && continue
|
|
23
|
+
LINE2=$(sed -n '2p' "$t")
|
|
24
|
+
if echo "$LINE2" | grep -q "<!-- session: $SESSION_ID -->"; then
|
|
25
|
+
MY_TRACKER="$t"
|
|
26
|
+
break
|
|
27
|
+
fi
|
|
28
|
+
done
|
|
29
|
+
|
|
30
|
+
[ -z "$MY_TRACKER" ] && exit 0
|
|
31
|
+
|
|
32
|
+
# Read tracker
|
|
33
|
+
TRACKER_CONTENT=$(cat "$MY_TRACKER")
|
|
34
|
+
TRACKER_NAME=$(basename "$MY_TRACKER")
|
|
35
|
+
TRACKER_REL=".claude/progress/$TRACKER_NAME"
|
|
36
|
+
|
|
37
|
+
# Extract spec path (line 3 format: <!-- spec: path -->)
|
|
38
|
+
SPEC_PATH=""
|
|
39
|
+
SPEC_CONTENT=""
|
|
40
|
+
SPEC_LINE=$(sed -n '3p' "$MY_TRACKER")
|
|
41
|
+
if echo "$SPEC_LINE" | grep -q "<!-- spec:"; then
|
|
42
|
+
SPEC_PATH=$(echo "$SPEC_LINE" | sed -n 's/<!-- spec: \(.*\) -->/\1/p')
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
if [ -n "$SPEC_PATH" ] && [ "$SPEC_PATH" != "None" ]; then
|
|
46
|
+
FULL_SPEC="$PROJECT_DIR/$SPEC_PATH"
|
|
47
|
+
if [ -f "$FULL_SPEC" ]; then
|
|
48
|
+
SPEC_CONTENT=$(cat "$FULL_SPEC")
|
|
49
|
+
fi
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# Count completed entries to show progress
|
|
53
|
+
DONE_COUNT=$(grep -c '^\- \[x\]' "$MY_TRACKER" 2>/dev/null || echo "0")
|
|
54
|
+
|
|
55
|
+
# Build context
|
|
56
|
+
CONTEXT="# SESSION CONTEXT RESTORED (post-compaction)
|
|
57
|
+
|
|
58
|
+
You are CONTINUING an existing work session. You are NOT starting fresh.
|
|
59
|
+
Your session ID: $SESSION_ID
|
|
60
|
+
|
|
61
|
+
## Active Progress: $TRACKER_REL ($DONE_COUNT entries)
|
|
62
|
+
$TRACKER_CONTENT
|
|
63
|
+
|
|
64
|
+
## REQUIRED: After reading this, immediately:
|
|
65
|
+
1. Re-read your progress file: Read file $PROJECT_DIR/$TRACKER_REL"
|
|
66
|
+
|
|
67
|
+
if [ -n "$SPEC_PATH" ] && [ "$SPEC_PATH" != "None" ]; then
|
|
68
|
+
CONTEXT="$CONTEXT
|
|
69
|
+
2. Re-read your spec: Read file $PROJECT_DIR/$SPEC_PATH"
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
CONTEXT="$CONTEXT
|
|
73
|
+
3. Review the last few log entries to understand where you left off
|
|
74
|
+
4. Re-read files listed in ## Files to rebuild code context
|
|
75
|
+
5. Continue working — do NOT ask the user what to do next unless genuinely stuck
|
|
76
|
+
|
|
77
|
+
## Hooks still active:
|
|
78
|
+
{{ACTIVE_HOOKS}}"
|
|
79
|
+
|
|
80
|
+
if [ -n "$SPEC_CONTENT" ]; then
|
|
81
|
+
CONTEXT="$CONTEXT
|
|
82
|
+
|
|
83
|
+
## Spec: $SPEC_PATH
|
|
84
|
+
$SPEC_CONTENT"
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
jq -n --arg ctx "$CONTEXT" '{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":$ctx}}'
|
|
88
|
+
exit 0
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface WriteOptions {
|
|
2
|
+
projectDir: string;
|
|
3
|
+
enableLint: boolean;
|
|
4
|
+
lintCommand: string;
|
|
5
|
+
lintExtensions: string;
|
|
6
|
+
lintHookFilename: string;
|
|
7
|
+
enableTypes: boolean;
|
|
8
|
+
typeCommand: string;
|
|
9
|
+
typeExtensions: string;
|
|
10
|
+
typesHookFilename: string;
|
|
11
|
+
activeHooksDescription: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function writeFiles(options: WriteOptions): {
|
|
14
|
+
commands: string[];
|
|
15
|
+
hooks: string[];
|
|
16
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { chmodSync, cpSync, existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync, } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
function getTemplateDir() {
|
|
5
|
+
const thisFile = fileURLToPath(import.meta.url);
|
|
6
|
+
/* In dist/write-files.js → templates are in dist/templates/ */
|
|
7
|
+
const dir = join(thisFile, "..", "templates");
|
|
8
|
+
if (existsSync(dir))
|
|
9
|
+
return dir;
|
|
10
|
+
/* Fallback: src layout (dev) */
|
|
11
|
+
return join(thisFile, "..", "..", "src", "templates");
|
|
12
|
+
}
|
|
13
|
+
function ensureDir(dir) {
|
|
14
|
+
if (!existsSync(dir)) {
|
|
15
|
+
mkdirSync(dir, { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function renderTemplate(content, vars) {
|
|
19
|
+
let result = content;
|
|
20
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
21
|
+
result = result.replaceAll(`{{{${key}}}}`, value);
|
|
22
|
+
result = result.replaceAll(`{{${key}}}`, value);
|
|
23
|
+
}
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
export function writeFiles(options) {
|
|
27
|
+
const templateDir = getTemplateDir();
|
|
28
|
+
const claudeDir = join(options.projectDir, ".claude");
|
|
29
|
+
const commandsTarget = join(claudeDir, "commands", "workerc");
|
|
30
|
+
const hooksTarget = join(claudeDir, "hooks");
|
|
31
|
+
const progressDir = join(claudeDir, "progress");
|
|
32
|
+
ensureDir(commandsTarget);
|
|
33
|
+
ensureDir(hooksTarget);
|
|
34
|
+
ensureDir(progressDir);
|
|
35
|
+
/* Copy command templates verbatim */
|
|
36
|
+
const commandsSrc = join(templateDir, "commands");
|
|
37
|
+
const commandFiles = readdirSync(commandsSrc).filter((f) => f.endsWith(".md"));
|
|
38
|
+
for (const file of commandFiles) {
|
|
39
|
+
cpSync(join(commandsSrc, file), join(commandsTarget, file));
|
|
40
|
+
}
|
|
41
|
+
/* Copy/template hook files */
|
|
42
|
+
const writtenHooks = [];
|
|
43
|
+
/* Tracker — verbatim copy */
|
|
44
|
+
cpSync(join(templateDir, "hooks", "post-edit-tracker.sh"), join(hooksTarget, "post-edit-tracker.sh"));
|
|
45
|
+
chmodSync(join(hooksTarget, "post-edit-tracker.sh"), 0o755);
|
|
46
|
+
writtenHooks.push("post-edit-tracker.sh");
|
|
47
|
+
/* Session start compact — template {{ACTIVE_HOOKS}} */
|
|
48
|
+
const compactSrc = readFileSync(join(templateDir, "hooks", "session-start-compact.sh"), "utf-8");
|
|
49
|
+
const compactRendered = renderTemplate(compactSrc, {
|
|
50
|
+
ACTIVE_HOOKS: options.activeHooksDescription,
|
|
51
|
+
});
|
|
52
|
+
writeFileSync(join(hooksTarget, "session-start-compact.sh"), compactRendered);
|
|
53
|
+
chmodSync(join(hooksTarget, "session-start-compact.sh"), 0o755);
|
|
54
|
+
writtenHooks.push("session-start-compact.sh");
|
|
55
|
+
/* Lint hook — optional, from template */
|
|
56
|
+
if (options.enableLint) {
|
|
57
|
+
const lintTmpl = readFileSync(join(templateDir, "hooks", "post-edit-lint.sh.tmpl"), "utf-8");
|
|
58
|
+
const lintRendered = renderTemplate(lintTmpl, {
|
|
59
|
+
LINT_COMMAND: options.lintCommand,
|
|
60
|
+
EXTENSIONS: options.lintExtensions,
|
|
61
|
+
});
|
|
62
|
+
writeFileSync(join(hooksTarget, options.lintHookFilename), lintRendered);
|
|
63
|
+
chmodSync(join(hooksTarget, options.lintHookFilename), 0o755);
|
|
64
|
+
writtenHooks.push(options.lintHookFilename);
|
|
65
|
+
}
|
|
66
|
+
/* Types hook — optional, from template */
|
|
67
|
+
if (options.enableTypes) {
|
|
68
|
+
const typesTmpl = readFileSync(join(templateDir, "hooks", "post-edit-types.sh.tmpl"), "utf-8");
|
|
69
|
+
const typesRendered = renderTemplate(typesTmpl, {
|
|
70
|
+
TYPE_COMMAND: options.typeCommand,
|
|
71
|
+
EXTENSIONS: options.typeExtensions,
|
|
72
|
+
});
|
|
73
|
+
writeFileSync(join(hooksTarget, options.typesHookFilename), typesRendered);
|
|
74
|
+
chmodSync(join(hooksTarget, options.typesHookFilename), 0o755);
|
|
75
|
+
writtenHooks.push(options.typesHookFilename);
|
|
76
|
+
}
|
|
77
|
+
return { commands: commandFiles, hooks: writtenHooks };
|
|
78
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@scriptgun/workerc",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Claude Code session management CLI — commands, hooks, and progress tracking",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"workerc": "./dist/bin.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/init.js",
|
|
10
|
+
"types": "./dist/init.d.ts",
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc && cp -r src/templates dist/templates",
|
|
17
|
+
"type:check": "tsc --noEmit"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"claude",
|
|
21
|
+
"claude-code",
|
|
22
|
+
"session",
|
|
23
|
+
"hooks",
|
|
24
|
+
"cli",
|
|
25
|
+
"workerc"
|
|
26
|
+
],
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/lovrozagar/workerc"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@clack/prompts": "1.0.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"typescript": "^5.9.3"
|
|
37
|
+
}
|
|
38
|
+
}
|