starling-ai 0.0.1 → 0.0.3
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/LICENSE +21 -0
- package/README.md +297 -0
- package/dist/index.js +48 -9
- package/package.json +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shuang Huang
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# Starling
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="vscode-extension/icons/starling.png" alt="Starling logo" width="160">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
Agent session manager for Claude Code and OpenAI Codex. Starling discovers local agent sessions, groups them by project, organizes them into hierarchical catalogs, and provides a VS Code sidebar for browsing, resuming, and managing sessions.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- Discover Claude Code and Codex sessions from local session files.
|
|
12
|
+
- Browse sessions by catalog, project, or recent activity.
|
|
13
|
+
- Create hierarchical catalogs such as `work/research/paper`.
|
|
14
|
+
- Add session metadata, titles, tags, notes, and catalog assignments.
|
|
15
|
+
- Resume Claude Code and Codex sessions from one command.
|
|
16
|
+
- Track token usage when it is available in the session file.
|
|
17
|
+
- Maintain a local session index at `~/.starling/session-index.json` for faster project and catalog views.
|
|
18
|
+
- Launch Claude Code or Codex through `starling run` and automatically assign the created session to a catalog.
|
|
19
|
+
- Manage Claude and Codex model profiles under `~/.starling/settings`.
|
|
20
|
+
- Use the included VS Code extension sidebar for Catalog, Projects, and Sessions.
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install -g starling-ai
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The npm package is named `starling-ai`, but the installed command is:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
starling --help
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Starling requires Node.js 20 or newer.
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
List recent sessions:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
starling session ls
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Show session details, including catalog metadata and token usage:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
starling session show <session-id>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Resume a session:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
starling resume <session-id>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Create a catalog and add a session:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
starling catalog create research/paper
|
|
60
|
+
starling catalog add research/paper <session-id> --title "Figure review"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Launch Codex and assign the new session to a catalog:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
starling run --catalog research/paper codex
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Launch Claude Code with a Starling config profile:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
starling run --config ds --catalog research/paper claude
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Starling options must be placed before the agent name. Everything after `claude` or `codex` is passed directly to that agent:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
starling run --catalog research/paper codex exec "summarize this repo"
|
|
79
|
+
starling run --catalog research/paper claude --dangerously-skip-permissions
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Commands
|
|
83
|
+
|
|
84
|
+
### Sessions
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
starling session ls
|
|
88
|
+
starling session ls --all
|
|
89
|
+
starling session ls --agent claude
|
|
90
|
+
starling session ls --cataloged
|
|
91
|
+
starling session ls --catalog research/paper
|
|
92
|
+
starling session show <session-id>
|
|
93
|
+
starling session resume <session-id>
|
|
94
|
+
starling session meta <session-id> --title "New title" --tags review,important
|
|
95
|
+
starling session note <session-id> "Follow up on benchmark results"
|
|
96
|
+
starling session unpin <session-id>
|
|
97
|
+
starling session delete <session-id> --yes
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Catalog assignment can also be managed from the session namespace:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
starling session catalog add <session-id> research/paper --title "Important run"
|
|
104
|
+
starling session catalog remove <session-id> research/paper
|
|
105
|
+
starling session catalog clear <session-id>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Catalogs
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
starling catalog create <name>
|
|
112
|
+
starling catalog create parent/child/grandchild
|
|
113
|
+
starling catalog create child --parent parent
|
|
114
|
+
starling catalog ls
|
|
115
|
+
starling catalog tree
|
|
116
|
+
starling catalog show <catalog>
|
|
117
|
+
starling catalog add <catalog> <session-id>
|
|
118
|
+
starling catalog detach <catalog> <session-id>
|
|
119
|
+
starling catalog clear <catalog>
|
|
120
|
+
starling catalog delete <catalog>
|
|
121
|
+
starling catalog del <catalog>
|
|
122
|
+
starling catalog rename <catalog> <new-name>
|
|
123
|
+
starling catalog edit <catalog> --rename <new-name>
|
|
124
|
+
starling catalog tag <catalog> tag1 tag2
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`starling cat` is an alias for `starling catalog`.
|
|
128
|
+
|
|
129
|
+
Catalog names may repeat when they live under different parents. Use a path such as `parent/child` or a catalog ID when a name is ambiguous.
|
|
130
|
+
|
|
131
|
+
### Projects
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
starling project ls
|
|
135
|
+
starling project ls --all
|
|
136
|
+
starling project ls --agent codex
|
|
137
|
+
starling project show /path/to/project
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
`starling prj` is an alias for `starling project`.
|
|
141
|
+
|
|
142
|
+
Project commands use the local session index by default. Rebuild or bypass it when needed:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
starling session index status
|
|
146
|
+
starling session index rebuild
|
|
147
|
+
starling session index clear
|
|
148
|
+
starling project ls --refresh-index
|
|
149
|
+
starling project ls --no-index
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Model Profiles
|
|
153
|
+
|
|
154
|
+
Model profiles are stored under:
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
~/.starling/settings/claude
|
|
158
|
+
~/.starling/settings/codex
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
List current and Starling-managed profiles:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
starling model ls
|
|
165
|
+
starling model ls --agent claude
|
|
166
|
+
starling model ls --agent codex
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Create a Claude profile:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
starling model add ds --agent claude \
|
|
173
|
+
--model deepseek-v4-pro \
|
|
174
|
+
--base-url https://api.example.com \
|
|
175
|
+
--api-key "$API_KEY"
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Create a Codex profile:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
starling model add demo --agent codex \
|
|
182
|
+
--model gpt-5.2 \
|
|
183
|
+
--base-url https://api.example.com/v1 \
|
|
184
|
+
--api-key "$OPENAI_API_KEY" \
|
|
185
|
+
--reasoning high \
|
|
186
|
+
--wire-api responses
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Use a profile when launching an agent:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
starling run --config demo --catalog research/paper codex
|
|
193
|
+
starling run --config ds --catalog research/paper claude
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
If `--config` is not provided, Starling uses the agent's normal default configuration.
|
|
197
|
+
|
|
198
|
+
## Configuration Files
|
|
199
|
+
|
|
200
|
+
Starling stores its own data in `~/.starling`:
|
|
201
|
+
|
|
202
|
+
```text
|
|
203
|
+
~/.starling/
|
|
204
|
+
session-index.json
|
|
205
|
+
settings/
|
|
206
|
+
claude/
|
|
207
|
+
<profile>.json
|
|
208
|
+
codex/
|
|
209
|
+
<profile>.json
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Claude profiles are JSON files that Starling passes to Claude Code as settings.
|
|
213
|
+
|
|
214
|
+
Codex profiles are JSON files with `auth` and `config` sections. Starling converts them into a temporary Codex config for the run, so `starling run --config <name> codex` does not overwrite the user's default `~/.codex/config.toml`.
|
|
215
|
+
|
|
216
|
+
Example Codex profile:
|
|
217
|
+
|
|
218
|
+
```json
|
|
219
|
+
{
|
|
220
|
+
"auth": {
|
|
221
|
+
"OPENAI_API_KEY": "sk-..."
|
|
222
|
+
},
|
|
223
|
+
"config": {
|
|
224
|
+
"model_provider": "custom",
|
|
225
|
+
"model": "gpt-5.2",
|
|
226
|
+
"model_reasoning_effort": "high",
|
|
227
|
+
"disable_response_storage": true,
|
|
228
|
+
"model_providers": {
|
|
229
|
+
"custom": {
|
|
230
|
+
"name": "custom",
|
|
231
|
+
"base_url": "https://api.example.com/v1",
|
|
232
|
+
"wire_api": "responses",
|
|
233
|
+
"requires_openai_auth": true
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## VS Code Extension
|
|
241
|
+
|
|
242
|
+
The repository includes a VS Code extension in `vscode-extension/`.
|
|
243
|
+
|
|
244
|
+
The Starling sidebar contains three views:
|
|
245
|
+
|
|
246
|
+
- Catalog: hierarchical catalog tree with sessions.
|
|
247
|
+
- Projects: project directory tree with session counts.
|
|
248
|
+
- Sessions: recent sessions with incremental loading.
|
|
249
|
+
|
|
250
|
+
The extension supports common right-click actions:
|
|
251
|
+
|
|
252
|
+
- Resume session.
|
|
253
|
+
- Show session details.
|
|
254
|
+
- Pin to catalog.
|
|
255
|
+
- Remove pin metadata.
|
|
256
|
+
- Delete session.
|
|
257
|
+
- Open project in a new VS Code window.
|
|
258
|
+
- Copy project path.
|
|
259
|
+
- Copy session ID.
|
|
260
|
+
|
|
261
|
+
The extension calls the `starling` CLI. If VS Code cannot find it on `PATH`, set `starling.cliPath` to an absolute path in VS Code settings.
|
|
262
|
+
|
|
263
|
+
Useful extension settings:
|
|
264
|
+
|
|
265
|
+
```json
|
|
266
|
+
{
|
|
267
|
+
"starling.cliPath": "starling",
|
|
268
|
+
"starling.cacheTtlSeconds": 30,
|
|
269
|
+
"starling.projectSessionLimit": 30,
|
|
270
|
+
"starling.sessionTreeLimit": 50
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Development
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
npm install
|
|
278
|
+
npm run build
|
|
279
|
+
npm run lint
|
|
280
|
+
npm test
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Build the CLI into `dist/index.js`:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
npm run build
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Run locally from the repository:
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
node dist/index.js --help
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## License
|
|
296
|
+
|
|
297
|
+
MIT
|
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
|
}
|
|
@@ -1637,11 +1643,18 @@ ${chalk4.yellow(`Pins in ${row.name} (${row.id})`)}`);
|
|
|
1637
1643
|
updateSpace(s.id, { tags: merged });
|
|
1638
1644
|
console.log(chalk4.green(`Tagged "${s.name}": ${merged.join(", ")}`));
|
|
1639
1645
|
});
|
|
1646
|
+
space.command("rename <catalog> <new-name>").description("Rename a catalog").action((catalog, newName) => {
|
|
1647
|
+
const updated = renameCatalog(catalog, newName);
|
|
1648
|
+
console.log(chalk4.green(`Renamed catalog: "${updated.name}" (${updated.id})`));
|
|
1649
|
+
});
|
|
1640
1650
|
space.command("edit <name>").description("Edit catalog metadata").option("-d, --description <desc>", "new description").option("--rename <new-name>", "rename the catalog").option("--parent <parent>", "set parent catalog").action((name, opts) => {
|
|
1641
1651
|
const s = resolveCatalogRef2(name);
|
|
1642
1652
|
const patch = {};
|
|
1643
1653
|
if (opts.description) patch.description = opts.description;
|
|
1644
|
-
if (opts.rename)
|
|
1654
|
+
if (opts.rename) {
|
|
1655
|
+
const nextName2 = validateCatalogName(opts.rename);
|
|
1656
|
+
patch.name = nextName2;
|
|
1657
|
+
}
|
|
1645
1658
|
if (opts.parent) {
|
|
1646
1659
|
const parent = resolveCatalogRef2(opts.parent);
|
|
1647
1660
|
if (parent.id === s.id) {
|
|
@@ -1667,6 +1680,32 @@ ${chalk4.yellow(`Pins in ${row.name} (${row.id})`)}`);
|
|
|
1667
1680
|
});
|
|
1668
1681
|
program2.addCommand(space);
|
|
1669
1682
|
}
|
|
1683
|
+
function renameCatalog(catalog, newName) {
|
|
1684
|
+
const s = resolveCatalogRef2(catalog);
|
|
1685
|
+
const trimmedName = validateCatalogName(newName);
|
|
1686
|
+
if (hasSiblingSpaceName(trimmedName, s.parent_id, s.id)) {
|
|
1687
|
+
console.error(chalk4.red(`Catalog already exists under this parent: ${trimmedName}`));
|
|
1688
|
+
process.exit(1);
|
|
1689
|
+
}
|
|
1690
|
+
const updated = updateSpace(s.id, { name: trimmedName });
|
|
1691
|
+
if (!updated) {
|
|
1692
|
+
console.error(chalk4.red(`Catalog not found: ${catalog}`));
|
|
1693
|
+
process.exit(1);
|
|
1694
|
+
}
|
|
1695
|
+
return updated;
|
|
1696
|
+
}
|
|
1697
|
+
function validateCatalogName(newName) {
|
|
1698
|
+
const trimmedName = newName.trim();
|
|
1699
|
+
if (!trimmedName) {
|
|
1700
|
+
console.error(chalk4.red("Catalog name cannot be empty."));
|
|
1701
|
+
process.exit(1);
|
|
1702
|
+
}
|
|
1703
|
+
if (trimmedName.includes("/")) {
|
|
1704
|
+
console.error(chalk4.red("Catalog rename expects a single catalog name, not a path."));
|
|
1705
|
+
process.exit(1);
|
|
1706
|
+
}
|
|
1707
|
+
return trimmedName;
|
|
1708
|
+
}
|
|
1670
1709
|
function isDescendantCatalog(candidate, root, spaces) {
|
|
1671
1710
|
let current = candidate;
|
|
1672
1711
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -4661,7 +4700,7 @@ function escapeRegex(value) {
|
|
|
4661
4700
|
// src/index.ts
|
|
4662
4701
|
var program = new Command7();
|
|
4663
4702
|
program.enablePositionalOptions();
|
|
4664
|
-
program.name("starling").description("Agent session manager \u2014 discover, pin, and organize AI coding sessions").version("0.
|
|
4703
|
+
program.name("starling").description("Agent session manager \u2014 discover, pin, and organize AI coding sessions").version("0.0.3");
|
|
4665
4704
|
registerSessionCommand(program);
|
|
4666
4705
|
registerPinCommand(program);
|
|
4667
4706
|
registerSpaceCommand(program);
|