starling-ai 0.0.2 → 0.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 +27 -13
- package/dist/index.js +62 -13
- package/package.json +5 -1
- package/scripts/install-agent-skills.js +28 -0
- package/skills/starling/SKILL.md +200 -0
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Agent session manager for Claude Code and OpenAI Codex. Starling discovers local
|
|
|
10
10
|
|
|
11
11
|
- Discover Claude Code and Codex sessions from local session files.
|
|
12
12
|
- Browse sessions by catalog, project, or recent activity.
|
|
13
|
-
- Create
|
|
13
|
+
- Create catalogs such as `paper-review`, with optional hierarchical paths when needed.
|
|
14
14
|
- Add session metadata, titles, tags, notes, and catalog assignments.
|
|
15
15
|
- Resume Claude Code and Codex sessions from one command.
|
|
16
16
|
- Track token usage when it is available in the session file.
|
|
@@ -31,6 +31,19 @@ The npm package is named `starling-ai`, but the installed command is:
|
|
|
31
31
|
starling --help
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
The npm install step also installs the bundled Starling skill to:
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
~/.codex/skills/starling/SKILL.md
|
|
38
|
+
~/.claude/skills/starling/SKILL.md
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
If npm lifecycle scripts were disabled with `--ignore-scripts`, install the skill manually from the package directory:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm explore -g starling-ai -- npm run install:skill
|
|
45
|
+
```
|
|
46
|
+
|
|
34
47
|
Starling requires Node.js 20 or newer.
|
|
35
48
|
|
|
36
49
|
## Quick Start
|
|
@@ -56,27 +69,27 @@ starling resume <session-id>
|
|
|
56
69
|
Create a catalog and add a session:
|
|
57
70
|
|
|
58
71
|
```bash
|
|
59
|
-
starling catalog create
|
|
60
|
-
starling catalog add
|
|
72
|
+
starling catalog create paper-review
|
|
73
|
+
starling catalog add paper-review <session-id> --title "Figure review"
|
|
61
74
|
```
|
|
62
75
|
|
|
63
76
|
Launch Codex and assign the new session to a catalog:
|
|
64
77
|
|
|
65
78
|
```bash
|
|
66
|
-
starling run --catalog
|
|
79
|
+
starling run --catalog paper-review codex
|
|
67
80
|
```
|
|
68
81
|
|
|
69
82
|
Launch Claude Code with a Starling config profile:
|
|
70
83
|
|
|
71
84
|
```bash
|
|
72
|
-
starling run --config ds --catalog
|
|
85
|
+
starling run --config ds --catalog paper-review claude
|
|
73
86
|
```
|
|
74
87
|
|
|
75
88
|
Starling options must be placed before the agent name. Everything after `claude` or `codex` is passed directly to that agent:
|
|
76
89
|
|
|
77
90
|
```bash
|
|
78
|
-
starling run --catalog
|
|
79
|
-
starling run --catalog
|
|
91
|
+
starling run --catalog paper-review codex exec "summarize this repo"
|
|
92
|
+
starling run --catalog paper-review claude --dangerously-skip-permissions
|
|
80
93
|
```
|
|
81
94
|
|
|
82
95
|
## Commands
|
|
@@ -88,7 +101,7 @@ starling session ls
|
|
|
88
101
|
starling session ls --all
|
|
89
102
|
starling session ls --agent claude
|
|
90
103
|
starling session ls --cataloged
|
|
91
|
-
starling session ls --catalog
|
|
104
|
+
starling session ls --catalog paper-review
|
|
92
105
|
starling session show <session-id>
|
|
93
106
|
starling session resume <session-id>
|
|
94
107
|
starling session meta <session-id> --title "New title" --tags review,important
|
|
@@ -100,8 +113,8 @@ starling session delete <session-id> --yes
|
|
|
100
113
|
Catalog assignment can also be managed from the session namespace:
|
|
101
114
|
|
|
102
115
|
```bash
|
|
103
|
-
starling session catalog add <session-id>
|
|
104
|
-
starling session catalog remove <session-id>
|
|
116
|
+
starling session catalog add <session-id> paper-review --title "Important run"
|
|
117
|
+
starling session catalog remove <session-id> paper-review
|
|
105
118
|
starling session catalog clear <session-id>
|
|
106
119
|
```
|
|
107
120
|
|
|
@@ -113,6 +126,7 @@ starling catalog create parent/child/grandchild
|
|
|
113
126
|
starling catalog create child --parent parent
|
|
114
127
|
starling catalog ls
|
|
115
128
|
starling catalog tree
|
|
129
|
+
starling catalog tree --sessions
|
|
116
130
|
starling catalog show <catalog>
|
|
117
131
|
starling catalog add <catalog> <session-id>
|
|
118
132
|
starling catalog detach <catalog> <session-id>
|
|
@@ -189,8 +203,8 @@ starling model add demo --agent codex \
|
|
|
189
203
|
Use a profile when launching an agent:
|
|
190
204
|
|
|
191
205
|
```bash
|
|
192
|
-
starling run --config demo --catalog
|
|
193
|
-
starling run --config ds --catalog
|
|
206
|
+
starling run --config demo --catalog paper-review codex
|
|
207
|
+
starling run --config ds --catalog paper-review claude
|
|
194
208
|
```
|
|
195
209
|
|
|
196
210
|
If `--config` is not provided, Starling uses the agent's normal default configuration.
|
|
@@ -243,7 +257,7 @@ The repository includes a VS Code extension in `vscode-extension/`.
|
|
|
243
257
|
|
|
244
258
|
The Starling sidebar contains three views:
|
|
245
259
|
|
|
246
|
-
- Catalog: hierarchical catalog tree with sessions.
|
|
260
|
+
- Catalog: hierarchical catalog tree, with sessions shown on request.
|
|
247
261
|
- Projects: project directory tree with session counts.
|
|
248
262
|
- Sessions: recent sessions with incremental loading.
|
|
249
263
|
|
package/dist/index.js
CHANGED
|
@@ -683,15 +683,21 @@ function removeSpace(id) {
|
|
|
683
683
|
const idx = store.spaces.findIndex((s) => s.id === id || s.name === id);
|
|
684
684
|
if (idx === -1) return false;
|
|
685
685
|
const space = store.spaces[idx];
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
686
|
+
const idsToRemove = /* @__PURE__ */ new Set([space.id]);
|
|
687
|
+
let changed = true;
|
|
688
|
+
while (changed) {
|
|
689
|
+
changed = false;
|
|
690
|
+
for (const candidate of store.spaces) {
|
|
691
|
+
if (candidate.parent_id && idsToRemove.has(candidate.parent_id) && !idsToRemove.has(candidate.id)) {
|
|
692
|
+
idsToRemove.add(candidate.id);
|
|
693
|
+
changed = true;
|
|
694
|
+
}
|
|
692
695
|
}
|
|
693
696
|
}
|
|
694
|
-
store.
|
|
697
|
+
for (const b of store.bookmarks) {
|
|
698
|
+
b.space_ids = b.space_ids.filter((sid) => !idsToRemove.has(sid));
|
|
699
|
+
}
|
|
700
|
+
store.spaces = store.spaces.filter((s) => !idsToRemove.has(s.id));
|
|
695
701
|
saveStore(store);
|
|
696
702
|
return true;
|
|
697
703
|
}
|
|
@@ -1546,9 +1552,9 @@ ${chalk4.yellow(`Pins in ${row.name} (${row.id})`)}`);
|
|
|
1546
1552
|
}
|
|
1547
1553
|
}
|
|
1548
1554
|
});
|
|
1549
|
-
space.command("tree").description("Display catalogs as a hierarchical tree").action(() => {
|
|
1555
|
+
space.command("tree").description("Display catalogs as a hierarchical tree").option("--sessions", "show sessions assigned to each catalog").action((opts) => {
|
|
1550
1556
|
const spaces = listSpaces();
|
|
1551
|
-
const bookmarks = listBookmarks();
|
|
1557
|
+
const bookmarks = opts.sessions ? listBookmarks() : [];
|
|
1552
1558
|
console.log(formatSpaceTree(spaces, bookmarks));
|
|
1553
1559
|
});
|
|
1554
1560
|
space.command("add <catalog> <session-id>").description("Add a session to a catalog").option("-t, --title <title>", "pin title when creating a new pin").option("--tags <tags>", "comma-separated tags when creating a new pin").action(async (catalog, sessionId, opts) => {
|
|
@@ -2982,6 +2988,7 @@ function registerRunCommand(program2) {
|
|
|
2982
2988
|
const beforeRun = hookRun ? /* @__PURE__ */ new Map() : await snapshotSessions(provider);
|
|
2983
2989
|
const beforeRunProjectFiles = provider === "claude" && !hookRun ? snapshotProjectSessions(normalizedCwd) : /* @__PURE__ */ new Map();
|
|
2984
2990
|
const cleanupRunState = async () => {
|
|
2991
|
+
syncClaudeProfileSettingsFromRunSettings(resolvedConfig, hookRun?.settingsPath ?? null);
|
|
2985
2992
|
cleanupClaudeRunHookSettings(hookRun);
|
|
2986
2993
|
await cleanupCodexRunConfig(codexConfig);
|
|
2987
2994
|
restoreCodexDefaultConfig(codexDefaultSnapshot);
|
|
@@ -3207,6 +3214,38 @@ function cleanupClaudeRunHookSettings(hookRun) {
|
|
|
3207
3214
|
}
|
|
3208
3215
|
}
|
|
3209
3216
|
}
|
|
3217
|
+
var CLAUDE_SETTINGS_SYNC_KEYS = [
|
|
3218
|
+
"permissions",
|
|
3219
|
+
"projects",
|
|
3220
|
+
"trust",
|
|
3221
|
+
"trustedProjects",
|
|
3222
|
+
"enableAllProjectMcpServers",
|
|
3223
|
+
"enabledMcpjsonServers",
|
|
3224
|
+
"disabledMcpjsonServers"
|
|
3225
|
+
];
|
|
3226
|
+
function syncClaudeProfileSettingsFromRunSettings(sourceConfigPath, runSettingsPath) {
|
|
3227
|
+
if (!sourceConfigPath || !runSettingsPath || !existsSync6(runSettingsPath)) return false;
|
|
3228
|
+
const sourceExt = extname2(sourceConfigPath).toLowerCase();
|
|
3229
|
+
if (sourceExt !== ".json" && sourceExt !== ".jsonc") return false;
|
|
3230
|
+
try {
|
|
3231
|
+
const sourceSettings = readSettingsJsonObject(sourceConfigPath, sourceExt === ".jsonc");
|
|
3232
|
+
const runSettings = readSettingsJsonObject(runSettingsPath, false);
|
|
3233
|
+
if (!sourceSettings || !runSettings) return false;
|
|
3234
|
+
let changed = false;
|
|
3235
|
+
for (const key of CLAUDE_SETTINGS_SYNC_KEYS) {
|
|
3236
|
+
if (!Object.prototype.hasOwnProperty.call(runSettings, key)) continue;
|
|
3237
|
+
if (jsonStable(sourceSettings[key]) === jsonStable(runSettings[key])) continue;
|
|
3238
|
+
sourceSettings[key] = cloneJsonValue(runSettings[key]);
|
|
3239
|
+
changed = true;
|
|
3240
|
+
}
|
|
3241
|
+
if (!changed) return false;
|
|
3242
|
+
atomicWriteJSON(sourceConfigPath, sourceSettings);
|
|
3243
|
+
return true;
|
|
3244
|
+
} catch (error) {
|
|
3245
|
+
console.error(chalk6.yellow(`Could not sync Claude settings to ${sourceConfigPath}: ${String(error)}`));
|
|
3246
|
+
return false;
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3210
3249
|
async function createCodexRunConfig(configPath) {
|
|
3211
3250
|
if (!configPath) {
|
|
3212
3251
|
return null;
|
|
@@ -3658,14 +3697,24 @@ function readSessionIdFromHookEntry(value) {
|
|
|
3658
3697
|
function readClaudeSettingsObject(configPath) {
|
|
3659
3698
|
if (!configPath) return {};
|
|
3660
3699
|
try {
|
|
3661
|
-
const
|
|
3662
|
-
|
|
3663
|
-
if (isRecord4(parsed)) return parsed;
|
|
3700
|
+
const parsed = readSettingsJsonObject(configPath, extname2(configPath).toLowerCase() === ".jsonc");
|
|
3701
|
+
if (parsed) return parsed;
|
|
3664
3702
|
} catch {
|
|
3665
3703
|
console.log(chalk6.yellow("Could not add Claude SessionStart hook because settings is not parseable JSON."));
|
|
3666
3704
|
}
|
|
3667
3705
|
return null;
|
|
3668
3706
|
}
|
|
3707
|
+
function readSettingsJsonObject(filePath, allowComments) {
|
|
3708
|
+
const raw = readFileSync5(filePath, "utf-8");
|
|
3709
|
+
const parsed = JSON.parse(allowComments ? stripJsonComments(raw) : raw);
|
|
3710
|
+
return isRecord4(parsed) ? parsed : null;
|
|
3711
|
+
}
|
|
3712
|
+
function jsonStable(value) {
|
|
3713
|
+
return JSON.stringify(value);
|
|
3714
|
+
}
|
|
3715
|
+
function cloneJsonValue(value) {
|
|
3716
|
+
return value === void 0 ? void 0 : JSON.parse(JSON.stringify(value));
|
|
3717
|
+
}
|
|
3669
3718
|
function isRecord4(value) {
|
|
3670
3719
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3671
3720
|
}
|
|
@@ -4694,7 +4743,7 @@ function escapeRegex(value) {
|
|
|
4694
4743
|
// src/index.ts
|
|
4695
4744
|
var program = new Command7();
|
|
4696
4745
|
program.enablePositionalOptions();
|
|
4697
|
-
program.name("starling").description("Agent session manager \u2014 discover, pin, and organize AI coding sessions").version("0.
|
|
4746
|
+
program.name("starling").description("Agent session manager \u2014 discover, pin, and organize AI coding sessions").version("0.0.4");
|
|
4698
4747
|
registerSessionCommand(program);
|
|
4699
4748
|
registerPinCommand(program);
|
|
4700
4749
|
registerSpaceCommand(program);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "starling-ai",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Agent session manager — discover, bookmark, and organize AI coding sessions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
14
|
"dist",
|
|
15
|
+
"skills",
|
|
16
|
+
"scripts/install-agent-skills.js",
|
|
15
17
|
"package.json",
|
|
16
18
|
"README.md",
|
|
17
19
|
"LICENSE"
|
|
@@ -19,6 +21,8 @@
|
|
|
19
21
|
"scripts": {
|
|
20
22
|
"build": "tsup",
|
|
21
23
|
"dev": "tsup --watch",
|
|
24
|
+
"postinstall": "node scripts/install-agent-skills.js",
|
|
25
|
+
"install:skill": "node scripts/install-agent-skills.js",
|
|
22
26
|
"prepack": "npm run build",
|
|
23
27
|
"test": "vitest run",
|
|
24
28
|
"lint": "tsc --noEmit"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
8
|
+
const source = join(packageRoot, "skills", "starling", "SKILL.md");
|
|
9
|
+
const targets = [
|
|
10
|
+
join(homedir(), ".codex", "skills", "starling", "SKILL.md"),
|
|
11
|
+
join(homedir(), ".claude", "skills", "starling", "SKILL.md"),
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
if (!existsSync(source)) {
|
|
16
|
+
console.warn(`[starling] Codex skill not found in package: ${source}`);
|
|
17
|
+
process.exit(0);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
for (const target of targets) {
|
|
21
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
22
|
+
copyFileSync(source, target);
|
|
23
|
+
console.log(`[starling] Installed skill: ${target}`);
|
|
24
|
+
}
|
|
25
|
+
} catch (error) {
|
|
26
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
27
|
+
console.warn(`[starling] Could not install skills: ${message}`);
|
|
28
|
+
}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: starling-agent-session
|
|
3
|
+
description: Use when working with Starling, the local agent session manager for Claude Code and Codex: organizing sessions into catalogs, managing projects/session, launching agents with catalog assignment, configuring Claude/Codex profiles.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Starling
|
|
7
|
+
|
|
8
|
+
Starling is a local session manager for Claude Code and Codex. It discovers session files, groups sessions by project, organizes them into catalogs, stores metadata under `~/.starling`, and provides a VS Code sidebar.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## Catalogs
|
|
12
|
+
|
|
13
|
+
Use one plain catalog name in examples unless explaining hierarchy:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
starling catalog create paper-review
|
|
17
|
+
starling catalog add paper-review <session-id> --title "Figure review"
|
|
18
|
+
starling catalog tree
|
|
19
|
+
starling catalog show paper-review
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Hierarchy is path-based:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
starling catalog create research/paper
|
|
26
|
+
starling catalog create child --parent research
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`research/paper` means catalog `paper` under parent catalog `research`; it is not a single catalog name.
|
|
30
|
+
|
|
31
|
+
Useful catalog operations:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
starling catalog ls
|
|
35
|
+
starling catalog show <catalog>
|
|
36
|
+
starling catalog detach <catalog> <session-id>
|
|
37
|
+
starling catalog clear <catalog>
|
|
38
|
+
starling catalog rename <catalog> <new-name>
|
|
39
|
+
starling catalog delete <catalog>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Deleting a catalog recursively deletes child catalogs from Starling metadata. It does not delete real session files.
|
|
43
|
+
|
|
44
|
+
## Sessions
|
|
45
|
+
|
|
46
|
+
Common session commands:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
starling session ls
|
|
50
|
+
starling session ls --all
|
|
51
|
+
starling session ls --cataloged
|
|
52
|
+
starling session ls --catalog paper-review
|
|
53
|
+
starling session show <session-id>
|
|
54
|
+
starling resume <session-id>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Manage catalog assignment from the session namespace:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
starling session catalog add <session-id> paper-review --title "Important run"
|
|
61
|
+
starling session catalog remove <session-id> paper-review
|
|
62
|
+
starling session catalog clear <session-id>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Use 13-character session ID display when changing UI or tables, unless full IDs are required.
|
|
66
|
+
|
|
67
|
+
## Projects And Index
|
|
68
|
+
|
|
69
|
+
Project views are built from the local session index by default:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
starling project ls
|
|
73
|
+
starling project ls --all
|
|
74
|
+
starling project show /path/to/project
|
|
75
|
+
starling session index status
|
|
76
|
+
starling session index rebuild
|
|
77
|
+
starling session index clear
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
If project output is stale, rebuild the index. If performance is being investigated, compare indexed and scan modes:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
starling project ls --refresh-index
|
|
84
|
+
starling project ls --no-index
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Running Agents
|
|
88
|
+
|
|
89
|
+
Starling arguments go before the agent name. Agent arguments go after the agent name and should be passed through unchanged:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
starling run --catalog paper-review codex
|
|
93
|
+
starling run --catalog paper-review codex exec "summarize this repo"
|
|
94
|
+
starling run --config ds --catalog paper-review claude
|
|
95
|
+
starling run --catalog paper-review claude --dangerously-skip-permissions
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
If `--config` is omitted, Starling should use the agent's normal default configuration and must not overwrite default Codex or Claude config files.
|
|
99
|
+
|
|
100
|
+
## Model Profiles
|
|
101
|
+
|
|
102
|
+
Profiles live under:
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
~/.starling/settings/claude/<name>.json
|
|
106
|
+
~/.starling/settings/codex/<name>.json
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
List profiles:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
starling model ls
|
|
113
|
+
starling model ls --agent claude
|
|
114
|
+
starling model ls --agent codex
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Create profiles:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
starling model add ds --agent claude --model deepseek-v4-pro --base-url https://api.example.com --api-key "$API_KEY"
|
|
121
|
+
starling model add demo --agent codex --model gpt-5.2 --base-url https://api.example.com/v1 --api-key "$OPENAI_API_KEY" --reasoning high --wire-api responses
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Codex profiles use JSON with `auth` and `config`. Starling converts them into temporary Codex config for a run.
|
|
125
|
+
|
|
126
|
+
## VS Code Extension
|
|
127
|
+
|
|
128
|
+
Extension source is in:
|
|
129
|
+
|
|
130
|
+
```text
|
|
131
|
+
vscode-extension/
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Compile before claiming extension changes work:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
cd /data20T/dev/Starling/vscode-extension
|
|
138
|
+
npm run compile
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The sidebar has three views in this order:
|
|
142
|
+
|
|
143
|
+
```text
|
|
144
|
+
Catalog
|
|
145
|
+
Projects
|
|
146
|
+
Sessions
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
The extension calls the `starling` CLI. If VS Code cannot find it, use the install prompt or set `starling.cliPath` to an absolute path.
|
|
150
|
+
|
|
151
|
+
## Development And Release
|
|
152
|
+
|
|
153
|
+
For local development:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
cd /data20T/dev/Starling
|
|
157
|
+
npm install
|
|
158
|
+
npm run build
|
|
159
|
+
npm run lint
|
|
160
|
+
npm test
|
|
161
|
+
npm link
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
For testing the published package:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
npm uninstall -g starling-ai
|
|
168
|
+
npm install -g starling-ai
|
|
169
|
+
starling --version
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Publishing uses tags:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
git tag vX.Y.Z
|
|
176
|
+
git tag vsx-vX.Y.Z
|
|
177
|
+
git push origin vX.Y.Z vsx-vX.Y.Z
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
`vX.Y.Z` triggers npm publish. `vsx-vX.Y.Z` triggers VS Code Marketplace publish. A GitHub Release can include both assets:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
npm pack --pack-destination .
|
|
184
|
+
cd vscode-extension && npx @vscode/vsce package
|
|
185
|
+
gh release create vX.Y.Z ../starling-ai-X.Y.Z.tgz starling-ai-X.Y.Z.vsix --title "vX.Y.Z" --generate-notes
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
If `gh release create` fails with a 403 while `GITHUB_TOKEN` is set, try:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
env -u GITHUB_TOKEN gh release create ...
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Guardrails
|
|
195
|
+
|
|
196
|
+
- Do not remove or rewrite user data in `~/.starling`, `~/.claude`, or `~/.codex` unless explicitly requested.
|
|
197
|
+
- Do not let `starling run --config <name> codex` mutate the user's default `~/.codex/config.toml`.
|
|
198
|
+
- Keep examples with a single catalog name unless the task is specifically about hierarchy.
|
|
199
|
+
- When changing CLI behavior, update README, tests, and `dist/index.js`.
|
|
200
|
+
- When changing extension behavior, update `vscode-extension/package.json` contributions if needed and run `npm run compile`.
|