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 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 form-data
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 list` | List all policies |
133
- | `unbound policy get <id>` | Get policy details |
134
- | `unbound policy create --name <n> --type <t>` | Create a 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` | Get reference data for policy creation |
138
- | `unbound policy effective <id>` | View effective policies for a user/group |
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
- Policy types: `SECURITY`, `MODEL`, `COST`
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unbound-cli",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "description": "CLI tool for Unbound - AI Gateway management",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -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, { url: opts.url });
114
+ const ok = await runMdmSetupAllBundle(opts.adminApiKey, { backendUrl: opts.backendUrl, frontendUrl: opts.frontendUrl });
112
115
  if (!ok) return;
113
116
  setupSucceeded = true;
114
117