@inspecto-dev/cli 0.2.0-alpha.6 → 0.3.0-alpha.1
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/.turbo/turbo-build.log +19 -20
- package/CHANGELOG.md +16 -0
- package/README.md +44 -9
- package/dist/bin.d.ts +1 -1
- package/dist/bin.js +448 -6
- package/dist/{chunk-PDDFPQJS.js → chunk-FZS2TLXQ.js} +620 -85
- package/dist/index.d.ts +106 -1
- package/dist/index.js +3 -1
- package/package.json +2 -2
- package/src/bin.ts +148 -0
- package/src/commands/apply.ts +5 -1
- package/src/commands/init.ts +60 -23
- package/src/commands/integration-install.ts +452 -0
- package/src/commands/onboard.ts +50 -0
- package/src/index.ts +4 -0
- package/src/inject/ast-injector.ts +15 -4
- package/src/inject/extension.ts +40 -24
- package/src/inject/gitignore.ts +10 -3
- package/src/onboarding/apply.ts +48 -9
- package/src/onboarding/planner.ts +6 -0
- package/src/onboarding/session.ts +434 -0
- package/src/onboarding/target-resolution.ts +116 -0
- package/src/types.ts +89 -0
- package/tests/apply.test.ts +47 -1
- package/tests/init.test.ts +31 -0
- package/tests/install-wrapper.test.ts +76 -0
- package/tests/integration-install.test.ts +294 -0
- package/tests/onboard.test.ts +258 -0
- package/.turbo/turbo-test.log +0 -16
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
DTS Build
|
|
18
|
-
DTS
|
|
19
|
-
DTS dist/
|
|
20
|
-
DTS dist/index.d.ts 4.90 KB
|
|
1
|
+
|
|
2
|
+
> @inspecto-dev/cli@0.3.0-alpha.1 build /Users/tangjie/hugo.felix/inspecto/packages/cli
|
|
3
|
+
> tsup
|
|
4
|
+
|
|
5
|
+
CLI Building entry: src/bin.ts, src/index.ts
|
|
6
|
+
CLI Using tsconfig: tsconfig.json
|
|
7
|
+
CLI tsup v8.5.1
|
|
8
|
+
CLI Using tsup config: /Users/tangjie/hugo.felix/inspecto/packages/cli/tsup.config.ts
|
|
9
|
+
CLI Target: node18
|
|
10
|
+
CLI Cleaning output folder
|
|
11
|
+
ESM Build start
|
|
12
|
+
ESM dist/index.js 319.00 B
|
|
13
|
+
ESM dist/bin.js 20.37 KB
|
|
14
|
+
ESM dist/chunk-FZS2TLXQ.js 103.35 KB
|
|
15
|
+
ESM ⚡️ Build success in 61ms
|
|
16
|
+
DTS Build start
|
|
17
|
+
DTS ⚡️ Build success in 5204ms
|
|
18
|
+
DTS dist/bin.d.ts 185.00 B
|
|
19
|
+
DTS dist/index.d.ts 7.79 KB
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @inspecto-dev/cli
|
|
2
2
|
|
|
3
|
+
## 0.3.0-alpha.1
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Prepare the first `0.3.0-alpha.1` release line for Inspecto's browser-first workflow.
|
|
8
|
+
- unify onboarding around assistant-first setup and the single-entry `inspecto onboard --json` contract
|
|
9
|
+
- stabilize the browser UX across `Inspect`, `Annotate`, and `Alt + Click` quick jump
|
|
10
|
+
- tighten prompt and settings schema boundaries and keep evidence toggles built-in
|
|
11
|
+
- refresh README, website, onboarding docs, and playgrounds to match the shipped workflow
|
|
12
|
+
- refactor large runtime modules without intended behavior changes
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- Updated dependencies
|
|
17
|
+
- @inspecto-dev/types@0.3.0-alpha.1
|
|
18
|
+
|
|
3
19
|
## 0.2.0-alpha.6
|
|
4
20
|
|
|
5
21
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -4,21 +4,37 @@ The official command-line interface for Inspecto. This tool automates the proces
|
|
|
4
4
|
|
|
5
5
|
## Onboarding Flow
|
|
6
6
|
|
|
7
|
-
For
|
|
7
|
+
For most users, the preferred setup path is assistant-first onboarding via the integrations documented in:
|
|
8
|
+
`packages/docs/integrations/onboarding-skills.md`
|
|
9
|
+
|
|
10
|
+
Install those assistant integration assets with:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npx @inspecto-dev/cli integrations install <assistant>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Supported assistants currently include `codex`, `claude-code`, `copilot`, `cursor`, `gemini`, `trae`, and `coco`.
|
|
17
|
+
|
|
18
|
+
Inspect available integration targets with:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx @inspecto-dev/cli integrations list
|
|
22
|
+
npx @inspecto-dev/cli integrations install codex
|
|
23
|
+
npx @inspecto-dev/cli integrations path <assistant>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Use `inspecto init` when you want a guided setup directly in the terminal, or when the assistant path is unavailable.
|
|
27
|
+
|
|
28
|
+
If you are building your own agent/runtime integration, the machine-readable flow is:
|
|
8
29
|
|
|
9
30
|
1. `inspecto detect --json`
|
|
10
31
|
2. `inspecto plan --json`
|
|
11
|
-
3. `inspecto apply`
|
|
32
|
+
3. `inspecto apply --json`
|
|
12
33
|
4. `inspecto doctor --json`
|
|
13
34
|
|
|
14
35
|
See the public onboarding contract for response shapes and field semantics:
|
|
15
36
|
`packages/docs/integrations/onboarding-contract.md`
|
|
16
37
|
|
|
17
|
-
Assistant-specific onboarding entrypoints are documented in:
|
|
18
|
-
`packages/docs/integrations/onboarding-skills.md`
|
|
19
|
-
|
|
20
|
-
Use `inspecto init` when you want a guided manual setup in the terminal, or when the structured flow is not available.
|
|
21
|
-
|
|
22
38
|
## Installation
|
|
23
39
|
|
|
24
40
|
You can use the CLI without installing it globally by using `npx`:
|
|
@@ -53,9 +69,9 @@ Previews the onboarding plan for the current project.
|
|
|
53
69
|
- Summarizes the proposed setup strategy and actions.
|
|
54
70
|
- Produces structured output that agents can inspect before applying changes.
|
|
55
71
|
|
|
56
|
-
### `inspecto apply`
|
|
72
|
+
### `inspecto apply [--json]`
|
|
57
73
|
|
|
58
|
-
Applies the onboarding plan to the current project.
|
|
74
|
+
Applies the onboarding plan to the current project. Use `--json` when the command is driven by an agent/runtime integration.
|
|
59
75
|
|
|
60
76
|
**Features:**
|
|
61
77
|
|
|
@@ -64,6 +80,25 @@ Applies the onboarding plan to the current project.
|
|
|
64
80
|
- Installs or configures the selected IDE extension when needed.
|
|
65
81
|
- Writes `.inspecto/settings.local.json` and updates `.gitignore` when appropriate.
|
|
66
82
|
|
|
83
|
+
### `inspecto integrations`
|
|
84
|
+
|
|
85
|
+
Manages assistant integration assets for the current project.
|
|
86
|
+
|
|
87
|
+
**Subcommands:**
|
|
88
|
+
|
|
89
|
+
- `inspecto integrations list` prints the supported assistant targets and their preferred install surfaces.
|
|
90
|
+
- `inspecto integrations path <assistant>` prints the concrete files that a selected variant will create.
|
|
91
|
+
- `inspecto integrations install <assistant>` installs the integration assets for the selected assistant.
|
|
92
|
+
|
|
93
|
+
Examples:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
inspecto integrations install codex
|
|
97
|
+
inspecto integrations path codex
|
|
98
|
+
inspecto integrations install claude-code --scope project
|
|
99
|
+
inspecto integrations install cursor --mode rules
|
|
100
|
+
```
|
|
101
|
+
|
|
67
102
|
### `inspecto doctor`
|
|
68
103
|
|
|
69
104
|
A diagnostic command to verify your current environment.
|
package/dist/bin.d.ts
CHANGED
package/dist/bin.js
CHANGED
|
@@ -2,18 +2,369 @@ import {
|
|
|
2
2
|
apply,
|
|
3
3
|
detect,
|
|
4
4
|
doctor,
|
|
5
|
+
exists,
|
|
5
6
|
init,
|
|
7
|
+
log,
|
|
8
|
+
onboard,
|
|
6
9
|
plan,
|
|
7
10
|
reportCommandError,
|
|
8
|
-
teardown
|
|
9
|
-
|
|
11
|
+
teardown,
|
|
12
|
+
writeFile
|
|
13
|
+
} from "./chunk-FZS2TLXQ.js";
|
|
10
14
|
|
|
11
15
|
// src/bin.ts
|
|
12
16
|
import { cac } from "cac";
|
|
13
|
-
import { fileURLToPath } from "url";
|
|
17
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
14
18
|
import { createRequire } from "module";
|
|
19
|
+
|
|
20
|
+
// src/commands/integration-install.ts
|
|
21
|
+
import fs from "fs/promises";
|
|
22
|
+
import { homedir } from "os";
|
|
23
|
+
import path from "path";
|
|
24
|
+
import { fileURLToPath } from "url";
|
|
25
|
+
var REPO_RAW_BASE = "https://raw.githubusercontent.com/inspecto-dev/inspecto/main";
|
|
26
|
+
var INTEGRATION_MANIFESTS = [
|
|
27
|
+
{
|
|
28
|
+
assistant: "codex",
|
|
29
|
+
type: "native-skill",
|
|
30
|
+
installTarget: "~/.codex/skills/",
|
|
31
|
+
preferredInstall: "npx @inspecto-dev/cli integrations install codex",
|
|
32
|
+
cliSupported: true
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
assistant: "claude-code",
|
|
36
|
+
type: "native-skill",
|
|
37
|
+
installTarget: ".claude/skills/ or ~/.claude/skills/",
|
|
38
|
+
preferredInstall: "npx @inspecto-dev/cli integrations install claude-code --scope project",
|
|
39
|
+
cliSupported: true
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
assistant: "copilot",
|
|
43
|
+
type: "instruction-template",
|
|
44
|
+
installTarget: ".github/copilot-instructions.md or AGENTS.md",
|
|
45
|
+
preferredInstall: "npx @inspecto-dev/cli integrations install copilot",
|
|
46
|
+
cliSupported: true
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
assistant: "cursor",
|
|
50
|
+
type: "rule-template",
|
|
51
|
+
installTarget: ".cursor/rules/inspecto-onboarding.mdc or AGENTS.md",
|
|
52
|
+
preferredInstall: "npx @inspecto-dev/cli integrations install cursor --mode rules",
|
|
53
|
+
cliSupported: true
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
assistant: "gemini",
|
|
57
|
+
type: "context-template",
|
|
58
|
+
installTarget: "GEMINI.md",
|
|
59
|
+
preferredInstall: "npx @inspecto-dev/cli integrations install gemini",
|
|
60
|
+
cliSupported: true
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
assistant: "trae",
|
|
64
|
+
type: "compatibility-template",
|
|
65
|
+
installTarget: "AGENTS.md",
|
|
66
|
+
preferredInstall: "npx @inspecto-dev/cli integrations install trae",
|
|
67
|
+
cliSupported: true
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
assistant: "coco",
|
|
71
|
+
type: "compatibility-template",
|
|
72
|
+
installTarget: "AGENTS.md",
|
|
73
|
+
preferredInstall: "npx @inspecto-dev/cli integrations install coco",
|
|
74
|
+
cliSupported: true
|
|
75
|
+
}
|
|
76
|
+
];
|
|
77
|
+
async function installIntegration(assistant, options = {}) {
|
|
78
|
+
const plan2 = resolveInstallPlan(assistant, options);
|
|
79
|
+
log.header("Inspecto Integration Install");
|
|
80
|
+
for (const asset of plan2.assets) {
|
|
81
|
+
if (await exists(asset.target) && !options.force) {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`Refusing to overwrite existing file: ${asset.target}. Re-run with --force if you want to replace it.`
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const downloadedAssets = [];
|
|
88
|
+
for (const asset of plan2.assets) {
|
|
89
|
+
const content = await loadAsset(asset);
|
|
90
|
+
downloadedAssets.push({ asset, content });
|
|
91
|
+
}
|
|
92
|
+
for (const { asset, content } of downloadedAssets) {
|
|
93
|
+
await writeFile(asset.target, content);
|
|
94
|
+
if (asset.executable) {
|
|
95
|
+
await fs.chmod(asset.target, 493);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
log.success(plan2.successMessage);
|
|
99
|
+
log.hint(plan2.nextStep);
|
|
100
|
+
}
|
|
101
|
+
function describeIntegration(assistant, options = {}) {
|
|
102
|
+
const manifest = getIntegrationManifest(assistant);
|
|
103
|
+
const targets = manifest.cliSupported ? resolveInstallPlan(assistant, options).assets.map((asset) => asset.target) : [manifest.installTarget];
|
|
104
|
+
return {
|
|
105
|
+
assistant: manifest.assistant,
|
|
106
|
+
type: manifest.type,
|
|
107
|
+
targets,
|
|
108
|
+
preferredInstall: manifest.preferredInstall,
|
|
109
|
+
cliSupported: manifest.cliSupported
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function printIntegrationList() {
|
|
113
|
+
log.header("Inspecto Integrations");
|
|
114
|
+
for (const manifest of INTEGRATION_MANIFESTS) {
|
|
115
|
+
const support = manifest.cliSupported ? "CLI" : "native installer";
|
|
116
|
+
log.info(`${manifest.assistant} \u2014 ${manifest.type} \u2014 ${manifest.installTarget} \u2014 ${support}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function printIntegrationPath(assistant, options = {}) {
|
|
120
|
+
const description = describeIntegration(assistant, options);
|
|
121
|
+
log.header(`Inspecto Integration Paths: ${description.assistant}`);
|
|
122
|
+
for (const target of description.targets) {
|
|
123
|
+
log.info(target);
|
|
124
|
+
}
|
|
125
|
+
if (description.cliSupported) {
|
|
126
|
+
log.hint(`Preferred install: ${description.preferredInstall}`);
|
|
127
|
+
} else {
|
|
128
|
+
log.hint(`Native install required: ${description.preferredInstall}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function resolveInstallPlan(assistant, options) {
|
|
132
|
+
switch (assistant) {
|
|
133
|
+
case "codex":
|
|
134
|
+
return resolveCodexPlan(options);
|
|
135
|
+
case "claude-code":
|
|
136
|
+
return resolveClaudeCodePlan(options);
|
|
137
|
+
case "copilot":
|
|
138
|
+
return resolveCopilotPlan(options);
|
|
139
|
+
case "cursor":
|
|
140
|
+
return resolveCursorPlan(options);
|
|
141
|
+
case "gemini":
|
|
142
|
+
return {
|
|
143
|
+
assets: [
|
|
144
|
+
{
|
|
145
|
+
source: `${REPO_RAW_BASE}/assistant-integrations/gemini/GEMINI.md`,
|
|
146
|
+
target: "GEMINI.md",
|
|
147
|
+
localSource: "assistant-integrations/gemini/GEMINI.md"
|
|
148
|
+
}
|
|
149
|
+
],
|
|
150
|
+
successMessage: "Installed Gemini context to GEMINI.md",
|
|
151
|
+
nextStep: "Start a new Gemini CLI session."
|
|
152
|
+
};
|
|
153
|
+
case "trae":
|
|
154
|
+
return {
|
|
155
|
+
assets: [
|
|
156
|
+
{
|
|
157
|
+
source: `${REPO_RAW_BASE}/assistant-integrations/trae/AGENTS.md`,
|
|
158
|
+
target: "AGENTS.md",
|
|
159
|
+
localSource: "assistant-integrations/trae/AGENTS.md"
|
|
160
|
+
}
|
|
161
|
+
],
|
|
162
|
+
successMessage: "Installed Trae compatibility instructions to AGENTS.md",
|
|
163
|
+
nextStep: "Open a new Trae chat."
|
|
164
|
+
};
|
|
165
|
+
case "coco":
|
|
166
|
+
return {
|
|
167
|
+
assets: [
|
|
168
|
+
{
|
|
169
|
+
source: `${REPO_RAW_BASE}/assistant-integrations/coco/AGENTS.md`,
|
|
170
|
+
target: "AGENTS.md",
|
|
171
|
+
localSource: "assistant-integrations/coco/AGENTS.md"
|
|
172
|
+
}
|
|
173
|
+
],
|
|
174
|
+
successMessage: "Installed Coco compatibility instructions to AGENTS.md",
|
|
175
|
+
nextStep: "Start a new Coco session."
|
|
176
|
+
};
|
|
177
|
+
default:
|
|
178
|
+
throw new Error(`Unknown assistant: ${assistant}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function getIntegrationManifest(assistant) {
|
|
182
|
+
const manifest = INTEGRATION_MANIFESTS.find((item) => item.assistant === assistant);
|
|
183
|
+
if (!manifest) {
|
|
184
|
+
throw new Error(
|
|
185
|
+
`Unknown assistant: ${assistant}. Run 'inspecto integrations list' to see available targets.`
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
return manifest;
|
|
189
|
+
}
|
|
190
|
+
function resolveCodexPlan(options) {
|
|
191
|
+
if (options.scope !== void 0) {
|
|
192
|
+
throw new Error("`--scope` is not supported for codex.");
|
|
193
|
+
}
|
|
194
|
+
if (options.mode !== void 0) {
|
|
195
|
+
throw new Error("`--mode` is not supported for codex.");
|
|
196
|
+
}
|
|
197
|
+
const baseDir = path.join(homedir(), ".codex/skills/inspecto-onboarding-codex");
|
|
198
|
+
return {
|
|
199
|
+
assets: [
|
|
200
|
+
{
|
|
201
|
+
source: `${REPO_RAW_BASE}/skills/inspecto-onboarding-codex/SKILL.md`,
|
|
202
|
+
target: path.join(baseDir, "SKILL.md"),
|
|
203
|
+
localSource: "skills/inspecto-onboarding-codex/SKILL.md"
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
source: `${REPO_RAW_BASE}/skills/inspecto-onboarding-codex/agents/openai.yaml`,
|
|
207
|
+
target: path.join(baseDir, "agents/openai.yaml"),
|
|
208
|
+
localSource: "skills/inspecto-onboarding-codex/agents/openai.yaml"
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
source: `${REPO_RAW_BASE}/skills/inspecto-onboarding-codex/scripts/run-inspecto.sh`,
|
|
212
|
+
target: path.join(baseDir, "scripts/run-inspecto.sh"),
|
|
213
|
+
executable: true,
|
|
214
|
+
localSource: "skills/inspecto-onboarding-codex/scripts/run-inspecto.sh"
|
|
215
|
+
}
|
|
216
|
+
],
|
|
217
|
+
successMessage: `Installed Codex skill to ${baseDir}`,
|
|
218
|
+
nextStep: "Restart Codex or start a new Codex session to load the skill."
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function resolveClaudeCodePlan(options) {
|
|
222
|
+
const scope = options.scope ?? "project";
|
|
223
|
+
const unsupportedMode = options.mode !== void 0;
|
|
224
|
+
if (unsupportedMode) {
|
|
225
|
+
throw new Error(
|
|
226
|
+
"`--mode` is not supported for claude-code. Use `--scope project|user` instead."
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
if (scope !== "project" && scope !== "user") {
|
|
230
|
+
throw new Error(`Unknown Claude Code scope: ${scope}`);
|
|
231
|
+
}
|
|
232
|
+
const baseDir = scope === "user" ? path.join(homedir(), ".claude/skills/inspecto-onboarding-claude-code") : ".claude/skills/inspecto-onboarding-claude-code";
|
|
233
|
+
return {
|
|
234
|
+
assets: [
|
|
235
|
+
{
|
|
236
|
+
source: `${REPO_RAW_BASE}/skills/inspecto-onboarding-claude-code/SKILL.md`,
|
|
237
|
+
target: path.join(baseDir, "SKILL.md"),
|
|
238
|
+
localSource: "skills/inspecto-onboarding-claude-code/SKILL.md"
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
source: `${REPO_RAW_BASE}/skills/inspecto-onboarding-claude-code/agents/openai.yaml`,
|
|
242
|
+
target: path.join(baseDir, "agents/openai.yaml"),
|
|
243
|
+
localSource: "skills/inspecto-onboarding-claude-code/agents/openai.yaml"
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
source: `${REPO_RAW_BASE}/skills/inspecto-onboarding-claude-code/scripts/run-inspecto.sh`,
|
|
247
|
+
target: path.join(baseDir, "scripts/run-inspecto.sh"),
|
|
248
|
+
executable: true,
|
|
249
|
+
localSource: "skills/inspecto-onboarding-claude-code/scripts/run-inspecto.sh"
|
|
250
|
+
}
|
|
251
|
+
],
|
|
252
|
+
successMessage: `Installed Claude Code skill to ${baseDir}`,
|
|
253
|
+
nextStep: "Restart Claude Code to load the new skill."
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function resolveCopilotPlan(options) {
|
|
257
|
+
const mode = options.mode ?? "instructions";
|
|
258
|
+
if (options.scope !== void 0) {
|
|
259
|
+
throw new Error(
|
|
260
|
+
"`--scope` is not supported for copilot. Use `--mode instructions|agents` instead."
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
switch (mode) {
|
|
264
|
+
case "instructions":
|
|
265
|
+
return {
|
|
266
|
+
assets: [
|
|
267
|
+
{
|
|
268
|
+
source: `${REPO_RAW_BASE}/assistant-integrations/copilot/.github/copilot-instructions.md`,
|
|
269
|
+
target: ".github/copilot-instructions.md",
|
|
270
|
+
localSource: "assistant-integrations/copilot/.github/copilot-instructions.md"
|
|
271
|
+
}
|
|
272
|
+
],
|
|
273
|
+
successMessage: "Installed Copilot instructions to .github/copilot-instructions.md",
|
|
274
|
+
nextStep: "Open a new Copilot chat or agent session."
|
|
275
|
+
};
|
|
276
|
+
case "agents":
|
|
277
|
+
return {
|
|
278
|
+
assets: [
|
|
279
|
+
{
|
|
280
|
+
source: `${REPO_RAW_BASE}/assistant-integrations/copilot/AGENTS.md`,
|
|
281
|
+
target: "AGENTS.md",
|
|
282
|
+
localSource: "assistant-integrations/copilot/AGENTS.md"
|
|
283
|
+
}
|
|
284
|
+
],
|
|
285
|
+
successMessage: "Installed Copilot compatibility instructions to AGENTS.md",
|
|
286
|
+
nextStep: "Open a new Copilot chat or agent session."
|
|
287
|
+
};
|
|
288
|
+
default:
|
|
289
|
+
throw new Error(`Unknown Copilot mode: ${mode}`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function resolveCursorPlan(options) {
|
|
293
|
+
const mode = options.mode ?? "rules";
|
|
294
|
+
if (options.scope !== void 0) {
|
|
295
|
+
throw new Error("`--scope` is not supported for cursor. Use `--mode rules|agents` instead.");
|
|
296
|
+
}
|
|
297
|
+
switch (mode) {
|
|
298
|
+
case "rules":
|
|
299
|
+
return {
|
|
300
|
+
assets: [
|
|
301
|
+
{
|
|
302
|
+
source: `${REPO_RAW_BASE}/assistant-integrations/cursor/.cursor/rules/inspecto-onboarding.mdc`,
|
|
303
|
+
target: ".cursor/rules/inspecto-onboarding.mdc",
|
|
304
|
+
localSource: "assistant-integrations/cursor/.cursor/rules/inspecto-onboarding.mdc"
|
|
305
|
+
}
|
|
306
|
+
],
|
|
307
|
+
successMessage: "Installed Cursor rule to .cursor/rules/inspecto-onboarding.mdc",
|
|
308
|
+
nextStep: "Open a new Cursor chat."
|
|
309
|
+
};
|
|
310
|
+
case "agents":
|
|
311
|
+
return {
|
|
312
|
+
assets: [
|
|
313
|
+
{
|
|
314
|
+
source: `${REPO_RAW_BASE}/assistant-integrations/cursor/AGENTS.md`,
|
|
315
|
+
target: "AGENTS.md",
|
|
316
|
+
localSource: "assistant-integrations/cursor/AGENTS.md"
|
|
317
|
+
}
|
|
318
|
+
],
|
|
319
|
+
successMessage: "Installed Cursor compatibility instructions to AGENTS.md",
|
|
320
|
+
nextStep: "Open a new Cursor chat."
|
|
321
|
+
};
|
|
322
|
+
default:
|
|
323
|
+
throw new Error(`Unknown Cursor mode: ${mode}`);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
async function loadAsset(asset) {
|
|
327
|
+
if (asset.localSource) {
|
|
328
|
+
const localPath = await resolveBundledAssetPath(asset.localSource);
|
|
329
|
+
if (localPath) {
|
|
330
|
+
return await fs.readFile(localPath, "utf-8");
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return await downloadAsset(asset.source);
|
|
334
|
+
}
|
|
335
|
+
async function resolveBundledAssetPath(relativePath) {
|
|
336
|
+
const startDir = path.dirname(fileURLToPath(import.meta.url));
|
|
337
|
+
let currentDir = startDir;
|
|
338
|
+
for (let depth = 0; depth < 8; depth += 1) {
|
|
339
|
+
const candidate = path.join(currentDir, relativePath);
|
|
340
|
+
if (await exists(candidate)) {
|
|
341
|
+
return candidate;
|
|
342
|
+
}
|
|
343
|
+
const parent = path.dirname(currentDir);
|
|
344
|
+
if (parent === currentDir) break;
|
|
345
|
+
currentDir = parent;
|
|
346
|
+
}
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
async function downloadAsset(source) {
|
|
350
|
+
let response;
|
|
351
|
+
try {
|
|
352
|
+
response = await fetch(source);
|
|
353
|
+
} catch (error) {
|
|
354
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
355
|
+
throw new Error(`Failed to download ${source}: ${reason}`);
|
|
356
|
+
}
|
|
357
|
+
if (!response.ok) {
|
|
358
|
+
throw new Error(`Failed to download ${source}: ${response.status} ${response.statusText}`);
|
|
359
|
+
}
|
|
360
|
+
return await response.text();
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// src/bin.ts
|
|
15
364
|
var require2 = createRequire(import.meta.url);
|
|
16
365
|
var { version } = require2("../package.json");
|
|
366
|
+
var integrationScopes = ["project", "user"];
|
|
367
|
+
var integrationModes = ["instructions", "agents", "rules"];
|
|
17
368
|
function exitWithError(error, options = {}) {
|
|
18
369
|
reportCommandError(error, {
|
|
19
370
|
debug: options.debug ?? false,
|
|
@@ -21,9 +372,11 @@ function exitWithError(error, options = {}) {
|
|
|
21
372
|
});
|
|
22
373
|
process.exit(1);
|
|
23
374
|
}
|
|
24
|
-
function createCli(
|
|
375
|
+
function createCli(_argv = process.argv) {
|
|
25
376
|
const cli = cac("inspecto");
|
|
26
|
-
cli.command("init", "Set up Inspecto in your project").option("--shared", "Share .inspecto/settings.json with your team via Git", { default: false }).option("--skip-install", "Skip npm dependency installation", { default: false }).option("--dry-run", "Preview changes without modifying files", { default: false }).option("--provider <provider>", "Set default provider (e.g. copilot, claude-code)").option("--no-extension", "Skip VS Code extension installation", { default: false }).option("--packages <names>", "(Monorepo) Comma-separated list of packages to inject").option("--force", "Force initialization even if environment is unsupported", {
|
|
377
|
+
cli.command("init", "Set up Inspecto in your project").option("--shared", "Share .inspecto/settings.json with your team via Git", { default: false }).option("--skip-install", "Skip npm dependency installation", { default: false }).option("--dry-run", "Preview changes without modifying files", { default: false }).option("--provider <provider>", "Set default provider (e.g. copilot, claude-code)").option("--no-extension", "Skip VS Code extension installation", { default: false }).option("--packages <names>", "(Monorepo) Comma-separated list of packages to inject").option("--force", "Force initialization even if environment is unsupported", {
|
|
378
|
+
default: false
|
|
379
|
+
}).option("--debug", "Enable debug mode to show full error traces", { default: false }).action(async (options) => {
|
|
27
380
|
try {
|
|
28
381
|
await init({
|
|
29
382
|
shared: options.shared ?? false,
|
|
@@ -47,6 +400,21 @@ function createCli(argv = process.argv) {
|
|
|
47
400
|
exitWithError(error, options);
|
|
48
401
|
}
|
|
49
402
|
});
|
|
403
|
+
cli.command("onboard", "Run assistant-oriented Inspecto onboarding in one structured flow").option("--json", "Print machine-readable JSON output", { default: false }).option("--target <packagePath>", "Select a monorepo target package explicitly").option("--yes", "Accept a lightweight confirmation gate automatically", { default: false }).option("--shared", "Write shared Inspecto settings instead of local-only settings").option("--skip-install", "Skip npm dependency installation").option("--dry-run", "Preview changes without modifying files").option("--no-extension", "Skip IDE extension installation").option("--debug", "Enable debug mode to show full error traces", { default: false }).action(async (options) => {
|
|
404
|
+
try {
|
|
405
|
+
await onboard({
|
|
406
|
+
json: options.json ?? false,
|
|
407
|
+
...options.target && { target: options.target },
|
|
408
|
+
yes: options.yes ?? false,
|
|
409
|
+
...options.shared !== void 0 && { shared: options.shared },
|
|
410
|
+
...options.skipInstall !== void 0 && { skipInstall: options.skipInstall },
|
|
411
|
+
...options.dryRun !== void 0 && { dryRun: options.dryRun },
|
|
412
|
+
...options.extension === false && { noExtension: true }
|
|
413
|
+
});
|
|
414
|
+
} catch (error) {
|
|
415
|
+
exitWithError(error, options);
|
|
416
|
+
}
|
|
417
|
+
});
|
|
50
418
|
cli.command("detect", "Detect whether the current project can be onboarded automatically").option("--json", "Print machine-readable JSON output", { default: false }).option("--debug", "Enable debug mode to show full error traces", { default: false }).action(async (options) => {
|
|
51
419
|
try {
|
|
52
420
|
await detect(options.json ?? false);
|
|
@@ -81,10 +449,84 @@ function createCli(argv = process.argv) {
|
|
|
81
449
|
exitWithError(error, options);
|
|
82
450
|
}
|
|
83
451
|
});
|
|
452
|
+
cli.command("integrations [...args]", "Manage assistant integration assets").option(
|
|
453
|
+
"--scope <scope>",
|
|
454
|
+
"Set install scope for supported assistants (e.g. claude-code: project|user)"
|
|
455
|
+
).option(
|
|
456
|
+
"--mode <mode>",
|
|
457
|
+
"Set install mode for supported assistants (e.g. copilot: instructions|agents)"
|
|
458
|
+
).option("--force", "Overwrite existing integration files", { default: false }).option("--debug", "Enable debug mode to show full error traces", { default: false }).action(async (args, options) => {
|
|
459
|
+
try {
|
|
460
|
+
const [subcommand, assistant, ...rest] = args;
|
|
461
|
+
const integrationOptions = buildIntegrationOptions(options);
|
|
462
|
+
if (subcommand === "list") {
|
|
463
|
+
if (assistant || rest.length > 0 || options.scope || options.mode || options.force) {
|
|
464
|
+
throw new Error(
|
|
465
|
+
"The `list` subcommand does not accept assistant names, --scope, --mode, or --force."
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
printIntegrationList();
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
if (subcommand === "path" && assistant) {
|
|
472
|
+
if (rest.length > 0) {
|
|
473
|
+
throw new Error("The `path` subcommand accepts exactly one assistant argument.");
|
|
474
|
+
}
|
|
475
|
+
if (options.force) {
|
|
476
|
+
throw new Error("The `path` subcommand does not support `--force`.");
|
|
477
|
+
}
|
|
478
|
+
printIntegrationPath(assistant, integrationOptions);
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
if (subcommand !== "install" || !assistant) {
|
|
482
|
+
throw new Error(
|
|
483
|
+
[
|
|
484
|
+
"Usage:",
|
|
485
|
+
" inspecto integrations list",
|
|
486
|
+
" inspecto integrations path <assistant> [--scope <scope>] [--mode <mode>]",
|
|
487
|
+
" inspecto integrations install <assistant> [--scope <scope>] [--mode <mode>] [--force]"
|
|
488
|
+
].join("\n")
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
if (rest.length > 0) {
|
|
492
|
+
throw new Error("The `install` subcommand accepts exactly one assistant argument.");
|
|
493
|
+
}
|
|
494
|
+
await installIntegration(assistant, {
|
|
495
|
+
...integrationOptions,
|
|
496
|
+
force: options.force ?? false
|
|
497
|
+
});
|
|
498
|
+
} catch (error) {
|
|
499
|
+
exitWithError(error, options);
|
|
500
|
+
}
|
|
501
|
+
});
|
|
84
502
|
cli.help();
|
|
85
503
|
cli.version(version);
|
|
86
504
|
return cli;
|
|
87
505
|
}
|
|
506
|
+
function buildIntegrationOptions(options) {
|
|
507
|
+
const resolved = {};
|
|
508
|
+
if (options.scope) {
|
|
509
|
+
if (isIntegrationScope(options.scope)) {
|
|
510
|
+
resolved.scope = options.scope;
|
|
511
|
+
} else {
|
|
512
|
+
throw new Error(`Unknown integration scope: ${options.scope}`);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
if (options.mode) {
|
|
516
|
+
if (isIntegrationMode(options.mode)) {
|
|
517
|
+
resolved.mode = options.mode;
|
|
518
|
+
} else {
|
|
519
|
+
throw new Error(`Unknown integration mode: ${options.mode}`);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
return resolved;
|
|
523
|
+
}
|
|
524
|
+
function isIntegrationScope(value) {
|
|
525
|
+
return integrationScopes.includes(value);
|
|
526
|
+
}
|
|
527
|
+
function isIntegrationMode(value) {
|
|
528
|
+
return integrationModes.includes(value);
|
|
529
|
+
}
|
|
88
530
|
async function runCli(argv = process.argv) {
|
|
89
531
|
const cli = createCli(argv);
|
|
90
532
|
const parsedArgv = [...argv];
|
|
@@ -95,7 +537,7 @@ async function runCli(argv = process.argv) {
|
|
|
95
537
|
}
|
|
96
538
|
}
|
|
97
539
|
var entryPath = process.argv[1];
|
|
98
|
-
if (entryPath &&
|
|
540
|
+
if (entryPath && fileURLToPath2(import.meta.url) === entryPath) {
|
|
99
541
|
void runCli();
|
|
100
542
|
}
|
|
101
543
|
export {
|