@intutic/cli 2.2.0 → 2.4.0
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 +8 -8
- package/dist/cli.d.ts +0 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +582 -21
- package/dist/cli.js.map +1 -1
- package/dist/commands/apiCommand.d.ts +40 -0
- package/dist/commands/apiCommand.d.ts.map +1 -0
- package/dist/commands/apiCommand.js +88 -0
- package/dist/commands/apiCommand.js.map +1 -0
- package/dist/commands/budget.d.ts +4 -0
- package/dist/commands/budget.d.ts.map +1 -1
- package/dist/commands/budget.js +8 -0
- package/dist/commands/budget.js.map +1 -1
- package/dist/commands/budgetLimits.d.ts +70 -0
- package/dist/commands/budgetLimits.d.ts.map +1 -0
- package/dist/commands/budgetLimits.js +223 -0
- package/dist/commands/budgetLimits.js.map +1 -0
- package/dist/commands/compliance.d.ts +122 -0
- package/dist/commands/compliance.d.ts.map +1 -0
- package/dist/commands/compliance.js +278 -0
- package/dist/commands/compliance.js.map +1 -0
- package/dist/commands/connect.d.ts +26 -1
- package/dist/commands/connect.d.ts.map +1 -1
- package/dist/commands/connect.js +109 -51
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/credentials.d.ts +6 -2
- package/dist/commands/credentials.d.ts.map +1 -1
- package/dist/commands/credentials.js +99 -10
- package/dist/commands/credentials.js.map +1 -1
- package/dist/commands/decision.d.ts +4 -4
- package/dist/commands/decision.js +4 -4
- package/dist/commands/disconnect.d.ts +4 -0
- package/dist/commands/disconnect.d.ts.map +1 -1
- package/dist/commands/disconnect.js +17 -3
- package/dist/commands/disconnect.js.map +1 -1
- package/dist/commands/doctor.d.ts +0 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +0 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/enforce.d.ts +1 -1
- package/dist/commands/enforce.js +1 -1
- package/dist/commands/enterprise.d.ts +3 -2
- package/dist/commands/enterprise.d.ts.map +1 -1
- package/dist/commands/enterprise.js +11 -3
- package/dist/commands/enterprise.js.map +1 -1
- package/dist/commands/env.js +1 -1
- package/dist/commands/exec.d.ts +2 -3
- package/dist/commands/exec.d.ts.map +1 -1
- package/dist/commands/exec.js +4 -5
- package/dist/commands/exec.js.map +1 -1
- package/dist/commands/gateLiveness.d.ts +15 -0
- package/dist/commands/gateLiveness.d.ts.map +1 -0
- package/dist/commands/gateLiveness.js +34 -0
- package/dist/commands/gateLiveness.js.map +1 -0
- package/dist/commands/gateway.d.ts +14 -4
- package/dist/commands/gateway.d.ts.map +1 -1
- package/dist/commands/gateway.js +34 -4
- package/dist/commands/gateway.js.map +1 -1
- package/dist/commands/github.d.ts +20 -0
- package/dist/commands/github.d.ts.map +1 -0
- package/dist/commands/github.js +41 -0
- package/dist/commands/github.js.map +1 -0
- package/dist/commands/guardrails.d.ts +28 -2
- package/dist/commands/guardrails.d.ts.map +1 -1
- package/dist/commands/guardrails.js +233 -24
- package/dist/commands/guardrails.js.map +1 -1
- package/dist/commands/incidents.d.ts +32 -0
- package/dist/commands/incidents.d.ts.map +1 -0
- package/dist/commands/incidents.js +94 -0
- package/dist/commands/incidents.js.map +1 -0
- package/dist/commands/init.d.ts +1 -2
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +1 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install-daemon.d.ts +1 -1
- package/dist/commands/install-daemon.js +2 -2
- package/dist/commands/integrity.d.ts +10 -2
- package/dist/commands/integrity.d.ts.map +1 -1
- package/dist/commands/integrity.js +3 -3
- package/dist/commands/integrity.js.map +1 -1
- package/dist/commands/inventory.d.ts +60 -0
- package/dist/commands/inventory.d.ts.map +1 -0
- package/dist/commands/inventory.js +141 -0
- package/dist/commands/inventory.js.map +1 -0
- package/dist/commands/judge.d.ts +1 -1
- package/dist/commands/judge.js +2 -2
- package/dist/commands/judge.js.map +1 -1
- package/dist/commands/login.d.ts +0 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +0 -1
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.d.ts +0 -1
- package/dist/commands/logout.d.ts.map +1 -1
- package/dist/commands/logout.js +0 -1
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/mcp.d.ts +31 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +65 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/notifications.d.ts +54 -0
- package/dist/commands/notifications.d.ts.map +1 -0
- package/dist/commands/notifications.js +151 -0
- package/dist/commands/notifications.js.map +1 -0
- package/dist/commands/org.d.ts +3 -3
- package/dist/commands/org.js +3 -3
- package/dist/commands/policy.d.ts +6 -1
- package/dist/commands/policy.d.ts.map +1 -1
- package/dist/commands/policy.js +77 -37
- package/dist/commands/policy.js.map +1 -1
- package/dist/commands/rollback.d.ts.map +1 -1
- package/dist/commands/rollback.js +3 -1
- package/dist/commands/rollback.js.map +1 -1
- package/dist/commands/routing.d.ts +1 -1
- package/dist/commands/routing.js +1 -1
- package/dist/commands/rules.d.ts +74 -0
- package/dist/commands/rules.d.ts.map +1 -0
- package/dist/commands/rules.js +283 -0
- package/dist/commands/rules.js.map +1 -0
- package/dist/commands/settings.d.ts +44 -0
- package/dist/commands/settings.d.ts.map +1 -0
- package/dist/commands/settings.js +110 -0
- package/dist/commands/settings.js.map +1 -0
- package/dist/commands/setup.d.ts +1 -1
- package/dist/commands/setup.js +1 -1
- package/dist/commands/siem.d.ts +53 -0
- package/dist/commands/siem.d.ts.map +1 -0
- package/dist/commands/siem.js +132 -0
- package/dist/commands/siem.js.map +1 -0
- package/dist/commands/skill.d.ts +5 -5
- package/dist/commands/skill.js +7 -7
- package/dist/commands/skill.js.map +1 -1
- package/dist/commands/status.d.ts +0 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +2 -3
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/syncContext.d.ts +0 -1
- package/dist/commands/syncContext.d.ts.map +1 -1
- package/dist/commands/syncContext.js +0 -1
- package/dist/commands/syncContext.js.map +1 -1
- package/dist/commands/team.d.ts +2 -2
- package/dist/commands/team.js +2 -2
- package/dist/commands/traces.d.ts +0 -3
- package/dist/commands/traces.d.ts.map +1 -1
- package/dist/commands/traces.js +0 -3
- package/dist/commands/traces.js.map +1 -1
- package/dist/commands/usage.d.ts +41 -0
- package/dist/commands/usage.d.ts.map +1 -0
- package/dist/commands/usage.js +129 -0
- package/dist/commands/usage.js.map +1 -0
- package/dist/commands/whoami.d.ts +0 -1
- package/dist/commands/whoami.d.ts.map +1 -1
- package/dist/commands/whoami.js +0 -1
- package/dist/commands/whoami.js.map +1 -1
- package/dist/config/keychain.d.ts +0 -1
- package/dist/config/keychain.d.ts.map +1 -1
- package/dist/config/keychain.js +0 -1
- package/dist/config/keychain.js.map +1 -1
- package/dist/config/paths.d.ts +0 -1
- package/dist/config/paths.d.ts.map +1 -1
- package/dist/config/paths.js +0 -1
- package/dist/config/paths.js.map +1 -1
- package/dist/config/store.d.ts +0 -1
- package/dist/config/store.d.ts.map +1 -1
- package/dist/config/store.js +0 -1
- package/dist/config/store.js.map +1 -1
- package/dist/harness/ag2.d.ts +1 -1
- package/dist/harness/ag2.js +1 -1
- package/dist/harness/agentFramework.d.ts +1 -1
- package/dist/harness/agentFramework.js +1 -1
- package/dist/harness/agenticOrchestrator.d.ts +1 -1
- package/dist/harness/agenticOrchestrator.js +2 -2
- package/dist/harness/agenticOrchestrator.js.map +1 -1
- package/dist/harness/agentsMd.d.ts +24 -0
- package/dist/harness/agentsMd.d.ts.map +1 -0
- package/dist/harness/agentsMd.js +28 -0
- package/dist/harness/agentsMd.js.map +1 -0
- package/dist/harness/aider.d.ts +3 -1
- package/dist/harness/aider.d.ts.map +1 -1
- package/dist/harness/aider.js +9 -7
- package/dist/harness/aider.js.map +1 -1
- package/dist/harness/antigravity.d.ts +23 -5
- package/dist/harness/antigravity.d.ts.map +1 -1
- package/dist/harness/antigravity.js +45 -55
- package/dist/harness/antigravity.js.map +1 -1
- package/dist/harness/autogen.d.ts +1 -1
- package/dist/harness/autogen.js +2 -2
- package/dist/harness/autogen.js.map +1 -1
- package/dist/harness/claudeCode.d.ts +22 -1
- package/dist/harness/claudeCode.d.ts.map +1 -1
- package/dist/harness/claudeCode.js +47 -3
- package/dist/harness/claudeCode.js.map +1 -1
- package/dist/harness/cline.d.ts.map +1 -1
- package/dist/harness/cline.js +14 -23
- package/dist/harness/cline.js.map +1 -1
- package/dist/harness/codex.d.ts +6 -1
- package/dist/harness/codex.d.ts.map +1 -1
- package/dist/harness/codex.js +23 -21
- package/dist/harness/codex.js.map +1 -1
- package/dist/harness/continue.d.ts +10 -4
- package/dist/harness/continue.d.ts.map +1 -1
- package/dist/harness/continue.js +22 -22
- package/dist/harness/continue.js.map +1 -1
- package/dist/harness/cursor.d.ts +5 -2
- package/dist/harness/cursor.d.ts.map +1 -1
- package/dist/harness/cursor.js +19 -23
- package/dist/harness/cursor.js.map +1 -1
- package/dist/harness/detector.d.ts +0 -1
- package/dist/harness/detector.d.ts.map +1 -1
- package/dist/harness/detector.js +0 -1
- package/dist/harness/detector.js.map +1 -1
- package/dist/harness/dsh.d.ts +5 -3
- package/dist/harness/dsh.d.ts.map +1 -1
- package/dist/harness/dsh.js +17 -29
- package/dist/harness/dsh.js.map +1 -1
- package/dist/harness/eve.d.ts +3 -4
- package/dist/harness/eve.d.ts.map +1 -1
- package/dist/harness/eve.js +3 -4
- package/dist/harness/eve.js.map +1 -1
- package/dist/harness/githubCopilot.d.ts +4 -1
- package/dist/harness/githubCopilot.d.ts.map +1 -1
- package/dist/harness/githubCopilot.js +12 -20
- package/dist/harness/githubCopilot.js.map +1 -1
- package/dist/harness/goose.d.ts +7 -3
- package/dist/harness/goose.d.ts.map +1 -1
- package/dist/harness/goose.js +18 -21
- package/dist/harness/goose.js.map +1 -1
- package/dist/harness/grok.d.ts +2 -2
- package/dist/harness/grok.d.ts.map +1 -1
- package/dist/harness/grok.js +13 -24
- package/dist/harness/grok.js.map +1 -1
- package/dist/harness/hermes.d.ts +6 -0
- package/dist/harness/hermes.d.ts.map +1 -1
- package/dist/harness/hermes.js +17 -16
- package/dist/harness/hermes.js.map +1 -1
- package/dist/harness/muse.d.ts +3 -7
- package/dist/harness/muse.d.ts.map +1 -1
- package/dist/harness/muse.js +15 -35
- package/dist/harness/muse.js.map +1 -1
- package/dist/harness/n8n.d.ts +13 -14
- package/dist/harness/n8n.d.ts.map +1 -1
- package/dist/harness/n8n.js +21 -181
- package/dist/harness/n8n.js.map +1 -1
- package/dist/harness/openWebUI.d.ts.map +1 -1
- package/dist/harness/openWebUI.js +5 -4
- package/dist/harness/openWebUI.js.map +1 -1
- package/dist/harness/openaiAgents.d.ts +1 -1
- package/dist/harness/openaiAgents.js +2 -2
- package/dist/harness/openaiAgents.js.map +1 -1
- package/dist/harness/openclaw.d.ts +8 -0
- package/dist/harness/openclaw.d.ts.map +1 -1
- package/dist/harness/openclaw.js +27 -12
- package/dist/harness/openclaw.js.map +1 -1
- package/dist/harness/opencode.d.ts +4 -5
- package/dist/harness/opencode.d.ts.map +1 -1
- package/dist/harness/opencode.js +15 -30
- package/dist/harness/opencode.js.map +1 -1
- package/dist/harness/openhands.d.ts +9 -3
- package/dist/harness/openhands.d.ts.map +1 -1
- package/dist/harness/openhands.js +30 -24
- package/dist/harness/openhands.js.map +1 -1
- package/dist/harness/pi.d.ts +7 -2
- package/dist/harness/pi.d.ts.map +1 -1
- package/dist/harness/pi.js +19 -18
- package/dist/harness/pi.js.map +1 -1
- package/dist/harness/rooCode.d.ts +12 -5
- package/dist/harness/rooCode.d.ts.map +1 -1
- package/dist/harness/rooCode.js +23 -39
- package/dist/harness/rooCode.js.map +1 -1
- package/dist/harness/rulesFiles.d.ts +53 -0
- package/dist/harness/rulesFiles.d.ts.map +1 -0
- package/dist/harness/rulesFiles.js +106 -0
- package/dist/harness/rulesFiles.js.map +1 -0
- package/dist/harness/smolagents.d.ts +2 -2
- package/dist/harness/smolagents.js +3 -3
- package/dist/harness/smolagents.js.map +1 -1
- package/dist/harness/types.d.ts +20 -6
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js +1 -95
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/windsurf.d.ts +6 -1
- package/dist/harness/windsurf.d.ts.map +1 -1
- package/dist/harness/windsurf.js +21 -24
- package/dist/harness/windsurf.js.map +1 -1
- package/dist/harness/xirp.d.ts +1 -2
- package/dist/harness/xirp.d.ts.map +1 -1
- package/dist/harness/xirp.js +2 -3
- package/dist/harness/xirp.js.map +1 -1
- package/dist/lib/api.d.ts +27 -1
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +55 -18
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/ciscoScanner.d.ts +1 -1
- package/dist/lib/ciscoScanner.js +1 -1
- package/dist/lib/decisionsLogRefresh.d.ts.map +1 -1
- package/dist/lib/decisionsLogRefresh.js +6 -7
- package/dist/lib/decisionsLogRefresh.js.map +1 -1
- package/dist/lib/deviceReport.d.ts +15 -0
- package/dist/lib/deviceReport.d.ts.map +1 -1
- package/dist/lib/deviceReport.js +30 -0
- package/dist/lib/deviceReport.js.map +1 -1
- package/dist/lib/gitHooks.d.ts +0 -1
- package/dist/lib/gitHooks.d.ts.map +1 -1
- package/dist/lib/gitHooks.js +8 -9
- package/dist/lib/gitHooks.js.map +1 -1
- package/dist/lib/gracefulShutdown.d.ts +1 -1
- package/dist/lib/gracefulShutdown.js +1 -1
- package/dist/lib/hash.d.ts +0 -1
- package/dist/lib/hash.d.ts.map +1 -1
- package/dist/lib/hash.js +0 -1
- package/dist/lib/hash.js.map +1 -1
- package/dist/lib/inventory.d.ts +47 -0
- package/dist/lib/inventory.d.ts.map +1 -0
- package/dist/lib/inventory.js +106 -0
- package/dist/lib/inventory.js.map +1 -0
- package/dist/lib/logger.d.ts +0 -1
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +0 -1
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/mdmManifest.d.ts +30 -2
- package/dist/lib/mdmManifest.d.ts.map +1 -1
- package/dist/lib/mdmManifest.js +50 -2
- package/dist/lib/mdmManifest.js.map +1 -1
- package/dist/lib/onboarding.d.ts +0 -1
- package/dist/lib/onboarding.d.ts.map +1 -1
- package/dist/lib/onboarding.js +1 -2
- package/dist/lib/onboarding.js.map +1 -1
- package/dist/lib/policySnapshot.d.ts +3 -2
- package/dist/lib/policySnapshot.d.ts.map +1 -1
- package/dist/lib/policySnapshot.js +6 -3
- package/dist/lib/policySnapshot.js.map +1 -1
- package/dist/lib/process.d.ts +5 -1
- package/dist/lib/process.d.ts.map +1 -1
- package/dist/lib/process.js +13 -4
- package/dist/lib/process.js.map +1 -1
- package/dist/lib/providerProbe.d.ts +3 -3
- package/dist/lib/providerProbe.d.ts.map +1 -1
- package/dist/lib/providerProbe.js +15 -7
- package/dist/lib/providerProbe.js.map +1 -1
- package/dist/lib/sandbox/firecracker.d.ts +3 -3
- package/dist/lib/sandbox/firecracker.js +3 -3
- package/dist/lib/sandbox/index.d.ts +2 -2
- package/dist/lib/sandbox/index.js +2 -2
- package/dist/lib/sandbox/oci.d.ts +1 -1
- package/dist/lib/sandbox/oci.js +1 -1
- package/dist/lib/sandbox/types.d.ts +1 -1
- package/dist/lib/sandbox/types.js +1 -1
- package/dist/lib/sopFrontMatter.d.ts +1 -1
- package/dist/lib/sopFrontMatter.js +1 -1
- package/package.json +6 -5
- package/resources/sandbox/Dockerfile +1 -1
- package/resources/sandbox/entrypoint.sh +4 -4
- package/resources/sandbox/firecracker-launch.sh +1 -1
- package/dist/harness/base.d.ts +0 -24
- package/dist/harness/base.d.ts.map +0 -1
- package/dist/harness/base.js +0 -74
- package/dist/harness/base.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* AI governance control plane for developer workspaces.
|
|
6
6
|
* Provides harness detection, config sync, and workspace management.
|
|
7
7
|
*
|
|
8
|
-
* LLD #8 — Sync Daemon / CLI
|
|
9
8
|
* HLD §3.14 — Real-Time State Mirroring
|
|
10
9
|
*
|
|
11
10
|
* @module
|
|
@@ -41,7 +40,7 @@ program
|
|
|
41
40
|
const { runInit } = await import('./commands/init.js');
|
|
42
41
|
await runInit(opts);
|
|
43
42
|
});
|
|
44
|
-
// ── Cohort setup wizard
|
|
43
|
+
// ── Cohort setup wizard ──────────────────────────────────────────────────
|
|
45
44
|
program
|
|
46
45
|
.command('setup')
|
|
47
46
|
.description('Guided setup: detect harnesses, configure a provider credential, and verify it')
|
|
@@ -111,9 +110,9 @@ program
|
|
|
111
110
|
const { runRollback } = await import('./commands/rollback.js');
|
|
112
111
|
await runRollback(opts);
|
|
113
112
|
});
|
|
114
|
-
program
|
|
113
|
+
const budgetCmd = program
|
|
115
114
|
.command('budget')
|
|
116
|
-
.description('Check remaining daily/monthly budget and list active loops')
|
|
115
|
+
.description('Check remaining daily/monthly budget and list active loops; set workspace, key and member budgets')
|
|
117
116
|
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
118
117
|
.option('--watch', 'Continuously print machine-local and workspace spend, one line per tick')
|
|
119
118
|
.option('--interval <seconds>', 'Tick interval in seconds for --watch', String(5))
|
|
@@ -126,6 +125,68 @@ program
|
|
|
126
125
|
const { runBudget } = await import('./commands/budget.js');
|
|
127
126
|
await runBudget(opts);
|
|
128
127
|
});
|
|
128
|
+
budgetCmd
|
|
129
|
+
.command('set')
|
|
130
|
+
.description("Set the workspace's daily and monthly caps, alert threshold and whether each cap refuses requests (OWNER, ADMIN)")
|
|
131
|
+
.option('--daily <usd>', 'Daily cap in USD (0: no daily cap; default: back to the $100 default)')
|
|
132
|
+
.option('--monthly <usd>', 'Monthly cap in USD (0: no monthly cap; default: back to the $500 default)')
|
|
133
|
+
.option('--threshold <pct>', 'Alert at this percentage of each cap')
|
|
134
|
+
.option('--daily-enforcement <mode>', 'hard (refuse what the day does not cover) or soft (alert only)')
|
|
135
|
+
.option('--monthly-enforcement <mode>', 'hard (refuse what the month does not cover) or soft (alert only)')
|
|
136
|
+
.option('--json', 'Output as JSON')
|
|
137
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
138
|
+
.action(async (_opts, cmd) => {
|
|
139
|
+
// optsWithGlobals: `budget` declares --dev too, and Commander gives a
|
|
140
|
+
// parent's option to the parent wherever it appears on the line.
|
|
141
|
+
const { runBudgetSet } = await import('./commands/budgetLimits.js');
|
|
142
|
+
await runBudgetSet(cmd.optsWithGlobals());
|
|
143
|
+
});
|
|
144
|
+
budgetCmd
|
|
145
|
+
.command('keys')
|
|
146
|
+
.description("Every virtual key's spend budgets, rate limit and spend today and this month")
|
|
147
|
+
.option('--json', 'Output as JSON')
|
|
148
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
149
|
+
.action(async (_opts, cmd) => {
|
|
150
|
+
const { runBudgetKeys } = await import('./commands/budgetLimits.js');
|
|
151
|
+
await runBudgetKeys(cmd.optsWithGlobals());
|
|
152
|
+
});
|
|
153
|
+
budgetCmd
|
|
154
|
+
.command('key <keyId>')
|
|
155
|
+
.description("Set a virtual key's spend budgets and rate limit (OWNER, ADMIN)")
|
|
156
|
+
.option('--daily <usd>', 'Day budget in USD, or none to remove it')
|
|
157
|
+
.option('--monthly <usd>', 'Month budget in USD, or none to remove it')
|
|
158
|
+
.option('--daily-enforcement <mode>', 'hard (refuse) or soft (alert only) for the day budget')
|
|
159
|
+
.option('--monthly-enforcement <mode>', 'hard (refuse) or soft (alert only) for the month budget')
|
|
160
|
+
.option('--rpm <n>', 'Requests per minute, or none to remove the limit')
|
|
161
|
+
.option('--tpm <n>', 'Tokens per minute, or none to remove the limit')
|
|
162
|
+
.option('--json', 'Output as JSON')
|
|
163
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
164
|
+
.action(async (keyId, _opts, cmd) => {
|
|
165
|
+
const { runBudgetKey } = await import('./commands/budgetLimits.js');
|
|
166
|
+
await runBudgetKey(keyId, cmd.optsWithGlobals());
|
|
167
|
+
});
|
|
168
|
+
budgetCmd
|
|
169
|
+
.command('members')
|
|
170
|
+
.description("The default member budget, and each member's budgets and spend (Biz Org+)")
|
|
171
|
+
.option('--json', 'Output as JSON')
|
|
172
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
173
|
+
.action(async (_opts, cmd) => {
|
|
174
|
+
const { runBudgetMembers } = await import('./commands/budgetLimits.js');
|
|
175
|
+
await runBudgetMembers(cmd.optsWithGlobals());
|
|
176
|
+
});
|
|
177
|
+
budgetCmd
|
|
178
|
+
.command('member <memberId>')
|
|
179
|
+
.description("Set a member's spend budgets, or the default member budget with `default` (OWNER, ADMIN; Biz Org+)")
|
|
180
|
+
.option('--daily <usd>', 'Day budget in USD, or none to remove it')
|
|
181
|
+
.option('--monthly <usd>', 'Month budget in USD, or none to remove it')
|
|
182
|
+
.option('--daily-enforcement <mode>', 'hard (refuse) or soft (alert only) for the day budget')
|
|
183
|
+
.option('--monthly-enforcement <mode>', 'hard (refuse) or soft (alert only) for the month budget')
|
|
184
|
+
.option('--json', 'Output as JSON')
|
|
185
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
186
|
+
.action(async (memberId, _opts, cmd) => {
|
|
187
|
+
const { runBudgetMember } = await import('./commands/budgetLimits.js');
|
|
188
|
+
await runBudgetMember(memberId, cmd.optsWithGlobals());
|
|
189
|
+
});
|
|
129
190
|
program
|
|
130
191
|
.command('predict-cost')
|
|
131
192
|
.description('Pre-flight cost estimate for a prompt/task before it runs (requires `intutic login`). ' +
|
|
@@ -257,7 +318,7 @@ policyCmd
|
|
|
257
318
|
});
|
|
258
319
|
policyCmd
|
|
259
320
|
.command('install')
|
|
260
|
-
.description('Validate and install a compiled WASM rule into the local proxy rules dir')
|
|
321
|
+
.description('Validate and install a compiled WASM rule (native or Rego) into the local proxy rules dir')
|
|
261
322
|
.requiredOption('--wasm <path>', 'Path to compiled WASM rule binary')
|
|
262
323
|
.option('--name <name>', 'Rule name (defaults to the file name)')
|
|
263
324
|
.option('--priority <NN>', 'Evaluation priority — lower runs first', '100')
|
|
@@ -283,7 +344,39 @@ policyCmd
|
|
|
283
344
|
const { runPolicyReplay } = await import('./commands/policy.js');
|
|
284
345
|
await runPolicyReplay(ruleId, opts);
|
|
285
346
|
});
|
|
286
|
-
//
|
|
347
|
+
// Rego policies as rules: compiled with OPA and packaged with the metadata
|
|
348
|
+
// the proxies read (`intutic rules build`), tested through the same host
|
|
349
|
+
// (`intutic rules test`). Installing and uploading are the same as for any rule.
|
|
350
|
+
const rulesCmd = program
|
|
351
|
+
.command('rules')
|
|
352
|
+
.description('Build and test Rego policies as Intutic rules');
|
|
353
|
+
rulesCmd
|
|
354
|
+
.command('build')
|
|
355
|
+
.description('Compile Rego to a rule with OPA (opa build -t wasm) and package it with its entrypoint and risk tier.\n' +
|
|
356
|
+
'\n' +
|
|
357
|
+
' Needs the opa binary on the PATH, or INTUTIC_OPA_BIN. Refuses a policy that\n' +
|
|
358
|
+
' needs a builtin Intutic does not provide, naming it.')
|
|
359
|
+
.requiredOption('--rego <path>', 'Rego file or directory')
|
|
360
|
+
.requiredOption('--entrypoint <package/rule>', 'The rule to evaluate, e.g. intutic/shell/deny')
|
|
361
|
+
.option('--risk-tier <tier>', 'Default risk tier for its decisions: low | medium | high | critical')
|
|
362
|
+
.option('--out <path>', 'Output .wasm path (default: build/<entrypoint>.wasm)')
|
|
363
|
+
.action(async (opts) => {
|
|
364
|
+
const { runRulesBuild } = await import('./commands/rules.js');
|
|
365
|
+
await runRulesBuild(opts);
|
|
366
|
+
});
|
|
367
|
+
rulesCmd
|
|
368
|
+
.command('test <module>')
|
|
369
|
+
.description('Evaluate a Rego rule against sample inputs locally, through the same host the proxies use.\n' +
|
|
370
|
+
'\n' +
|
|
371
|
+
' Each --input file holds one input document, or an array of\n' +
|
|
372
|
+
' {"name", "input", "expect": "allow|deny|hold|reask"} cases. Exits 1 when a\n' +
|
|
373
|
+
' case gets a decision other than the one it expects.')
|
|
374
|
+
.requiredOption('--input <file...>', 'JSON file(s) of inputs or cases')
|
|
375
|
+
.action(async (module, opts) => {
|
|
376
|
+
const { runRulesTest } = await import('./commands/rules.js');
|
|
377
|
+
await runRulesTest(module, opts);
|
|
378
|
+
});
|
|
379
|
+
// Policy Clause Ledger. `intutic policy` is the WASM loop and
|
|
287
380
|
// `intutic sops` is files on disk; this namespace is the cited guardrails
|
|
288
381
|
// extracted from policy documents and their shadow -> promote lifecycle.
|
|
289
382
|
const guardrailsCmd = program
|
|
@@ -369,6 +462,7 @@ guardrailsCmd
|
|
|
369
462
|
.description('List guardrails with their status and shadow evidence')
|
|
370
463
|
.option('--status <status>', 'PROPOSED | SHADOW | ENFORCING | REJECTED | RETIRED')
|
|
371
464
|
.option('--target <target>', 'hook_rule | sop_front_matter | wasm_rule | workspace_setting')
|
|
465
|
+
.option('--provenance <provenance>', 'extracted | authored')
|
|
372
466
|
.option('--doc <docId>', 'Only guardrails cited from this document')
|
|
373
467
|
.option('--limit <n>', 'Max rows (default 50, capped at 200)')
|
|
374
468
|
.option('--json', 'Output as JSON')
|
|
@@ -386,6 +480,51 @@ guardrailsCmd
|
|
|
386
480
|
const { runGuardrailsShow } = await import('./commands/guardrails.js');
|
|
387
481
|
await runGuardrailsShow(guardrailId, opts);
|
|
388
482
|
});
|
|
483
|
+
/** The IR flags `guardrails create` and `guardrails update` share; a file (`--file`) is the alternative. */
|
|
484
|
+
function guardrailIrOptions(cmd) {
|
|
485
|
+
return cmd
|
|
486
|
+
.option('--file <path>', 'YAML or JSON: a bare IR, or { name, description, ir }')
|
|
487
|
+
.option('--name <name>', 'One-line label (at most 80 characters)')
|
|
488
|
+
.option('--description <text>', 'What the rule is for; shown where an extracted guardrail shows its quote')
|
|
489
|
+
.option('--kind <kind>', 'hook_rule | deny_tools | review_before | requires_before | forbid_after | max_calls | forbid_with | wasm_predicate | allowed_models | egress_allow')
|
|
490
|
+
.option('--title <title>', 'hook_rule, wasm_predicate: the title in the block message')
|
|
491
|
+
.option('--tools <list>', 'hook_rule, deny_tools: comma-separated tool names')
|
|
492
|
+
.option('--tokens <list>', 'review_before: comma-separated tool or action tokens')
|
|
493
|
+
.option('--arg-contains <literal>', 'hook_rule: fire only when the input contains this (repeatable)', (v, prev = []) => [...prev, v])
|
|
494
|
+
.option('--arg-not-contains <literal>', 'hook_rule: fire only when the input does not contain this (repeatable)', (v, prev = []) => [...prev, v])
|
|
495
|
+
.option('--first <token>', 'requires_before, forbid_after: the first token')
|
|
496
|
+
.option('--then <token>', 'requires_before, forbid_after: the second token')
|
|
497
|
+
.option('--token <token>', 'max_calls, forbid_with: the token')
|
|
498
|
+
.option('--limit <n>', 'max_calls: the most calls allowed')
|
|
499
|
+
.option('--taint <taint>', 'forbid_with: secrets() | pii()')
|
|
500
|
+
.option('--roles <list>', 'Comma-separated roles the rule applies to (default: everyone)')
|
|
501
|
+
.option('--models <list>', 'allowed_models: comma-separated model ids')
|
|
502
|
+
.option('--hosts <list>', 'egress_allow: comma-separated hosts, suffixes or IPv4 CIDRs')
|
|
503
|
+
.option('--rationale <text>', 'wasm_predicate: why it re-asks')
|
|
504
|
+
.option('--predicate <json>', 'wasm_predicate: the predicate as JSON')
|
|
505
|
+
.option('--json', 'Output as JSON')
|
|
506
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)');
|
|
507
|
+
}
|
|
508
|
+
guardrailIrOptions(guardrailsCmd.command('create').description('Author a guardrail directly: the same IR and checks as an extracted one, created PROPOSED')).action(async (opts) => {
|
|
509
|
+
const { runGuardrailsCreate } = await import('./commands/guardrails.js');
|
|
510
|
+
await runGuardrailsCreate(opts);
|
|
511
|
+
});
|
|
512
|
+
guardrailIrOptions(guardrailsCmd
|
|
513
|
+
.command('update <guardrailId>')
|
|
514
|
+
.description('Edit an authored guardrail: a name or description in place; a changed IR creates the next version, PROPOSED with no evidence')
|
|
515
|
+
.option('--clear-description', 'Remove the description')).action(async (guardrailId, opts) => {
|
|
516
|
+
const { runGuardrailsUpdate } = await import('./commands/guardrails.js');
|
|
517
|
+
await runGuardrailsUpdate(guardrailId, opts);
|
|
518
|
+
});
|
|
519
|
+
guardrailsCmd
|
|
520
|
+
.command('delete <guardrailId>')
|
|
521
|
+
.description('Retire an authored guardrail and undo what it wrote; its history is kept')
|
|
522
|
+
.option('--json', 'Output as JSON')
|
|
523
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
524
|
+
.action(async (guardrailId, opts) => {
|
|
525
|
+
const { runGuardrailsDelete } = await import('./commands/guardrails.js');
|
|
526
|
+
await runGuardrailsDelete(guardrailId, opts);
|
|
527
|
+
});
|
|
389
528
|
guardrailsCmd
|
|
390
529
|
.command('approve-shadow <guardrailId>')
|
|
391
530
|
.description('Ship a proposed guardrail in shadow: it reports, never blocks')
|
|
@@ -501,7 +640,7 @@ program
|
|
|
501
640
|
const { runStart } = await import('./commands/start.js');
|
|
502
641
|
await runStart(opts);
|
|
503
642
|
});
|
|
504
|
-
// L2 mandatory egress firewall
|
|
643
|
+
// L2 mandatory egress firewall. Makes the governing proxy
|
|
505
644
|
// non-optional: default-deny host egress to everything except the proxy, DNS,
|
|
506
645
|
// and declared infra. apply/remove need root; generate/status do not.
|
|
507
646
|
const enforceCmd = program
|
|
@@ -602,8 +741,8 @@ program
|
|
|
602
741
|
});
|
|
603
742
|
program
|
|
604
743
|
.command('decisions-log-refresh')
|
|
605
|
-
.description('One-shot refresh of the governed decisions log (.intutic/DECISIONS.md
|
|
606
|
-
'harness
|
|
744
|
+
.description('One-shot refresh of the governed decisions log (.intutic/DECISIONS.md, and the recent ' +
|
|
745
|
+
'entries in each governed harness\'s instructions file) — no-ops if decisionsLogEnabled is off. Invoked by the optional ' +
|
|
607
746
|
'post-merge Git hook `intutic init` installs; safe to run manually.')
|
|
608
747
|
.action(async () => {
|
|
609
748
|
const { refreshDecisionsLog } = await import('./lib/decisionsLogRefresh.js');
|
|
@@ -617,8 +756,8 @@ program
|
|
|
617
756
|
.command('exec')
|
|
618
757
|
.description('Execute a command wrapped with Intutic proxy environment variables')
|
|
619
758
|
.argument('[command...]', 'Command and arguments to execute (e.g. -- claude)')
|
|
620
|
-
// Run the agent inside an isolated sandbox whose ONLY egress is the proxy
|
|
621
|
-
//
|
|
759
|
+
// Run the agent inside an isolated sandbox whose ONLY egress is the proxy:
|
|
760
|
+
// cap-drop, no-new-privileges, read-only rootfs, resource caps,
|
|
622
761
|
// and a default-deny egress firewall the agent cannot undo.
|
|
623
762
|
.option('--sandbox [kind]', 'Run the agent in an isolated sandbox (kind: oci | firecracker; default oci)')
|
|
624
763
|
.option('--sandbox-image <image>', 'Sandbox image (must contain the agent + nftables + capsh); the default is built locally on first use', DEFAULT_SANDBOX_IMAGE)
|
|
@@ -717,6 +856,33 @@ findings
|
|
|
717
856
|
const { runFindingsEchoReport } = await import('./commands/findings.js');
|
|
718
857
|
await runFindingsEchoReport(opts);
|
|
719
858
|
});
|
|
859
|
+
// ── Governance incidents ───────────────────────────────────────────────────
|
|
860
|
+
const incidentsCmd = program
|
|
861
|
+
.command('incidents')
|
|
862
|
+
.description('Governance incidents, as on Findings › Incidents (OWNER, ADMIN, EM)');
|
|
863
|
+
incidentsCmd
|
|
864
|
+
.command('list')
|
|
865
|
+
.description('Incidents ranked by review priority, filtered by status, severity and type')
|
|
866
|
+
.option('--status <status>', 'Only incidents with this status: OPEN, RESOLVED or AUTO_RESOLVED')
|
|
867
|
+
.option('--severity <severity>', 'Only incidents of this severity: CRITICAL, HIGH, MEDIUM or LOW')
|
|
868
|
+
.option('--type <type>', 'Only incidents of this type, e.g. SCOPE_VIOLATION, WASM_RULE_REFUSED or SYSTEM_ANOMALY')
|
|
869
|
+
.option('--page <n>', 'The page to show (default 1)')
|
|
870
|
+
.option('--limit <n>', 'Incidents per page (default 20, at most 100)')
|
|
871
|
+
.option('--json', 'Output as JSON')
|
|
872
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
873
|
+
.action(async (opts) => {
|
|
874
|
+
const { runIncidentsList } = await import('./commands/incidents.js');
|
|
875
|
+
await runIncidentsList(opts);
|
|
876
|
+
});
|
|
877
|
+
incidentsCmd
|
|
878
|
+
.command('show <incidentId>')
|
|
879
|
+
.description('One incident in full, with its escalation details')
|
|
880
|
+
.option('--json', 'Output as JSON')
|
|
881
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
882
|
+
.action(async (incidentId, opts) => {
|
|
883
|
+
const { runIncidentsShow } = await import('./commands/incidents.js');
|
|
884
|
+
await runIncidentsShow(incidentId, opts);
|
|
885
|
+
});
|
|
720
886
|
// ── Trace integrity ────────────────────────────────────────────────────────
|
|
721
887
|
const integrity = program
|
|
722
888
|
.command('integrity')
|
|
@@ -874,8 +1040,8 @@ daemon
|
|
|
874
1040
|
.option('--mcp', 'Show the MCP proxy daemon instead of the sync-daemon')
|
|
875
1041
|
.action(async (opts) => {
|
|
876
1042
|
// `mcpDaemonStatus` was exported and never called by any command until the
|
|
877
|
-
// reachability test widened to the status/stop/start verbs (
|
|
878
|
-
// shape, one more time).
|
|
1043
|
+
// reachability test widened to the status/stop/start verbs (the same
|
|
1044
|
+
// exported-but-unreachable shape, one more time).
|
|
879
1045
|
const { daemonStatus, proxyServiceStatus, mcpDaemonStatus } = await import('./commands/install-daemon.js');
|
|
880
1046
|
await (opts.proxy ? proxyServiceStatus() : opts.mcp ? mcpDaemonStatus() : daemonStatus());
|
|
881
1047
|
});
|
|
@@ -886,8 +1052,8 @@ daemon
|
|
|
886
1052
|
.option('--mcp', 'Stop the MCP proxy daemon instead of the sync-daemon')
|
|
887
1053
|
.action(async (opts) => {
|
|
888
1054
|
// `mcpDaemonStop` was exported and never called by any command until the
|
|
889
|
-
// reachability test widened to the status/stop/start verbs (
|
|
890
|
-
// shape, one more time).
|
|
1055
|
+
// reachability test widened to the status/stop/start verbs (the same
|
|
1056
|
+
// exported-but-unreachable shape, one more time).
|
|
891
1057
|
const { daemonStop, proxyServiceStop, mcpDaemonStop } = await import('./commands/install-daemon.js');
|
|
892
1058
|
await (opts.proxy ? proxyServiceStop() : opts.mcp ? mcpDaemonStop() : daemonStop());
|
|
893
1059
|
});
|
|
@@ -898,8 +1064,8 @@ daemon
|
|
|
898
1064
|
.option('--mcp', 'Start the MCP proxy daemon instead of the sync-daemon')
|
|
899
1065
|
.action(async (opts) => {
|
|
900
1066
|
// `mcpDaemonStart` was exported and never called by any command until the
|
|
901
|
-
// reachability test widened to the status/stop/start verbs (
|
|
902
|
-
// shape, one more time).
|
|
1067
|
+
// reachability test widened to the status/stop/start verbs (the same
|
|
1068
|
+
// exported-but-unreachable shape, one more time).
|
|
903
1069
|
const { daemonStart, proxyServiceStart, mcpDaemonStart } = await import('./commands/install-daemon.js');
|
|
904
1070
|
await (opts.proxy ? proxyServiceStart() : opts.mcp ? mcpDaemonStart() : daemonStart());
|
|
905
1071
|
});
|
|
@@ -1022,7 +1188,7 @@ decisionCmd
|
|
|
1022
1188
|
const { runDecisionReject } = await import('./commands/decision.js');
|
|
1023
1189
|
await runDecisionReject(holdId, opts);
|
|
1024
1190
|
});
|
|
1025
|
-
// ── Gateway commands
|
|
1191
|
+
// ── Gateway commands ─────────────────────────────────────────────────────
|
|
1026
1192
|
//
|
|
1027
1193
|
// Self-hosted gateway registration/management. Previously reachable only by
|
|
1028
1194
|
// hand-written curl against services/control-plane/src/routes/gateways.ts —
|
|
@@ -1080,6 +1246,15 @@ gatewayCmd
|
|
|
1080
1246
|
const gatewayConfigCmd = gatewayCmd
|
|
1081
1247
|
.command('config')
|
|
1082
1248
|
.description('Manage a gateway\'s remote config (requireVk, requireProvisionedKey)');
|
|
1249
|
+
gatewayConfigCmd
|
|
1250
|
+
.command('get <gateway_id>')
|
|
1251
|
+
.description('Show the config values set on a gateway and their version')
|
|
1252
|
+
.option('--json', 'Output as JSON')
|
|
1253
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1254
|
+
.action(async (gatewayId, opts) => {
|
|
1255
|
+
const { runGatewayConfigGet } = await import('./commands/gateway.js');
|
|
1256
|
+
await runGatewayConfigGet(gatewayId, opts);
|
|
1257
|
+
});
|
|
1083
1258
|
gatewayConfigCmd
|
|
1084
1259
|
.command('set <gateway_id>')
|
|
1085
1260
|
.description('Update one or both config flags on a gateway')
|
|
@@ -1112,7 +1287,7 @@ gatewayCmd
|
|
|
1112
1287
|
const { runGatewayResolve } = await import('./commands/gateway.js');
|
|
1113
1288
|
await runGatewayResolve(opts);
|
|
1114
1289
|
});
|
|
1115
|
-
// ── Provider credentials
|
|
1290
|
+
// ── Provider credentials ─────────────────────────────────────────────────
|
|
1116
1291
|
//
|
|
1117
1292
|
// Provision a workspace's own upstream provider keys — the BYO-key wizard's
|
|
1118
1293
|
// API, previously dashboard-only. See commands/credentials.ts's module doc.
|
|
@@ -1132,6 +1307,7 @@ credentialsCmd
|
|
|
1132
1307
|
.command('set <provider>')
|
|
1133
1308
|
.description('Provision or rotate a provider credential (e.g. --field apiKey=sk-ant-...)')
|
|
1134
1309
|
.option('--field <key=value>', 'A credential field; repeat for multi-field providers', (v, prev) => [...prev, v], [])
|
|
1310
|
+
.option('--field-file <key=path>', 'A credential field read from a file (e.g. a service-account JSON key)', (v, prev) => [...prev, v], [])
|
|
1135
1311
|
.option('--json', 'Output as JSON')
|
|
1136
1312
|
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1137
1313
|
.action(async (provider, opts) => {
|
|
@@ -1146,7 +1322,16 @@ credentialsCmd
|
|
|
1146
1322
|
const { runCredentialsUnset } = await import('./commands/credentials.js');
|
|
1147
1323
|
await runCredentialsUnset(provider, opts);
|
|
1148
1324
|
});
|
|
1149
|
-
|
|
1325
|
+
credentialsCmd
|
|
1326
|
+
.command('models <provider>')
|
|
1327
|
+
.description('The models a provider credential can reach, as recorded when it was last checked')
|
|
1328
|
+
.option('--json', 'Output as JSON')
|
|
1329
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1330
|
+
.action(async (provider, opts) => {
|
|
1331
|
+
const { runCredentialsModels } = await import('./commands/credentials.js');
|
|
1332
|
+
await runCredentialsModels(provider, opts);
|
|
1333
|
+
});
|
|
1334
|
+
// ── DCT Token Attenuation (HLD §5.6 Patent Family A) ─────────────────────
|
|
1150
1335
|
//
|
|
1151
1336
|
// "CLI mints, dashboard audits": this is the mint/inspect half. See
|
|
1152
1337
|
// commands/attenuate.ts's module doc.
|
|
@@ -1169,7 +1354,7 @@ attenuateCmd
|
|
|
1169
1354
|
const { runAttenuateChain } = await import('./commands/attenuate.js');
|
|
1170
1355
|
await runAttenuateChain(chainId, opts);
|
|
1171
1356
|
});
|
|
1172
|
-
// ── Org signup + team management
|
|
1357
|
+
// ── Org signup + team management ─────────────────────────────────────────
|
|
1173
1358
|
const orgCmd = program
|
|
1174
1359
|
.command('org')
|
|
1175
1360
|
.description('Create and manage orgs');
|
|
@@ -1228,5 +1413,381 @@ teamCmd
|
|
|
1228
1413
|
const { runTeamCreateWorkspace } = await import('./commands/team.js');
|
|
1229
1414
|
await runTeamCreateWorkspace(teamId, opts);
|
|
1230
1415
|
});
|
|
1416
|
+
// ── Operator commands ────────────────────────────────────────────────────
|
|
1417
|
+
//
|
|
1418
|
+
// Workspace settings, the MCP server registry, notification rules, SIEM
|
|
1419
|
+
// destinations and the fleet reports, each over its existing control-plane
|
|
1420
|
+
// route. Previously dashboard-only. See commands/apiCommand.ts for the shape
|
|
1421
|
+
// they share.
|
|
1422
|
+
const settingsCmd = program
|
|
1423
|
+
.command('settings')
|
|
1424
|
+
.description('Read and change workspace settings (MCP policy, budgets, group policy, config content upload, ...)');
|
|
1425
|
+
settingsCmd
|
|
1426
|
+
.command('get [key]')
|
|
1427
|
+
.description('Print every workspace setting, or one')
|
|
1428
|
+
.option('--json', 'Output as JSON')
|
|
1429
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1430
|
+
.action(async (key, opts) => {
|
|
1431
|
+
const { runSettingsGet } = await import('./commands/settings.js');
|
|
1432
|
+
await runSettingsGet(key, opts);
|
|
1433
|
+
});
|
|
1434
|
+
settingsCmd
|
|
1435
|
+
.command('set <key> [value]')
|
|
1436
|
+
.description('Change one setting; the value is JSON when it parses as JSON, else a string')
|
|
1437
|
+
.option('--file <path>', 'Read the value from a JSON file instead')
|
|
1438
|
+
.option('--json', 'Output as JSON')
|
|
1439
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1440
|
+
.action(async (key, value, opts) => {
|
|
1441
|
+
const { runSettingsSet } = await import('./commands/settings.js');
|
|
1442
|
+
await runSettingsSet(key, value, opts);
|
|
1443
|
+
});
|
|
1444
|
+
const mcpCmd = program
|
|
1445
|
+
.command('mcp')
|
|
1446
|
+
.description('Review the MCP servers the workspace\'s MCP proxies have seen, and decide on them');
|
|
1447
|
+
mcpCmd
|
|
1448
|
+
.command('list')
|
|
1449
|
+
.description('Every MCP server seen, its status and tools, and the registry\'s default policy')
|
|
1450
|
+
.option('--json', 'Output as JSON')
|
|
1451
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1452
|
+
.action(async (opts) => {
|
|
1453
|
+
const { runMcpList } = await import('./commands/mcp.js');
|
|
1454
|
+
await runMcpList(opts);
|
|
1455
|
+
});
|
|
1456
|
+
for (const [action, desc] of [
|
|
1457
|
+
['approve', 'Approve an MCP server; MCP proxies let it run'],
|
|
1458
|
+
['block', 'Block an MCP server; MCP proxies refuse it'],
|
|
1459
|
+
['reset', 'Return an MCP server to the approval queue'],
|
|
1460
|
+
]) {
|
|
1461
|
+
mcpCmd
|
|
1462
|
+
.command(`${action} <server_id>`)
|
|
1463
|
+
.description(desc)
|
|
1464
|
+
.option('--json', 'Output as JSON')
|
|
1465
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1466
|
+
.action(async (serverId, opts) => {
|
|
1467
|
+
const { runMcpDecide } = await import('./commands/mcp.js');
|
|
1468
|
+
await runMcpDecide(action, serverId, opts);
|
|
1469
|
+
});
|
|
1470
|
+
}
|
|
1471
|
+
for (const [action, enabled, desc] of [
|
|
1472
|
+
['enable-tool', true, 'Switch one tool of an MCP server back on'],
|
|
1473
|
+
['disable-tool', false, 'Switch one tool of an MCP server off; MCP proxies refuse calls to it'],
|
|
1474
|
+
]) {
|
|
1475
|
+
mcpCmd
|
|
1476
|
+
.command(`${action} <server_id> <tool>`)
|
|
1477
|
+
.description(desc)
|
|
1478
|
+
.option('--json', 'Output as JSON')
|
|
1479
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1480
|
+
.action(async (serverId, tool, opts) => {
|
|
1481
|
+
const { runMcpTool } = await import('./commands/mcp.js');
|
|
1482
|
+
await runMcpTool(serverId, tool, enabled, opts);
|
|
1483
|
+
});
|
|
1484
|
+
}
|
|
1485
|
+
const notificationsCmd = program
|
|
1486
|
+
.command('notifications')
|
|
1487
|
+
.description('Manage notification rules: which events go to Slack, email, a webhook or PagerDuty');
|
|
1488
|
+
function ruleOptions(cmd) {
|
|
1489
|
+
return cmd
|
|
1490
|
+
.option('--slack-channel <id>', 'Slack channel ID, for the slack channel')
|
|
1491
|
+
.option('--email <addresses>', 'Comma-separated recipients (up to 20), for the email channel')
|
|
1492
|
+
.option('--webhook-url <url>', 'HTTPS URL, for the webhook channel')
|
|
1493
|
+
.option('--pagerduty-key <key>', 'Routing key, for the pagerduty channel')
|
|
1494
|
+
.option('--severity <list>', 'Only events of these comma-separated severities')
|
|
1495
|
+
.option('--harness <list>', 'Only events from these comma-separated harnesses')
|
|
1496
|
+
.option('--user <ids>', 'Only events from these comma-separated user ids')
|
|
1497
|
+
.option('--cooldown <minutes>', 'Minimum minutes between two notifications of this rule (1-1440)')
|
|
1498
|
+
.option('--json', 'Output as JSON')
|
|
1499
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)');
|
|
1500
|
+
}
|
|
1501
|
+
notificationsCmd
|
|
1502
|
+
.command('list')
|
|
1503
|
+
.description('List notification rules')
|
|
1504
|
+
.option('--json', 'Output as JSON')
|
|
1505
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1506
|
+
.action(async (opts) => {
|
|
1507
|
+
const { runNotificationsList } = await import('./commands/notifications.js');
|
|
1508
|
+
await runNotificationsList(opts);
|
|
1509
|
+
});
|
|
1510
|
+
ruleOptions(notificationsCmd
|
|
1511
|
+
.command('create')
|
|
1512
|
+
.description('Create a notification rule; a webhook rule prints its signing secret once')
|
|
1513
|
+
.requiredOption('--event <type>', 'Event type, e.g. incident.created or mcp.server.candidate')
|
|
1514
|
+
.requiredOption('--channel <channel>', 'slack, email, webhook or pagerduty')
|
|
1515
|
+
.option('--disabled', 'Create the rule switched off')).action(async (opts) => {
|
|
1516
|
+
const { runNotificationsCreate } = await import('./commands/notifications.js');
|
|
1517
|
+
await runNotificationsCreate(opts);
|
|
1518
|
+
});
|
|
1519
|
+
ruleOptions(notificationsCmd
|
|
1520
|
+
.command('update <rule_id>')
|
|
1521
|
+
.description('Change a notification rule; only the fields given change')
|
|
1522
|
+
.option('--event <type>', 'Event type')
|
|
1523
|
+
.option('--channel <channel>', 'slack, email, webhook or pagerduty')
|
|
1524
|
+
.option('--enable', 'Switch the rule on')
|
|
1525
|
+
.option('--disable', 'Switch the rule off')).action(async (ruleId, opts) => {
|
|
1526
|
+
const { runNotificationsUpdate } = await import('./commands/notifications.js');
|
|
1527
|
+
await runNotificationsUpdate(ruleId, opts);
|
|
1528
|
+
});
|
|
1529
|
+
notificationsCmd
|
|
1530
|
+
.command('delete <rule_id>')
|
|
1531
|
+
.description('Delete a notification rule')
|
|
1532
|
+
.option('--json', 'Output as JSON')
|
|
1533
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1534
|
+
.action(async (ruleId, opts) => {
|
|
1535
|
+
const { runNotificationsDelete } = await import('./commands/notifications.js');
|
|
1536
|
+
await runNotificationsDelete(ruleId, opts);
|
|
1537
|
+
});
|
|
1538
|
+
notificationsCmd
|
|
1539
|
+
.command('rotate-secret <rule_id>')
|
|
1540
|
+
.description('Replace a webhook rule\'s signing secret and print the new one once')
|
|
1541
|
+
.option('--json', 'Output as JSON')
|
|
1542
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1543
|
+
.action(async (ruleId, opts) => {
|
|
1544
|
+
const { runNotificationsRotateSecret } = await import('./commands/notifications.js');
|
|
1545
|
+
await runNotificationsRotateSecret(ruleId, opts);
|
|
1546
|
+
});
|
|
1547
|
+
const siemCmd = program
|
|
1548
|
+
.command('siem')
|
|
1549
|
+
.description('Manage SIEM export destinations and the event sources each receives');
|
|
1550
|
+
function destinationOptions(cmd) {
|
|
1551
|
+
return cmd
|
|
1552
|
+
.option('--sources <list>', 'Comma-separated event sources this destination receives (see `intutic siem sources`)')
|
|
1553
|
+
.option('--default-sources', 'Receive the default set: every source except the opt-in ones')
|
|
1554
|
+
.option('--batch-size <n>', 'Events per delivery batch')
|
|
1555
|
+
.option('--flush-interval-ms <ms>', 'Longest wait before a partial batch is sent')
|
|
1556
|
+
.option('--json', 'Output as JSON')
|
|
1557
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)');
|
|
1558
|
+
}
|
|
1559
|
+
siemCmd
|
|
1560
|
+
.command('list')
|
|
1561
|
+
.description('List SIEM destinations (credentials masked)')
|
|
1562
|
+
.option('--json', 'Output as JSON')
|
|
1563
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1564
|
+
.action(async (opts) => {
|
|
1565
|
+
const { runSiemList } = await import('./commands/siem.js');
|
|
1566
|
+
await runSiemList(opts);
|
|
1567
|
+
});
|
|
1568
|
+
siemCmd
|
|
1569
|
+
.command('show <destination_id>')
|
|
1570
|
+
.description('Show one SIEM destination (credentials masked)')
|
|
1571
|
+
.option('--json', 'Output as JSON')
|
|
1572
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1573
|
+
.action(async (destinationId, opts) => {
|
|
1574
|
+
const { runSiemShow } = await import('./commands/siem.js');
|
|
1575
|
+
await runSiemShow(destinationId, opts);
|
|
1576
|
+
});
|
|
1577
|
+
siemCmd
|
|
1578
|
+
.command('sources')
|
|
1579
|
+
.description('List the event sources a destination can receive, and which are opt-in')
|
|
1580
|
+
.option('--json', 'Output as JSON')
|
|
1581
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1582
|
+
.action(async (opts) => {
|
|
1583
|
+
const { runSiemSources } = await import('./commands/siem.js');
|
|
1584
|
+
await runSiemSources(opts);
|
|
1585
|
+
});
|
|
1586
|
+
destinationOptions(siemCmd
|
|
1587
|
+
.command('create')
|
|
1588
|
+
.description('Create a SIEM destination; a webhook destination prints its signing secret once')
|
|
1589
|
+
.requiredOption('--name <name>', 'Display name')
|
|
1590
|
+
.requiredOption('--type <adapter>', 'syslog_cef, webhook_https, splunk_hec, datadog_logs, gcs or s3')
|
|
1591
|
+
.requiredOption('--config <path>', 'JSON file with the adapter settings and credentials')).action(async (opts) => {
|
|
1592
|
+
const { runSiemCreate } = await import('./commands/siem.js');
|
|
1593
|
+
await runSiemCreate(opts);
|
|
1594
|
+
});
|
|
1595
|
+
destinationOptions(siemCmd
|
|
1596
|
+
.command('update <destination_id>')
|
|
1597
|
+
.description('Change a SIEM destination; only the fields given change')
|
|
1598
|
+
.option('--name <name>', 'Display name')
|
|
1599
|
+
.option('--config <path>', 'JSON file with the new adapter settings; a secret left out or left masked keeps its stored value')
|
|
1600
|
+
.option('--enable', 'Turn a deactivated destination back on')).action(async (destinationId, opts) => {
|
|
1601
|
+
const { runSiemUpdate } = await import('./commands/siem.js');
|
|
1602
|
+
await runSiemUpdate(destinationId, opts);
|
|
1603
|
+
});
|
|
1604
|
+
siemCmd
|
|
1605
|
+
.command('delete <destination_id>')
|
|
1606
|
+
.description('Deactivate a SIEM destination; it stops receiving events and stays listed')
|
|
1607
|
+
.option('--json', 'Output as JSON')
|
|
1608
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1609
|
+
.action(async (destinationId, opts) => {
|
|
1610
|
+
const { runSiemDelete } = await import('./commands/siem.js');
|
|
1611
|
+
await runSiemDelete(destinationId, opts);
|
|
1612
|
+
});
|
|
1613
|
+
siemCmd
|
|
1614
|
+
.command('rotate-secret <destination_id>')
|
|
1615
|
+
.description('Replace a webhook destination\'s signing secret and print the new one once')
|
|
1616
|
+
.option('--json', 'Output as JSON')
|
|
1617
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1618
|
+
.action(async (destinationId, opts) => {
|
|
1619
|
+
const { runSiemRotateSecret } = await import('./commands/siem.js');
|
|
1620
|
+
await runSiemRotateSecret(destinationId, opts);
|
|
1621
|
+
});
|
|
1622
|
+
const complianceCmd = program
|
|
1623
|
+
.command('compliance')
|
|
1624
|
+
.description('Compliance framework reports and the evidence archive');
|
|
1625
|
+
complianceCmd
|
|
1626
|
+
.command('coverage <framework_id>')
|
|
1627
|
+
.description('Coverage of eu_ai_act, iso_42001, nist_ai_rmf or mitre_atlas from the latest probe results')
|
|
1628
|
+
.option('--format <format>', 'Download the report: json, md, csv or pdf')
|
|
1629
|
+
.option('--out <path>', 'Write the report to this file instead of stdout')
|
|
1630
|
+
.option('--json', 'Output as JSON')
|
|
1631
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1632
|
+
.action(async (frameworkId, opts) => {
|
|
1633
|
+
const { runComplianceCoverage } = await import('./commands/compliance.js');
|
|
1634
|
+
await runComplianceCoverage(frameworkId, opts);
|
|
1635
|
+
});
|
|
1636
|
+
complianceCmd
|
|
1637
|
+
.command('collect')
|
|
1638
|
+
.description('Run a fresh evidence collection and seal it into an archive (OWNER, ADMIN)')
|
|
1639
|
+
.option('--from <date>', 'Start of the evidence period, ISO 8601 (default: 90 days before --to)')
|
|
1640
|
+
.option('--to <date>', 'End of the evidence period, ISO 8601 (default: now)')
|
|
1641
|
+
.option('--out <path>', 'Also write the archive to this file')
|
|
1642
|
+
.option('--json', 'Output as JSON')
|
|
1643
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1644
|
+
.action(async (opts) => {
|
|
1645
|
+
const { runComplianceCollect } = await import('./commands/compliance.js');
|
|
1646
|
+
await runComplianceCollect(opts);
|
|
1647
|
+
});
|
|
1648
|
+
complianceCmd
|
|
1649
|
+
.command('download <run_id>')
|
|
1650
|
+
.description('Download a stored evidence archive (OWNER, ADMIN)')
|
|
1651
|
+
.option('--out <path>', 'Write the archive to this file instead of stdout')
|
|
1652
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1653
|
+
.action(async (runId, opts) => {
|
|
1654
|
+
const { runComplianceDownload } = await import('./commands/compliance.js');
|
|
1655
|
+
await runComplianceDownload(runId, opts);
|
|
1656
|
+
});
|
|
1657
|
+
complianceCmd
|
|
1658
|
+
.command('verify <file>')
|
|
1659
|
+
.description('Check an evidence archive\'s hashes and signature offline')
|
|
1660
|
+
.option('--jwks <path>', 'The published signing keys, saved from /.well-known/intutic-trace-signing.json (default: fetch them)')
|
|
1661
|
+
.option('--json', 'Output as JSON')
|
|
1662
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1663
|
+
.action(async (file, opts) => {
|
|
1664
|
+
const { runComplianceVerify } = await import('./commands/compliance.js');
|
|
1665
|
+
await runComplianceVerify(file, opts);
|
|
1666
|
+
});
|
|
1667
|
+
const usageCmd = program
|
|
1668
|
+
.command('usage')
|
|
1669
|
+
.description('LLM usage across the fleet, by member, team, branch, commit or pull request');
|
|
1670
|
+
for (const [view, handler, desc] of [
|
|
1671
|
+
['members', 'runUsageMembers', 'Usage per member'],
|
|
1672
|
+
['teams', 'runUsageTeams', 'Usage per team (SCIM group)'],
|
|
1673
|
+
['branches', 'runUsageBranches', 'Usage per repository and branch'],
|
|
1674
|
+
['commits', 'runUsageCommits', 'Usage per HEAD commit'],
|
|
1675
|
+
]) {
|
|
1676
|
+
usageCmd
|
|
1677
|
+
.command(view)
|
|
1678
|
+
.description(desc)
|
|
1679
|
+
.option('--period <period>', 'daily (today) or monthly (this month)', 'monthly')
|
|
1680
|
+
.option('--json', 'Output as JSON')
|
|
1681
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1682
|
+
.action(async (opts) => {
|
|
1683
|
+
const usage = await import('./commands/usage.js');
|
|
1684
|
+
await usage[handler](opts);
|
|
1685
|
+
});
|
|
1686
|
+
}
|
|
1687
|
+
usageCmd
|
|
1688
|
+
.command('pull-requests')
|
|
1689
|
+
.description('Usage per GitHub pull request')
|
|
1690
|
+
.option('--period <period>', 'daily (today) or monthly (this month)', 'monthly')
|
|
1691
|
+
.option('--refresh', 'Look the branches up on GitHub first (OWNER, ADMIN, EM)')
|
|
1692
|
+
.option('--json', 'Output as JSON')
|
|
1693
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1694
|
+
.action(async (opts) => {
|
|
1695
|
+
const { runUsagePullRequests } = await import('./commands/usage.js');
|
|
1696
|
+
await runUsagePullRequests(opts);
|
|
1697
|
+
});
|
|
1698
|
+
const githubWebhookCmd = program
|
|
1699
|
+
.command('github')
|
|
1700
|
+
.description('GitHub integration for cost per pull request')
|
|
1701
|
+
.command('webhook')
|
|
1702
|
+
.description('The pull-request webhook: payload URL and signing secret');
|
|
1703
|
+
githubWebhookCmd
|
|
1704
|
+
.command('show')
|
|
1705
|
+
.description('Show the payload URL and when the secret was made')
|
|
1706
|
+
.option('--json', 'Output as JSON')
|
|
1707
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1708
|
+
.action(async (opts) => {
|
|
1709
|
+
const { runGithubWebhookShow } = await import('./commands/github.js');
|
|
1710
|
+
await runGithubWebhookShow(opts);
|
|
1711
|
+
});
|
|
1712
|
+
githubWebhookCmd
|
|
1713
|
+
.command('rotate-secret')
|
|
1714
|
+
.description('Make the webhook, or replace its secret (printed once)')
|
|
1715
|
+
.option('--json', 'Output as JSON')
|
|
1716
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1717
|
+
.action(async (opts) => {
|
|
1718
|
+
const { runGithubWebhookRotateSecret } = await import('./commands/github.js');
|
|
1719
|
+
await runGithubWebhookRotateSecret(opts);
|
|
1720
|
+
});
|
|
1721
|
+
const inventoryCmd = program
|
|
1722
|
+
.command('inventory')
|
|
1723
|
+
.description('AI harnesses, MCP servers and skills on connected developer machines, governed or not');
|
|
1724
|
+
inventoryCmd
|
|
1725
|
+
.command('summary')
|
|
1726
|
+
.description('Counts of machines, harnesses, MCP servers and skills, and how many are ungoverned')
|
|
1727
|
+
.option('--json', 'Output as JSON')
|
|
1728
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1729
|
+
.action(async (opts) => {
|
|
1730
|
+
const { runInventorySummary } = await import('./commands/inventory.js');
|
|
1731
|
+
await runInventorySummary(opts);
|
|
1732
|
+
});
|
|
1733
|
+
inventoryCmd
|
|
1734
|
+
.command('devices')
|
|
1735
|
+
.description('Every machine that reports, with its id (what --device takes), counts and last report')
|
|
1736
|
+
.option('--json', 'Output as JSON')
|
|
1737
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1738
|
+
.action(async (opts) => {
|
|
1739
|
+
const { runInventoryDevices } = await import('./commands/inventory.js');
|
|
1740
|
+
await runInventoryDevices(opts);
|
|
1741
|
+
});
|
|
1742
|
+
for (const [view, handler, desc] of [
|
|
1743
|
+
['harnesses', 'runInventoryHarnesses', 'Harnesses by machine, with gate state and status'],
|
|
1744
|
+
['mcp-servers', 'runInventoryMcpServers', 'MCP servers by machine, wrapped by the MCP proxy or not'],
|
|
1745
|
+
]) {
|
|
1746
|
+
inventoryCmd
|
|
1747
|
+
.command(view)
|
|
1748
|
+
.description(desc)
|
|
1749
|
+
.option('--status <status>', 'Only rows with this status')
|
|
1750
|
+
.option('--harness <harness>', 'Only rows for this harness')
|
|
1751
|
+
.option('--device <device_id>', 'Only rows from this machine')
|
|
1752
|
+
.option('--search <text>', 'Only rows whose name or hostname contains this text')
|
|
1753
|
+
.option('--csv', 'Download as CSV, the same file the dashboard exports')
|
|
1754
|
+
.option('--out <path>', 'With --csv: write to this file instead of stdout')
|
|
1755
|
+
.option('--json', 'Output as JSON')
|
|
1756
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1757
|
+
.action(async (opts) => {
|
|
1758
|
+
const inventory = await import('./commands/inventory.js');
|
|
1759
|
+
await inventory[handler](opts);
|
|
1760
|
+
});
|
|
1761
|
+
}
|
|
1762
|
+
inventoryCmd
|
|
1763
|
+
.command('skills')
|
|
1764
|
+
.description('Skill bundles by machine, with their content scan result')
|
|
1765
|
+
.option('--device <device_id>', 'Only rows from this machine')
|
|
1766
|
+
.option('--search <text>', 'Only rows whose name or hostname contains this text')
|
|
1767
|
+
.option('--json', 'Output as JSON')
|
|
1768
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1769
|
+
.action(async (opts) => {
|
|
1770
|
+
const { runInventorySkills } = await import('./commands/inventory.js');
|
|
1771
|
+
await runInventorySkills(opts);
|
|
1772
|
+
});
|
|
1773
|
+
inventoryCmd
|
|
1774
|
+
.command('disconnects')
|
|
1775
|
+
.description('Machines that ran `intutic disconnect`, newest first: what they disconnected, who and when')
|
|
1776
|
+
.option('--limit <n>', 'At most this many (default 100, at most 500)')
|
|
1777
|
+
.option('--json', 'Output as JSON')
|
|
1778
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1779
|
+
.action(async (opts) => {
|
|
1780
|
+
const { runInventoryDisconnects } = await import('./commands/inventory.js');
|
|
1781
|
+
await runInventoryDisconnects(opts);
|
|
1782
|
+
});
|
|
1783
|
+
program
|
|
1784
|
+
.command('gate-liveness')
|
|
1785
|
+
.description('Whether each installed harness\'s gate is reporting, and any open silent-gate alert')
|
|
1786
|
+
.option('--json', 'Output as JSON')
|
|
1787
|
+
.option('--dev', 'Use local control plane (http://localhost:3001)')
|
|
1788
|
+
.action(async (opts) => {
|
|
1789
|
+
const { runGateLiveness } = await import('./commands/gateLiveness.js');
|
|
1790
|
+
await runGateLiveness(opts);
|
|
1791
|
+
});
|
|
1231
1792
|
program.parse();
|
|
1232
1793
|
//# sourceMappingURL=cli.js.map
|