@inspecto-dev/cli 0.2.0-alpha.0 → 0.2.0-alpha.2

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/dist/index.d.ts CHANGED
@@ -7,9 +7,10 @@ interface InitOptions {
7
7
  shared: boolean;
8
8
  skipInstall: boolean;
9
9
  dryRun: boolean;
10
- prefer?: string;
10
+ provider?: string;
11
11
  noExtension: boolean;
12
12
  packages?: string[];
13
+ force: boolean;
13
14
  }
14
15
  /** A single mutation recorded in install.lock */
15
16
  interface Mutation {
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  doctor,
3
3
  init,
4
4
  teardown
5
- } from "./chunk-4RR7PTRN.js";
5
+ } from "./chunk-V57BJXGZ.js";
6
6
  export {
7
7
  doctor,
8
8
  init,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inspecto-dev/cli",
3
- "version": "0.2.0-alpha.0",
3
+ "version": "0.2.0-alpha.2",
4
4
  "description": "CLI tools for Inspecto onboarding and lifecycle management",
5
5
  "keywords": [
6
6
  "inspecto",
@@ -16,9 +16,10 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "cac": "^6.7.14",
19
+ "magicast": "^0.5.2",
19
20
  "picocolors": "^1.0.0",
20
21
  "prompts": "^2.4.2",
21
- "@inspecto-dev/types": "0.2.0-alpha.0"
22
+ "@inspecto-dev/types": "0.2.0-alpha.2"
22
23
  },
23
24
  "devDependencies": {
24
25
  "@types/node": "^20.0.0",
package/src/bin.ts CHANGED
@@ -3,87 +3,101 @@
3
3
  //
4
4
  // v1 scope: VS Code | React + Vue | Vite + Webpack + Rspack + esbuild + Rollup
5
5
  // ============================================================
6
- import { parseArgs } from 'node:util'
6
+ import { cac, type CAC } from 'cac'
7
+ import { createRequire } from 'node:module'
7
8
  import { init } from './commands/init.js'
8
9
  import { doctor } from './commands/doctor.js'
9
10
  import { teardown } from './commands/teardown.js'
10
11
  import { log } from './utils/logger.js'
11
12
 
12
- const HELP = `
13
- Inspecto CLI (v1)
13
+ const require = createRequire(import.meta.url)
14
+ const { version } = require('../package.json')
14
15
 
15
- Supported: VS Code | React + Vue | Vite + Webpack + Rspack + esbuild + Rollup
16
+ // cac object
17
+ const cli: CAC = cac('inspecto')
16
18
 
17
- Usage:
18
- inspecto init Set up Inspecto in your project
19
- inspecto doctor Diagnose your Inspecto installation
20
- inspecto teardown Remove Inspecto from your project
21
-
22
- Init Options:
23
- --shared Share .inspecto/settings.json with your team via Git
24
- --skip-install Skip npm dependency installation
25
- --dry-run Preview changes without modifying files
26
- --prefer <tool> Set default AI tool (e.g. github-copilot, claude-code)
27
- --no-extension Skip VS Code extension installation
28
- --packages <names> (Monorepo) Comma-separated list of packages to inject
19
+ interface GlobalOptions {
20
+ debug?: boolean
21
+ }
29
22
 
30
- Examples:
31
- npx inspecto init
32
- npx inspecto init --shared --prefer github-copilot
33
- npx inspecto init --dry-run
34
- npx inspecto doctor
35
- npx inspecto teardown
36
- `
23
+ interface InitCommandOptions extends GlobalOptions {
24
+ shared?: boolean
25
+ skipInstall?: boolean
26
+ dryRun?: boolean
27
+ provider?: string
28
+ noExtension?: boolean
29
+ packages?: string
30
+ force?: boolean
31
+ }
37
32
 
38
- async function main() {
39
- const args = process.argv.slice(2)
40
- const command = args[0]
33
+ cli
34
+ .command('init', 'Set up Inspecto in your project')
35
+ .option('--shared', 'Share .inspecto/settings.json with your team via Git', { default: false })
36
+ .option('--skip-install', 'Skip npm dependency installation', { default: false })
37
+ .option('--dry-run', 'Preview changes without modifying files', { default: false })
38
+ .option('--provider <provider>', 'Set default provider (e.g. copilot, claude-code)')
39
+ .option('--no-extension', 'Skip VS Code extension installation', { default: false })
40
+ .option('--packages <names>', '(Monorepo) Comma-separated list of packages to inject')
41
+ .option('--force', 'Force initialization even if environment is unsupported', { default: false })
42
+ .option('--debug', 'Enable debug mode to show full error traces', { default: false })
43
+ .action(async (options: InitCommandOptions) => {
44
+ try {
45
+ await init({
46
+ shared: options.shared ?? false,
47
+ skipInstall: options.skipInstall ?? false,
48
+ dryRun: options.dryRun ?? false,
49
+ ...(options.provider && { provider: options.provider }), // Changed from prefer to provider
50
+ noExtension: options.noExtension ?? false,
51
+ ...(options.packages && {
52
+ packages: options.packages.split(',').map((s: string) => s.trim()),
53
+ }),
54
+ force: options.force ?? false,
55
+ })
56
+ } catch (err) {
57
+ log.error(err instanceof Error ? err.message : String(err))
58
+ if (options.debug && err instanceof Error && err.stack) {
59
+ console.error(err.stack)
60
+ }
61
+ process.exit(1)
62
+ }
63
+ })
41
64
 
42
- if (!command || command === '--help' || command === '-h') {
43
- console.log(HELP)
44
- process.exit(0)
45
- }
65
+ cli
66
+ .command('doctor', 'Diagnose your Inspecto installation')
67
+ .option('--debug', 'Enable debug mode to show full error traces', { default: false })
68
+ .action(async (options: GlobalOptions) => {
69
+ try {
70
+ await doctor()
71
+ } catch (err) {
72
+ log.error(err instanceof Error ? err.message : String(err))
73
+ if (options.debug && err instanceof Error && err.stack) {
74
+ console.error(err.stack)
75
+ }
76
+ process.exit(1)
77
+ }
78
+ })
46
79
 
47
- try {
48
- switch (command) {
49
- case 'init': {
50
- const { values } = parseArgs({
51
- args: args.slice(1),
52
- options: {
53
- shared: { type: 'boolean', default: false },
54
- 'skip-install': { type: 'boolean', default: false },
55
- 'dry-run': { type: 'boolean', default: false },
56
- prefer: { type: 'string' },
57
- 'no-extension': { type: 'boolean', default: false },
58
- packages: { type: 'string' },
59
- },
60
- strict: true,
61
- })
62
- await init({
63
- shared: values.shared ?? false,
64
- skipInstall: values['skip-install'] ?? false,
65
- dryRun: values['dry-run'] ?? false,
66
- ...(values.prefer && { prefer: values.prefer }),
67
- noExtension: values['no-extension'] ?? false,
68
- ...(values.packages && { packages: values.packages.split(',').map(s => s.trim()) }),
69
- })
70
- break
80
+ cli
81
+ .command('teardown', 'Remove Inspecto from your project')
82
+ .option('--debug', 'Enable debug mode to show full error traces', { default: false })
83
+ .action(async (options: GlobalOptions) => {
84
+ try {
85
+ await teardown()
86
+ } catch (err) {
87
+ log.error(err instanceof Error ? err.message : String(err))
88
+ if (options.debug && err instanceof Error && err.stack) {
89
+ console.error(err.stack)
71
90
  }
72
- case 'doctor':
73
- await doctor()
74
- break
75
- case 'teardown':
76
- await teardown()
77
- break
78
- default:
79
- log.error(`Unknown command: ${command}`)
80
- console.log(HELP)
81
- process.exit(1)
91
+ process.exit(1)
82
92
  }
83
- } catch (err) {
84
- log.error(err instanceof Error ? err.message : String(err))
85
- process.exit(1)
86
- }
87
- }
93
+ })
88
94
 
89
- main()
95
+ cli.help()
96
+ cli.version(version)
97
+
98
+ try {
99
+ cli.parse()
100
+ } catch (err) {
101
+ log.error(err instanceof Error ? err.message : String(err))
102
+ process.exit(1)
103
+ }
@@ -8,7 +8,7 @@ import { detectPackageManager, getInstallCommand } from '../detect/package-manag
8
8
  import { detectBuildTools } from '../detect/build-tool.js'
9
9
  import { detectFrameworks } from '../detect/framework.js'
10
10
  import { detectIDE } from '../detect/ide.js'
11
- import { detectAITools } from '../detect/ai-tool.js'
11
+ import { detectProviders } from '../detect/provider.js'
12
12
  import { isExtensionInstalled } from '../inject/extension.js'
13
13
 
14
14
  interface DiagResult {
@@ -29,8 +29,18 @@ export async function doctor(): Promise<void> {
29
29
  return
30
30
  }
31
31
 
32
+ // Run detections concurrently
33
+ const [ideProbe, frameworkResult, providerProbe, pm, buildResult, extInstalled] =
34
+ await Promise.all([
35
+ detectIDE(root),
36
+ detectFrameworks(root),
37
+ detectProviders(root),
38
+ detectPackageManager(root),
39
+ detectBuildTools(root),
40
+ isExtensionInstalled(),
41
+ ])
42
+
32
43
  // Check 2: IDE
33
- const ideProbe = await detectIDE(root)
34
44
  if (ideProbe.detected.length === 0) {
35
45
  log.warn('IDE: not detected')
36
46
  result.warnings++
@@ -46,13 +56,12 @@ export async function doctor(): Promise<void> {
46
56
  )
47
57
  } else {
48
58
  const names = ideProbe.detected.map(d => d.ide).join(', ')
49
- log.warn(`IDE: ${names} (not supported in v1, VS Code only)`)
59
+ log.warn(`IDE: ${names} (not supported in v1, VS Code, Cursor, Trae only)`)
50
60
  result.warnings++
51
61
  }
52
62
  }
53
63
 
54
64
  // Check 3: Supported framework
55
- const frameworkResult = await detectFrameworks(root)
56
65
  if (frameworkResult.supported.length > 0) {
57
66
  log.success(`Framework: ${frameworkResult.supported.join(', ')}`)
58
67
  } else if (frameworkResult.unsupported.length > 0) {
@@ -64,26 +73,25 @@ export async function doctor(): Promise<void> {
64
73
  result.warnings++
65
74
  }
66
75
 
67
- // Check 3.5: AI Tools
68
- const aiProbe = await detectAITools(root)
69
- if (aiProbe.detected.length === 0) {
70
- log.warn('AI Tool: none detected')
76
+ // Check 3.5: Providers
77
+ if (providerProbe.detected.length === 0) {
78
+ log.warn('Provider: none detected')
71
79
  log.hint('Inspecto works best with Claude Code, Trae CLI, or GitHub Copilot')
72
80
  result.warnings++
73
81
  } else {
74
- const aiNames = aiProbe.detected
82
+ const aiNames = providerProbe.detected
75
83
  .map(d => {
76
- const modeLabels = d.toolModes.map(mode =>
77
- mode === 'plugin' ? 'VS Code Extension' : 'Terminal CLI',
84
+ const modeLabels = d.providerModes.map(mode =>
85
+ mode === 'extension' ? 'VS Code Extension' : 'Terminal CLI',
78
86
  )
79
87
  return `${d.label} (${modeLabels.join(' & ')})`
80
88
  })
81
89
  .join(', ')
82
- log.success(`AI Tool: ${aiNames}`)
90
+ log.success(`Provider: ${aiNames}`)
83
91
  }
84
92
 
85
93
  // Check 4: @inspecto-dev/plugin installed
86
- const pluginPath = path.join(root, 'node_modules', '@inspecto', 'plugin')
94
+ const pluginPath = path.join(root, 'node_modules', '@inspecto-dev', 'plugin')
87
95
  if (await exists(pluginPath)) {
88
96
  const pkgJson = await readJSON<{ version?: string }>(path.join(pluginPath, 'package.json'))
89
97
  const version = pkgJson?.version ?? 'unknown'
@@ -96,26 +104,25 @@ export async function doctor(): Promise<void> {
96
104
  }
97
105
 
98
106
  // Check 5: Plugin injected in build config
99
- const buildResult = await detectBuildTools(root)
100
107
  if (buildResult.supported.length > 0) {
101
108
  let injected = false
102
109
  for (const bt of buildResult.supported) {
103
110
  const content = await readFile(path.join(root, bt.configPath))
104
111
  if (content && content.includes('@inspecto-dev/plugin')) {
105
- log.success(`Plugin injected in ${bt.configPath}`)
112
+ log.success(`Plugin configured in ${bt.configPath}`)
106
113
  injected = true
107
114
  break
108
115
  }
109
116
  }
110
117
  if (!injected) {
111
- log.error('Plugin not injected in any build config')
112
- log.hint('Fix: npx inspecto init')
118
+ log.error('Plugin not configured in any build config')
119
+ log.hint('Fix: npx @inspecto-dev/cli init')
113
120
  result.errors++
114
121
  }
115
122
  } else if (buildResult.unsupported.length > 0) {
116
123
  const names = buildResult.unsupported.join(', ')
117
124
  log.warn(`Build tool: ${names} (not supported in v1)`)
118
- log.hint('v1 supports: Vite, Webpack, Rspack, esbuild, Rollup')
125
+ log.hint('current version supports: Vite, Webpack, Rspack, esbuild, Rollup')
119
126
  result.warnings++
120
127
  } else {
121
128
  log.warn('No recognized build config found')
@@ -123,7 +130,6 @@ export async function doctor(): Promise<void> {
123
130
  }
124
131
 
125
132
  // Check 6: VS Code extension
126
- const extInstalled = await isExtensionInstalled()
127
133
  if (extInstalled) {
128
134
  log.success('VS Code extension detected')
129
135
  } else {
@@ -138,22 +144,29 @@ export async function doctor(): Promise<void> {
138
144
  }
139
145
  }
140
146
 
141
- // Check 7: settings.json
142
- const settingsPath = path.join(root, '.inspecto', 'settings.json')
143
- if (await exists(settingsPath)) {
144
- const settings = await readJSON(settingsPath)
147
+ // Check 7: settings
148
+ const settingsJsonPath = path.join(root, '.inspecto', 'settings.json')
149
+ const settingsLocalPath = path.join(root, '.inspecto', 'settings.local.json')
150
+
151
+ const hasSettingsJson = await exists(settingsJsonPath)
152
+ const hasSettingsLocal = await exists(settingsLocalPath)
153
+
154
+ if (hasSettingsJson || hasSettingsLocal) {
155
+ const targetPath = hasSettingsLocal ? settingsLocalPath : settingsJsonPath
156
+ const fileName = hasSettingsLocal ? 'settings.local.json' : 'settings.json'
157
+ const settings = await readJSON(targetPath)
145
158
  if (settings) {
146
- log.success('.inspecto/settings.json valid')
159
+ log.success(`.inspecto/${fileName} valid`)
147
160
  } else {
148
- log.error('.inspecto/settings.json has invalid JSON')
161
+ log.error(`.inspecto/${fileName} has invalid JSON`)
149
162
  log.hint(
150
- 'Fix: Manually correct the syntax errors, or delete the file and re-run npx inspecto init',
163
+ 'Fix: Manually correct the syntax errors, or delete the file and re-run npx @inspecto-dev/cli init',
151
164
  )
152
165
  result.errors++
153
166
  }
154
167
  } else {
155
- log.warn('.inspecto/settings.json not found (using defaults)')
156
- log.hint('Optional: npx inspecto init')
168
+ log.warn('No .inspecto/settings.json or settings.local.json found (using defaults)')
169
+ log.hint('Optional: npx @inspecto-dev/cli init')
157
170
  result.warnings++
158
171
  }
159
172