chief-clancy 0.2.0 → 0.3.1

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.
Files changed (141) hide show
  1. package/README.md +13 -24
  2. package/dist/bundle/clancy-afk.js +101 -0
  3. package/dist/bundle/clancy-once.js +13902 -0
  4. package/dist/installer/file-ops/file-ops.d.ts +32 -0
  5. package/dist/installer/file-ops/file-ops.d.ts.map +1 -0
  6. package/dist/installer/file-ops/file-ops.js +58 -0
  7. package/dist/installer/file-ops/file-ops.js.map +1 -0
  8. package/dist/installer/hook-installer/hook-installer.d.ts +29 -0
  9. package/dist/installer/hook-installer/hook-installer.d.ts.map +1 -0
  10. package/dist/installer/hook-installer/hook-installer.js +96 -0
  11. package/dist/installer/hook-installer/hook-installer.js.map +1 -0
  12. package/dist/installer/install.d.ts +3 -0
  13. package/dist/installer/install.d.ts.map +1 -0
  14. package/dist/installer/install.js +248 -0
  15. package/dist/installer/install.js.map +1 -0
  16. package/dist/installer/manifest/manifest.d.ts +41 -0
  17. package/dist/installer/manifest/manifest.d.ts.map +1 -0
  18. package/dist/installer/manifest/manifest.js +97 -0
  19. package/dist/installer/manifest/manifest.js.map +1 -0
  20. package/dist/installer/prompts/prompts.d.ts +33 -0
  21. package/dist/installer/prompts/prompts.d.ts.map +1 -0
  22. package/dist/installer/prompts/prompts.js +55 -0
  23. package/dist/installer/prompts/prompts.js.map +1 -0
  24. package/dist/schemas/env.d.ts +75 -0
  25. package/dist/schemas/env.d.ts.map +1 -0
  26. package/dist/schemas/env.js +40 -0
  27. package/dist/schemas/env.js.map +1 -0
  28. package/dist/schemas/github.d.ts +27 -0
  29. package/dist/schemas/github.d.ts.map +1 -0
  30. package/dist/schemas/github.js +17 -0
  31. package/dist/schemas/github.js.map +1 -0
  32. package/dist/schemas/index.d.ts +9 -0
  33. package/dist/schemas/index.d.ts.map +1 -0
  34. package/dist/schemas/index.js +5 -0
  35. package/dist/schemas/index.js.map +1 -0
  36. package/dist/schemas/jira.d.ts +37 -0
  37. package/dist/schemas/jira.d.ts.map +1 -0
  38. package/dist/schemas/jira.js +37 -0
  39. package/dist/schemas/jira.js.map +1 -0
  40. package/dist/schemas/linear.d.ts +67 -0
  41. package/dist/schemas/linear.d.ts.map +1 -0
  42. package/dist/schemas/linear.js +50 -0
  43. package/dist/schemas/linear.js.map +1 -0
  44. package/dist/scripts/afk/afk.d.ts +21 -0
  45. package/dist/scripts/afk/afk.d.ts.map +1 -0
  46. package/dist/scripts/afk/afk.js +124 -0
  47. package/dist/scripts/afk/afk.js.map +1 -0
  48. package/dist/scripts/board/github/github.d.ts +40 -0
  49. package/dist/scripts/board/github/github.d.ts.map +1 -0
  50. package/dist/scripts/board/github/github.js +121 -0
  51. package/dist/scripts/board/github/github.js.map +1 -0
  52. package/dist/scripts/board/jira/jira.d.ts +90 -0
  53. package/dist/scripts/board/jira/jira.d.ts.map +1 -0
  54. package/dist/scripts/board/jira/jira.js +251 -0
  55. package/dist/scripts/board/jira/jira.js.map +1 -0
  56. package/dist/scripts/board/linear/linear.d.ts +85 -0
  57. package/dist/scripts/board/linear/linear.d.ts.map +1 -0
  58. package/dist/scripts/board/linear/linear.js +209 -0
  59. package/dist/scripts/board/linear/linear.js.map +1 -0
  60. package/dist/scripts/once/once.d.ts +12 -0
  61. package/dist/scripts/once/once.d.ts.map +1 -0
  62. package/dist/scripts/once/once.js +330 -0
  63. package/dist/scripts/once/once.js.map +1 -0
  64. package/dist/scripts/shared/branch/branch.d.ts +50 -0
  65. package/dist/scripts/shared/branch/branch.d.ts.map +1 -0
  66. package/dist/scripts/shared/branch/branch.js +61 -0
  67. package/dist/scripts/shared/branch/branch.js.map +1 -0
  68. package/dist/scripts/shared/claude-cli/claude-cli.d.ts +17 -0
  69. package/dist/scripts/shared/claude-cli/claude-cli.d.ts.map +1 -0
  70. package/dist/scripts/shared/claude-cli/claude-cli.js +35 -0
  71. package/dist/scripts/shared/claude-cli/claude-cli.js.map +1 -0
  72. package/dist/scripts/shared/env-parser/env-parser.d.ts +30 -0
  73. package/dist/scripts/shared/env-parser/env-parser.d.ts.map +1 -0
  74. package/dist/scripts/shared/env-parser/env-parser.js +64 -0
  75. package/dist/scripts/shared/env-parser/env-parser.js.map +1 -0
  76. package/dist/scripts/shared/env-schema/env-schema.d.ts +27 -0
  77. package/dist/scripts/shared/env-schema/env-schema.d.ts.map +1 -0
  78. package/dist/scripts/shared/env-schema/env-schema.js +46 -0
  79. package/dist/scripts/shared/env-schema/env-schema.js.map +1 -0
  80. package/dist/scripts/shared/git-ops/git-ops.d.ts +52 -0
  81. package/dist/scripts/shared/git-ops/git-ops.d.ts.map +1 -0
  82. package/dist/scripts/shared/git-ops/git-ops.js +107 -0
  83. package/dist/scripts/shared/git-ops/git-ops.js.map +1 -0
  84. package/dist/scripts/shared/http/http.d.ts +52 -0
  85. package/dist/scripts/shared/http/http.d.ts.map +1 -0
  86. package/dist/scripts/shared/http/http.js +74 -0
  87. package/dist/scripts/shared/http/http.js.map +1 -0
  88. package/dist/scripts/shared/notify/notify.d.ts +46 -0
  89. package/dist/scripts/shared/notify/notify.d.ts.map +1 -0
  90. package/dist/scripts/shared/notify/notify.js +88 -0
  91. package/dist/scripts/shared/notify/notify.js.map +1 -0
  92. package/dist/scripts/shared/preflight/preflight.d.ts +40 -0
  93. package/dist/scripts/shared/preflight/preflight.d.ts.map +1 -0
  94. package/dist/scripts/shared/preflight/preflight.js +84 -0
  95. package/dist/scripts/shared/preflight/preflight.js.map +1 -0
  96. package/dist/scripts/shared/progress/progress.d.ts +25 -0
  97. package/dist/scripts/shared/progress/progress.d.ts.map +1 -0
  98. package/dist/scripts/shared/progress/progress.js +46 -0
  99. package/dist/scripts/shared/progress/progress.js.map +1 -0
  100. package/dist/scripts/shared/prompt/prompt.d.ts +38 -0
  101. package/dist/scripts/shared/prompt/prompt.d.ts.map +1 -0
  102. package/dist/scripts/shared/prompt/prompt.js +77 -0
  103. package/dist/scripts/shared/prompt/prompt.js.map +1 -0
  104. package/dist/types/board.d.ts +13 -0
  105. package/dist/types/board.d.ts.map +1 -0
  106. package/dist/types/board.js +5 -0
  107. package/dist/types/board.js.map +1 -0
  108. package/dist/types/index.d.ts +3 -0
  109. package/dist/types/index.d.ts.map +1 -0
  110. package/dist/types/index.js +2 -0
  111. package/dist/types/index.js.map +1 -0
  112. package/dist/utils/ansi/ansi.d.ts +55 -0
  113. package/dist/utils/ansi/ansi.d.ts.map +1 -0
  114. package/dist/utils/ansi/ansi.js +55 -0
  115. package/dist/utils/ansi/ansi.js.map +1 -0
  116. package/dist/utils/parse-json/parse-json.d.ts +20 -0
  117. package/dist/utils/parse-json/parse-json.d.ts.map +1 -0
  118. package/dist/utils/parse-json/parse-json.js +27 -0
  119. package/dist/utils/parse-json/parse-json.js.map +1 -0
  120. package/hooks/clancy-check-update.js +2 -2
  121. package/hooks/clancy-credential-guard.js +8 -1
  122. package/package.json +48 -8
  123. package/registry/boards.json +3 -6
  124. package/src/templates/CLAUDE.md +1 -1
  125. package/src/workflows/doctor.md +32 -23
  126. package/src/workflows/init.md +101 -26
  127. package/src/workflows/logs.md +13 -6
  128. package/src/workflows/map-codebase.md +17 -16
  129. package/src/workflows/once.md +22 -12
  130. package/src/workflows/review.md +40 -27
  131. package/src/workflows/run.md +20 -12
  132. package/src/workflows/scaffold.md +5 -1034
  133. package/src/workflows/settings.md +9 -6
  134. package/src/workflows/status.md +17 -8
  135. package/src/workflows/uninstall.md +11 -6
  136. package/src/workflows/update.md +20 -13
  137. package/bin/install.js +0 -362
  138. package/src/templates/scripts/clancy-afk.sh +0 -111
  139. package/src/templates/scripts/clancy-once-github.sh +0 -249
  140. package/src/templates/scripts/clancy-once-linear.sh +0 -320
  141. package/src/templates/scripts/clancy-once.sh +0 -322
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ansi.d.ts","sourceRoot":"","sources":["../../../src/utils/ansi/ansi.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,GAAG,GAAI,GAAG,MAAM,KAAG,MAA8B,CAAC;AAE/D;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,GAAG,MAAM,KAAG,MAA8B,CAAC;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,GAAG,MAAM,KAAG,MAAiC,CAAC;AAEnE;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,GAAG,MAAM,KAAG,MAA+B,CAAC;AAEjE;;;;;GAKG;AACH,eAAO,MAAM,KAAK,GAAI,GAAG,MAAM,KAAG,MAA+B,CAAC;AAElE;;;;;GAKG;AACH,eAAO,MAAM,GAAG,GAAI,GAAG,MAAM,KAAG,MAA+B,CAAC;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,MAAM,GAAI,GAAG,MAAM,KAAG,MAA+B,CAAC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * ANSI escape code helpers for terminal output.
3
+ *
4
+ * Wraps strings in ANSI sequences for styling in CLI environments.
5
+ */
6
+ /**
7
+ * Dim the given string (reduced intensity).
8
+ *
9
+ * @param s - The string to style.
10
+ * @returns The string wrapped in ANSI dim codes.
11
+ */
12
+ export const dim = (s) => `\x1b[2m${s}\x1b[0m`;
13
+ /**
14
+ * Bold the given string.
15
+ *
16
+ * @param s - The string to style.
17
+ * @returns The string wrapped in ANSI bold codes.
18
+ */
19
+ export const bold = (s) => `\x1b[1m${s}\x1b[0m`;
20
+ /**
21
+ * Colour the given string blue (bold).
22
+ *
23
+ * @param s - The string to style.
24
+ * @returns The string wrapped in ANSI blue codes.
25
+ */
26
+ export const blue = (s) => `\x1b[1;34m${s}\x1b[0m`;
27
+ /**
28
+ * Colour the given string cyan.
29
+ *
30
+ * @param s - The string to style.
31
+ * @returns The string wrapped in ANSI cyan codes.
32
+ */
33
+ export const cyan = (s) => `\x1b[36m${s}\x1b[0m`;
34
+ /**
35
+ * Colour the given string green.
36
+ *
37
+ * @param s - The string to style.
38
+ * @returns The string wrapped in ANSI green codes.
39
+ */
40
+ export const green = (s) => `\x1b[32m${s}\x1b[0m`;
41
+ /**
42
+ * Colour the given string red.
43
+ *
44
+ * @param s - The string to style.
45
+ * @returns The string wrapped in ANSI red codes.
46
+ */
47
+ export const red = (s) => `\x1b[31m${s}\x1b[0m`;
48
+ /**
49
+ * Colour the given string yellow.
50
+ *
51
+ * @param s - The string to style.
52
+ * @returns The string wrapped in ANSI yellow codes.
53
+ */
54
+ export const yellow = (s) => `\x1b[33m${s}\x1b[0m`;
55
+ //# sourceMappingURL=ansi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ansi.js","sourceRoot":"","sources":["../../../src/utils/ansi/ansi.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;AAEhE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC;AAEnE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC;AAEjE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC;AAElE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC;AAEhE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Safely parse a JSON string, returning `undefined` on failure.
3
+ *
4
+ * Hooks and scripts receive JSON from external sources — this helper
5
+ * avoids try/catch boilerplate and never throws.
6
+ *
7
+ * @param raw - The JSON string to parse.
8
+ * @returns The parsed value cast to `T`, or `undefined` if parsing fails.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * const data = parseJson<{ name: string }>('{"name":"clancy"}');
13
+ * // data?.name === 'clancy'
14
+ *
15
+ * const bad = parseJson('not json');
16
+ * // bad === undefined
17
+ * ```
18
+ */
19
+ export declare function parseJson<T = unknown>(raw: string): T | undefined;
20
+ //# sourceMappingURL=parse-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-json.d.ts","sourceRoot":"","sources":["../../../src/utils/parse-json/parse-json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,SAAS,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAMjE"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Safely parse a JSON string, returning `undefined` on failure.
3
+ *
4
+ * Hooks and scripts receive JSON from external sources — this helper
5
+ * avoids try/catch boilerplate and never throws.
6
+ *
7
+ * @param raw - The JSON string to parse.
8
+ * @returns The parsed value cast to `T`, or `undefined` if parsing fails.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * const data = parseJson<{ name: string }>('{"name":"clancy"}');
13
+ * // data?.name === 'clancy'
14
+ *
15
+ * const bad = parseJson('not json');
16
+ * // bad === undefined
17
+ * ```
18
+ */
19
+ export function parseJson(raw) {
20
+ try {
21
+ return JSON.parse(raw);
22
+ }
23
+ catch {
24
+ return undefined;
25
+ }
26
+ }
27
+ //# sourceMappingURL=parse-json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-json.js","sourceRoot":"","sources":["../../../src/utils/parse-json/parse-json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,SAAS,CAAc,GAAW;IAChD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAM,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -37,7 +37,7 @@ if (!fs.existsSync(cacheDir)) {
37
37
  // This script returns immediately so it never delays session start.
38
38
  const child = spawn(process.execPath, ['-e', `
39
39
  const fs = require('fs');
40
- const { execSync } = require('child_process');
40
+ const { execFileSync } = require('child_process');
41
41
 
42
42
  const cacheFile = ${JSON.stringify(cacheFile)};
43
43
  const versionFile = ${JSON.stringify(versionFile)};
@@ -47,7 +47,7 @@ const child = spawn(process.execPath, ['-e', `
47
47
 
48
48
  let latest = null;
49
49
  try {
50
- latest = execSync('npm view chief-clancy version', {
50
+ latest = execFileSync('npm', ['view', 'chief-clancy', 'version'], {
51
51
  encoding: 'utf8',
52
52
  timeout: 10000,
53
53
  windowsHide: true,
@@ -66,8 +66,15 @@ function scanForCredentials(content) {
66
66
  return matches;
67
67
  }
68
68
 
69
+ // Read hook input — Claude Code passes PreToolUse data as a JSON argument.
70
+ // Fall back to stdin for forward compatibility with potential API changes.
71
+ function readInput() {
72
+ if (process.argv[2]) return process.argv[2];
73
+ try { return require('fs').readFileSync('/dev/stdin', 'utf8'); } catch { return '{}'; }
74
+ }
75
+
69
76
  try {
70
- const input = JSON.parse(process.argv[2] || '{}');
77
+ const input = JSON.parse(readInput());
71
78
  const toolName = input.tool_name || '';
72
79
  const toolInput = input.tool_input || {};
73
80
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chief-clancy",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "Autonomous, board-driven development for Claude Code — scaffolds docs, integrates Kanban boards, runs tickets in a loop.",
5
5
  "keywords": [
6
6
  "claude",
@@ -23,21 +23,61 @@
23
23
  },
24
24
  "license": "MIT",
25
25
  "author": "Alex Clapperton",
26
+ "type": "module",
26
27
  "bin": {
27
- "clancy": "bin/install.js"
28
+ "clancy": "dist/installer/install.js"
28
29
  },
29
- "main": "bin/install.js",
30
+ "main": "dist/installer/install.js",
30
31
  "files": [
31
- "bin/",
32
+ "dist/",
32
33
  "hooks/",
33
- "src/",
34
+ "src/commands/",
35
+ "src/workflows/",
36
+ "src/agents/",
37
+ "src/templates/",
34
38
  "registry/"
35
39
  ],
36
40
  "scripts": {
37
- "test": "bash test/unit/jira.test.sh && bash test/unit/github.test.sh && bash test/unit/linear.test.sh && bash test/unit/scaffold.test.sh && bash test/unit/credential-guard.test.sh",
38
- "smoke": "bash test/smoke/smoke.sh"
41
+ "clean": "rm -rf dist",
42
+ "build": "npm run clean && tsc && tsc-alias && npm run bundle",
43
+ "bundle": "mkdir -p dist/bundle && esbuild dist/scripts/once/once.js --bundle --platform=node --format=esm --target=node22 --outfile=dist/bundle/clancy-once.js && esbuild dist/scripts/afk/afk.js --bundle --platform=node --format=esm --target=node22 --outfile=dist/bundle/clancy-afk.js",
44
+ "dev": "vitest",
45
+ "test": "vitest run",
46
+ "test:coverage": "vitest run --coverage",
47
+ "lint": "eslint .",
48
+ "lint:fix": "eslint . --fix",
49
+ "format": "prettier --write .",
50
+ "format:check": "prettier --check .",
51
+ "typecheck": "tsc --noEmit",
52
+ "prepublishOnly": "npm run build",
53
+ "prepare": "husky"
54
+ },
55
+ "lint-staged": {
56
+ "*.ts": [
57
+ "eslint --fix",
58
+ "prettier --write"
59
+ ]
39
60
  },
40
61
  "engines": {
41
- "node": ">=18.0.0"
62
+ "node": ">=22.0.0"
63
+ },
64
+ "devDependencies": {
65
+ "@eslint/js": "^10.0.1",
66
+ "@trivago/prettier-plugin-sort-imports": "^6.0.2",
67
+ "@types/node": "^25.4.0",
68
+ "@vitest/coverage-v8": "^4.0.18",
69
+ "esbuild": "^0.27.3",
70
+ "eslint": "^10.0.3",
71
+ "eslint-config-prettier": "^10.1.8",
72
+ "eslint-plugin-prettier": "^5.5.5",
73
+ "husky": "^9.1.7",
74
+ "jiti": "^2.6.1",
75
+ "lint-staged": "^16.3.3",
76
+ "prettier": "^3.8.1",
77
+ "tsc-alias": "^1.8.16",
78
+ "typescript": "^5.9.3",
79
+ "typescript-eslint": "^8.57.0",
80
+ "vitest": "^4.0.18",
81
+ "zod": "^4.3.6"
42
82
  }
43
83
  }
@@ -14,8 +14,7 @@
14
14
  "CLANCY_JQL_SPRINT",
15
15
  "CLANCY_LABEL",
16
16
  "CLANCY_BASE_BRANCH"
17
- ],
18
- "script": "clancy-once.sh"
17
+ ]
19
18
  },
20
19
  {
21
20
  "id": "github",
@@ -27,8 +26,7 @@
27
26
  "GITHUB_REPO",
28
27
  "CLANCY_LABEL",
29
28
  "CLANCY_BASE_BRANCH"
30
- ],
31
- "script": "clancy-once-github.sh"
29
+ ]
32
30
  },
33
31
  {
34
32
  "id": "linear",
@@ -40,8 +38,7 @@
40
38
  "LINEAR_TEAM_ID",
41
39
  "CLANCY_LABEL",
42
40
  "CLANCY_BASE_BRANCH"
43
- ],
44
- "script": "clancy-once-linear.sh"
41
+ ]
45
42
  }
46
43
  ]
47
44
  }
@@ -4,7 +4,7 @@
4
4
  This project uses Clancy for autonomous ticket-driven development.
5
5
 
6
6
  ### Version check
7
- At the start of each session, read `~/.claude/cache/clancy-update-check.json` (use the Bash tool). If it exists and `update_available` is true, display exactly:
7
+ At the start of each session, read `~/.claude/cache/clancy-update-check.json` (use the Read tool). If it exists and `update_available` is true, display exactly:
8
8
  `⚠ Clancy update available: v{installed} → v{latest}. Run /clancy:update to upgrade.`
9
9
  Then continue normally. If the file is missing or unreadable, continue silently.
10
10
 
@@ -4,7 +4,7 @@ Before doing anything else, check for updates:
4
4
 
5
5
  1. Run: `npm show chief-clancy version`
6
6
  2. Read the installed version from the Clancy `package.json`
7
- 3. If a newer version exists, print: `ℹ Clancy v{current} → v{latest} available. Run /clancy:update to upgrade.` then continue normally.
7
+ 3. If a newer version exists, print: `ℹ️ Clancy v{current} → v{latest} available. Run /clancy:update to upgrade.` then continue normally.
8
8
  4. If already on latest, continue silently.
9
9
  5. If the npm check fails for any reason (offline, network error), continue silently. Never block on this.
10
10
 
@@ -22,7 +22,7 @@ Diagnose your Clancy setup — test every configured integration and report what
22
22
 
23
23
  - Verify Clancy commands are installed (`.claude/commands/clancy/` or `~/.claude/commands/clancy/`)
24
24
  - Read installed version from `package.json` in the commands directory
25
- - Print: `✓ Clancy v{version} installed ({location})`
25
+ - Print: `✅ Clancy v{version} installed ({location})`
26
26
 
27
27
  ---
28
28
 
@@ -32,24 +32,23 @@ Test each required binary:
32
32
 
33
33
  | Binary | Check | Fix hint |
34
34
  |---|---|---|
35
- | `jq` | `command -v jq` | `brew install jq` / `apt install jq` |
36
- | `curl` | `command -v curl` | Install curl for your OS |
35
+ | `node` | `command -v node` | Install Node.js 22+ |
37
36
  | `git` | `command -v git` | Install git for your OS |
38
37
 
39
- Print `✓` or `✗` for each.
38
+ Print `✅` or `❌` for each.
40
39
 
41
40
  ---
42
41
 
43
42
  ## Step 3 — Check project setup
44
43
 
45
- - `.clancy/` exists → `✓ .clancy/ found`
46
- - `.clancy/clancy-once.sh` exists and is executable `✓ clancy-once.sh`
47
- - `.clancy/clancy-afk.sh` exists and is executable `✓ clancy-afk.sh`
48
- - `.clancy/.env` exists → `✓ .clancy/.env found`
49
- - `.clancy/docs/` has non-empty files → `✓ codebase docs present ({N} files)`
44
+ - `.clancy/` exists → `✅ .clancy/ found`
45
+ - `.clancy/clancy-once.js` exists → `✅ clancy-once.js`
46
+ - `.clancy/clancy-afk.js` exists → `✅ clancy-afk.js`
47
+ - `.clancy/.env` exists → `✅ .clancy/.env found`
48
+ - `.clancy/docs/` has non-empty files → `✅ codebase docs present ({N} files)`
50
49
 
51
- If `.clancy/` is missing: `✗ .clancy/ not found — run /clancy:init`
52
- If `.clancy/.env` is missing: `✗ .clancy/.env not found — run /clancy:init`
50
+ If `.clancy/` is missing: `❌ .clancy/ not found — run /clancy:init`
51
+ If `.clancy/.env` is missing: `❌ .clancy/.env not found — run /clancy:init`
53
52
 
54
53
  ---
55
54
 
@@ -78,8 +77,8 @@ Source `.clancy/.env` and detect which board is configured:
78
77
 
79
78
  **Figma** — if `FIGMA_API_KEY` is set:
80
79
  - Call `GET https://api.figma.com/v1/me` with `X-Figma-Token: $FIGMA_API_KEY`
81
- - On success: print `✓ Figma connected — {email}`
82
- - On 403: print `✗ Figma authentication failed. Check FIGMA_API_KEY in .clancy/.env.`
80
+ - On success: print `✅ Figma connected — {email}`
81
+ - On 403: print `❌ Figma authentication failed. Check FIGMA_API_KEY in .clancy/.env.`
83
82
  - Note: Figma's API does not expose plan information — check your plan at figma.com/settings
84
83
 
85
84
  **Playwright** — if `PLAYWRIGHT_ENABLED=true`:
@@ -97,19 +96,29 @@ Source `.clancy/.env` and detect which board is configured:
97
96
  ## Step 6 — Summary
98
97
 
99
98
  ```
100
- Clancy doctor {N} checks passed, {N} warnings, {N} failures
99
+ 🚨 Clancy — Doctor
100
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
101
101
 
102
- Clancy v0.1.0 installed (global)
103
- ✓ jq, curl, git — all present
104
- ✓ .clancy/ set up — 10 docs present
105
- ✓ Jira connected — PROJ reachable
106
- ✓ Figma connected — alex@example.com (check plan at figma.com/settings)
107
- ✗ PLAYWRIGHT_STORYBOOK_PORT — not set in .clancy/.env
102
+ {N} checks passed, {N} warnings, {N} failures
108
103
 
109
- Fix the items, then run /clancy:once to verify end-to-end.
104
+ Clancy v0.1.0 installed (global)
105
+ ✅ node, git — all present
106
+ ✅ .clancy/ set up — 10 docs present
107
+ ✅ Jira connected — PROJ reachable
108
+ ✅ Figma connected — alex@example.com (check plan at figma.com/settings)
109
+ ❌ PLAYWRIGHT_STORYBOOK_PORT — not set in .clancy/.env
110
+
111
+ Fix the ❌ items, then run /clancy:once to verify end-to-end.
112
+
113
+ "We've got a 415 in progress — a config disturbance."
110
114
  ```
111
115
 
112
116
  If all checks pass:
113
117
  ```
114
- All good. Run /clancy:once to pick up your first ticket.
118
+ 🚨 Clancy Doctor
119
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
120
+
121
+ All {N} checks passed.
122
+
123
+ "Nothing to see here, folks. Move along." — Run /clancy:once to pick up your first ticket.
115
124
  ```
@@ -30,20 +30,20 @@ Before proceeding, silently run `command -v` for each required binary:
30
30
 
31
31
  | Binary | Install hint |
32
32
  |---|---|
33
- | `jq` | `brew install jq` / `apt install jq` |
34
- | `curl` | pre-installed on macOS and most Linux |
33
+ | `node` | Install Node.js 22+ (nodejs.org) |
35
34
  | `git` | `brew install git` / `apt install git` |
35
+ | `claude` | `npm install -g @anthropic-ai/claude-code` |
36
36
 
37
37
  If all are present: continue silently.
38
38
 
39
39
  If any are missing, output:
40
40
 
41
41
  ```
42
- Missing prerequisites:
42
+ ⚠️ Missing prerequisites:
43
43
 
44
- jqbrew install jq (or apt install jq on Linux)
44
+ nodeInstall Node.js 22+ (nodejs.org)
45
45
 
46
- Clancy's shell scripts require these binaries to run. Install them, then re-run /clancy:init.
46
+ Clancy requires these binaries to run. Install them, then re-run /clancy:init.
47
47
  ```
48
48
 
49
49
  List only the missing ones. Then stop — do not proceed with setup until prerequisites are satisfied.
@@ -54,9 +54,16 @@ List only the missing ones. Then stop — do not proceed with setup until prereq
54
54
 
55
55
  Output:
56
56
 
57
+ ```
58
+ 🚨 Clancy — Init
59
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
60
+
61
+ "Chief Wiggum reporting for duty."
62
+
57
63
  Clancy pulls tickets from your Kanban board, implements them, commits, and squash-merges — one ticket per run, fresh context every time.
58
64
 
59
65
  Let's get you set up.
66
+ ```
60
67
 
61
68
  ---
62
69
 
@@ -79,13 +86,12 @@ Clancy currently supports Jira, GitHub Issues, and Linear out of the box.
79
86
 
80
87
  Your board isn't supported yet — but you can add it:
81
88
  · Open an issue: github.com/Pushedskydiver/clancy/issues
82
- · Contribute one: see CONTRIBUTING.md — adding a board is just a script template + a boards.json entry
89
+ · Contribute one: see CONTRIBUTING.md — adding a board is a TypeScript module + a boards.json entry
83
90
 
84
91
  In the meantime, you can still use Clancy manually:
85
92
  · Run /clancy:map-codebase to scan and document your codebase
86
- · Use the clancy-once.sh template from the GitHub repo as a starting point
87
- · Implement your board's API fetch, store credentials in .clancy/.env
88
- · Point clancy-afk.sh at your custom script via CLANCY_ONCE_SCRIPT in .clancy/.env
93
+ · Run `npx -y chief-clancy@latest` and implement your board's API module
94
+ · Store credentials in .clancy/.env
89
95
 
90
96
  Do not scaffold anything after this message. Stop completely.
91
97
 
@@ -124,6 +130,65 @@ If enter is pressed with no value: skip — omit the label clause entirely (Clan
124
130
 
125
131
  ---
126
132
 
133
+ ### Q2b: Board credential verification
134
+
135
+ After collecting all credentials for the chosen board, verify the connection before continuing.
136
+
137
+ **Jira** — call `GET {JIRA_BASE_URL}/rest/api/3/project/{JIRA_PROJECT_KEY}` with basic auth (`{JIRA_USER}:{JIRA_API_TOKEN}` base64-encoded in the `Authorization: Basic` header).
138
+
139
+ On success (HTTP 200), show:
140
+ ```
141
+ ✅ Jira connected — project {JIRA_PROJECT_KEY} reachable.
142
+ ```
143
+
144
+ On failure, show:
145
+ ```
146
+ ❌ Couldn't connect to Jira (HTTP {status}).
147
+ Check your credentials in the values you just entered.
148
+
149
+ [1] Re-enter credentials
150
+ ```
151
+
152
+ If [1]: go back to Q2 and re-ask all Jira questions. If the user wants to abandon setup entirely, they can Ctrl+C.
153
+
154
+ **GitHub Issues** — call `GET https://api.github.com/repos/{GITHUB_REPO}` with `Authorization: Bearer {GITHUB_TOKEN}` and `X-GitHub-Api-Version: 2022-11-28`.
155
+
156
+ On success (HTTP 200), show:
157
+ ```
158
+ ✅ GitHub connected — {GITHUB_REPO} reachable.
159
+ ```
160
+
161
+ On failure, show:
162
+ ```
163
+ ❌ Couldn't connect to GitHub (HTTP {status}).
164
+ Check your token has `repo` scope and the repo name is correct.
165
+
166
+ [1] Re-enter credentials
167
+ ```
168
+
169
+ If [1]: go back to Q2 and re-ask all GitHub questions. If the user wants to abandon setup entirely, they can Ctrl+C.
170
+
171
+ **Linear** — call `POST https://api.linear.app/graphql` with `Authorization: {LINEAR_API_KEY}` (no Bearer prefix) and body `{"query": "{ viewer { id name } }"}`.
172
+
173
+ On success (HTTP 200 with `data.viewer`), show:
174
+ ```
175
+ ✅ Linear connected — {viewer.name}.
176
+ ```
177
+
178
+ On failure, show:
179
+ ```
180
+ ❌ Couldn't connect to Linear.
181
+ Check your API key at linear.app/settings/api.
182
+
183
+ [1] Re-enter credentials
184
+ ```
185
+
186
+ If [1]: go back to Q2 and re-ask all Linear questions. If the user wants to abandon setup entirely, they can Ctrl+C.
187
+
188
+ Never silently continue with unverified credentials — the user must fix their credentials or exit with Ctrl+C.
189
+
190
+ ---
191
+
127
192
  ### Q3 (Jira only): Status name
128
193
 
129
194
  Output:
@@ -134,7 +199,7 @@ Common values: To Do, Selected for Development, Ready, Open
134
199
  [1] To Do (default)
135
200
  [2] Enter a different value
136
201
 
137
- Store as `CLANCY_JQL_STATUS` in `.clancy/.env`. Always wrap the value in double quotes — status names often contain spaces (e.g. `CLANCY_JQL_STATUS="Selected for Development"`) and unquoted values with spaces cause bash parse errors when the file is sourced.
202
+ Store as `CLANCY_JQL_STATUS` in `.clancy/.env`. Always wrap the value in double quotes — status names often contain spaces (e.g. `CLANCY_JQL_STATUS="Selected for Development"`).
138
203
 
139
204
  ---
140
205
 
@@ -176,34 +241,40 @@ Store the detected (or confirmed) value as `CLANCY_BASE_BRANCH` in `.clancy/.env
176
241
 
177
242
  Create `.clancy/` directory and the following:
178
243
 
179
- 1. Write the correct `clancy-once.sh` for the chosen board to `.clancy/clancy-once.sh` use the exact script content from scaffold.md, do not generate or modify it
180
- 2. Write `clancy-afk.sh` to `.clancy/clancy-afk.sh` use the exact script content from scaffold.md, do not generate or modify it
181
- 3. Make both scripts executable: `chmod +x .clancy/*.sh`
182
- 4. Create `.clancy/docs/` with 10 empty template files (UPPERCASE.md with section headings only):
244
+ 1. Verify `.clancy/clancy-once.js` and `.clancy/clancy-afk.js` exist (copied by the installer). If missing, tell the user to run `npx -y chief-clancy@latest` and stop.
245
+ 2. Create `.clancy/docs/` with 10 empty template files (UPPERCASE.md with section headings only):
183
246
  - STACK.md, INTEGRATIONS.md, ARCHITECTURE.md, CONVENTIONS.md, TESTING.md
184
247
  - GIT.md, DESIGN-SYSTEM.md, ACCESSIBILITY.md, DEFINITION-OF-DONE.md, CONCERNS.md
185
- 5. Write the correct `.env.example` for the chosen board to `.clancy/.env.example` — use the exact content from scaffold.md
186
- 6. Write collected credentials to `.clancy/.env` (if the user provided them)
187
- 7. Handle `CLAUDE.md` — follow the merge logic in scaffold.md exactly:
248
+ 3. Write the correct `.env.example` for the chosen board to `.clancy/.env.example` — use the exact content from scaffold.md
249
+ 4. Write collected credentials to `.clancy/.env` (if the user provided them)
250
+ 5. Handle `CLAUDE.md` — follow the merge logic in scaffold.md exactly:
188
251
  - If no CLAUDE.md: write the full template as `CLAUDE.md`
189
252
  - If CLAUDE.md exists without `<!-- clancy:start -->`: append the Clancy section to the end
190
253
  - If CLAUDE.md exists with `<!-- clancy:start -->`: replace only the content between the markers
191
254
  - Never overwrite the entire file
192
- 8. Check `.gitignore` — if `.clancy/.env` is not listed, append it
255
+ 6. Check `.gitignore` — if `.clancy/.env` is not listed, append it
193
256
 
194
257
  ---
195
258
 
196
259
  ## Step 4b — Commit scaffold
197
260
 
198
- After scaffolding, commit everything created (excluding `.clancy/.env` which contains credentials):
261
+ After scaffolding, ask the user whether to commit the scaffolded files:
262
+
263
+ ```
264
+ Commit the Clancy scaffold to git? (recommended) [Y/n]
265
+ ```
266
+
267
+ If yes (or enter): commit everything created (excluding `.clancy/.env` which contains credentials):
199
268
 
200
269
  ```bash
201
- git add .clancy/clancy-once.sh .clancy/clancy-afk.sh .clancy/.env.example .clancy/docs/ CLAUDE.md .gitignore
202
- git commit -m "chore(clancy): initialise — scaffold scripts, docs templates, and config"
270
+ git add .clancy/.env.example .clancy/docs/ CLAUDE.md .gitignore
271
+ git commit -m "chore(clancy): initialise — scaffold docs templates and config"
203
272
  ```
204
273
 
205
274
  If `CLAUDE.md` was not modified (it already existed and was not changed), omit it from the `git add`. If `.gitignore` was not modified, omit it too. Only stage files that actually changed.
206
275
 
276
+ If no: skip the commit silently. The user can commit manually later.
277
+
207
278
  ---
208
279
 
209
280
  ## Step 5 — Optional enhancements
@@ -240,7 +311,7 @@ If a key is entered:
240
311
  1. Verify the key by calling `GET https://api.figma.com/v1/me` with `X-Figma-Token: {key}`
241
312
  2. On success, show:
242
313
  ```
243
- Figma connected: {email}
314
+ Figma connected: {email}
244
315
 
245
316
  Note: Figma's API does not expose plan information.
246
317
  Clancy uses 3 MCP calls per ticket (metadata, design context, screenshot).
@@ -252,7 +323,7 @@ If a key is entered:
252
323
 
253
324
  If `GET /v1/me` fails (non-200), show:
254
325
  ```
255
- Couldn't verify Figma API key (HTTP {status}).
326
+ Couldn't verify Figma API key (HTTP {status}).
256
327
  Double-check it at figma.com/settings → Personal access tokens.
257
328
 
258
329
  [1] Try a different key
@@ -413,11 +484,15 @@ If no: output "Run /clancy:map-codebase when you're ready." then continue to fin
413
484
 
414
485
  Output:
415
486
 
416
- Clancy is ready.
487
+ ```
488
+ ╔═══════════════════════════════════════════════════════════╗
489
+ ║ ✅ Clancy is ready. ║
490
+ ╚═══════════════════════════════════════════════════════════╝
417
491
 
418
- - Scripts: `.clancy/clancy-once.sh`, `.clancy/clancy-afk.sh`
492
+ - Scripts: `.clancy/clancy-once.js`, `.clancy/clancy-afk.js`
419
493
  - Docs: `.clancy/docs/` (10 files)
420
494
  - Config: `.clancy/.env`
421
495
  - CLAUDE.md: updated
422
496
 
423
- Run `/clancy:dry-run` to preview the first ticket without making changes, `/clancy:once` to pick it up, or `/clancy:run` to process the full queue.
497
+ "Clancy's on the beat." — Run /clancy:dry-run to preview, /clancy:once to pick up a ticket, or /clancy:run to process the queue.
498
+ ```
@@ -10,7 +10,12 @@ Read `.clancy/progress.txt` and present a formatted summary.
10
10
 
11
11
  If `.clancy/progress.txt` does not exist:
12
12
  ```
13
- No progress logged yet. Run /clancy:once or /clancy:run to get started.
13
+ 🚨 Clancy Logs
14
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
15
+
16
+ No progress logged yet.
17
+
18
+ "The law is powerless to help you... but not for long." — Run /clancy:once or /clancy:run to get started.
14
19
  ```
15
20
  Stop.
16
21
 
@@ -43,15 +48,16 @@ If only 1–3 DONE entries: show a flat list, skip grouping.
43
48
  If 4+ entries, show the full grouped display:
44
49
 
45
50
  ```
46
- Clancy Progress Log
47
- ───────────────────────────────────────
51
+ 🚨 Clancy Logs
52
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
53
+
48
54
  Total tickets completed: {count}
49
55
  First run: {YYYY-MM-DD}
50
56
  Latest run: {YYYY-MM-DD}
51
57
 
52
58
  This week ({Mon date}–{Sun date or today}):
53
- {TICKET-KEY} {Summary}
54
- {TICKET-KEY} {Summary}
59
+ {TICKET-KEY} {Summary}
60
+ {TICKET-KEY} {Summary}
55
61
  ...
56
62
 
57
63
  By epic:
@@ -59,9 +65,10 @@ By epic:
59
65
  {EPIC-KEY} {Epic name or prefix} {bar} {count} tickets
60
66
  (other) {bar} {count} tickets
61
67
 
68
+ Reviews run: {N}
62
69
  Full log: .clancy/progress.txt
63
70
 
64
- Reviews run: {N}
71
+ "The law is powerless to help you, but here's what Clancy's done."
65
72
  ```
66
73
 
67
74
  ### Display rules