@invariant.guru/cli 0.5.4 → 0.5.5
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 +402 -111
- package/dist/main.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,112 +1,268 @@
|
|
|
1
1
|
# Invariant CLI
|
|
2
2
|
|
|
3
|
-
A package manager for
|
|
3
|
+
A package manager for AI coding-agent context. Install, compose, and sync reusable agents, skills, commands, rules, contexts, and instructions into `.claude/`, `.cursor/`, and other CLI target folders.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- Node.js `>= 24`
|
|
8
|
+
- `git` on `PATH` (used for GitHub package sources)
|
|
4
9
|
|
|
5
10
|
## Installation
|
|
6
11
|
|
|
7
12
|
```bash
|
|
8
|
-
|
|
13
|
+
# npm
|
|
14
|
+
npm install -g @invariant.guru/cli
|
|
15
|
+
|
|
16
|
+
# yarn
|
|
17
|
+
yarn global add @invariant.guru/cli
|
|
18
|
+
|
|
19
|
+
# pnpm
|
|
20
|
+
pnpm add -g @invariant.guru/cli
|
|
9
21
|
```
|
|
10
22
|
|
|
11
|
-
|
|
23
|
+
Verify and keep it current:
|
|
12
24
|
|
|
13
25
|
```bash
|
|
14
|
-
|
|
15
|
-
invariant
|
|
26
|
+
invariant version
|
|
27
|
+
invariant update --check
|
|
28
|
+
invariant update
|
|
29
|
+
```
|
|
16
30
|
|
|
17
|
-
|
|
18
|
-
invariant install everything-claude-code
|
|
31
|
+
## Getting Started
|
|
19
32
|
|
|
20
|
-
|
|
21
|
-
invariant add agent:everything-claude-code/planner
|
|
33
|
+
The core loop is **init → install → add → sync**, with `plan` on top when you start a task.
|
|
22
34
|
|
|
23
|
-
|
|
24
|
-
|
|
35
|
+
### 1. `invariant init` — set up the project
|
|
36
|
+
|
|
37
|
+
Run once at the repository root. Creates `invariant.json` (the manifest) and `.invariant/` (cache, contexts, instructions, sessions, codegraph).
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
invariant init # defaults to the `claude` target
|
|
41
|
+
invariant init claude cursor # multiple targets
|
|
42
|
+
invariant init --name my-project
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Supported targets: `claude`, `codex`, `cursor`, `windsurf`, `aider`, `copilot`.
|
|
46
|
+
|
|
47
|
+
### 2. `invariant install` — pull a package
|
|
48
|
+
|
|
49
|
+
Packages come from the registry or straight from GitHub. Installing caches the package **and** activates its items.
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# From GitHub (owner/repo, optional #ref)
|
|
53
|
+
invariant install github:invariant-guru/inv-nest-clean-architecture
|
|
54
|
+
|
|
55
|
+
# Pin a branch or tag
|
|
56
|
+
invariant install github:invariant-guru/inv-nest-clean-architecture#main
|
|
57
|
+
|
|
58
|
+
# From the registry (same package, published name)
|
|
59
|
+
invariant install nest-clean-architecture
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
This writes the package into `invariant.json`:
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"packages": {
|
|
67
|
+
"nest-clean-architecture": {
|
|
68
|
+
"name": "nest-clean-architecture",
|
|
69
|
+
"version": "1.0.0",
|
|
70
|
+
"source": "github",
|
|
71
|
+
"sourceUrl": "github:invariant-guru/inv-nest-clean-architecture"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 3. `invariant add` — pick what's active
|
|
78
|
+
|
|
79
|
+
`install` already activates everything. Use `add` to curate: a whole package, one item type, or a single item.
|
|
80
|
+
|
|
81
|
+
**Add the whole module** — every agent, skill, command, rule, context, and instruction the package ships:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
invariant add nest-clean-architecture
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
Adding all items from nest-clean-architecture...
|
|
89
|
+
✓ Added items from nest-clean-architecture
|
|
90
|
+
agents:
|
|
91
|
+
- clean-architect
|
|
92
|
+
skills:
|
|
93
|
+
- implement-aggregate-root
|
|
94
|
+
- implement-command
|
|
95
|
+
- implement-query
|
|
96
|
+
- ...
|
|
97
|
+
rules:
|
|
98
|
+
- aggregate-root
|
|
99
|
+
- command
|
|
100
|
+
- ...
|
|
101
|
+
instructions:
|
|
102
|
+
- nest-clean-architecture
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Add one type** — e.g. only the skills, or only the rules:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
invariant add skills:nest-clean-architecture
|
|
109
|
+
invariant add rules:nest-clean-architecture
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Add single items** — one target per item, mixed types allowed:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
invariant add agent:nest-clean-architecture/clean-architect
|
|
116
|
+
invariant add skill:nest-clean-architecture/implement-command \
|
|
117
|
+
rule:nest-clean-architecture/command
|
|
25
118
|
```
|
|
26
119
|
|
|
120
|
+
Check what landed with `invariant inspect nest-clean-architecture`, or use `invariant add-interactive` for a checkbox tree of every installed item.
|
|
121
|
+
|
|
122
|
+
### 4. `invariant sync` — write the files
|
|
123
|
+
|
|
124
|
+
`sync` renders the active set into each configured target: `CLAUDE.md`, `.claude/agents/`, `.claude/skills/<name>/SKILL.md`, `.claude/commands/`, `.claude/rules/`, and the equivalents for other targets.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
invariant sync
|
|
128
|
+
invariant sync --target claude
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`add`, `install`, and `add-interactive` all accept `-s, --sync` to do this in one shot:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
invariant install github:invariant-guru/inv-nest-clean-architecture --sync
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### 5. `invariant plan` — start a task
|
|
138
|
+
|
|
139
|
+
Composes a session file under `.invariant/sessions/` containing your prompt plus the active instructions (and optionally a context), then prints the one-liner to paste into your agent.
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
invariant plan "implement the cargo booking command"
|
|
143
|
+
invariant plan "implement the cargo booking command" --context nest-clean-architecture/dev
|
|
144
|
+
invariant plan "implement the cargo booking command" --full
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
When the session is done, stamp it:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
invariant plan:complete <session-id> --summary "Booking command + tests"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Full walkthrough
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
invariant init claude
|
|
157
|
+
invariant install github:invariant-guru/inv-nest-clean-architecture
|
|
158
|
+
invariant add nest-clean-architecture # activate the whole module
|
|
159
|
+
invariant sync
|
|
160
|
+
invariant plan "add the cargo booking command"
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
27
165
|
## Commands
|
|
28
166
|
|
|
29
|
-
### `invariant init`
|
|
167
|
+
### `invariant init [targets...]`
|
|
30
168
|
|
|
31
|
-
Initialize
|
|
169
|
+
Initialize a new invariant project with the given target CLI(s). Defaults to `claude`.
|
|
32
170
|
|
|
33
171
|
```bash
|
|
34
172
|
invariant init
|
|
173
|
+
invariant init claude cursor
|
|
35
174
|
invariant init --name my-project
|
|
175
|
+
invariant init --hybrid
|
|
36
176
|
```
|
|
37
177
|
|
|
38
|
-
|
|
178
|
+
| Option | Description |
|
|
179
|
+
|--------|-------------|
|
|
180
|
+
| `-n, --name <name>` | Project name (defaults to directory name) |
|
|
181
|
+
| `--hybrid` | Initialize as hybrid mode — project *and* package in one directory |
|
|
182
|
+
|
|
183
|
+
### `invariant install [packages...]`
|
|
39
184
|
|
|
40
|
-
Install packages from the registry
|
|
185
|
+
Install packages from the registry or GitHub and activate their items. If the package already has curated `active` entries in `invariant.json`, exactly those are restored; otherwise all items are added.
|
|
41
186
|
|
|
42
187
|
```bash
|
|
43
|
-
invariant install
|
|
188
|
+
invariant install github:invariant-guru/inv-nest-clean-architecture
|
|
189
|
+
invariant install github:invariant-guru/inv-nest-clean-architecture#v1.2.0
|
|
190
|
+
invariant install nest-clean-architecture
|
|
191
|
+
invariant install nest-clean-architecture@1.0.0
|
|
44
192
|
|
|
45
|
-
#
|
|
193
|
+
# Reinstall every package declared in invariant.json
|
|
46
194
|
invariant install
|
|
47
195
|
|
|
48
|
-
#
|
|
49
|
-
invariant install
|
|
50
|
-
|
|
51
|
-
# Run `invariant sync` automatically afterwards
|
|
52
|
-
invariant install everything-claude-code --sync
|
|
196
|
+
# Cache only, activate nothing
|
|
197
|
+
invariant install nest-clean-architecture --no-add
|
|
53
198
|
```
|
|
54
199
|
|
|
200
|
+
Source syntax:
|
|
201
|
+
|
|
202
|
+
| Form | Meaning |
|
|
203
|
+
|------|---------|
|
|
204
|
+
| `name` | Registry package, latest version |
|
|
205
|
+
| `name@version` | Registry package, pinned version |
|
|
206
|
+
| `github:owner/repo` | GitHub repo, default branch |
|
|
207
|
+
| `github:owner/repo#ref` | GitHub repo at a branch, tag, or commit |
|
|
208
|
+
|
|
55
209
|
| Option | Description |
|
|
56
210
|
|--------|-------------|
|
|
57
211
|
| `--no-add` | Only cache the package, do not activate its items |
|
|
58
212
|
| `-s, --sync` | Run `invariant sync` after installing |
|
|
59
213
|
|
|
60
|
-
### `invariant add
|
|
61
|
-
|
|
62
|
-
Activate items from installed packages. Accepts one or more targets.
|
|
214
|
+
### `invariant add [targets...]`
|
|
63
215
|
|
|
64
|
-
|
|
65
|
-
# Add all items from a package
|
|
66
|
-
invariant add everything-claude-code
|
|
216
|
+
Activate items from cached packages. Accepts one or more targets.
|
|
67
217
|
|
|
68
|
-
|
|
69
|
-
invariant add agent:everything-claude-code/planner
|
|
218
|
+
Target formats:
|
|
70
219
|
|
|
71
|
-
|
|
72
|
-
|
|
220
|
+
| Form | Meaning |
|
|
221
|
+
|------|---------|
|
|
222
|
+
| `<package>` | All items from the package |
|
|
223
|
+
| `<type>:<package>` | All items of that type |
|
|
224
|
+
| `<type>:<package>/<item>` | One specific item |
|
|
225
|
+
| `<package>/<item>` | One item, searching every type |
|
|
73
226
|
|
|
74
|
-
|
|
75
|
-
invariant add agent:pkg-a/planner skill:pkg-b/tdd
|
|
227
|
+
Types (singular or plural): `agent`, `skill`, `command`, `rule`, `context`, `instruction`.
|
|
76
228
|
|
|
77
|
-
|
|
78
|
-
invariant add
|
|
229
|
+
```bash
|
|
230
|
+
invariant add nest-clean-architecture
|
|
231
|
+
invariant add agent:nest-clean-architecture/clean-architect
|
|
232
|
+
invariant add skill:nest-clean-architecture/implement-query \
|
|
233
|
+
skill:nest-clean-architecture/implement-repository
|
|
234
|
+
invariant add rules:nest-clean-architecture # every rule
|
|
235
|
+
invariant add agent:nest-clean-architecture/clean-architect skill:skills/skill-creator --sync
|
|
79
236
|
```
|
|
80
237
|
|
|
238
|
+
Run with no arguments to print usage.
|
|
239
|
+
|
|
81
240
|
| Option | Description |
|
|
82
241
|
|--------|-------------|
|
|
83
242
|
| `-s, --sync` | Run `invariant sync` after adding |
|
|
84
243
|
|
|
85
244
|
### `invariant add-interactive`
|
|
86
245
|
|
|
87
|
-
Interactively select/unselect what's active — like `yarn upgrade-interactive`. Checked rows reflect
|
|
246
|
+
Interactively select/unselect what's active — like `yarn upgrade-interactive`. Checked rows reflect current activation state; checking adds, unchecking removes.
|
|
88
247
|
|
|
89
|
-
|
|
248
|
+
Default view is a **hierarchical tree**: package → item type → item. Toggling a package or type row **cascades** to its items. Category rows show a `selected/total` count and a tri-state glyph — `◉` all, `◐` some, `◯` none:
|
|
90
249
|
|
|
91
250
|
```
|
|
92
|
-
◐ nest-clean-architecture@1.0.0
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
251
|
+
◐ nest-clean-architecture@1.0.0 1/3
|
|
252
|
+
│
|
|
253
|
+
├─ ◯ agents 0/1
|
|
254
|
+
│ └─ ◯ clean-architect
|
|
255
|
+
│
|
|
256
|
+
└─ ◐ skills 1/2
|
|
257
|
+
├─ ◉ implement-command
|
|
258
|
+
└─ ◯ implement-query
|
|
98
259
|
```
|
|
99
260
|
|
|
100
|
-
Keys: `↑↓` move · `space` toggle (cascades on a package/type row) · `a` all · `i` invert · `enter` confirm.
|
|
261
|
+
Keys: `↑↓` move · `space` toggle (cascades on a package/type row) · `a` toggle all · `i` invert · `enter` confirm.
|
|
101
262
|
|
|
102
263
|
```bash
|
|
103
|
-
#
|
|
104
|
-
invariant add-interactive
|
|
105
|
-
|
|
106
|
-
# Coarse selection: one checkbox per whole package
|
|
107
|
-
invariant add-interactive --packages
|
|
108
|
-
|
|
109
|
-
# Apply changes and sync immediately
|
|
264
|
+
invariant add-interactive # item-level tree (default)
|
|
265
|
+
invariant add-interactive --packages # one checkbox per whole package
|
|
110
266
|
invariant add-interactive --sync
|
|
111
267
|
```
|
|
112
268
|
|
|
@@ -118,124 +274,259 @@ In `--packages` mode an already-active package left checked is untouched, so a c
|
|
|
118
274
|
| `-s, --sync` | Run `invariant sync` after applying changes |
|
|
119
275
|
| `-t, --target <target>` | With `--sync`, sync only to a specific target |
|
|
120
276
|
|
|
121
|
-
### `invariant remove
|
|
277
|
+
### `invariant remove [targets...]`
|
|
122
278
|
|
|
123
|
-
|
|
279
|
+
Deactivate items (inverse of `add`). The package stays in cache. Same target formats as `add`.
|
|
124
280
|
|
|
125
281
|
```bash
|
|
126
|
-
|
|
127
|
-
invariant remove
|
|
282
|
+
invariant remove nest-clean-architecture
|
|
283
|
+
invariant remove agent:nest-clean-architecture/clean-architect
|
|
284
|
+
invariant remove rules:nest-clean-architecture
|
|
285
|
+
invariant remove skill:nest-clean-architecture/implement-saga \
|
|
286
|
+
skill:nest-clean-architecture/implement-saga-test
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### `invariant uninstall <packages...>`
|
|
128
290
|
|
|
129
|
-
|
|
130
|
-
invariant remove agent:everything-claude-code/planner
|
|
291
|
+
Completely remove packages: deletes all added items, drops the cache, and removes them from `invariant.json`.
|
|
131
292
|
|
|
132
|
-
|
|
133
|
-
invariant
|
|
293
|
+
```bash
|
|
294
|
+
invariant uninstall nest-clean-architecture
|
|
295
|
+
invariant uninstall nest-clean-architecture skills
|
|
134
296
|
```
|
|
135
297
|
|
|
136
|
-
### `invariant
|
|
298
|
+
### `invariant sync`
|
|
137
299
|
|
|
138
|
-
|
|
300
|
+
Sync active instructions, contexts, and items to every configured CLI target (or just one).
|
|
139
301
|
|
|
140
302
|
```bash
|
|
141
|
-
invariant
|
|
303
|
+
invariant sync
|
|
304
|
+
invariant sync --target cursor
|
|
142
305
|
```
|
|
143
306
|
|
|
307
|
+
| Option | Description |
|
|
308
|
+
|--------|-------------|
|
|
309
|
+
| `-t, --target <target>` | Sync only to a specific target (`claude`, `codex`, `cursor`, `windsurf`, `aider`, `copilot`) |
|
|
310
|
+
|
|
144
311
|
### `invariant inspect [package]`
|
|
145
312
|
|
|
146
313
|
Show package contents with active items highlighted.
|
|
147
314
|
|
|
148
|
-
**Without a target** —
|
|
315
|
+
**Without a target** — only active items across all installed packages:
|
|
149
316
|
|
|
150
317
|
```bash
|
|
151
318
|
invariant inspect
|
|
152
319
|
```
|
|
153
320
|
|
|
154
321
|
```
|
|
155
|
-
|
|
322
|
+
nest-clean-architecture@1.0.0
|
|
156
323
|
────────────────────────────────────────
|
|
157
324
|
agents/
|
|
158
|
-
✓
|
|
325
|
+
✓ clean-architect
|
|
159
326
|
skills/
|
|
160
|
-
✓
|
|
327
|
+
✓ implement-command
|
|
161
328
|
```
|
|
162
329
|
|
|
163
|
-
**With `--details`** —
|
|
330
|
+
**With `--details`** — all items, active and inactive, across all packages. **With a package name** — always all items for that package.
|
|
164
331
|
|
|
165
332
|
```bash
|
|
166
333
|
invariant inspect --details
|
|
334
|
+
invariant inspect nest-clean-architecture
|
|
167
335
|
```
|
|
168
336
|
|
|
337
|
+
| Option | Description |
|
|
338
|
+
|--------|-------------|
|
|
339
|
+
| `-d, --details` | Show all items including inactive ones |
|
|
340
|
+
|
|
341
|
+
### `invariant list`
|
|
342
|
+
|
|
343
|
+
List installed or available packages.
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
invariant list # installed packages
|
|
347
|
+
invariant list --remote # available packages from the registry
|
|
348
|
+
invariant list --active # only packages with active items
|
|
169
349
|
```
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
350
|
+
|
|
351
|
+
| Option | Description |
|
|
352
|
+
|--------|-------------|
|
|
353
|
+
| `-r, --remote` | List available packages from the registry |
|
|
354
|
+
| `-a, --active` | List only active packages |
|
|
355
|
+
|
|
356
|
+
### `invariant plan <prompt>`
|
|
357
|
+
|
|
358
|
+
Generate a session file in `.invariant/sessions/` with the task instructions plus active context.
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
invariant plan "implement user authentication"
|
|
362
|
+
invariant plan "implement user authentication" --full
|
|
363
|
+
invariant plan "implement user authentication" --context nest-clean-architecture/dev
|
|
182
364
|
```
|
|
183
365
|
|
|
184
|
-
|
|
366
|
+
| Option | Description |
|
|
367
|
+
|--------|-------------|
|
|
368
|
+
| `-c, --context <context>` | Context to include (format: `package/context-name`) |
|
|
369
|
+
| `-f, --full` | Inline full content from active packages instead of referencing the context file |
|
|
370
|
+
|
|
371
|
+
### `invariant plan:complete <session>`
|
|
372
|
+
|
|
373
|
+
Stamp a completion header at the top of a finished session file.
|
|
185
374
|
|
|
186
375
|
```bash
|
|
187
|
-
invariant
|
|
376
|
+
invariant plan:complete session-uuid --summary "Auth command + e2e tests"
|
|
377
|
+
invariant plan:complete session-uuid -n "Follow-up: rate limiting" -d 2026-08-19
|
|
188
378
|
```
|
|
189
379
|
|
|
190
|
-
|
|
|
191
|
-
|
|
192
|
-
| `-
|
|
380
|
+
| Option | Description |
|
|
381
|
+
|--------|-------------|
|
|
382
|
+
| `-s, --summary <summary>` | Short resume of what the session accomplished |
|
|
383
|
+
| `-n, --note <note>` | Extra note line (repeatable) |
|
|
384
|
+
| `-d, --date <date>` | Completion date (`YYYY-MM-DD`), defaults to today |
|
|
193
385
|
|
|
194
|
-
### `invariant
|
|
386
|
+
### `invariant scan`
|
|
195
387
|
|
|
196
|
-
|
|
388
|
+
Scan the codebase with embedded tree-sitter grammars and write a CodeGraph to `.invariant/codegraph/` — a structured inventory of files, languages, and top-level symbols for LLM navigation.
|
|
197
389
|
|
|
198
390
|
```bash
|
|
199
|
-
invariant
|
|
200
|
-
invariant
|
|
201
|
-
invariant
|
|
391
|
+
invariant scan
|
|
392
|
+
invariant scan --scope apps/cli src/core/auth
|
|
393
|
+
invariant scan --include "src/**/*.ts" --exclude "**/*.spec.ts"
|
|
394
|
+
invariant scan --max-files 2000
|
|
202
395
|
```
|
|
203
396
|
|
|
204
|
-
|
|
397
|
+
| Option | Description |
|
|
398
|
+
|--------|-------------|
|
|
399
|
+
| `-i, --include <globs...>` | Include globs (default: `**/*`) |
|
|
400
|
+
| `-e, --exclude <globs...>` | Extra exclude globs (on top of sensible defaults) |
|
|
401
|
+
| `-s, --scope <scopes...>` | Scope the scan to specific paths |
|
|
402
|
+
| `--max-files <count>` | Cap total scanned files (default: 5000) |
|
|
403
|
+
| `--max-size <bytes>` | Skip files larger than this (default: 1 MB) |
|
|
404
|
+
|
|
405
|
+
Supported languages: TypeScript, JavaScript, Python, Go, Rust, JSON, Markdown, HTML, CSS.
|
|
205
406
|
|
|
206
|
-
|
|
407
|
+
### `invariant package <subcommand>`
|
|
408
|
+
|
|
409
|
+
Package authoring — for repositories that *are* an invariant package.
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
invariant package create --name my-pkg --version 1.0.0 --author "Me"
|
|
413
|
+
invariant package refresh
|
|
414
|
+
invariant package validate
|
|
415
|
+
invariant package publish
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
| Subcommand | Description |
|
|
419
|
+
|------------|-------------|
|
|
420
|
+
| `create` | Scan the current folder and add package metadata to `invariant.json` |
|
|
421
|
+
| `refresh` | Rescan items on disk and update `invariant.json` |
|
|
422
|
+
| `validate` | Validate the items declared in `invariant.json` against disk |
|
|
423
|
+
| `publish` | Validate, bundle, and publish the package to the registry |
|
|
424
|
+
|
|
425
|
+
`package create` options: `-n, --name`, `--version`, `-d, --description`, `-a, --author`, `-l, --license`, `-r, --repository`.
|
|
426
|
+
|
|
427
|
+
### `invariant proxy <subcommand>`
|
|
428
|
+
|
|
429
|
+
Shared local LLM proxy daemon. Routes a repo's agent traffic through a local proxy by writing a managed env block (`ANTHROPIC_BASE_URL`) into `.claude/settings.json`.
|
|
430
|
+
|
|
431
|
+
```bash
|
|
432
|
+
invariant proxy start
|
|
433
|
+
invariant proxy status
|
|
434
|
+
invariant proxy status --json
|
|
435
|
+
invariant proxy on # route the current repo (or `on <dir>`)
|
|
436
|
+
invariant proxy off # revert the managed env block
|
|
437
|
+
invariant proxy stop
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
| Subcommand | Description |
|
|
441
|
+
|------------|-------------|
|
|
442
|
+
| `start` | Start the shared proxy daemon |
|
|
443
|
+
| `stop` | Stop the daemon (token is preserved) |
|
|
444
|
+
| `status` | Daemon status, routes, and per-repo activations (`--json`) |
|
|
445
|
+
| `on [dir]` | Route a repo through the proxy |
|
|
446
|
+
| `off [dir]` | Revert the managed env block (daemon keeps running) |
|
|
447
|
+
|
|
448
|
+
Agents read `ANTHROPIC_BASE_URL` once at launch — restart running sessions after `proxy on`.
|
|
449
|
+
|
|
450
|
+
### `invariant claude [args...]`
|
|
451
|
+
|
|
452
|
+
Launch Claude Code through the proxy, auto-starting the daemon. All arguments pass through untouched.
|
|
207
453
|
|
|
208
454
|
```bash
|
|
209
455
|
invariant claude
|
|
456
|
+
invariant claude -- --resume
|
|
210
457
|
```
|
|
211
458
|
|
|
212
|
-
### `invariant
|
|
459
|
+
### `invariant stats [subcommand]`
|
|
213
460
|
|
|
214
|
-
|
|
461
|
+
Inspect Claude Code token usage and cost.
|
|
215
462
|
|
|
216
463
|
```bash
|
|
217
|
-
invariant
|
|
218
|
-
invariant
|
|
219
|
-
invariant
|
|
464
|
+
invariant stats
|
|
465
|
+
invariant stats --live
|
|
466
|
+
invariant stats --since 7d --format table
|
|
467
|
+
invariant stats cost
|
|
468
|
+
invariant stats models
|
|
469
|
+
invariant stats sessions
|
|
470
|
+
invariant stats projects
|
|
220
471
|
```
|
|
221
472
|
|
|
222
|
-
|
|
473
|
+
| Subcommand | Description |
|
|
474
|
+
|------------|-------------|
|
|
475
|
+
| `cost` | Cost drill-down with cache savings |
|
|
476
|
+
| `models` | Per-model token and cost aggregate |
|
|
477
|
+
| `sessions` | Per-session breakdown (sorted by cost) |
|
|
478
|
+
| `projects` | Per-project aggregate (implies `--all-projects`) |
|
|
479
|
+
|
|
480
|
+
| Option | Description |
|
|
481
|
+
|--------|-------------|
|
|
482
|
+
| `--live` | Open the interactive dashboard |
|
|
483
|
+
| `--since <duration>` | Start of window (e.g. `7d`, `24h`, `today`) |
|
|
484
|
+
| `--until <duration>` | End of window (default: now) |
|
|
485
|
+
| `--format <format>` | `markdown`, `json`, or `table` |
|
|
486
|
+
| `--project <path>` | Absolute path to scope to |
|
|
487
|
+
| `--all-projects` | Aggregate across every project |
|
|
488
|
+
| `--model <id>` | Filter by model id |
|
|
489
|
+
| `--include-turns` | (JSON only) include per-turn records |
|
|
490
|
+
| `--verbose` | Print parse warnings and diagnostics |
|
|
491
|
+
|
|
492
|
+
### `invariant version`
|
|
223
493
|
|
|
224
|
-
|
|
494
|
+
Display the CLI version.
|
|
495
|
+
|
|
496
|
+
### `invariant update`
|
|
497
|
+
|
|
498
|
+
Update the CLI to the latest version, using the package manager it was installed with.
|
|
225
499
|
|
|
226
500
|
```bash
|
|
227
|
-
invariant
|
|
228
|
-
invariant
|
|
229
|
-
invariant
|
|
501
|
+
invariant update
|
|
502
|
+
invariant update --check
|
|
503
|
+
invariant update --version 0.5.4
|
|
230
504
|
```
|
|
231
505
|
|
|
232
|
-
|
|
|
233
|
-
|
|
234
|
-
| `-
|
|
235
|
-
| `-
|
|
236
|
-
| `-l, --language <langs...>` | Restrict to specific languages |
|
|
237
|
-
| `-f, --format <format>` | `json`, `markdown`, or `both` (default: `both`) |
|
|
238
|
-
| `--max-files <n>` | Cap total scanned files (default: 5000) |
|
|
239
|
-
| `--max-size <bytes>` | Skip files larger than this (default: 1 MB) |
|
|
506
|
+
| Option | Description |
|
|
507
|
+
|--------|-------------|
|
|
508
|
+
| `-v, --version <version>` | Update to a specific version |
|
|
509
|
+
| `-c, --check` | Only check whether an update is available |
|
|
240
510
|
|
|
241
|
-
|
|
511
|
+
---
|
|
512
|
+
|
|
513
|
+
## Project layout
|
|
514
|
+
|
|
515
|
+
After `init` + `install` + `sync`:
|
|
516
|
+
|
|
517
|
+
```
|
|
518
|
+
.
|
|
519
|
+
├── invariant.json # manifest: targets, packages, active items
|
|
520
|
+
├── .invariant/
|
|
521
|
+
│ ├── cache/ # downloaded packages
|
|
522
|
+
│ ├── contexts/ # rendered contexts
|
|
523
|
+
│ ├── instructions/ # rendered instructions
|
|
524
|
+
│ ├── sessions/ # `invariant plan` output
|
|
525
|
+
│ └── codegraph/ # `invariant scan` output
|
|
526
|
+
├── CLAUDE.md # generated by `invariant sync`
|
|
527
|
+
└── .claude/
|
|
528
|
+
├── agents/<name>.md
|
|
529
|
+
├── skills/<name>/SKILL.md
|
|
530
|
+
├── commands/<name>.md
|
|
531
|
+
└── rules/<name>.md
|
|
532
|
+
```
|
package/dist/main.js
CHANGED
|
@@ -969,7 +969,7 @@ Follow Clean Architecture principles:
|
|
|
969
969
|
`}]}),F_}async fetchPackage(F_){const O_=this.packages.get(F_);if(!O_)throw new Rd.RegistryFetchError(`Package "${F_}" not found`);return md.Package.create({manifest:{name:O_.name,version:O_.version,description:O_.description,author:O_.author},items:O_.items,source:{type:"registry"}})}async fetchFromGitHub(F_,O_,I_){return md.Package.create({manifest:{name:O_,version:I_||"main",description:`Package from github:${F_}/${O_}`,author:F_,repository:`https://github.com/${F_}/${O_}`},items:[{type:"instructions",path:"instructions/readme.md",content:`# ${O_}
|
|
970
970
|
|
|
971
971
|
This is a stub package from GitHub: ${F_}/${O_}
|
|
972
|
-
`}],source:{type:"github",owner:F_,repo:O_,ref:I_}})}async getVersions(F_){const O_=this.packages.get(F_);return O_?[O_.version]:[]}async search(F_){const O_=[],I_=F_.toLowerCase();for(const M_ of this.packages.values())(M_.name.toLowerCase().includes(I_)||M_.description.toLowerCase().includes(I_))&&O_.push({name:M_.name,version:M_.version,description:M_.description,author:M_.author,source:"registry"});return O_}async getLatestVersion(F_){const O_=this.packages.get(F_);if(!O_)throw new Rd.RegistryFetchError(`Package "${F_}" not found`);return O_.version}async exists(F_){return this.packages.has(F_)}async listAll(){const F_=[];for(const O_ of this.packages.values())F_.push({name:O_.name,version:O_.version,description:O_.description,author:O_.author,source:"registry"});return F_}async publishPackage(F_,O_,I_){return this.packages.set(F_.name,{name:F_.name,version:F_.version,description:F_.description||"",author:F_.author||"",items:[]}),{name:F_.name,version:F_.version,url:`inmemory://${F_.name}`}}};return inMemoryRegistry_queryBuilder.InMemoryRegistryQueryBuilder=D_,inMemoryRegistry_queryBuilder.InMemoryRegistryQueryBuilder=D_=t([(0,fd.Injectable)(),Xf("design:paramtypes",[])],D_),inMemoryRegistry_queryBuilder}e(requireInMemoryRegistry_queryBuilder,"requireInMemoryRegistry_queryBuilder");var httpRegistry_queryBuilder={},hasRequiredHttpRegistry_queryBuilder;function requireHttpRegistry_queryBuilder(){if(hasRequiredHttpRegistry_queryBuilder)return httpRegistry_queryBuilder;hasRequiredHttpRegistry_queryBuilder=1;var t=httpRegistry_queryBuilder&&httpRegistry_queryBuilder.__decorate||function(F_,O_,I_,M_){var L_=arguments.length,U_=L_<3?O_:M_===null?M_=Object.getOwnPropertyDescriptor(O_,I_):M_,W_;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")U_=Reflect.decorate(F_,O_,I_,M_);else for(var z_=F_.length-1;z_>=0;z_--)(W_=F_[z_])&&(U_=(L_<3?W_(U_):L_>3?W_(O_,I_,U_):W_(O_,I_))||U_);return L_>3&&U_&&Object.defineProperty(O_,I_,U_),U_};Object.defineProperty(httpRegistry_queryBuilder,"__esModule",{value:!0}),httpRegistry_queryBuilder.HttpRegistryQueryBuilder=void 0;const Xf=requireCommon$1(),fd=require$$3$2,pd=requirePersistence$3(),md=requireDomain$1(),Rd=requireErrors$3(),D_="https://api.invariant.dev";let P_=class extends pd.RegistryQueryBuilder{static{e(this,"HttpRegistryQueryBuilder")}get baseUrl(){return(process.env.INVARIANT_REGISTRY_URL||D_).replace(/\/$/,"")}async fetchFromGitHub(O_,I_,M_){const L_=M_||"main",U_=`https://codeload.github.com/${O_}/${I_}/tar.gz/${L_}`,W_=await this.downloadAndExtractTarball(U_),z_=`${I_}-${L_}/`;let X_;const K_=W_.find(Z_=>Z_.path===`${z_}invariant.json`);if(K_){const Z_=JSON.parse(K_.content);X_={name:Z_.name,version:Z_.version,description:Z_.description,author:Z_.author,repository:Z_.repository}}else X_={name:I_,version:L_,description:`Package from github:${O_}/${I_}`,author:O_};const G_=[...md.PACKAGE_ITEM_TYPES],Q_=[];for(const Z_ of G_){const $0=`${z_}${Z_}/`,B0=W_.filter(G0=>G0.path.startsWith($0)&&G0.path.endsWith(".md"));for(const G0 of B0){const Z0=G0.path.slice(z_.length);Q_.push({type:Z_,path:Z0,content:G0.content})}}return md.Package.create({manifest:{name:X_.name,version:X_.version,description:X_.description,author:X_.author,license:X_.license,repository:X_.repository||`https://github.com/${O_}/${I_}`},items:Q_,source:{type:"github",owner:O_,repo:I_,ref:L_}})}async downloadAndExtractTarball(O_){const I_=await fetch(O_,{headers:{"User-Agent":"invariant-cli"}});if(!I_.ok)throw I_.status===404?new Rd.RegistryFetchError(`Repository or branch not found: ${O_}`):new Rd.RegistryFetchError(`Failed to download: ${I_.status} ${I_.statusText}`);const M_=Buffer.from(await I_.arrayBuffer()),L_=fd.gunzipSync(M_);return this.parseTar(L_)}parseTar(O_){const I_=[];let M_=0;for(;M_<O_.length;){const L_=O_.slice(M_,M_+512);if(L_.every(G_=>G_===0))break;const U_=L_.indexOf(0),W_=L_.slice(0,Math.min(U_,100)).toString("utf-8"),z_=L_.slice(124,136).toString("utf-8").trim(),X_=parseInt(z_,8)||0,K_=L_[156];if(M_+=512,(K_===48||K_===0)&&X_>0){const G_=O_.slice(M_,M_+X_).toString("utf-8");I_.push({path:W_,content:G_})}M_+=Math.ceil(X_/512)*512}return I_}async exists(O_){const I_=`${this.baseUrl}/package/${encodeURIComponent(O_)}`,M_=await fetch(I_,{headers:{"User-Agent":"invariant-cli"}});if(M_.status===404)return!1;if(!M_.ok)throw new Rd.RegistryFetchError(`Registry error: ${M_.status}`);return!0}async fetchPackage(O_,I_){const M_=I_||await this.getLatestVersion(O_),L_=`${this.baseUrl}/package/${encodeURIComponent(O_)}/${encodeURIComponent(M_)}/download`,U_=await fetch(L_,{headers:{"User-Agent":"invariant-cli"}});if(U_.status===404)throw new Rd.RegistryFetchError(`Package "${O_}@${M_}" not found`);if(!U_.ok)throw new Rd.RegistryFetchError(`Download failed: ${U_.status}`);const W_=Buffer.from(await U_.arrayBuffer()),z_=fd.gunzipSync(W_),X_=this.parseTar(z_);return this.buildPackageFromEntries(X_,O_,M_)}async getVersions(O_){return(await this.getPackageDetails(O_)).versions.map(M_=>M_.version)}async getLatestVersion(O_){const I_=await this.getPackageDetails(O_);if(I_.versions.length===0)throw new Rd.RegistryFetchError(`Package "${O_}" has no versions`);return I_.versions[0].version}async search(O_){const I_=new URLSearchParams({q:O_,take:"100"}),M_=`${this.baseUrl}/package/search?${I_}`,L_=await fetch(M_,{headers:{"User-Agent":"invariant-cli"}});if(!L_.ok)throw new Rd.RegistryFetchError(`Search failed: ${L_.status}`);const U_=await L_.json();return this.mapSearchResults(U_)}async listAll(){const O_=`${this.baseUrl}/package/search?take=1000`,I_=await fetch(O_,{headers:{"User-Agent":"invariant-cli"}});if(!I_.ok)throw new Rd.RegistryFetchError(`List failed: ${I_.status}`);const M_=await I_.json();return this.mapSearchResults(M_)}async publishPackage(O_,I_,M_){const L_=`${this.baseUrl}/package/publish`,U_=new FormData;U_.append("name",O_.name),U_.append("version",O_.version),U_.append("description",O_.description||""),U_.append("author",O_.author||""),U_.append("readmeContent","");const W_=new Blob([new Uint8Array(I_)],{type:"application/gzip"});U_.append("tarball",W_,`${O_.name}-${O_.version}.tgz`);const z_=await fetch(L_,{method:"POST",headers:{"User-Agent":"invariant-cli",Authorization:`Bearer ${M_}`},body:U_});if(!z_.ok){const X_=await z_.text();throw new Rd.RegistryFetchError(`Publish failed: ${z_.status} ${X_}`)}return{name:O_.name,version:O_.version,url:`${this.baseUrl}/package/${O_.name}`}}async getPackageDetails(O_){const I_=`${this.baseUrl}/package/${encodeURIComponent(O_)}`,M_=await fetch(I_,{headers:{"User-Agent":"invariant-cli"}});if(M_.status===404)throw new Rd.RegistryFetchError(`Package "${O_}" not found`);if(!M_.ok)throw new Rd.RegistryFetchError(`Registry error: ${M_.status}`);return M_.json()}mapSearchResults(O_){return O_.items.map(I_=>({name:I_.name,version:I_.latestVersion,description:I_.description,author:I_.author,source:"registry"}))}buildPackageFromEntries(O_,I_,M_){let L_={name:I_,version:M_};const U_=O_.find(X_=>X_.path==="invariant.json"||X_.path.endsWith("/invariant.json"));if(U_){const X_=JSON.parse(U_.content);L_={name:X_.name||I_,version:X_.version||M_,description:X_.description,author:X_.author,license:X_.license,repository:X_.repository}}const W_=[...md.PACKAGE_ITEM_TYPES],z_=[];for(const X_ of W_)for(const K_ of O_){const G_=this.matchItemPath(K_.path,X_);G_&&K_.path.endsWith(".md")&&z_.push({type:X_,path:G_,content:K_.content})}return md.Package.create({manifest:L_,items:z_,source:{type:"registry"}})}matchItemPath(O_,I_){if(O_.startsWith(`${I_}/`))return O_;const M_=O_.indexOf(`/${I_}/`);return M_!==-1?O_.slice(M_+1):null}};return httpRegistry_queryBuilder.HttpRegistryQueryBuilder=P_,httpRegistry_queryBuilder.HttpRegistryQueryBuilder=P_=t([(0,Xf.Injectable)()],P_),httpRegistry_queryBuilder}e(requireHttpRegistry_queryBuilder,"requireHttpRegistry_queryBuilder");var hasRequiredPersistence$2;function requirePersistence$2(){return hasRequiredPersistence$2||(hasRequiredPersistence$2=1,(function(t){var Xf=persistence$2&&persistence$2.__createBinding||(Object.create?(function(pd,md,Rd,D_){D_===void 0&&(D_=Rd);var P_=Object.getOwnPropertyDescriptor(md,Rd);(!P_||("get"in P_?!md.__esModule:P_.writable||P_.configurable))&&(P_={enumerable:!0,get:e(function(){return md[Rd]},"get")}),Object.defineProperty(pd,D_,P_)}):(function(pd,md,Rd,D_){D_===void 0&&(D_=Rd),pd[D_]=md[Rd]})),fd=persistence$2&&persistence$2.__exportStar||function(pd,md){for(var Rd in pd)Rd!=="default"&&!Object.prototype.hasOwnProperty.call(md,Rd)&&Xf(md,pd,Rd)};Object.defineProperty(t,"__esModule",{value:!0}),fd(requireFileSystemStorage_repository(),t),fd(requireInMemoryRegistry_queryBuilder(),t),fd(requireHttpRegistry_queryBuilder(),t)})(persistence$2)),persistence$2}e(requirePersistence$2,"requirePersistence$2");var gateways$2={},claudeCodeCliTarget_gateway={},hasRequiredClaudeCodeCliTarget_gateway;function requireClaudeCodeCliTarget_gateway(){if(hasRequiredClaudeCodeCliTarget_gateway)return claudeCodeCliTarget_gateway;hasRequiredClaudeCodeCliTarget_gateway=1;var t=claudeCodeCliTarget_gateway&&claudeCodeCliTarget_gateway.__decorate||function(F_,O_,I_,M_){var L_=arguments.length,U_=L_<3?O_:M_===null?M_=Object.getOwnPropertyDescriptor(O_,I_):M_,W_;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")U_=Reflect.decorate(F_,O_,I_,M_);else for(var z_=F_.length-1;z_>=0;z_--)(W_=F_[z_])&&(U_=(L_<3?W_(U_):L_>3?W_(O_,I_,U_):W_(O_,I_))||U_);return L_>3&&U_&&Object.defineProperty(O_,I_,U_),U_};Object.defineProperty(claudeCodeCliTarget_gateway,"__esModule",{value:!0}),claudeCodeCliTarget_gateway.ClaudeCodeCliTargetGateway=void 0;const Xf=requireCommon$1(),fd=require$$1$5,pd=require$$2$2,md=requireGateways$3(),Rd=".claude",D_="CLAUDE.md";let P_=class extends md.CliTargetGateway{static{e(this,"ClaudeCodeCliTargetGateway")}constructor(){super(...arguments),this.config={name:"claude",displayName:"Claude Code",supportsItemTypes:!0}}async copyItem(O_,I_,M_,L_){const U_=pd.join(O_,Rd,I_);await fd.mkdir(U_,{recursive:!0});const W_=[];if(L_.length===1&&!L_[0].relativePath.includes("/")){const z_=pd.join(U_,M_+".md");await fd.writeFile(z_,L_[0].content,"utf-8"),W_.push(z_)}else{const z_=pd.join(U_,M_);for(const X_ of L_){const K_=pd.join(z_,X_.relativePath);await fd.mkdir(pd.dirname(K_),{recursive:!0}),await fd.writeFile(K_,X_.content,"utf-8"),W_.push(K_)}}return{files:W_,itemNames:[M_]}}async removeItem(O_,I_,M_){const L_=pd.join(O_,Rd,I_),U_=pd.join(L_,M_);try{if((await fd.stat(U_)).isDirectory()){await fd.rm(U_,{recursive:!0});return}}catch{}try{await fd.unlink(U_+".md")}catch{}}async generateContextFile(O_,I_){const M_=pd.join(O_,D_);return await fd.writeFile(M_,I_,"utf-8"),M_}async contextFileExists(O_){try{return await fd.access(pd.join(O_,D_)),!0}catch{return!1}}async resolveItemPath(O_,I_,M_){const L_=pd.join(O_,Rd,I_),U_=pd.join(L_,M_);try{if((await fd.stat(U_)).isDirectory())return pd.join(Rd,I_,M_)}catch{}const W_=U_+".md";try{return await fd.access(W_),pd.join(Rd,I_,M_+".md")}catch{}return null}};return claudeCodeCliTarget_gateway.ClaudeCodeCliTargetGateway=P_,claudeCodeCliTarget_gateway.ClaudeCodeCliTargetGateway=P_=t([(0,Xf.Injectable)()],P_),claudeCodeCliTarget_gateway}e(requireClaudeCodeCliTarget_gateway,"requireClaudeCodeCliTarget_gateway");var codexCliTarget_gateway={},hasRequiredCodexCliTarget_gateway;function requireCodexCliTarget_gateway(){if(hasRequiredCodexCliTarget_gateway)return codexCliTarget_gateway;hasRequiredCodexCliTarget_gateway=1;var t=codexCliTarget_gateway&&codexCliTarget_gateway.__decorate||function(P_,F_,O_,I_){var M_=arguments.length,L_=M_<3?F_:I_===null?I_=Object.getOwnPropertyDescriptor(F_,O_):I_,U_;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")L_=Reflect.decorate(P_,F_,O_,I_);else for(var W_=P_.length-1;W_>=0;W_--)(U_=P_[W_])&&(L_=(M_<3?U_(L_):M_>3?U_(F_,O_,L_):U_(F_,O_))||L_);return M_>3&&L_&&Object.defineProperty(F_,O_,L_),L_};Object.defineProperty(codexCliTarget_gateway,"__esModule",{value:!0}),codexCliTarget_gateway.CodexCliTargetGateway=void 0;const Xf=requireCommon$1(),fd=require$$1$5,pd=require$$2$2,md=requireGateways$3(),Rd="AGENTS.md";let D_=class extends md.CliTargetGateway{static{e(this,"CodexCliTargetGateway")}constructor(){super(...arguments),this.config={name:"codex",displayName:"OpenAI Codex",supportsItemTypes:!1}}async copyItem(F_,O_,I_,M_){return{files:[],itemNames:[]}}async removeItem(F_,O_,I_){}async generateContextFile(F_,O_){const I_=pd.join(F_,Rd);return await fd.writeFile(I_,O_,"utf-8"),I_}async contextFileExists(F_){try{return await fd.access(pd.join(F_,Rd)),!0}catch{return!1}}async resolveItemPath(F_,O_,I_){return null}};return codexCliTarget_gateway.CodexCliTargetGateway=D_,codexCliTarget_gateway.CodexCliTargetGateway=D_=t([(0,Xf.Injectable)()],D_),codexCliTarget_gateway}e(requireCodexCliTarget_gateway,"requireCodexCliTarget_gateway");var cursorCliTarget_gateway={},hasRequiredCursorCliTarget_gateway;function requireCursorCliTarget_gateway(){if(hasRequiredCursorCliTarget_gateway)return cursorCliTarget_gateway;hasRequiredCursorCliTarget_gateway=1;var t=cursorCliTarget_gateway&&cursorCliTarget_gateway.__decorate||function(P_,F_,O_,I_){var M_=arguments.length,L_=M_<3?F_:I_===null?I_=Object.getOwnPropertyDescriptor(F_,O_):I_,U_;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")L_=Reflect.decorate(P_,F_,O_,I_);else for(var W_=P_.length-1;W_>=0;W_--)(U_=P_[W_])&&(L_=(M_<3?U_(L_):M_>3?U_(F_,O_,L_):U_(F_,O_))||L_);return M_>3&&L_&&Object.defineProperty(F_,O_,L_),L_};Object.defineProperty(cursorCliTarget_gateway,"__esModule",{value:!0}),cursorCliTarget_gateway.CursorCliTargetGateway=void 0;const Xf=requireCommon$1(),fd=require$$1$5,pd=require$$2$2,md=requireGateways$3(),Rd=".cursor/rules";let D_=class extends md.CliTargetGateway{static{e(this,"CursorCliTargetGateway")}constructor(){super(...arguments),this.config={name:"cursor",displayName:"Cursor",supportsItemTypes:!1}}async copyItem(F_,O_,I_,M_){const L_=pd.join(F_,Rd);await fd.mkdir(L_,{recursive:!0});const U_=I_+".mdc",W_=pd.join(L_,U_),z_=this.concatenateFiles(M_),X_=this.wrapWithFrontmatter(z_,O_,I_);return await fd.writeFile(W_,X_,"utf-8"),{files:[W_],itemNames:[I_]}}async removeItem(F_,O_,I_){const M_=I_+".mdc";try{await fd.unlink(pd.join(F_,Rd,M_))}catch{}}async generateContextFile(F_,O_){const I_=pd.join(F_,Rd);await fd.mkdir(I_,{recursive:!0});const M_=pd.join(I_,"invariant-context.mdc"),L_=this.wrapWithFrontmatter(O_,"context","Invariant project context");return await fd.writeFile(M_,L_,"utf-8"),M_}async contextFileExists(F_){try{return await fd.access(pd.join(F_,Rd,"invariant-context.mdc")),!0}catch{return!1}}async resolveItemPath(F_,O_,I_){const M_=pd.join(F_,Rd,I_+".mdc");try{return await fd.access(M_),pd.join(Rd,I_+".mdc")}catch{return null}}concatenateFiles(F_){return F_.length===1?F_[0].content:F_.map(O_=>O_.content).join(`
|
|
972
|
+
`}],source:{type:"github",owner:F_,repo:O_,ref:I_}})}async getVersions(F_){const O_=this.packages.get(F_);return O_?[O_.version]:[]}async search(F_){const O_=[],I_=F_.toLowerCase();for(const M_ of this.packages.values())(M_.name.toLowerCase().includes(I_)||M_.description.toLowerCase().includes(I_))&&O_.push({name:M_.name,version:M_.version,description:M_.description,author:M_.author,source:"registry"});return O_}async getLatestVersion(F_){const O_=this.packages.get(F_);if(!O_)throw new Rd.RegistryFetchError(`Package "${F_}" not found`);return O_.version}async exists(F_){return this.packages.has(F_)}async listAll(){const F_=[];for(const O_ of this.packages.values())F_.push({name:O_.name,version:O_.version,description:O_.description,author:O_.author,source:"registry"});return F_}async publishPackage(F_,O_,I_){return this.packages.set(F_.name,{name:F_.name,version:F_.version,description:F_.description||"",author:F_.author||"",items:[]}),{name:F_.name,version:F_.version,url:`inmemory://${F_.name}`}}};return inMemoryRegistry_queryBuilder.InMemoryRegistryQueryBuilder=D_,inMemoryRegistry_queryBuilder.InMemoryRegistryQueryBuilder=D_=t([(0,fd.Injectable)(),Xf("design:paramtypes",[])],D_),inMemoryRegistry_queryBuilder}e(requireInMemoryRegistry_queryBuilder,"requireInMemoryRegistry_queryBuilder");var httpRegistry_queryBuilder={},hasRequiredHttpRegistry_queryBuilder;function requireHttpRegistry_queryBuilder(){if(hasRequiredHttpRegistry_queryBuilder)return httpRegistry_queryBuilder;hasRequiredHttpRegistry_queryBuilder=1;var t=httpRegistry_queryBuilder&&httpRegistry_queryBuilder.__decorate||function(F_,O_,I_,M_){var L_=arguments.length,U_=L_<3?O_:M_===null?M_=Object.getOwnPropertyDescriptor(O_,I_):M_,W_;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")U_=Reflect.decorate(F_,O_,I_,M_);else for(var z_=F_.length-1;z_>=0;z_--)(W_=F_[z_])&&(U_=(L_<3?W_(U_):L_>3?W_(O_,I_,U_):W_(O_,I_))||U_);return L_>3&&U_&&Object.defineProperty(O_,I_,U_),U_};Object.defineProperty(httpRegistry_queryBuilder,"__esModule",{value:!0}),httpRegistry_queryBuilder.HttpRegistryQueryBuilder=void 0;const Xf=requireCommon$1(),fd=require$$3$2,pd=requirePersistence$3(),md=requireDomain$1(),Rd=requireErrors$3(),D_="https://api.invariant.dev";let P_=class extends pd.RegistryQueryBuilder{static{e(this,"HttpRegistryQueryBuilder")}get baseUrl(){return(process.env.INVARIANT_REGISTRY_URL||D_).replace(/\/$/,"")}async fetchFromGitHub(O_,I_,M_){const L_=M_||"main",U_=`https://codeload.github.com/${O_}/${I_}/tar.gz/${L_}`,W_=await this.downloadAndExtractTarball(U_),z_=`${I_}-${L_}/`;let X_;const K_=W_.find(Z_=>Z_.path===`${z_}invariant.json`);if(K_){const Z_=JSON.parse(K_.content);X_={name:Z_.name,version:Z_.version,description:Z_.description,author:Z_.author,repository:Z_.repository}}else X_={name:I_,version:L_,description:`Package from github:${O_}/${I_}`,author:O_};const G_=[...md.PACKAGE_ITEM_TYPES],Q_=[];for(const Z_ of G_){const $0=`${z_}${Z_}/`,B0=W_.filter(G0=>G0.path.startsWith($0)&&G0.path.endsWith(".md"));for(const G0 of B0){const Z0=G0.path.slice(z_.length);Q_.push({type:Z_,path:Z0,content:G0.content})}}return md.Package.create({manifest:{name:X_.name,version:X_.version,description:X_.description,author:X_.author,license:X_.license,repository:X_.repository||`https://github.com/${O_}/${I_}`},items:Q_,source:{type:"github",owner:O_,repo:I_,ref:L_}})}async downloadAndExtractTarball(O_){const I_=await fetch(O_,{headers:{"User-Agent":"invariant-cli"}});if(!I_.ok)throw I_.status===404?new Rd.RegistryFetchError(`Repository or branch not found: ${O_}`):new Rd.RegistryFetchError(`Failed to download: ${I_.status} ${I_.statusText}`);const M_=Buffer.from(await I_.arrayBuffer()),L_=fd.gunzipSync(M_);return this.parseTar(L_)}parseTar(O_){const I_=[];let M_=0;for(;M_<O_.length;){const L_=O_.slice(M_,M_+512);if(L_.every(G_=>G_===0))break;const U_=L_.indexOf(0),W_=L_.slice(0,Math.min(U_,100)).toString("utf-8"),z_=L_.slice(124,136).toString("utf-8").trim(),X_=parseInt(z_,8)||0,K_=L_[156];if(M_+=512,(K_===48||K_===0)&&X_>0){const G_=O_.slice(M_,M_+X_).toString("utf-8");I_.push({path:W_,content:G_})}M_+=Math.ceil(X_/512)*512}return I_}async exists(O_){const I_=`${this.baseUrl}/package/${encodeURIComponent(O_)}`,M_=await fetch(I_,{headers:{"User-Agent":"invariant-cli"}});if(M_.status===404)return!1;if(!M_.ok)throw new Rd.RegistryFetchError(`Registry error: ${M_.status}`);return!0}async fetchPackage(O_,I_){const M_=I_||await this.getLatestVersion(O_),L_=`${this.baseUrl}/package/${encodeURIComponent(O_)}/${encodeURIComponent(M_)}/download`,U_=await fetch(L_,{headers:{"User-Agent":"invariant-cli"}});if(U_.status===404)throw new Rd.RegistryFetchError(`Package "${O_}@${M_}" not found`);if(!U_.ok)throw new Rd.RegistryFetchError(`Download failed: ${U_.status}`);const W_=Buffer.from(await U_.arrayBuffer()),z_=fd.gunzipSync(W_),X_=this.parseTar(z_);return this.buildPackageFromEntries(X_,O_,M_)}async getVersions(O_){return(await this.getPackageDetails(O_)).versions.map(M_=>M_.version)}async getLatestVersion(O_){const I_=await this.getPackageDetails(O_);if(I_.versions.length===0)throw new Rd.RegistryFetchError(`Package "${O_}" has no versions`);return I_.versions[0].version}async search(O_){const I_=new URLSearchParams({q:O_,take:"100"}),M_=`${this.baseUrl}/package/search?${I_}`,L_=await fetch(M_,{headers:{"User-Agent":"invariant-cli"}});if(!L_.ok)throw new Rd.RegistryFetchError(`Search failed: ${L_.status}`);const U_=await L_.json();return this.mapSearchResults(U_)}async listAll(){const O_=`${this.baseUrl}/package/search?take=1000`,I_=await fetch(O_,{headers:{"User-Agent":"invariant-cli"}});if(!I_.ok)throw new Rd.RegistryFetchError(`List failed: ${I_.status}`);const M_=await I_.json();return this.mapSearchResults(M_)}async publishPackage(O_,I_,M_){const L_=`${this.baseUrl}/package/publish`,U_=new FormData;U_.append("name",O_.name),U_.append("version",O_.version),U_.append("description",O_.description||""),U_.append("author",O_.author||""),U_.append("readmeContent","");const W_=new Blob([new Uint8Array(I_)],{type:"application/gzip"});U_.append("tarball",W_,`${O_.name}-${O_.version}.tgz`);const z_=await fetch(L_,{method:"POST",headers:{"User-Agent":"invariant-cli",Authorization:`Bearer ${M_}`},body:U_});if(!z_.ok){const X_=await z_.text();throw new Rd.RegistryFetchError(`Publish failed: ${z_.status} ${X_}`)}return{name:O_.name,version:O_.version,url:`${this.baseUrl}/package/${O_.name}`}}async getPackageDetails(O_){const I_=`${this.baseUrl}/package/${encodeURIComponent(O_)}`,M_=await fetch(I_,{headers:{"User-Agent":"invariant-cli"}});if(M_.status===404)throw new Rd.RegistryFetchError(`Package "${O_}" not found`);if(!M_.ok)throw new Rd.RegistryFetchError(`Registry error: ${M_.status}`);return M_.json()}mapSearchResults(O_){return O_.items.map(I_=>({name:I_.name,version:I_.latestVersion,description:I_.description,author:I_.author,source:"registry"}))}buildPackageFromEntries(O_,I_,M_){let L_={name:I_,version:M_};const U_=O_.find(X_=>X_.path==="invariant.json"||X_.path.endsWith("/invariant.json"));if(U_){const X_=JSON.parse(U_.content);L_={name:X_.name||I_,version:X_.version||M_,description:X_.description,author:X_.author,license:X_.license,repository:X_.repository}}const W_=[...md.PACKAGE_ITEM_TYPES],z_=[];for(const X_ of W_)for(const K_ of O_){const G_=this.matchItemPath(K_.path,X_);G_&&K_.path.endsWith(".md")&&z_.push({type:X_,path:G_,content:K_.content})}return md.Package.create({manifest:L_,items:z_,source:{type:"registry"}})}matchItemPath(O_,I_){if(O_.startsWith(`${I_}/`))return O_;const M_=O_.indexOf(`/${I_}/`);return M_!==-1?O_.slice(M_+1):null}};return httpRegistry_queryBuilder.HttpRegistryQueryBuilder=P_,httpRegistry_queryBuilder.HttpRegistryQueryBuilder=P_=t([(0,Xf.Injectable)()],P_),httpRegistry_queryBuilder}e(requireHttpRegistry_queryBuilder,"requireHttpRegistry_queryBuilder");var hasRequiredPersistence$2;function requirePersistence$2(){return hasRequiredPersistence$2||(hasRequiredPersistence$2=1,(function(t){var Xf=persistence$2&&persistence$2.__createBinding||(Object.create?(function(pd,md,Rd,D_){D_===void 0&&(D_=Rd);var P_=Object.getOwnPropertyDescriptor(md,Rd);(!P_||("get"in P_?!md.__esModule:P_.writable||P_.configurable))&&(P_={enumerable:!0,get:e(function(){return md[Rd]},"get")}),Object.defineProperty(pd,D_,P_)}):(function(pd,md,Rd,D_){D_===void 0&&(D_=Rd),pd[D_]=md[Rd]})),fd=persistence$2&&persistence$2.__exportStar||function(pd,md){for(var Rd in pd)Rd!=="default"&&!Object.prototype.hasOwnProperty.call(md,Rd)&&Xf(md,pd,Rd)};Object.defineProperty(t,"__esModule",{value:!0}),fd(requireFileSystemStorage_repository(),t),fd(requireInMemoryRegistry_queryBuilder(),t),fd(requireHttpRegistry_queryBuilder(),t)})(persistence$2)),persistence$2}e(requirePersistence$2,"requirePersistence$2");var gateways$2={},claudeCodeCliTarget_gateway={},hasRequiredClaudeCodeCliTarget_gateway;function requireClaudeCodeCliTarget_gateway(){if(hasRequiredClaudeCodeCliTarget_gateway)return claudeCodeCliTarget_gateway;hasRequiredClaudeCodeCliTarget_gateway=1;var t=claudeCodeCliTarget_gateway&&claudeCodeCliTarget_gateway.__decorate||function(F_,O_,I_,M_){var L_=arguments.length,U_=L_<3?O_:M_===null?M_=Object.getOwnPropertyDescriptor(O_,I_):M_,W_;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")U_=Reflect.decorate(F_,O_,I_,M_);else for(var z_=F_.length-1;z_>=0;z_--)(W_=F_[z_])&&(U_=(L_<3?W_(U_):L_>3?W_(O_,I_,U_):W_(O_,I_))||U_);return L_>3&&U_&&Object.defineProperty(O_,I_,U_),U_};Object.defineProperty(claudeCodeCliTarget_gateway,"__esModule",{value:!0}),claudeCodeCliTarget_gateway.ClaudeCodeCliTargetGateway=void 0;const Xf=requireCommon$1(),fd=require$$1$5,pd=require$$2$2,md=requireGateways$3(),Rd=".claude",D_="CLAUDE.md";let P_=class extends md.CliTargetGateway{static{e(this,"ClaudeCodeCliTargetGateway")}constructor(){super(...arguments),this.config={name:"claude",displayName:"Claude Code",supportsItemTypes:!0}}async copyItem(O_,I_,M_,L_){const U_=pd.join(O_,Rd,I_);await fd.mkdir(U_,{recursive:!0});const W_=[];if(I_!=="skills"&&L_.length===1&&!L_[0].relativePath.includes("/")){const X_=pd.join(U_,M_+".md");await fd.writeFile(X_,L_[0].content,"utf-8"),W_.push(X_)}else{const X_=pd.join(U_,M_);for(const K_ of L_){const G_=pd.join(X_,K_.relativePath);await fd.mkdir(pd.dirname(G_),{recursive:!0}),await fd.writeFile(G_,K_.content,"utf-8"),W_.push(G_)}}return{files:W_,itemNames:[M_]}}async removeItem(O_,I_,M_){const L_=pd.join(O_,Rd,I_),U_=pd.join(L_,M_);try{if((await fd.stat(U_)).isDirectory()){await fd.rm(U_,{recursive:!0});return}}catch{}try{await fd.unlink(U_+".md")}catch{}}async generateContextFile(O_,I_){const M_=pd.join(O_,D_);return await fd.writeFile(M_,I_,"utf-8"),M_}async contextFileExists(O_){try{return await fd.access(pd.join(O_,D_)),!0}catch{return!1}}async resolveItemPath(O_,I_,M_){const L_=pd.join(O_,Rd,I_),U_=pd.join(L_,M_);try{if((await fd.stat(U_)).isDirectory())return pd.join(Rd,I_,M_)}catch{}const W_=U_+".md";try{return await fd.access(W_),pd.join(Rd,I_,M_+".md")}catch{}return null}};return claudeCodeCliTarget_gateway.ClaudeCodeCliTargetGateway=P_,claudeCodeCliTarget_gateway.ClaudeCodeCliTargetGateway=P_=t([(0,Xf.Injectable)()],P_),claudeCodeCliTarget_gateway}e(requireClaudeCodeCliTarget_gateway,"requireClaudeCodeCliTarget_gateway");var codexCliTarget_gateway={},hasRequiredCodexCliTarget_gateway;function requireCodexCliTarget_gateway(){if(hasRequiredCodexCliTarget_gateway)return codexCliTarget_gateway;hasRequiredCodexCliTarget_gateway=1;var t=codexCliTarget_gateway&&codexCliTarget_gateway.__decorate||function(P_,F_,O_,I_){var M_=arguments.length,L_=M_<3?F_:I_===null?I_=Object.getOwnPropertyDescriptor(F_,O_):I_,U_;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")L_=Reflect.decorate(P_,F_,O_,I_);else for(var W_=P_.length-1;W_>=0;W_--)(U_=P_[W_])&&(L_=(M_<3?U_(L_):M_>3?U_(F_,O_,L_):U_(F_,O_))||L_);return M_>3&&L_&&Object.defineProperty(F_,O_,L_),L_};Object.defineProperty(codexCliTarget_gateway,"__esModule",{value:!0}),codexCliTarget_gateway.CodexCliTargetGateway=void 0;const Xf=requireCommon$1(),fd=require$$1$5,pd=require$$2$2,md=requireGateways$3(),Rd="AGENTS.md";let D_=class extends md.CliTargetGateway{static{e(this,"CodexCliTargetGateway")}constructor(){super(...arguments),this.config={name:"codex",displayName:"OpenAI Codex",supportsItemTypes:!1}}async copyItem(F_,O_,I_,M_){return{files:[],itemNames:[]}}async removeItem(F_,O_,I_){}async generateContextFile(F_,O_){const I_=pd.join(F_,Rd);return await fd.writeFile(I_,O_,"utf-8"),I_}async contextFileExists(F_){try{return await fd.access(pd.join(F_,Rd)),!0}catch{return!1}}async resolveItemPath(F_,O_,I_){return null}};return codexCliTarget_gateway.CodexCliTargetGateway=D_,codexCliTarget_gateway.CodexCliTargetGateway=D_=t([(0,Xf.Injectable)()],D_),codexCliTarget_gateway}e(requireCodexCliTarget_gateway,"requireCodexCliTarget_gateway");var cursorCliTarget_gateway={},hasRequiredCursorCliTarget_gateway;function requireCursorCliTarget_gateway(){if(hasRequiredCursorCliTarget_gateway)return cursorCliTarget_gateway;hasRequiredCursorCliTarget_gateway=1;var t=cursorCliTarget_gateway&&cursorCliTarget_gateway.__decorate||function(P_,F_,O_,I_){var M_=arguments.length,L_=M_<3?F_:I_===null?I_=Object.getOwnPropertyDescriptor(F_,O_):I_,U_;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")L_=Reflect.decorate(P_,F_,O_,I_);else for(var W_=P_.length-1;W_>=0;W_--)(U_=P_[W_])&&(L_=(M_<3?U_(L_):M_>3?U_(F_,O_,L_):U_(F_,O_))||L_);return M_>3&&L_&&Object.defineProperty(F_,O_,L_),L_};Object.defineProperty(cursorCliTarget_gateway,"__esModule",{value:!0}),cursorCliTarget_gateway.CursorCliTargetGateway=void 0;const Xf=requireCommon$1(),fd=require$$1$5,pd=require$$2$2,md=requireGateways$3(),Rd=".cursor/rules";let D_=class extends md.CliTargetGateway{static{e(this,"CursorCliTargetGateway")}constructor(){super(...arguments),this.config={name:"cursor",displayName:"Cursor",supportsItemTypes:!1}}async copyItem(F_,O_,I_,M_){const L_=pd.join(F_,Rd);await fd.mkdir(L_,{recursive:!0});const U_=I_+".mdc",W_=pd.join(L_,U_),z_=this.concatenateFiles(M_),X_=this.wrapWithFrontmatter(z_,O_,I_);return await fd.writeFile(W_,X_,"utf-8"),{files:[W_],itemNames:[I_]}}async removeItem(F_,O_,I_){const M_=I_+".mdc";try{await fd.unlink(pd.join(F_,Rd,M_))}catch{}}async generateContextFile(F_,O_){const I_=pd.join(F_,Rd);await fd.mkdir(I_,{recursive:!0});const M_=pd.join(I_,"invariant-context.mdc"),L_=this.wrapWithFrontmatter(O_,"context","Invariant project context");return await fd.writeFile(M_,L_,"utf-8"),M_}async contextFileExists(F_){try{return await fd.access(pd.join(F_,Rd,"invariant-context.mdc")),!0}catch{return!1}}async resolveItemPath(F_,O_,I_){const M_=pd.join(F_,Rd,I_+".mdc");try{return await fd.access(M_),pd.join(Rd,I_+".mdc")}catch{return null}}concatenateFiles(F_){return F_.length===1?F_[0].content:F_.map(O_=>O_.content).join(`
|
|
973
973
|
|
|
974
974
|
`)}wrapWithFrontmatter(F_,O_,I_){return`---
|
|
975
975
|
description: "${O_}: ${I_}"
|