@agentic15.com/agentic15-claude-zen 5.0.2 → 5.0.4
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/README.md +253 -42
- package/package.json +1 -1
- package/src/cli/AuthCommand.js +201 -201
package/README.md
CHANGED
|
@@ -9,36 +9,207 @@
|
|
|
9
9
|
|
|
10
10
|
## Overview
|
|
11
11
|
|
|
12
|
+
<table>
|
|
13
|
+
<tr>
|
|
14
|
+
<td width="50%">
|
|
15
|
+
|
|
16
|
+
### What is Agentic15 Claude Zen?
|
|
17
|
+
|
|
12
18
|
Agentic15 Claude Zen is a structured development framework designed to work seamlessly with Claude Code. It provides task tracking, workflow structure, and GitHub integration without enforcing rigid testing requirements.
|
|
13
19
|
|
|
14
20
|
**Philosophy:** Structure, not enforcement. The framework provides commands and organization, while Claude decides when tests are appropriate.
|
|
15
21
|
|
|
22
|
+
</td>
|
|
23
|
+
<td width="50%">
|
|
24
|
+
|
|
25
|
+
### Key Benefits
|
|
26
|
+
|
|
27
|
+
- ✅ **Task tracking** and organization
|
|
28
|
+
- ✅ **Consistent workflow** structure
|
|
29
|
+
- ✅ **GitHub integration** with automated PRs
|
|
30
|
+
- ✅ **Manual UI testing** tools
|
|
31
|
+
- ✅ **Flexible** - no mandatory testing
|
|
32
|
+
- ✅ **Claude Code optimized** hooks
|
|
33
|
+
|
|
34
|
+
</td>
|
|
35
|
+
</tr>
|
|
36
|
+
</table>
|
|
37
|
+
|
|
16
38
|
---
|
|
17
39
|
|
|
18
40
|
## Quick Start
|
|
19
41
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
42
|
+
### 1. Create Project
|
|
43
|
+
Creates new project with framework structure
|
|
44
|
+
|
|
45
|
+
**Bash/Mac/Linux:**
|
|
46
|
+
```bash
|
|
47
|
+
npx @agentic15.com/agentic15-claude-zen my-project
|
|
48
|
+
cd my-project
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**PowerShell (Windows):**
|
|
52
|
+
```powershell
|
|
53
|
+
npx "@agentic15.com/agentic15-claude-zen" my-project
|
|
54
|
+
cd my-project
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
### 2. Initialize Git
|
|
60
|
+
Links project to GitHub (required for PRs)
|
|
28
61
|
|
|
29
|
-
|
|
62
|
+
```bash
|
|
63
|
+
git init
|
|
64
|
+
git branch -M main
|
|
65
|
+
git add .
|
|
66
|
+
git commit -m "Initial commit"
|
|
67
|
+
|
|
68
|
+
gh repo create OWNER/REPO --public
|
|
69
|
+
git remote add origin https://github.com/OWNER/REPO.git
|
|
70
|
+
git push -u origin main
|
|
71
|
+
```
|
|
30
72
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
73
|
+
**Note:** Replace `OWNER/REPO` with your GitHub username/repo
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
### 3. Configure Auth
|
|
78
|
+
One-time GitHub authentication setup
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npx agentic15 auth
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
### 4. Create Plan
|
|
87
|
+
Generates and locks project plan
|
|
88
|
+
|
|
89
|
+
**In Terminal:**
|
|
90
|
+
```bash
|
|
91
|
+
npx agentic15 plan "Build a todo app with add, remove, and list features"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**In Claude Code (launch from project directory):**
|
|
95
|
+
```
|
|
96
|
+
Ask: "Create the project plan from the requirements file"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Back in Terminal:**
|
|
100
|
+
```bash
|
|
101
|
+
npx agentic15 plan
|
|
102
|
+
git add .
|
|
103
|
+
git commit -m "Add initial project plan"
|
|
104
|
+
git push
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Important:** Commit plan to main BEFORE enabling branch protection
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
### 5. Enable Branch Protection
|
|
112
|
+
Enforces PR-only workflow for all future changes
|
|
113
|
+
|
|
114
|
+
**Bash/Mac/Linux:**
|
|
115
|
+
```bash
|
|
116
|
+
cat > /tmp/protection.json << 'EOF'
|
|
117
|
+
{
|
|
118
|
+
"required_pull_request_reviews": {
|
|
119
|
+
"required_approving_review_count": 0
|
|
120
|
+
},
|
|
121
|
+
"enforce_admins": false,
|
|
122
|
+
"allow_force_pushes": false,
|
|
123
|
+
"allow_deletions": false,
|
|
124
|
+
"required_status_checks": null,
|
|
125
|
+
"restrictions": null
|
|
126
|
+
}
|
|
127
|
+
EOF
|
|
128
|
+
|
|
129
|
+
gh api repos/OWNER/REPO/branches/main/protection -X PUT \
|
|
130
|
+
-H "Accept: application/vnd.github+json" \
|
|
131
|
+
--input /tmp/protection.json
|
|
132
|
+
|
|
133
|
+
gh api repos/OWNER/REPO -X PATCH \
|
|
134
|
+
-H "Accept: application/vnd.github+json" \
|
|
135
|
+
-f delete_branch_on_merge=true
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**PowerShell (Windows):**
|
|
139
|
+
```powershell
|
|
140
|
+
$body = @"
|
|
141
|
+
{
|
|
142
|
+
"required_pull_request_reviews": {
|
|
143
|
+
"required_approving_review_count": 0
|
|
144
|
+
},
|
|
145
|
+
"enforce_admins": false,
|
|
146
|
+
"allow_force_pushes": false,
|
|
147
|
+
"allow_deletions": false,
|
|
148
|
+
"required_status_checks": null,
|
|
149
|
+
"restrictions": null
|
|
150
|
+
}
|
|
151
|
+
"@
|
|
152
|
+
|
|
153
|
+
echo $body | gh api repos/OWNER/REPO/branches/main/protection -X PUT -H "Accept: application/vnd.github+json" --input -
|
|
154
|
+
|
|
155
|
+
gh api repos/OWNER/REPO -X PATCH -H "Accept: application/vnd.github+json" -f delete_branch_on_merge=true
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
### 6. Start First Task
|
|
161
|
+
Creates feature branch for first task
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
npx agentic15 task next
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Daily Development Workflow
|
|
170
|
+
|
|
171
|
+
### 1. Implement (Claude Code)
|
|
172
|
+
Ask: "Implement the active task"
|
|
173
|
+
|
|
174
|
+
Claude writes code in `Agent/` directory
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
### 2. Commit & PR (Your Terminal)
|
|
179
|
+
```bash
|
|
180
|
+
npx agentic15 commit
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Stages changes, commits, pushes, creates PR
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
### 3. Review (GitHub)
|
|
188
|
+
Review and merge the PR
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
### 4. Sync & Next (Your Terminal)
|
|
193
|
+
```bash
|
|
194
|
+
npx agentic15 sync
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Syncs with main, deletes feature branch
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
npx agentic15 task next
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Starts next task
|
|
37
204
|
|
|
38
205
|
---
|
|
39
206
|
|
|
40
207
|
## Core Features
|
|
41
208
|
|
|
209
|
+
<table>
|
|
210
|
+
<tr>
|
|
211
|
+
<td width="50%">
|
|
212
|
+
|
|
42
213
|
### Commands
|
|
43
214
|
|
|
44
215
|
| Command | Description |
|
|
@@ -52,6 +223,9 @@ Agentic15 Claude Zen is a structured development framework designed to work seam
|
|
|
52
223
|
| `npx agentic15 visual-test <url>` | Capture UI screenshots and console errors |
|
|
53
224
|
| `npx agentic15 auth` | Configure GitHub authentication |
|
|
54
225
|
|
|
226
|
+
</td>
|
|
227
|
+
<td width="50%">
|
|
228
|
+
|
|
55
229
|
### Workflow Automation
|
|
56
230
|
|
|
57
231
|
The framework automates:
|
|
@@ -67,38 +241,51 @@ The framework automates:
|
|
|
67
241
|
plan → task → code → commit → PR → merge → sync → next task
|
|
68
242
|
```
|
|
69
243
|
|
|
244
|
+
</td>
|
|
245
|
+
</tr>
|
|
246
|
+
</table>
|
|
247
|
+
|
|
70
248
|
---
|
|
71
249
|
|
|
72
250
|
## Project Structure
|
|
73
251
|
|
|
252
|
+
<table>
|
|
253
|
+
<tr>
|
|
254
|
+
<td width="50%">
|
|
255
|
+
|
|
256
|
+
### Directory Layout
|
|
257
|
+
|
|
74
258
|
```
|
|
75
259
|
my-project/
|
|
76
260
|
├── node_modules/
|
|
77
261
|
│ └── @agentic15.com/agentic15-claude-zen/
|
|
78
|
-
│ └── framework/ # Framework files
|
|
262
|
+
│ └── framework/ # Framework files
|
|
79
263
|
│ ├── hooks/ # Claude Code hooks
|
|
80
264
|
│ ├── settings.json # Framework settings
|
|
81
265
|
│ ├── PLAN-SCHEMA.json
|
|
82
266
|
│ ├── PROJECT-PLAN-TEMPLATE.json
|
|
83
267
|
│ └── POST-INSTALL.md
|
|
84
|
-
├── .claude/ # User-generated content
|
|
268
|
+
├── .claude/ # User-generated content
|
|
85
269
|
│ ├── ACTIVE-PLAN # Current active plan
|
|
86
|
-
│ ├── plans/ # Your project plans
|
|
270
|
+
│ ├── plans/ # Your project plans
|
|
87
271
|
│ │ └── {planId}/
|
|
88
272
|
│ │ ├── TASK-TRACKER.json
|
|
89
273
|
│ │ └── tasks/
|
|
90
|
-
│ ├── settings.json # References framework
|
|
91
|
-
│ └── settings.local.json # Local overrides
|
|
274
|
+
│ ├── settings.json # References framework
|
|
275
|
+
│ └── settings.local.json # Local overrides
|
|
92
276
|
├── Agent/ # Your code workspace
|
|
93
277
|
│ ├── src/ # Source code
|
|
94
278
|
│ └── tests/ # Tests (optional)
|
|
95
|
-
├── scripts/ # Build
|
|
279
|
+
├── scripts/ # Build utilities
|
|
96
280
|
└── package.json # Project dependencies
|
|
97
281
|
```
|
|
98
282
|
|
|
283
|
+
</td>
|
|
284
|
+
<td width="50%">
|
|
285
|
+
|
|
99
286
|
### Framework Upgrades
|
|
100
287
|
|
|
101
|
-
Framework files live in `node_modules` and are automatically updated
|
|
288
|
+
Framework files live in `node_modules` and are automatically updated:
|
|
102
289
|
|
|
103
290
|
```bash
|
|
104
291
|
# Upgrade to latest version
|
|
@@ -118,10 +305,18 @@ npm install @agentic15.com/agentic15-claude-zen@5.0.0
|
|
|
118
305
|
- ✅ Your plans and tasks in `.claude/plans/`
|
|
119
306
|
- ✅ Your local settings in `.claude/settings.local.json`
|
|
120
307
|
|
|
308
|
+
</td>
|
|
309
|
+
</tr>
|
|
310
|
+
</table>
|
|
311
|
+
|
|
121
312
|
---
|
|
122
313
|
|
|
123
314
|
## GitHub Integration
|
|
124
315
|
|
|
316
|
+
<table>
|
|
317
|
+
<tr>
|
|
318
|
+
<td width="50%">
|
|
319
|
+
|
|
125
320
|
### Authentication
|
|
126
321
|
|
|
127
322
|
The framework uses **GitHub CLI (`gh`)** for authentication - no personal access tokens needed!
|
|
@@ -137,6 +332,11 @@ This command will:
|
|
|
137
332
|
3. Auto-detect your repository owner/repo from git remote
|
|
138
333
|
4. Save configuration to `.claude/settings.local.json`
|
|
139
334
|
|
|
335
|
+
**Note:** Authentication is handled by `gh` CLI - no token field needed.
|
|
336
|
+
|
|
337
|
+
</td>
|
|
338
|
+
<td width="50%">
|
|
339
|
+
|
|
140
340
|
### Manual Configuration (Optional)
|
|
141
341
|
|
|
142
342
|
If you need to override the auto-detected values, create or edit `.claude/settings.local.json`:
|
|
@@ -144,41 +344,55 @@ If you need to override the auto-detected values, create or edit `.claude/settin
|
|
|
144
344
|
{
|
|
145
345
|
"github": {
|
|
146
346
|
"enabled": true,
|
|
147
|
-
"autoCreate":
|
|
148
|
-
"autoUpdate":
|
|
149
|
-
"autoClose":
|
|
347
|
+
"autoCreate": false,
|
|
348
|
+
"autoUpdate": false,
|
|
349
|
+
"autoClose": false,
|
|
150
350
|
"owner": "your-username",
|
|
151
351
|
"repo": "your-repo"
|
|
152
352
|
}
|
|
153
353
|
}
|
|
154
354
|
```
|
|
155
355
|
|
|
156
|
-
**Note:**
|
|
356
|
+
**Note:** Default settings have `autoCreate`, `autoUpdate`, and `autoClose` set to `false` to give you full control. Set them to `true` if you want automatic GitHub issue management.
|
|
157
357
|
|
|
158
|
-
### Features
|
|
159
|
-
- **Auto-create issues:** When starting tasks
|
|
160
|
-
- **Auto-update issues:** When creating PRs
|
|
161
|
-
- **Auto-close issues:** When merging to main (
|
|
358
|
+
### Features (Optional - Enable in settings)
|
|
359
|
+
- **Auto-create issues:** When starting tasks (set `autoCreate: true`)
|
|
360
|
+
- **Auto-update issues:** When creating PRs (set `autoUpdate: true`)
|
|
361
|
+
- **Auto-close issues:** When merging to main (set `autoClose: true`)
|
|
162
362
|
- **Secure authentication:** Uses `gh` CLI credentials
|
|
163
363
|
|
|
364
|
+
</td>
|
|
365
|
+
</tr>
|
|
366
|
+
</table>
|
|
367
|
+
|
|
164
368
|
---
|
|
165
369
|
|
|
166
|
-
## Requirements
|
|
370
|
+
## Requirements & Philosophy
|
|
371
|
+
|
|
372
|
+
<table>
|
|
373
|
+
<tr>
|
|
374
|
+
<td width="50%">
|
|
375
|
+
|
|
376
|
+
### Requirements
|
|
167
377
|
|
|
168
378
|
- **Node.js:** 18.0.0 or higher
|
|
169
379
|
- **Git:** Any recent version
|
|
170
380
|
- **GitHub CLI:** `gh` command-line tool
|
|
171
381
|
- **GitHub Account:** For issue and PR management
|
|
172
382
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
## Documentation
|
|
383
|
+
### Documentation
|
|
176
384
|
|
|
177
385
|
- **[CHANGELOG.md](CHANGELOG.md)** - Version history and release notes
|
|
178
386
|
|
|
179
|
-
|
|
387
|
+
### Support
|
|
388
|
+
|
|
389
|
+
- **Issues:** https://github.com/agentic15/claude-zen/issues
|
|
390
|
+
- **Documentation:** https://github.com/agentic15/claude-zen
|
|
180
391
|
|
|
181
|
-
|
|
392
|
+
</td>
|
|
393
|
+
<td width="50%">
|
|
394
|
+
|
|
395
|
+
### Philosophy
|
|
182
396
|
|
|
183
397
|
**Structure, Not Enforcement**
|
|
184
398
|
|
|
@@ -196,12 +410,9 @@ The framework does NOT enforce:
|
|
|
196
410
|
|
|
197
411
|
**You decide:** When to write tests, what tools to use, and how to ensure quality. The framework provides structure and tools, not rigid rules.
|
|
198
412
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
- **Issues:** https://github.com/agentic15/claude-zen/issues
|
|
204
|
-
- **Documentation:** https://github.com/agentic15/claude-zen
|
|
413
|
+
</td>
|
|
414
|
+
</tr>
|
|
415
|
+
</table>
|
|
205
416
|
|
|
206
417
|
---
|
|
207
418
|
|
package/package.json
CHANGED
package/src/cli/AuthCommand.js
CHANGED
|
@@ -1,201 +1,201 @@
|
|
|
1
|
-
import { execSync } from 'child_process';
|
|
2
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
3
|
-
import { join, dirname } from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
import readline from 'readline';
|
|
6
|
-
|
|
7
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
-
const __dirname = dirname(__filename);
|
|
9
|
-
|
|
10
|
-
export class AuthCommand {
|
|
11
|
-
static async setup() {
|
|
12
|
-
console.log('\n🔐 GitHub Authentication Setup\n');
|
|
13
|
-
|
|
14
|
-
// Step 1: Check if gh CLI is installed
|
|
15
|
-
if (!this.isGhInstalled()) {
|
|
16
|
-
console.log('❌ GitHub CLI (gh) is not installed\n');
|
|
17
|
-
console.log('Please install GitHub CLI first:');
|
|
18
|
-
console.log(' - macOS: brew install gh');
|
|
19
|
-
console.log(' - Windows: winget install --id GitHub.cli');
|
|
20
|
-
console.log(' - Linux: https://github.com/cli/cli/blob/trunk/docs/install_linux.md\n');
|
|
21
|
-
console.log('Or visit: https://cli.github.com/\n');
|
|
22
|
-
process.exit(1);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Step 2: Check if already authenticated with gh
|
|
26
|
-
if (!this.isGhAuthenticated()) {
|
|
27
|
-
console.log('📝 You need to authenticate with GitHub CLI\n');
|
|
28
|
-
console.log('Running: gh auth login\n');
|
|
29
|
-
|
|
30
|
-
try {
|
|
31
|
-
execSync('gh auth login', { stdio: 'inherit' });
|
|
32
|
-
} catch (error) {
|
|
33
|
-
console.log('\n❌ GitHub authentication failed\n');
|
|
34
|
-
process.exit(1);
|
|
35
|
-
}
|
|
36
|
-
} else {
|
|
37
|
-
console.log('✓ Already authenticated with GitHub CLI\n');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Step 3: Display current git configuration
|
|
41
|
-
this.displayGitConfig();
|
|
42
|
-
|
|
43
|
-
// Step 4: Confirm configuration
|
|
44
|
-
const configOk = await this.confirmConfig();
|
|
45
|
-
if (!configOk) {
|
|
46
|
-
this.showConfigCommands();
|
|
47
|
-
console.log('\n❌ Setup cancelled. Please configure git first.\n');
|
|
48
|
-
process.exit(1);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Step 5: Auto-detect owner/repo
|
|
52
|
-
const { owner, repo } = this.detectRepo();
|
|
53
|
-
|
|
54
|
-
// Step 6: Save configuration (no token needed, gh CLI handles auth)
|
|
55
|
-
this.saveConfig(owner, repo);
|
|
56
|
-
|
|
57
|
-
console.log('\n✅ GitHub authentication configured successfully!\n');
|
|
58
|
-
console.log(` Owner: ${owner}`);
|
|
59
|
-
console.log(` Repo: ${repo}`);
|
|
60
|
-
console.log(` Auth: Using gh CLI credentials`);
|
|
61
|
-
console.log(` Config: .claude/settings.local.json\n`);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
static isGhInstalled() {
|
|
65
|
-
try {
|
|
66
|
-
execSync('gh --version', { stdio: 'pipe' });
|
|
67
|
-
return true;
|
|
68
|
-
} catch (error) {
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
static isGhAuthenticated() {
|
|
74
|
-
try {
|
|
75
|
-
execSync('gh auth status', { stdio: 'pipe' });
|
|
76
|
-
return true;
|
|
77
|
-
} catch (error) {
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
static displayGitConfig() {
|
|
83
|
-
console.log('📋 Current Git Configuration:\n');
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
// Global config
|
|
87
|
-
const globalName = execSync('git config --global user.name', { encoding: 'utf-8' }).trim();
|
|
88
|
-
const globalEmail = execSync('git config --global user.email', { encoding: 'utf-8' }).trim();
|
|
89
|
-
|
|
90
|
-
console.log(' Global:');
|
|
91
|
-
console.log(` - user.name: ${globalName || '(not set)'}`);
|
|
92
|
-
console.log(` - user.email: ${globalEmail || '(not set)'}`);
|
|
93
|
-
|
|
94
|
-
// Local config (project-specific)
|
|
95
|
-
try {
|
|
96
|
-
const localName = execSync('git config --local user.name', { encoding: 'utf-8' }).trim();
|
|
97
|
-
const localEmail = execSync('git config --local user.email', { encoding: 'utf-8' }).trim();
|
|
98
|
-
|
|
99
|
-
if (localName || localEmail) {
|
|
100
|
-
console.log('\n Local (this project):');
|
|
101
|
-
console.log(` - user.name: ${localName || '(not set)'}`);
|
|
102
|
-
console.log(` - user.email: ${localEmail || '(not set)'}`);
|
|
103
|
-
}
|
|
104
|
-
} catch (e) {
|
|
105
|
-
// No local config, that's ok
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
console.log('');
|
|
109
|
-
} catch (error) {
|
|
110
|
-
console.log(' ⚠️ Unable to read git config. Is git installed?\n');
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
static showConfigCommands() {
|
|
115
|
-
console.log('\n💡 To configure git, use these commands:\n');
|
|
116
|
-
console.log(' Global (all projects):');
|
|
117
|
-
console.log(' git config --global user.name "Your Name"');
|
|
118
|
-
console.log(' git config --global user.email "your@email.com"\n');
|
|
119
|
-
console.log(' Local (this project only):');
|
|
120
|
-
console.log(' git config --local user.name "Your Name"');
|
|
121
|
-
console.log(' git config --local user.email "your@email.com"\n');
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
static async confirmConfig() {
|
|
125
|
-
const rl = readline.createInterface({
|
|
126
|
-
input: process.stdin,
|
|
127
|
-
output: process.stdout
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
return new Promise((resolve) => {
|
|
131
|
-
rl.question('Is this configuration correct? (y/n): ', (answer) => {
|
|
132
|
-
rl.close();
|
|
133
|
-
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
static detectRepo() {
|
|
140
|
-
try {
|
|
141
|
-
// Get remote URL
|
|
142
|
-
const remoteUrl = execSync('git config --get remote.origin.url', { encoding: 'utf-8' }).trim();
|
|
143
|
-
|
|
144
|
-
// Parse owner/repo from URL
|
|
145
|
-
// Handles: git@github.com:owner/repo.git or https://github.com/owner/repo.git
|
|
146
|
-
const match = remoteUrl.match(/github\.com[:/]([^/]+)\/(.+?)(\.git)?$/);
|
|
147
|
-
|
|
148
|
-
if (match) {
|
|
149
|
-
return {
|
|
150
|
-
owner: match[1],
|
|
151
|
-
repo: match[2]
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
} catch (error) {
|
|
155
|
-
// Fallback if no remote
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Fallback: prompt user
|
|
159
|
-
console.log('\n⚠️ Could not auto-detect repository from git remote.');
|
|
160
|
-
console.log(' Using placeholder values. Update .claude/settings.local.json manually.\n');
|
|
161
|
-
|
|
162
|
-
return {
|
|
163
|
-
owner: 'your-github-username',
|
|
164
|
-
repo: 'your-repo-name'
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
static saveConfig(owner, repo) {
|
|
169
|
-
const settingsPath = join(process.cwd(), '.claude', 'settings.local.json');
|
|
170
|
-
const settingsDir = dirname(settingsPath);
|
|
171
|
-
|
|
172
|
-
// Ensure directory exists
|
|
173
|
-
if (!existsSync(settingsDir)) {
|
|
174
|
-
mkdirSync(settingsDir, { recursive: true });
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Read existing settings or create new
|
|
178
|
-
let settings = {};
|
|
179
|
-
if (existsSync(settingsPath)) {
|
|
180
|
-
try {
|
|
181
|
-
settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
|
182
|
-
} catch (e) {
|
|
183
|
-
// Invalid JSON, start fresh
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Update GitHub config (no token needed, gh CLI handles auth)
|
|
188
|
-
settings.github = {
|
|
189
|
-
enabled: true,
|
|
190
|
-
autoCreate:
|
|
191
|
-
autoUpdate:
|
|
192
|
-
autoClose:
|
|
193
|
-
owner,
|
|
194
|
-
repo,
|
|
195
|
-
comment: "Authentication handled by gh CLI (no token needed)"
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
// Write settings
|
|
199
|
-
writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
200
|
-
}
|
|
201
|
-
}
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
3
|
+
import { join, dirname } from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import readline from 'readline';
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
|
|
10
|
+
export class AuthCommand {
|
|
11
|
+
static async setup() {
|
|
12
|
+
console.log('\n🔐 GitHub Authentication Setup\n');
|
|
13
|
+
|
|
14
|
+
// Step 1: Check if gh CLI is installed
|
|
15
|
+
if (!this.isGhInstalled()) {
|
|
16
|
+
console.log('❌ GitHub CLI (gh) is not installed\n');
|
|
17
|
+
console.log('Please install GitHub CLI first:');
|
|
18
|
+
console.log(' - macOS: brew install gh');
|
|
19
|
+
console.log(' - Windows: winget install --id GitHub.cli');
|
|
20
|
+
console.log(' - Linux: https://github.com/cli/cli/blob/trunk/docs/install_linux.md\n');
|
|
21
|
+
console.log('Or visit: https://cli.github.com/\n');
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Step 2: Check if already authenticated with gh
|
|
26
|
+
if (!this.isGhAuthenticated()) {
|
|
27
|
+
console.log('📝 You need to authenticate with GitHub CLI\n');
|
|
28
|
+
console.log('Running: gh auth login\n');
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
execSync('gh auth login', { stdio: 'inherit' });
|
|
32
|
+
} catch (error) {
|
|
33
|
+
console.log('\n❌ GitHub authentication failed\n');
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
console.log('✓ Already authenticated with GitHub CLI\n');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Step 3: Display current git configuration
|
|
41
|
+
this.displayGitConfig();
|
|
42
|
+
|
|
43
|
+
// Step 4: Confirm configuration
|
|
44
|
+
const configOk = await this.confirmConfig();
|
|
45
|
+
if (!configOk) {
|
|
46
|
+
this.showConfigCommands();
|
|
47
|
+
console.log('\n❌ Setup cancelled. Please configure git first.\n');
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Step 5: Auto-detect owner/repo
|
|
52
|
+
const { owner, repo } = this.detectRepo();
|
|
53
|
+
|
|
54
|
+
// Step 6: Save configuration (no token needed, gh CLI handles auth)
|
|
55
|
+
this.saveConfig(owner, repo);
|
|
56
|
+
|
|
57
|
+
console.log('\n✅ GitHub authentication configured successfully!\n');
|
|
58
|
+
console.log(` Owner: ${owner}`);
|
|
59
|
+
console.log(` Repo: ${repo}`);
|
|
60
|
+
console.log(` Auth: Using gh CLI credentials`);
|
|
61
|
+
console.log(` Config: .claude/settings.local.json\n`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static isGhInstalled() {
|
|
65
|
+
try {
|
|
66
|
+
execSync('gh --version', { stdio: 'pipe' });
|
|
67
|
+
return true;
|
|
68
|
+
} catch (error) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static isGhAuthenticated() {
|
|
74
|
+
try {
|
|
75
|
+
execSync('gh auth status', { stdio: 'pipe' });
|
|
76
|
+
return true;
|
|
77
|
+
} catch (error) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
static displayGitConfig() {
|
|
83
|
+
console.log('📋 Current Git Configuration:\n');
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
// Global config
|
|
87
|
+
const globalName = execSync('git config --global user.name', { encoding: 'utf-8' }).trim();
|
|
88
|
+
const globalEmail = execSync('git config --global user.email', { encoding: 'utf-8' }).trim();
|
|
89
|
+
|
|
90
|
+
console.log(' Global:');
|
|
91
|
+
console.log(` - user.name: ${globalName || '(not set)'}`);
|
|
92
|
+
console.log(` - user.email: ${globalEmail || '(not set)'}`);
|
|
93
|
+
|
|
94
|
+
// Local config (project-specific)
|
|
95
|
+
try {
|
|
96
|
+
const localName = execSync('git config --local user.name', { encoding: 'utf-8' }).trim();
|
|
97
|
+
const localEmail = execSync('git config --local user.email', { encoding: 'utf-8' }).trim();
|
|
98
|
+
|
|
99
|
+
if (localName || localEmail) {
|
|
100
|
+
console.log('\n Local (this project):');
|
|
101
|
+
console.log(` - user.name: ${localName || '(not set)'}`);
|
|
102
|
+
console.log(` - user.email: ${localEmail || '(not set)'}`);
|
|
103
|
+
}
|
|
104
|
+
} catch (e) {
|
|
105
|
+
// No local config, that's ok
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
console.log('');
|
|
109
|
+
} catch (error) {
|
|
110
|
+
console.log(' ⚠️ Unable to read git config. Is git installed?\n');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static showConfigCommands() {
|
|
115
|
+
console.log('\n💡 To configure git, use these commands:\n');
|
|
116
|
+
console.log(' Global (all projects):');
|
|
117
|
+
console.log(' git config --global user.name "Your Name"');
|
|
118
|
+
console.log(' git config --global user.email "your@email.com"\n');
|
|
119
|
+
console.log(' Local (this project only):');
|
|
120
|
+
console.log(' git config --local user.name "Your Name"');
|
|
121
|
+
console.log(' git config --local user.email "your@email.com"\n');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
static async confirmConfig() {
|
|
125
|
+
const rl = readline.createInterface({
|
|
126
|
+
input: process.stdin,
|
|
127
|
+
output: process.stdout
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
return new Promise((resolve) => {
|
|
131
|
+
rl.question('Is this configuration correct? (y/n): ', (answer) => {
|
|
132
|
+
rl.close();
|
|
133
|
+
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
static detectRepo() {
|
|
140
|
+
try {
|
|
141
|
+
// Get remote URL
|
|
142
|
+
const remoteUrl = execSync('git config --get remote.origin.url', { encoding: 'utf-8' }).trim();
|
|
143
|
+
|
|
144
|
+
// Parse owner/repo from URL
|
|
145
|
+
// Handles: git@github.com:owner/repo.git or https://github.com/owner/repo.git
|
|
146
|
+
const match = remoteUrl.match(/github\.com[:/]([^/]+)\/(.+?)(\.git)?$/);
|
|
147
|
+
|
|
148
|
+
if (match) {
|
|
149
|
+
return {
|
|
150
|
+
owner: match[1],
|
|
151
|
+
repo: match[2]
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
} catch (error) {
|
|
155
|
+
// Fallback if no remote
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Fallback: prompt user
|
|
159
|
+
console.log('\n⚠️ Could not auto-detect repository from git remote.');
|
|
160
|
+
console.log(' Using placeholder values. Update .claude/settings.local.json manually.\n');
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
owner: 'your-github-username',
|
|
164
|
+
repo: 'your-repo-name'
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
static saveConfig(owner, repo) {
|
|
169
|
+
const settingsPath = join(process.cwd(), '.claude', 'settings.local.json');
|
|
170
|
+
const settingsDir = dirname(settingsPath);
|
|
171
|
+
|
|
172
|
+
// Ensure directory exists
|
|
173
|
+
if (!existsSync(settingsDir)) {
|
|
174
|
+
mkdirSync(settingsDir, { recursive: true });
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Read existing settings or create new
|
|
178
|
+
let settings = {};
|
|
179
|
+
if (existsSync(settingsPath)) {
|
|
180
|
+
try {
|
|
181
|
+
settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
|
182
|
+
} catch (e) {
|
|
183
|
+
// Invalid JSON, start fresh
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Update GitHub config (no token needed, gh CLI handles auth)
|
|
188
|
+
settings.github = {
|
|
189
|
+
enabled: true,
|
|
190
|
+
autoCreate: false,
|
|
191
|
+
autoUpdate: false,
|
|
192
|
+
autoClose: false,
|
|
193
|
+
owner,
|
|
194
|
+
repo,
|
|
195
|
+
comment: "Authentication handled by gh CLI (no token needed)"
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
// Write settings
|
|
199
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
200
|
+
}
|
|
201
|
+
}
|