@slahon/lazykit 1.3.0 → 1.3.2
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 +19 -4
- package/git.js +10 -1
- package/init.js +40 -23
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,12 +21,14 @@ Run this from your **project's root directory** — the same folder that contain
|
|
|
21
21
|
- Node.js 18+
|
|
22
22
|
- A GitHub repository with a remote set up (`git remote -v` should show a GitHub URL)
|
|
23
23
|
- A Claude Pro or Max subscription ([claude.ai](https://claude.ai))
|
|
24
|
-
- Claude Code
|
|
25
|
-
- GitHub CLI (`gh`) —
|
|
24
|
+
- **Claude Code CLI** — `npm install -g @anthropic-ai/claude-code`
|
|
25
|
+
- **GitHub CLI (`gh`)** — `brew install gh` or [cli.github.com](https://cli.github.com), then `gh auth login`
|
|
26
26
|
- **Claude Code GitHub App** installed on your repo — [github.com/apps/claude](https://github.com/apps/claude) *(required for the Actions workflow to run)*
|
|
27
27
|
|
|
28
28
|
> **All `npx @slahon/lazykit` commands must be run from your project's root directory** — the folder where your `.git` directory lives and your GitHub remote is configured.
|
|
29
29
|
|
|
30
|
+
`init` checks for `gh` and `claude` before proceeding. If either is missing or not authenticated, it will show you exactly what to install and wait for you to confirm before continuing — no need to restart.
|
|
31
|
+
|
|
30
32
|
## How it works
|
|
31
33
|
|
|
32
34
|
### 1. Open an issue using the LazyKit Task template
|
|
@@ -137,9 +139,22 @@ During `npx @slahon/lazykit@latest init` you will be asked:
|
|
|
137
139
|
|
|
138
140
|
LazyKit uses your Claude Pro/Max subscription via an OAuth token — no pay-per-token API billing.
|
|
139
141
|
|
|
140
|
-
`init
|
|
142
|
+
During `init`, LazyKit runs `claude setup-token` and tries to capture the token automatically. On many systems a browser window opens, you approve access, and the token is stored as `CLAUDE_CODE_OAUTH_TOKEN` in your repo secrets without any extra steps.
|
|
143
|
+
|
|
144
|
+
If the token can't be captured automatically (varies by system), LazyKit falls back and shows you how to get it:
|
|
145
|
+
|
|
146
|
+
**Option A — run in a new terminal:**
|
|
147
|
+
```bash
|
|
148
|
+
claude setup-token
|
|
149
|
+
```
|
|
150
|
+
If the browser doesn't open, copy the URL it prints and open it manually in your browser.
|
|
151
|
+
|
|
152
|
+
**Option B — get it directly from Claude.ai:**
|
|
153
|
+
1. Go to `https://claude.ai/settings/claude-code`
|
|
154
|
+
2. Click **"Generate token"**
|
|
155
|
+
3. Copy the token (starts with `sk-ant-oat...`)
|
|
141
156
|
|
|
142
|
-
|
|
157
|
+
Then paste it when LazyKit prompts you — it sets the GitHub secret automatically.
|
|
143
158
|
|
|
144
159
|
**Token expiry:** OAuth tokens can expire. Run `lazykit status` to check the age of your token. If it's expired, re-run `npx @slahon/lazykit@latest init` to generate and store a fresh one.
|
|
145
160
|
|
package/git.js
CHANGED
|
@@ -91,6 +91,15 @@ function detectStack() {
|
|
|
91
91
|
return stack.length > 0 ? stack.join(' + ') : null;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
function isClaudeAvailable() {
|
|
95
|
+
try {
|
|
96
|
+
execSync('claude --version', { stdio: 'ignore' });
|
|
97
|
+
return true;
|
|
98
|
+
} catch {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
94
103
|
function hasBranchProtection({ owner, repo }) {
|
|
95
104
|
try {
|
|
96
105
|
execSync(`gh api repos/${owner}/${repo}/branches/main/protection`, { stdio: 'pipe' });
|
|
@@ -100,4 +109,4 @@ function hasBranchProtection({ owner, repo }) {
|
|
|
100
109
|
}
|
|
101
110
|
}
|
|
102
111
|
|
|
103
|
-
module.exports = { getGitRemote, parseGitHubRepo, isGitRepo, isGhCliAvailable, isGhAuthenticated, detectStack, hasBranchProtection };
|
|
112
|
+
module.exports = { getGitRemote, parseGitHubRepo, isGitRepo, isGhCliAvailable, isGhAuthenticated, isClaudeAvailable, detectStack, hasBranchProtection };
|
package/init.js
CHANGED
|
@@ -8,7 +8,7 @@ const ora = require('ora');
|
|
|
8
8
|
|
|
9
9
|
const { log } = require('./logger');
|
|
10
10
|
const { ask, confirm } = require('./prompt');
|
|
11
|
-
const { isGitRepo, getGitRemote, parseGitHubRepo, isGhCliAvailable, isGhAuthenticated, detectStack, hasBranchProtection } = require('./git');
|
|
11
|
+
const { isGitRepo, getGitRemote, parseGitHubRepo, isGhCliAvailable, isGhAuthenticated, isClaudeAvailable, detectStack, hasBranchProtection } = require('./git');
|
|
12
12
|
const { generateWorkflow } = require('./workflow');
|
|
13
13
|
const { generateClaudeMd } = require('./claude-md');
|
|
14
14
|
const { generateIssueTemplate } = require('./issue-template');
|
|
@@ -45,28 +45,38 @@ async function init({ dryRun = false } = {}) {
|
|
|
45
45
|
process.exit(1);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
// ─── Step 2: Check
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
log.
|
|
54
|
-
console.log(chalk.gray('
|
|
55
|
-
console.log(chalk.gray('
|
|
56
|
-
console.log(chalk.gray('
|
|
57
|
-
|
|
58
|
-
const cont = await confirm('Continue without gh? (some steps will be manual)', false);
|
|
59
|
-
if (!cont) process.exit(0);
|
|
60
|
-
} else if (!isGhAuthenticated()) {
|
|
61
|
-
log.warn('GitHub CLI is not authenticated.');
|
|
62
|
-
console.log(chalk.gray('\n Run the following to log in, then re-run LazyKit:\n'));
|
|
63
|
-
console.log(chalk.cyan(' gh auth login'));
|
|
64
|
-
console.log(chalk.gray('\n Then re-run: ') + chalk.cyan('npx @slahon/lazykit@latest init\n'));
|
|
65
|
-
const cont = await confirm('Continue without gh auth? (some steps will be manual)', false);
|
|
66
|
-
if (!cont) process.exit(0);
|
|
67
|
-
} else {
|
|
68
|
-
ghReady = true;
|
|
48
|
+
// ─── Step 2: Check dependencies (mandatory) ──────────────────────────────
|
|
49
|
+
|
|
50
|
+
// gh CLI
|
|
51
|
+
while (!isGhCliAvailable()) {
|
|
52
|
+
log.error('GitHub CLI (gh) is required but not found.');
|
|
53
|
+
console.log(chalk.gray('\n LazyKit uses gh to create labels, set secrets, and enable PR permissions.\n'));
|
|
54
|
+
console.log(chalk.gray(' Install it from: ') + chalk.cyan('https://cli.github.com'));
|
|
55
|
+
console.log(chalk.gray(' macOS: ') + chalk.cyan('brew install gh'));
|
|
56
|
+
console.log(chalk.gray(' Windows: ') + chalk.cyan('winget install --id GitHub.cli\n'));
|
|
57
|
+
await confirm('Press Enter once gh is installed to check again', true);
|
|
69
58
|
}
|
|
59
|
+
log.success('GitHub CLI (gh) found');
|
|
60
|
+
|
|
61
|
+
// gh auth
|
|
62
|
+
while (!isGhAuthenticated()) {
|
|
63
|
+
log.error('GitHub CLI is not authenticated.');
|
|
64
|
+
console.log(chalk.gray('\n Run this in your terminal, then come back:\n'));
|
|
65
|
+
console.log(chalk.cyan(' gh auth login\n'));
|
|
66
|
+
await confirm('Press Enter once you are logged in to check again', true);
|
|
67
|
+
}
|
|
68
|
+
log.success('GitHub CLI authenticated');
|
|
69
|
+
|
|
70
|
+
// Claude Code CLI
|
|
71
|
+
while (!isClaudeAvailable()) {
|
|
72
|
+
log.error('Claude Code CLI is required but not found.');
|
|
73
|
+
console.log(chalk.gray('\n Install it with:\n'));
|
|
74
|
+
console.log(chalk.cyan(' npm install -g @anthropic-ai/claude-code\n'));
|
|
75
|
+
await confirm('Press Enter once Claude Code is installed to check again', true);
|
|
76
|
+
}
|
|
77
|
+
log.success('Claude Code CLI found');
|
|
78
|
+
|
|
79
|
+
const ghReady = true;
|
|
70
80
|
|
|
71
81
|
log.blank();
|
|
72
82
|
|
|
@@ -203,7 +213,14 @@ async function init({ dryRun = false } = {}) {
|
|
|
203
213
|
if (!token) {
|
|
204
214
|
console.log();
|
|
205
215
|
log.warn('Could not capture the token automatically.');
|
|
206
|
-
console.log(chalk.gray(' If
|
|
216
|
+
console.log(chalk.gray('\n If no browser opened, here\'s how to get your token manually:\n'));
|
|
217
|
+
console.log(chalk.bold(' Option A — run in a new terminal window:'));
|
|
218
|
+
console.log(chalk.cyan(' claude setup-token'));
|
|
219
|
+
console.log(chalk.gray(' If the browser still doesn\'t open, copy the URL it prints and open it manually.\n'));
|
|
220
|
+
console.log(chalk.bold(' Option B — get it directly from Claude.ai:'));
|
|
221
|
+
console.log(chalk.gray(' 1. Go to: ') + chalk.cyan('https://claude.ai/settings/claude-code'));
|
|
222
|
+
console.log(chalk.gray(' 2. Click "Generate token"'));
|
|
223
|
+
console.log(chalk.gray(' 3. Copy the token (starts with sk-ant-oat...)\n'));
|
|
207
224
|
const pasted = await ask('Paste your token here (or press Enter to skip)', '');
|
|
208
225
|
if (pasted && pasted.trim().startsWith('sk-ant-oat')) {
|
|
209
226
|
token = pasted.trim();
|