unbound-cli 0.4.0 → 0.5.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/LOCAL_DEV.md +76 -2
- package/README.md +82 -7
- package/package.json +1 -1
- package/src/commands/onboard.js +6 -3
- package/src/commands/policy.js +1704 -212
- package/src/commands/setup.js +38 -20
- package/src/index.js +26 -7
package/LOCAL_DEV.md
CHANGED
|
@@ -43,6 +43,47 @@ node src/index.js config reset-url
|
|
|
43
43
|
node src/index.js config reset-frontend-url
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
## Point setup scripts to a local backend / frontend
|
|
47
|
+
|
|
48
|
+
The `setup`, `setup mdm`, `onboard`, and `onboard-mdm` commands invoke Python setup scripts from the `setup` repo. Those scripts:
|
|
49
|
+
|
|
50
|
+
- Ping `https://backend.getunbound.ai/api/v1/setup/complete/` when a tool is configured (override with `--backend-url`).
|
|
51
|
+
- Use the frontend URL for the browser-auth callback if `--api-key` is not already stored (override with `--frontend-url`, passed through to the scripts as `--domain`).
|
|
52
|
+
|
|
53
|
+
Both flags are hidden from `--help` (dev-only) and work on every setup-invoking command:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Single tool — override backend only, or both
|
|
57
|
+
node src/index.js setup cursor --backend-url http://localhost:8000
|
|
58
|
+
node src/index.js setup cursor --backend-url http://localhost:8000 --frontend-url http://localhost:3000
|
|
59
|
+
node src/index.js setup claude-code --gateway --backend-url http://localhost:8000 --frontend-url http://localhost:3000
|
|
60
|
+
|
|
61
|
+
# Default bundle
|
|
62
|
+
node src/index.js setup --all --backend-url http://localhost:8000 --frontend-url http://localhost:3000
|
|
63
|
+
|
|
64
|
+
# Multiple explicit tools
|
|
65
|
+
node src/index.js setup cursor claude-code-gateway --backend-url http://localhost:8000 --frontend-url http://localhost:3000
|
|
66
|
+
|
|
67
|
+
# Interactive mode (select tools, then apply overrides to all selected)
|
|
68
|
+
node src/index.js setup --backend-url http://localhost:8000 --frontend-url http://localhost:3000
|
|
69
|
+
|
|
70
|
+
# MDM (requires sudo; MDM scripts ignore --frontend-url since they don't use browser auth)
|
|
71
|
+
sudo node src/index.js setup mdm --admin-api-key <ADMIN_KEY> --all --backend-url http://localhost:8000
|
|
72
|
+
|
|
73
|
+
# Onboarding (combined setup + discover)
|
|
74
|
+
node src/index.js onboard --api-key <USER_KEY> --discovery-key <DISCOVERY_KEY> \
|
|
75
|
+
--backend-url http://localhost:8000 --frontend-url http://localhost:3000
|
|
76
|
+
sudo node src/index.js onboard-mdm --admin-api-key <ADMIN_KEY> --discovery-key <DISCOVERY_KEY> \
|
|
77
|
+
--backend-url http://localhost:8000
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
When omitted, scripts default to `https://backend.getunbound.ai` and the stored frontend URL (or `https://gateway.getunbound.ai`).
|
|
81
|
+
|
|
82
|
+
Notes:
|
|
83
|
+
- `--backend-url` / `--frontend-url` only affect the setup scripts. They do not change the CLI's own API calls (use `config set-url` / `UNBOUND_API_URL` / `config set-frontend-url` / `UNBOUND_FRONTEND_URL` for that).
|
|
84
|
+
- `onboard` and `onboard-mdm` also take a visible `--domain <url>` flag — that one is for the **discovery** backend (a separate repo), not the setup scripts' frontend. The two flags don't conflict.
|
|
85
|
+
- MDM setup scripts (`setup mdm`, `onboard-mdm`) don't do browser auth, so `--frontend-url` is a no-op there; only `--backend-url` is meaningful.
|
|
86
|
+
|
|
46
87
|
## Verify config
|
|
47
88
|
|
|
48
89
|
```bash
|
|
@@ -68,11 +109,44 @@ node src/index.js login --base-url http://localhost:8000 --api-key <your-key>
|
|
|
68
109
|
node src/index.js whoami
|
|
69
110
|
node src/index.js status
|
|
70
111
|
|
|
71
|
-
# Policies
|
|
112
|
+
# Policies — overview
|
|
113
|
+
node src/index.js policy # overview + docs links
|
|
114
|
+
node src/index.js policy form-data # reference data (must produce output — bugfix)
|
|
72
115
|
node src/index.js policy list
|
|
73
116
|
node src/index.js policy list --type SECURITY --json
|
|
74
117
|
node src/index.js policy get 1
|
|
75
|
-
node src/index.js policy
|
|
118
|
+
node src/index.js policy effective 1
|
|
119
|
+
|
|
120
|
+
# Policy type subcommands
|
|
121
|
+
node src/index.js policy cost --help
|
|
122
|
+
node src/index.js policy model --help
|
|
123
|
+
node src/index.js policy security --help
|
|
124
|
+
node src/index.js policy tool --help
|
|
125
|
+
|
|
126
|
+
# Cost policies
|
|
127
|
+
node src/index.js policy cost list
|
|
128
|
+
node src/index.js policy cost create --name "Test Cost" --monthly-budget 500 --group engg
|
|
129
|
+
node src/index.js policy cost update 5 --monthly-budget 750
|
|
130
|
+
|
|
131
|
+
# Model policies
|
|
132
|
+
node src/index.js policy model create --name "No Opus" --all-models --excluded claude-3-opus
|
|
133
|
+
node src/index.js policy model create --name "Sonnet Only" --allowed claude-3-5-sonnet
|
|
134
|
+
|
|
135
|
+
# Security policies
|
|
136
|
+
node src/index.js policy security create --name "Block PII" --sub-type guardrails \
|
|
137
|
+
--guardrail PII:BLOCK --guardrail Secrets:REDACT
|
|
138
|
+
node src/index.js policy security create --name "Route 429s" --sub-type error-code-routing \
|
|
139
|
+
--error-route 429:gpt-4:claude-3-5-sonnet
|
|
140
|
+
|
|
141
|
+
# Tool policies (separate backend: /api/v1/command-policies/)
|
|
142
|
+
node src/index.js policy tool list
|
|
143
|
+
node src/index.js policy tool families
|
|
144
|
+
node src/index.js policy tool mcp-servers
|
|
145
|
+
node src/index.js policy tool create-terminal --name "Block rm -rf" \
|
|
146
|
+
--command-family filesystem --field command='rm -rf*' --action BLOCK \
|
|
147
|
+
--custom-message "Destructive command blocked."
|
|
148
|
+
node src/index.js policy tool create-mcp --name "Audit Linear writes" \
|
|
149
|
+
--mcp-server Linear --mcp-action-type write --action AUDIT
|
|
76
150
|
|
|
77
151
|
# Users
|
|
78
152
|
node src/index.js users list
|
package/README.md
CHANGED
|
@@ -127,17 +127,92 @@ Scan a device for installed AI coding tools and report findings to Unbound. Uses
|
|
|
127
127
|
|
|
128
128
|
### Policies (Admin only)
|
|
129
129
|
|
|
130
|
+
Unbound has **four** policy types. Each has its own subcommand with guided flag-based create/update. Tool policies live on a separate backend endpoint but are reachable under the same `policy` command tree.
|
|
131
|
+
|
|
132
|
+
Docs: https://docs.getunbound.ai/policies
|
|
133
|
+
|
|
134
|
+
| Type | Subcommand | Purpose | Docs |
|
|
135
|
+
|---|---|---|---|
|
|
136
|
+
| **Cost** | `unbound policy cost` | Monthly budget limits per user group | https://docs.getunbound.ai/policies/cost-policies |
|
|
137
|
+
| **Model** | `unbound policy model` | Control which AI models are available | https://docs.getunbound.ai/policies/model-policies |
|
|
138
|
+
| **Security** | `unbound policy security` | Guardrails (PII, secrets), routing rules | https://docs.getunbound.ai/policies/security-policies |
|
|
139
|
+
| **Tool** | `unbound policy tool` | Shell command and MCP tool controls | https://docs.getunbound.ai/policies/tool-policies |
|
|
140
|
+
|
|
141
|
+
Generic commands (Cost/Model/Security only):
|
|
142
|
+
|
|
130
143
|
| Command | Description |
|
|
131
144
|
|---------|-------------|
|
|
132
|
-
| `unbound policy
|
|
133
|
-
| `unbound policy
|
|
134
|
-
| `unbound policy
|
|
135
|
-
| `unbound policy update <id>` | Update a policy |
|
|
145
|
+
| `unbound policy` | Overview of types and subcommands |
|
|
146
|
+
| `unbound policy list [--type COST\|MODEL\|SECURITY]` | List policies |
|
|
147
|
+
| `unbound policy get <id>` | Get a policy's details |
|
|
136
148
|
| `unbound policy delete <id>` | Delete a policy |
|
|
137
|
-
| `unbound policy form-data` |
|
|
138
|
-
| `unbound policy effective <id
|
|
149
|
+
| `unbound policy form-data` | Reference data: user groups, models, guardrails, tool types, command policies |
|
|
150
|
+
| `unbound policy effective <id> [--user\|--group]` | View effective policies for a user or group |
|
|
151
|
+
|
|
152
|
+
Cost policy examples:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
# Create a $1,000/month cap for the engg user group
|
|
156
|
+
unbound policy cost create --name "Eng Budget" --monthly-budget 1000 --group engg
|
|
157
|
+
|
|
158
|
+
# Change the budget
|
|
159
|
+
unbound policy cost update 5 --monthly-budget 1500
|
|
160
|
+
|
|
161
|
+
# List just cost policies
|
|
162
|
+
unbound policy cost list
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Model policy examples:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
# Allow only specific models
|
|
169
|
+
unbound policy model create --name "Sonnet Only" --allowed claude-3-5-sonnet
|
|
170
|
+
|
|
171
|
+
# Allow everything except specific models
|
|
172
|
+
unbound policy model create --name "No Opus" --all-models --excluded claude-3-opus
|
|
173
|
+
|
|
174
|
+
# List all model policies
|
|
175
|
+
unbound policy model list
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Security policy examples:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# Block PII, redact secrets, for the engg group
|
|
182
|
+
unbound policy security create --name "Block PII" --sub-type guardrails \
|
|
183
|
+
--guardrail PII:BLOCK --guardrail Secrets:REDACT --group engg
|
|
184
|
+
|
|
185
|
+
# Default-route gpt-4 traffic to claude-3-5-sonnet
|
|
186
|
+
unbound policy security create --name "Prefer Sonnet" --sub-type default-routing \
|
|
187
|
+
--route gpt-4:claude-3-5-sonnet
|
|
188
|
+
|
|
189
|
+
# Fall back on 429s
|
|
190
|
+
unbound policy security create --name "429 Fallback" --sub-type error-code-routing \
|
|
191
|
+
--error-route 429:gpt-4:claude-3-5-sonnet
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Tool policy examples:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
# See what command families and MCP servers are available
|
|
198
|
+
unbound policy tool families
|
|
199
|
+
unbound policy tool mcp-servers
|
|
200
|
+
|
|
201
|
+
# Block destructive shell commands
|
|
202
|
+
unbound policy tool create-terminal --name "Block rm -rf" --command-family filesystem \
|
|
203
|
+
--field command='rm -rf*' --action BLOCK --custom-message "Destructive command blocked."
|
|
204
|
+
|
|
205
|
+
# Audit Linear write operations via MCP
|
|
206
|
+
unbound policy tool create-mcp --name "Audit Linear writes" --mcp-server Linear \
|
|
207
|
+
--mcp-action-type write --action AUDIT
|
|
208
|
+
|
|
209
|
+
# List, get, delete
|
|
210
|
+
unbound policy tool list
|
|
211
|
+
unbound policy tool get <id>
|
|
212
|
+
unbound policy tool delete <id>
|
|
213
|
+
```
|
|
139
214
|
|
|
140
|
-
|
|
215
|
+
Before creating any policy, run `unbound policy form-data` to see available user group names, model names, guardrail names, and existing command policies. The CLI accepts names (e.g. `engg`, `claude-3-opus`, `PII`) and resolves them to backend IDs automatically. You can also pass numeric IDs directly.
|
|
141
216
|
|
|
142
217
|
### Users
|
|
143
218
|
|
package/package.json
CHANGED
package/src/commands/onboard.js
CHANGED
|
@@ -27,6 +27,8 @@ function register(program) {
|
|
|
27
27
|
.requiredOption('--api-key <key>', 'User API key (for tool setup and login)')
|
|
28
28
|
.requiredOption('--discovery-key <key>', 'Discovery API key (for device scan)')
|
|
29
29
|
.option('--domain <url>', 'Backend URL for discovery', DEFAULT_DOMAIN)
|
|
30
|
+
.addOption(new Option('--backend-url <url>', 'Override backend URL for setup scripts (dev only)').hideHelp())
|
|
31
|
+
.addOption(new Option('--frontend-url <url>', 'Override frontend URL for setup scripts (dev only)').hideHelp())
|
|
30
32
|
.addHelpText('after', `
|
|
31
33
|
Runs the full onboarding flow for an end user:
|
|
32
34
|
1. Logs in with --api-key and stores credentials.
|
|
@@ -54,7 +56,7 @@ Examples:
|
|
|
54
56
|
|
|
55
57
|
console.log('');
|
|
56
58
|
output.info('Step 1/2: Installing tool bundle');
|
|
57
|
-
const ok = await runSetupAllBundle(apiKey);
|
|
59
|
+
const ok = await runSetupAllBundle(apiKey, { backendUrl: opts.backendUrl, frontendUrl: opts.frontendUrl });
|
|
58
60
|
if (!ok) return;
|
|
59
61
|
setupSucceeded = true;
|
|
60
62
|
|
|
@@ -87,7 +89,8 @@ Examples:
|
|
|
87
89
|
.requiredOption('--admin-api-key <key>', 'Admin API key for MDM enrollment')
|
|
88
90
|
.requiredOption('--discovery-key <key>', 'Discovery API key (for device scan)')
|
|
89
91
|
.option('--domain <url>', 'Backend URL for discovery', DEFAULT_DOMAIN)
|
|
90
|
-
.addOption(new Option('--url <url>', 'Override backend URL for setup scripts').hideHelp())
|
|
92
|
+
.addOption(new Option('--backend-url <url>', 'Override backend URL for setup scripts (dev only)').hideHelp())
|
|
93
|
+
.addOption(new Option('--frontend-url <url>', 'Override frontend URL for setup scripts (dev only)').hideHelp())
|
|
91
94
|
.addHelpText('after', `
|
|
92
95
|
Runs the full MDM onboarding flow for device enrollment:
|
|
93
96
|
1. Installs the MDM tool bundle: ${MDM_ALL_TOOLS.join(', ')}.
|
|
@@ -108,7 +111,7 @@ Examples:
|
|
|
108
111
|
|
|
109
112
|
console.log('');
|
|
110
113
|
output.info('Step 1/2: Installing MDM tool bundle');
|
|
111
|
-
const ok = await runMdmSetupAllBundle(opts.adminApiKey, {
|
|
114
|
+
const ok = await runMdmSetupAllBundle(opts.adminApiKey, { backendUrl: opts.backendUrl, frontendUrl: opts.frontendUrl });
|
|
112
115
|
if (!ok) return;
|
|
113
116
|
setupSucceeded = true;
|
|
114
117
|
|