octocode-cli 1.2.5 → 1.2.6
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 +56 -22
- package/out/octocode-cli.js +80 -148
- package/package.json +2 -2
- package/skills/octocode-implement/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -41,19 +41,27 @@ npx octocode-cli
|
|
|
41
41
|
## 📦 Installation & Usage
|
|
42
42
|
|
|
43
43
|
### Interactive Mode
|
|
44
|
+
|
|
44
45
|
The recommended way to use Octocode CLI. Access all features through a unified menu:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
|
|
47
|
+
| Menu Item | Description |
|
|
48
|
+
|-----------|-------------|
|
|
49
|
+
| **🐙 Octocode MCP** | Install and configure Octocode MCP for your IDEs |
|
|
50
|
+
| **🐙 Octocode Skills** | Install AI-powered research, planning & review skills |
|
|
51
|
+
| **🧠 Manage System Skills** | Browse skills marketplace and manage installed skills |
|
|
52
|
+
| **🔑 Manage Auth** | Sign in/out via Octocode OAuth or gh CLI |
|
|
53
|
+
| **⚡ Manage System MCP** | Sync configs, browse MCP marketplace, inspect settings |
|
|
48
54
|
|
|
49
55
|
```bash
|
|
50
56
|
npx octocode-cli
|
|
51
57
|
```
|
|
52
58
|
|
|
53
59
|
### CLI Commands
|
|
60
|
+
|
|
54
61
|
For automation and power users, Octocode CLI offers a comprehensive command-line interface.
|
|
55
62
|
|
|
56
63
|
#### 1. Install Octocode MCP
|
|
64
|
+
|
|
57
65
|
Install the GitHub MCP server for your preferred IDE.
|
|
58
66
|
|
|
59
67
|
```bash
|
|
@@ -64,56 +72,82 @@ octocode-cli install
|
|
|
64
72
|
octocode-cli install --ide cursor --method npx
|
|
65
73
|
octocode-cli install --ide claude-desktop --method direct
|
|
66
74
|
octocode-cli install --ide windsurf
|
|
75
|
+
octocode-cli install --ide zed
|
|
67
76
|
```
|
|
68
77
|
|
|
78
|
+
**Supported IDEs**: `cursor`, `claude-desktop`, `claude-code`, `windsurf`, `zed`, `vscode-cline`, `vscode-roo`, `vscode-continue`, `opencode`, `trae`, `antigravity`
|
|
79
|
+
|
|
69
80
|
#### 2. Manage Authentication
|
|
81
|
+
|
|
70
82
|
Securely authenticate with GitHub. Credentials are encrypted (AES-256-GCM) and stored in `~/.octocode/`.
|
|
71
83
|
|
|
72
84
|
```bash
|
|
73
|
-
# Interactive login
|
|
85
|
+
# Interactive login (OAuth device flow)
|
|
74
86
|
octocode-cli login
|
|
75
87
|
|
|
76
|
-
# Check status
|
|
88
|
+
# Check authentication status
|
|
77
89
|
octocode-cli status
|
|
78
90
|
|
|
79
91
|
# Enterprise Login
|
|
80
92
|
octocode-cli login --hostname github.mycompany.com
|
|
93
|
+
|
|
94
|
+
# Sign out
|
|
95
|
+
octocode-cli logout
|
|
96
|
+
|
|
97
|
+
# Auth management menu
|
|
98
|
+
octocode-cli auth
|
|
81
99
|
```
|
|
82
100
|
|
|
83
|
-
#### 3.
|
|
101
|
+
#### 3. Get GitHub Token
|
|
102
|
+
|
|
103
|
+
Retrieve tokens for scripting or debugging.
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Get token (auto: env → gh → octocode)
|
|
107
|
+
octocode-cli token
|
|
108
|
+
|
|
109
|
+
# Get token from specific source
|
|
110
|
+
octocode-cli token --type=octocode
|
|
111
|
+
octocode-cli token --type=gh
|
|
112
|
+
|
|
113
|
+
# Show token source and user info
|
|
114
|
+
octocode-cli token --source
|
|
115
|
+
|
|
116
|
+
# JSON output for scripting
|
|
117
|
+
octocode-cli token --json
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### 4. Sync Configurations
|
|
121
|
+
|
|
84
122
|
Keep your MCP settings consistent across different editors.
|
|
85
123
|
|
|
86
124
|
```bash
|
|
87
125
|
# Sync all IDEs
|
|
88
126
|
octocode-cli sync
|
|
89
127
|
|
|
90
|
-
# Preview changes
|
|
128
|
+
# Preview changes (dry run)
|
|
91
129
|
octocode-cli sync --dry-run
|
|
130
|
+
|
|
131
|
+
# Show sync status
|
|
132
|
+
octocode-cli sync --status
|
|
133
|
+
|
|
134
|
+
# Force sync (auto-resolve conflicts)
|
|
135
|
+
octocode-cli sync --force
|
|
92
136
|
```
|
|
93
137
|
|
|
94
|
-
####
|
|
138
|
+
#### 5. Manage Skills
|
|
139
|
+
|
|
95
140
|
Install AI skills for Claude Code.
|
|
96
141
|
|
|
97
142
|
```bash
|
|
98
143
|
# List available skills
|
|
99
144
|
octocode-cli skills list
|
|
100
145
|
|
|
101
|
-
# Install all
|
|
146
|
+
# Install all skills
|
|
102
147
|
octocode-cli skills install
|
|
103
|
-
```
|
|
104
148
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
```bash
|
|
109
|
-
# Logout from GitHub
|
|
110
|
-
octocode-cli logout
|
|
111
|
-
|
|
112
|
-
# Get GitHub token (for scripting)
|
|
113
|
-
octocode-cli token
|
|
114
|
-
|
|
115
|
-
# Auth management menu
|
|
116
|
-
octocode-cli auth
|
|
149
|
+
# Force reinstall (overwrite existing)
|
|
150
|
+
octocode-cli skills install --force
|
|
117
151
|
```
|
|
118
152
|
|
|
119
153
|
---
|
package/out/octocode-cli.js
CHANGED
|
@@ -79,7 +79,12 @@ class TimeoutError extends Error {
|
|
|
79
79
|
async function withTimeout(promise, ms) {
|
|
80
80
|
return Promise.race([
|
|
81
81
|
promise,
|
|
82
|
-
new Promise(
|
|
82
|
+
new Promise(
|
|
83
|
+
(_, reject) => setTimeout(
|
|
84
|
+
() => reject(new TimeoutError(`Operation timed out after ${ms}ms`)),
|
|
85
|
+
ms
|
|
86
|
+
)
|
|
87
|
+
)
|
|
83
88
|
]);
|
|
84
89
|
}
|
|
85
90
|
let _keychainAvailable = null;
|
|
@@ -99,8 +104,7 @@ const credentialsCache = /* @__PURE__ */ new Map();
|
|
|
99
104
|
const CACHE_TTL_MS$1 = 5 * 60 * 1e3;
|
|
100
105
|
function isCacheValid$1(hostname) {
|
|
101
106
|
const cached = credentialsCache.get(hostname);
|
|
102
|
-
if (!cached)
|
|
103
|
-
return false;
|
|
107
|
+
if (!cached) return false;
|
|
104
108
|
const age = Date.now() - cached.cachedAt;
|
|
105
109
|
return age < CACHE_TTL_MS$1;
|
|
106
110
|
}
|
|
@@ -156,20 +160,17 @@ async function keychainStore(hostname, credentials) {
|
|
|
156
160
|
await setPassword(KEYCHAIN_SERVICE, hostname, data);
|
|
157
161
|
}
|
|
158
162
|
async function keychainGet(hostname) {
|
|
159
|
-
if (!checkKeychainAvailable())
|
|
160
|
-
return null;
|
|
163
|
+
if (!checkKeychainAvailable()) return null;
|
|
161
164
|
try {
|
|
162
165
|
const data = await getPassword(KEYCHAIN_SERVICE, hostname);
|
|
163
|
-
if (!data)
|
|
164
|
-
return null;
|
|
166
|
+
if (!data) return null;
|
|
165
167
|
return JSON.parse(data);
|
|
166
168
|
} catch {
|
|
167
169
|
return null;
|
|
168
170
|
}
|
|
169
171
|
}
|
|
170
172
|
async function keychainDelete(hostname) {
|
|
171
|
-
if (!checkKeychainAvailable())
|
|
172
|
-
return false;
|
|
173
|
+
if (!checkKeychainAvailable()) return false;
|
|
173
174
|
try {
|
|
174
175
|
return await deletePassword(KEYCHAIN_SERVICE, hostname);
|
|
175
176
|
} catch {
|
|
@@ -223,7 +224,9 @@ function readCredentialsStore() {
|
|
|
223
224
|
const decrypted = decrypt(encryptedContent);
|
|
224
225
|
return JSON.parse(decrypted);
|
|
225
226
|
} catch (error) {
|
|
226
|
-
console.error(
|
|
227
|
+
console.error(
|
|
228
|
+
"\n ⚠ Warning: Could not read credentials file. You may need to login again."
|
|
229
|
+
);
|
|
227
230
|
console.error(` File: ${CREDENTIALS_FILE}`);
|
|
228
231
|
if (error instanceof Error && error.message) {
|
|
229
232
|
console.error(` Reason: ${error.message}
|
|
@@ -251,7 +254,9 @@ function removeFromFileStorage(hostname) {
|
|
|
251
254
|
}
|
|
252
255
|
return false;
|
|
253
256
|
} catch (err) {
|
|
254
|
-
console.warn(
|
|
257
|
+
console.warn(
|
|
258
|
+
`[token-storage] Failed to remove from file storage: ${err instanceof Error ? err.message : String(err)}`
|
|
259
|
+
);
|
|
255
260
|
return false;
|
|
256
261
|
}
|
|
257
262
|
}
|
|
@@ -285,12 +290,17 @@ async function storeCredentials(credentials) {
|
|
|
285
290
|
};
|
|
286
291
|
if (isSecureStorageAvailable()) {
|
|
287
292
|
try {
|
|
288
|
-
await withTimeout(
|
|
293
|
+
await withTimeout(
|
|
294
|
+
keychainStore(hostname, normalizedCredentials),
|
|
295
|
+
KEYRING_TIMEOUT_MS
|
|
296
|
+
);
|
|
289
297
|
removeFromFileStorage(hostname);
|
|
290
298
|
invalidateCredentialsCache(hostname);
|
|
291
299
|
return { success: true, insecureStorageUsed: false };
|
|
292
300
|
} catch (err) {
|
|
293
|
-
console.warn(
|
|
301
|
+
console.warn(
|
|
302
|
+
`[token-storage] Keyring storage failed, using file fallback: ${err instanceof Error ? err.message : String(err)}`
|
|
303
|
+
);
|
|
294
304
|
}
|
|
295
305
|
}
|
|
296
306
|
try {
|
|
@@ -301,7 +311,9 @@ async function storeCredentials(credentials) {
|
|
|
301
311
|
return { success: true, insecureStorageUsed: true };
|
|
302
312
|
} catch (fileError) {
|
|
303
313
|
console.error(`[token-storage] CRITICAL: All storage methods failed!`);
|
|
304
|
-
console.error(
|
|
314
|
+
console.error(
|
|
315
|
+
` Error: ${fileError instanceof Error ? fileError.message : String(fileError)}`
|
|
316
|
+
);
|
|
305
317
|
throw new Error("Failed to store credentials");
|
|
306
318
|
}
|
|
307
319
|
}
|
|
@@ -324,12 +336,16 @@ async function getCredentials(hostname = "github.com", options) {
|
|
|
324
336
|
async function fetchCredentialsFromStorage(normalizedHostname) {
|
|
325
337
|
if (isSecureStorageAvailable()) {
|
|
326
338
|
try {
|
|
327
|
-
const creds = await withTimeout(
|
|
328
|
-
|
|
329
|
-
|
|
339
|
+
const creds = await withTimeout(
|
|
340
|
+
keychainGet(normalizedHostname),
|
|
341
|
+
KEYRING_TIMEOUT_MS
|
|
342
|
+
);
|
|
343
|
+
if (creds) return creds;
|
|
330
344
|
} catch (err) {
|
|
331
345
|
if (!(err instanceof TimeoutError)) {
|
|
332
|
-
console.warn(
|
|
346
|
+
console.warn(
|
|
347
|
+
`[token-storage] Keyring read failed: ${err instanceof Error ? err.message : String(err)}`
|
|
348
|
+
);
|
|
333
349
|
}
|
|
334
350
|
}
|
|
335
351
|
}
|
|
@@ -355,9 +371,14 @@ async function deleteCredentials(hostname = "github.com") {
|
|
|
355
371
|
let deletedFromFile = false;
|
|
356
372
|
if (isSecureStorageAvailable()) {
|
|
357
373
|
try {
|
|
358
|
-
deletedFromKeyring = await withTimeout(
|
|
374
|
+
deletedFromKeyring = await withTimeout(
|
|
375
|
+
keychainDelete(normalizedHostname),
|
|
376
|
+
KEYRING_TIMEOUT_MS
|
|
377
|
+
);
|
|
359
378
|
} catch (err) {
|
|
360
|
-
console.warn(
|
|
379
|
+
console.warn(
|
|
380
|
+
`[token-storage] Keyring delete failed: ${err instanceof Error ? err.message : String(err)}`
|
|
381
|
+
);
|
|
361
382
|
}
|
|
362
383
|
}
|
|
363
384
|
const store = readCredentialsStore();
|
|
@@ -7843,18 +7864,18 @@ defineLazyProperty(apps, "safari", () => detectPlatformBinary({
|
|
|
7843
7864
|
darwin: "Safari"
|
|
7844
7865
|
}));
|
|
7845
7866
|
const SKILLS_MARKETPLACES = [
|
|
7846
|
-
// ===
|
|
7867
|
+
// === OCTOCODE SKILLS ===
|
|
7847
7868
|
{
|
|
7848
|
-
id: "octocode-
|
|
7849
|
-
name: "
|
|
7850
|
-
type: "
|
|
7851
|
-
owner: "
|
|
7869
|
+
id: "octocode-skills",
|
|
7870
|
+
name: "Octocode Skills",
|
|
7871
|
+
type: "github",
|
|
7872
|
+
owner: "bgauryy",
|
|
7852
7873
|
repo: "octocode-mcp",
|
|
7853
7874
|
branch: "main",
|
|
7854
|
-
skillsPath: "
|
|
7875
|
+
skillsPath: "skills",
|
|
7855
7876
|
skillPattern: "skill-folders",
|
|
7856
|
-
description: "
|
|
7857
|
-
url: "https://github.com/
|
|
7877
|
+
description: "Research, planning, implementation & PR review skills",
|
|
7878
|
+
url: "https://github.com/bgauryy/octocode-mcp/tree/main/skills"
|
|
7858
7879
|
},
|
|
7859
7880
|
// === COMMUNITY MARKETPLACES ===
|
|
7860
7881
|
{
|
|
@@ -8472,7 +8493,7 @@ async function installSkill(skill) {
|
|
|
8472
8493
|
}
|
|
8473
8494
|
async function showOfficialFlowMenu(totalSkills, notInstalledCount) {
|
|
8474
8495
|
console.log();
|
|
8475
|
-
console.log(` ${bold("Octocode
|
|
8496
|
+
console.log(` ${bold("🐙 Octocode Skills")}`);
|
|
8476
8497
|
console.log(` ${dim(`${totalSkills} skills available`)}`);
|
|
8477
8498
|
console.log();
|
|
8478
8499
|
const choices = [];
|
|
@@ -8634,69 +8655,17 @@ async function runMarketplaceFlow() {
|
|
|
8634
8655
|
}
|
|
8635
8656
|
}
|
|
8636
8657
|
}
|
|
8637
|
-
async function
|
|
8638
|
-
const source = SKILLS_MARKETPLACES.find((s) => s.id === "octocode-
|
|
8639
|
-
if (!source) {
|
|
8640
|
-
return {
|
|
8641
|
-
installed: 0,
|
|
8642
|
-
alreadyInstalled: 0,
|
|
8643
|
-
failed: 0,
|
|
8644
|
-
allInstalled: false
|
|
8645
|
-
};
|
|
8646
|
-
}
|
|
8647
|
-
let skills;
|
|
8648
|
-
try {
|
|
8649
|
-
skills = await fetchMarketplaceSkills(source);
|
|
8650
|
-
} catch {
|
|
8651
|
-
return {
|
|
8652
|
-
installed: 0,
|
|
8653
|
-
alreadyInstalled: 0,
|
|
8654
|
-
failed: 0,
|
|
8655
|
-
allInstalled: false
|
|
8656
|
-
};
|
|
8657
|
-
}
|
|
8658
|
-
if (skills.length === 0) {
|
|
8659
|
-
return { installed: 0, alreadyInstalled: 0, failed: 0, allInstalled: true };
|
|
8660
|
-
}
|
|
8661
|
-
const destDir = getSkillsDestDir();
|
|
8662
|
-
const skillsToInstall = skills.filter((skill) => !isSkillInstalled(skill.name));
|
|
8663
|
-
const alreadyInstalled = skills.length - skillsToInstall.length;
|
|
8664
|
-
if (skillsToInstall.length === 0) {
|
|
8665
|
-
return {
|
|
8666
|
-
installed: 0,
|
|
8667
|
-
alreadyInstalled,
|
|
8668
|
-
failed: 0,
|
|
8669
|
-
allInstalled: true
|
|
8670
|
-
};
|
|
8671
|
-
}
|
|
8672
|
-
let installed = 0;
|
|
8673
|
-
let failed = 0;
|
|
8674
|
-
for (const skill of skillsToInstall) {
|
|
8675
|
-
const result = await installMarketplaceSkill(skill, destDir);
|
|
8676
|
-
if (result.success) {
|
|
8677
|
-
installed++;
|
|
8678
|
-
} else {
|
|
8679
|
-
failed++;
|
|
8680
|
-
}
|
|
8681
|
-
}
|
|
8682
|
-
return {
|
|
8683
|
-
installed,
|
|
8684
|
-
alreadyInstalled,
|
|
8685
|
-
failed,
|
|
8686
|
-
allInstalled: failed === 0
|
|
8687
|
-
};
|
|
8688
|
-
}
|
|
8689
|
-
async function runOctocodeOfficialFlow() {
|
|
8690
|
-
const source = SKILLS_MARKETPLACES.find((s) => s.id === "octocode-official");
|
|
8658
|
+
async function runOctocodeSkillsFlow() {
|
|
8659
|
+
const source = SKILLS_MARKETPLACES.find((s) => s.id === "octocode-skills");
|
|
8691
8660
|
if (!source) {
|
|
8692
8661
|
console.log();
|
|
8693
|
-
console.log(` ${c("red", "✗")} Octocode
|
|
8662
|
+
console.log(` ${c("red", "✗")} Octocode Skills source not found`);
|
|
8694
8663
|
console.log();
|
|
8695
8664
|
await pressEnterToContinue$2();
|
|
8696
8665
|
return;
|
|
8697
8666
|
}
|
|
8698
8667
|
console.log();
|
|
8699
|
-
const spinner = new Spinner(`Loading
|
|
8668
|
+
const spinner = new Spinner(`Loading Octocode Skills...`).start();
|
|
8700
8669
|
let skills;
|
|
8701
8670
|
try {
|
|
8702
8671
|
skills = await fetchMarketplaceSkills(source);
|
|
@@ -8721,8 +8690,8 @@ async function runOctocodeOfficialFlow() {
|
|
|
8721
8690
|
const notInstalledCount = skills.filter(
|
|
8722
8691
|
(s) => !isSkillInstalled(s.name)
|
|
8723
8692
|
).length;
|
|
8724
|
-
let
|
|
8725
|
-
while (
|
|
8693
|
+
let inFlow = true;
|
|
8694
|
+
while (inFlow) {
|
|
8726
8695
|
const menuChoice = await showOfficialFlowMenu(
|
|
8727
8696
|
skills.length,
|
|
8728
8697
|
notInstalledCount
|
|
@@ -8730,7 +8699,7 @@ async function runOctocodeOfficialFlow() {
|
|
|
8730
8699
|
switch (menuChoice) {
|
|
8731
8700
|
case "install-all":
|
|
8732
8701
|
await installAllSkills(skills);
|
|
8733
|
-
|
|
8702
|
+
inFlow = false;
|
|
8734
8703
|
break;
|
|
8735
8704
|
case "browse": {
|
|
8736
8705
|
let inSkillsBrowser = true;
|
|
@@ -8749,7 +8718,7 @@ async function runOctocodeOfficialFlow() {
|
|
|
8749
8718
|
}
|
|
8750
8719
|
case "back":
|
|
8751
8720
|
default:
|
|
8752
|
-
|
|
8721
|
+
inFlow = false;
|
|
8753
8722
|
break;
|
|
8754
8723
|
}
|
|
8755
8724
|
}
|
|
@@ -8861,11 +8830,6 @@ async function showSkillsMenu(installedCount) {
|
|
|
8861
8830
|
description: "View, remove, or inspect individual skills"
|
|
8862
8831
|
});
|
|
8863
8832
|
}
|
|
8864
|
-
choices.push({
|
|
8865
|
-
name: "🐙 Octocode Official 📦",
|
|
8866
|
-
value: "octocode-official",
|
|
8867
|
-
description: "Research, PR review, local search & more"
|
|
8868
|
-
});
|
|
8869
8833
|
choices.push({
|
|
8870
8834
|
name: "🌐 Browse Marketplace",
|
|
8871
8835
|
value: "marketplace",
|
|
@@ -9145,9 +9109,6 @@ async function runSkillsMenu() {
|
|
|
9145
9109
|
case "manage":
|
|
9146
9110
|
await manageInstalledSkills();
|
|
9147
9111
|
break;
|
|
9148
|
-
case "octocode-official":
|
|
9149
|
-
await runOctocodeOfficialFlow();
|
|
9150
|
-
break;
|
|
9151
9112
|
case "marketplace":
|
|
9152
9113
|
await runMarketplaceFlow();
|
|
9153
9114
|
break;
|
|
@@ -9802,6 +9763,23 @@ function buildSkillsMenuItem(skills) {
|
|
|
9802
9763
|
description: `${c("cyan", "→")} Install skills for AI-powered coding workflows`
|
|
9803
9764
|
};
|
|
9804
9765
|
}
|
|
9766
|
+
function buildOctocodeSkillsMenuItem(skills) {
|
|
9767
|
+
const octocodeSkillsInstalled = skills.skills.filter(
|
|
9768
|
+
(s) => s.name.startsWith("octocode-") && s.installed
|
|
9769
|
+
).length;
|
|
9770
|
+
if (octocodeSkillsInstalled > 0) {
|
|
9771
|
+
return {
|
|
9772
|
+
name: `🐙 Octocode Skills ${c("green", "✓")}`,
|
|
9773
|
+
value: "octocode-skills",
|
|
9774
|
+
description: `${octocodeSkillsInstalled} installed • Research, planning & review`
|
|
9775
|
+
};
|
|
9776
|
+
}
|
|
9777
|
+
return {
|
|
9778
|
+
name: "🐙 Octocode Skills",
|
|
9779
|
+
value: "octocode-skills",
|
|
9780
|
+
description: "Install AI-powered research, planning & review skills"
|
|
9781
|
+
};
|
|
9782
|
+
}
|
|
9805
9783
|
function getAuthSourceDisplay(auth2) {
|
|
9806
9784
|
switch (auth2.tokenSource) {
|
|
9807
9785
|
case "gh-cli":
|
|
@@ -9893,10 +9871,7 @@ function printContextualHints(state) {
|
|
|
9893
9871
|
c("yellow", ` ▸ Prompts: Use /research, /plan, /implement in chat`)
|
|
9894
9872
|
);
|
|
9895
9873
|
console.log(
|
|
9896
|
-
c(
|
|
9897
|
-
"yellow",
|
|
9898
|
-
` ▸ Skills: Add all via Manage System Skills → Octocode Official`
|
|
9899
|
-
)
|
|
9874
|
+
c("yellow", ` ▸ Skills: Add via 🐙 Octocode Skills in main menu`)
|
|
9900
9875
|
);
|
|
9901
9876
|
console.log(
|
|
9902
9877
|
c(
|
|
@@ -9923,6 +9898,7 @@ async function showMainMenu(state) {
|
|
|
9923
9898
|
printContextualHints(state);
|
|
9924
9899
|
const choices = [];
|
|
9925
9900
|
choices.push(buildOctocodeMenuItem(state));
|
|
9901
|
+
choices.push(buildOctocodeSkillsMenuItem(state.skills));
|
|
9926
9902
|
choices.push(buildSkillsMenuItem(state.skills));
|
|
9927
9903
|
choices.push(buildAuthMenuItem(state.githubAuth));
|
|
9928
9904
|
choices.push({
|
|
@@ -9978,14 +9954,6 @@ async function showOctocodeMenu(state) {
|
|
|
9978
9954
|
description: "Server options & preferences"
|
|
9979
9955
|
});
|
|
9980
9956
|
}
|
|
9981
|
-
if (!state.skills.allInstalled && state.skills.hasSkills) {
|
|
9982
|
-
const notInstalled = state.skills.skills.filter((s) => !s.installed).length;
|
|
9983
|
-
choices.push({
|
|
9984
|
-
name: `🧠 Install All Skills ${c("cyan", `(${notInstalled} available)`)}`,
|
|
9985
|
-
value: "install-skills",
|
|
9986
|
-
description: "One-click install of all Octocode skills"
|
|
9987
|
-
});
|
|
9988
|
-
}
|
|
9989
9957
|
choices.push(
|
|
9990
9958
|
new Separator()
|
|
9991
9959
|
);
|
|
@@ -10032,45 +10000,6 @@ async function runOctocodeFlow() {
|
|
|
10032
10000
|
await runConfigOptionsFlow();
|
|
10033
10001
|
console.log();
|
|
10034
10002
|
break;
|
|
10035
|
-
case "install-skills": {
|
|
10036
|
-
console.log();
|
|
10037
|
-
const skillsSpinner = new Spinner(
|
|
10038
|
-
"Installing all Octocode skills..."
|
|
10039
|
-
).start();
|
|
10040
|
-
const result = await installAllOctocodeSkills();
|
|
10041
|
-
if (result.installed > 0) {
|
|
10042
|
-
skillsSpinner.succeed(
|
|
10043
|
-
`Installed ${result.installed} skill${result.installed !== 1 ? "s" : ""}!`
|
|
10044
|
-
);
|
|
10045
|
-
console.log();
|
|
10046
|
-
console.log(
|
|
10047
|
-
` ${c("green", "✓")} ${result.installed} skill${result.installed !== 1 ? "s" : ""} installed successfully`
|
|
10048
|
-
);
|
|
10049
|
-
if (result.alreadyInstalled > 0) {
|
|
10050
|
-
console.log(
|
|
10051
|
-
` ${dim(`(${result.alreadyInstalled} already installed)`)}`
|
|
10052
|
-
);
|
|
10053
|
-
}
|
|
10054
|
-
if (result.failed > 0) {
|
|
10055
|
-
console.log(
|
|
10056
|
-
` ${c("yellow", "⚠")} ${result.failed} skill${result.failed !== 1 ? "s" : ""} failed to install`
|
|
10057
|
-
);
|
|
10058
|
-
}
|
|
10059
|
-
console.log();
|
|
10060
|
-
console.log(` ${bold("Skills are now available in Claude Code!")}`);
|
|
10061
|
-
} else if (result.allInstalled) {
|
|
10062
|
-
skillsSpinner.succeed("All skills already installed!");
|
|
10063
|
-
console.log();
|
|
10064
|
-
console.log(` ${c("green", "✓")} All Octocode skills are installed`);
|
|
10065
|
-
} else {
|
|
10066
|
-
skillsSpinner.fail("Failed to install skills");
|
|
10067
|
-
console.log();
|
|
10068
|
-
console.log(` ${c("red", "✗")} Could not install skills`);
|
|
10069
|
-
}
|
|
10070
|
-
console.log();
|
|
10071
|
-
await pressEnterToContinue();
|
|
10072
|
-
break;
|
|
10073
|
-
}
|
|
10074
10003
|
case "back":
|
|
10075
10004
|
default:
|
|
10076
10005
|
inMenu = false;
|
|
@@ -10505,6 +10434,9 @@ async function handleMenuChoice(choice) {
|
|
|
10505
10434
|
case "octocode":
|
|
10506
10435
|
await runOctocodeFlow();
|
|
10507
10436
|
return true;
|
|
10437
|
+
case "octocode-skills":
|
|
10438
|
+
await runOctocodeSkillsFlow();
|
|
10439
|
+
return true;
|
|
10508
10440
|
case "skills":
|
|
10509
10441
|
await runSkillsMenu();
|
|
10510
10442
|
return true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "octocode-cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.6",
|
|
4
4
|
"description": "Interactive CLI installer for octocode-mcp - Configure MCP servers for Cursor, Claude Desktop, and more",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"octocode",
|
|
@@ -33,13 +33,13 @@
|
|
|
33
33
|
"@octokit/auth-oauth-device": "^8.0.3",
|
|
34
34
|
"@octokit/oauth-methods": "^6.0.2",
|
|
35
35
|
"@octokit/request": "^10.0.7",
|
|
36
|
+
"octocode-shared": "1.0.0",
|
|
36
37
|
"open": "^11.0.0"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
40
|
"@types/node": "^22.15.29",
|
|
40
41
|
"@vitest/coverage-v8": "^4.0.16",
|
|
41
42
|
"eslint": "^9.18.0",
|
|
42
|
-
"octocode-shared": "workspace:^",
|
|
43
43
|
"tsx": "^4.21.0",
|
|
44
44
|
"typescript": "^5.9.3",
|
|
45
45
|
"vite": "^7.3.0",
|