cc-discipline 2.8.1 → 2.9.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 (3) hide show
  1. package/bin/cli.js +147 -0
  2. package/init.sh +13 -5
  3. package/package.json +2 -2
package/bin/cli.js ADDED
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env node
2
+ // cc-discipline CLI entry point (cross-platform)
3
+ // Detects platform and spawns bash with correct paths
4
+
5
+ const { execSync, spawnSync } = require('child_process');
6
+ const path = require('path');
7
+ const fs = require('fs');
8
+
9
+ const PKG_DIR = path.resolve(__dirname, '..');
10
+ const args = process.argv.slice(2);
11
+
12
+ // Find bash executable
13
+ function findBash() {
14
+ // Unix: bash is always available
15
+ if (process.platform !== 'win32') return 'bash';
16
+
17
+ // Windows: try common Git Bash locations
18
+ const candidates = [
19
+ 'C:\\Program Files\\Git\\bin\\bash.exe',
20
+ 'C:\\Program Files (x86)\\Git\\bin\\bash.exe',
21
+ process.env.PROGRAMFILES + '\\Git\\bin\\bash.exe',
22
+ ];
23
+
24
+ for (const candidate of candidates) {
25
+ if (fs.existsSync(candidate)) return candidate;
26
+ }
27
+
28
+ // Try PATH
29
+ try {
30
+ execSync('bash --version', { stdio: 'ignore' });
31
+ return 'bash';
32
+ } catch (e) {
33
+ console.error('Error: bash not found. Please install Git for Windows (https://git-scm.com/download/win)');
34
+ console.error('Git Bash is required to run cc-discipline on Windows.');
35
+ process.exit(1);
36
+ }
37
+ }
38
+
39
+ const bash = findBash();
40
+
41
+ // Convert Windows path to Unix-style for bash
42
+ function toUnixPath(p) {
43
+ if (process.platform !== 'win32') return p;
44
+ // C:\Users\foo → /c/Users/foo
45
+ return p.replace(/\\/g, '/').replace(/^([A-Za-z]):/, (_, drive) => '/' + drive.toLowerCase());
46
+ }
47
+
48
+ // Route subcommands
49
+ const command = args[0] || 'init';
50
+ const restArgs = args.slice(1);
51
+
52
+ let script;
53
+ let scriptArgs;
54
+
55
+ switch (command) {
56
+ case 'init':
57
+ script = path.join(PKG_DIR, 'init.sh');
58
+ scriptArgs = restArgs;
59
+ break;
60
+ case 'upgrade':
61
+ script = path.join(PKG_DIR, 'init.sh');
62
+ scriptArgs = ['--auto', ...restArgs];
63
+ break;
64
+ case 'status':
65
+ script = path.join(PKG_DIR, 'lib', 'status.sh');
66
+ scriptArgs = [];
67
+ break;
68
+ case 'doctor':
69
+ script = path.join(PKG_DIR, 'lib', 'doctor.sh');
70
+ scriptArgs = [];
71
+ break;
72
+ case 'add-stack':
73
+ if (restArgs.length === 0) {
74
+ console.log('Usage: cc-discipline add-stack <numbers>');
75
+ console.log(' e.g.: cc-discipline add-stack 3 4');
76
+ process.exit(1);
77
+ }
78
+ script = path.join(PKG_DIR, 'init.sh');
79
+ scriptArgs = ['--stack', restArgs.join(' '), '--no-global'];
80
+ break;
81
+ case 'remove-stack':
82
+ script = path.join(PKG_DIR, 'lib', 'stack-remove.sh');
83
+ scriptArgs = restArgs;
84
+ break;
85
+ case '-v':
86
+ case '--version':
87
+ case 'version':
88
+ const pkg = require(path.join(PKG_DIR, 'package.json'));
89
+ console.log(`cc-discipline v${pkg.version}`);
90
+ process.exit(0);
91
+ case '-h':
92
+ case '--help':
93
+ case 'help':
94
+ const ver = require(path.join(PKG_DIR, 'package.json')).version;
95
+ console.log(`cc-discipline v${ver} — Discipline framework for Claude Code
96
+
97
+ Usage: cc-discipline <command> [options]
98
+
99
+ Commands:
100
+ init [options] Install discipline into current project (default)
101
+ upgrade Upgrade rules/hooks (shortcut for init --auto)
102
+ add-stack <numbers> Add stack rules (e.g., add-stack 3 4)
103
+ remove-stack <numbers> Remove stack rules
104
+ status Show installed version, stacks, and hooks
105
+ doctor Check installation integrity
106
+ version Show version
107
+
108
+ Init options:
109
+ --auto Non-interactive with defaults
110
+ --stack <choices> Stack selection: 1-7, space-separated
111
+ --name <name> Project name (default: directory name)
112
+ --global Install global rules to ~/.claude/CLAUDE.md
113
+ --no-global Skip global rules install
114
+
115
+ Stacks:
116
+ 1=RTL 2=Embedded 3=Python 4=JS/TS 5=Mobile 6=Fullstack 7=General
117
+
118
+ Examples:
119
+ npx cc-discipline # Interactive setup
120
+ npx cc-discipline init --auto # Non-interactive defaults
121
+ npx cc-discipline init --auto --stack "3 4" # Python + JS/TS
122
+ npx cc-discipline upgrade # Upgrade to latest
123
+ npx cc-discipline status # Check what's installed
124
+ npx cc-discipline doctor # Diagnose issues`);
125
+ process.exit(0);
126
+ default:
127
+ console.error(`Unknown command: ${command}`);
128
+ console.error("Run 'cc-discipline --help' for usage");
129
+ process.exit(1);
130
+ }
131
+
132
+ // Run the bash script
133
+ const unixScript = toUnixPath(script);
134
+ const pkgVersion = require(path.join(PKG_DIR, 'package.json')).version;
135
+ const env = {
136
+ ...process.env,
137
+ CC_DISCIPLINE_PKG_DIR: process.platform === 'win32' ? toUnixPath(PKG_DIR) : PKG_DIR,
138
+ CC_DISCIPLINE_VERSION: pkgVersion,
139
+ };
140
+
141
+ const result = spawnSync(bash, [unixScript, ...scriptArgs], {
142
+ stdio: 'inherit',
143
+ env,
144
+ cwd: process.cwd(),
145
+ });
146
+
147
+ process.exit(result.status || 0);
package/init.sh CHANGED
@@ -5,12 +5,20 @@
5
5
  # cd your-project && bash /path/to/init.sh --stack "3 4" --name myapp --global
6
6
  # Or: curl -sL https://raw.githubusercontent.com/YOU/cc-discipline/main/init.sh | bash
7
7
 
8
- set -e
8
+ # On Windows (Git Bash), set -e causes silent failures due to path/command differences.
9
+ # Use explicit error checking for critical operations instead.
10
+ if [[ "$(uname -s)" != MINGW* ]] && [[ "$(uname -s)" != MSYS* ]]; then
11
+ set -e
12
+ fi
9
13
 
10
- # ─── Version (single source: package.json) ───
11
- _INIT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
- if command -v node &>/dev/null && [ -f "$_INIT_DIR/package.json" ]; then
13
- VERSION=$(node -p "require('$_INIT_DIR/package.json').version" 2>/dev/null)
14
+ # ─── Version ───
15
+ # cli.js sets CC_DISCIPLINE_VERSION on Windows where node paths are tricky
16
+ VERSION="${CC_DISCIPLINE_VERSION:-unknown}"
17
+ if [ "$VERSION" = "unknown" ]; then
18
+ _INIT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
19
+ if command -v node &>/dev/null && [ -f "$_INIT_DIR/package.json" ]; then
20
+ VERSION=$(node -p "require('$_INIT_DIR/package.json').version" 2>/dev/null) || true
21
+ fi
14
22
  fi
15
23
  VERSION="${VERSION:-unknown}"
16
24
 
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "cc-discipline",
3
- "version": "2.8.1",
3
+ "version": "2.9.1",
4
4
  "description": "Discipline framework for Claude Code — rules, hooks, and agents that keep AI on track",
5
5
  "bin": {
6
- "cc-discipline": "bin/cli.sh"
6
+ "cc-discipline": "bin/cli.js"
7
7
  },
8
8
  "files": [
9
9
  "bin/",