unbound-cli 0.2.0 → 0.2.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/README.md CHANGED
@@ -60,7 +60,9 @@ Automated setup (downloads scripts, sets env vars, configures tool):
60
60
  | `unbound setup claude-code --subscription` | Hooks only (keep your Claude subscription) |
61
61
  | `unbound setup claude-code --gateway` | Use Unbound as the AI provider |
62
62
  | `unbound setup gemini-cli` | Set GEMINI_API_KEY and base URL |
63
- | `unbound setup codex` | Set OPENAI_API_KEY and base URL |
63
+ | `unbound setup codex` | Interactive mode selection (subscription or gateway) |
64
+ | `unbound setup codex --subscription` | Hooks only (keep your OpenAI subscription) |
65
+ | `unbound setup codex --gateway` | Use Unbound as the AI provider |
64
66
 
65
67
  Instruction-only (shows API key and base URL to configure manually):
66
68
 
@@ -87,12 +89,12 @@ Configure all users on a device via MDM. Requires root.
87
89
  | Command | Description |
88
90
  |---------|-------------|
89
91
  | `sudo unbound setup mdm --admin-api-key KEY --all` | Set up all tools |
90
- | `sudo unbound setup mdm --admin-api-key KEY cursor codex` | Set up specific tools |
92
+ | `sudo unbound setup mdm --admin-api-key KEY cursor codex-subscription` | Set up specific tools |
91
93
  | `sudo unbound setup mdm --admin-api-key KEY --clear cursor` | Remove config for specific tools |
92
94
 
93
- Available tools: `cursor`, `claude-code-subscription`, `claude-code-gateway`, `gemini-cli`, `codex`
95
+ Available tools: `cursor`, `claude-code-subscription`, `claude-code-gateway`, `gemini-cli`, `codex-subscription`, `codex-gateway`
94
96
 
95
- `claude-code-subscription` and `claude-code-gateway` are mutually exclusive. When using `--all`, `claude-code-subscription` is used by default.
97
+ `claude-code-subscription` and `claude-code-gateway` are mutually exclusive. `codex-subscription` and `codex-gateway` are mutually exclusive. When using `--all`, subscription mode is used by default for Claude Code and Codex.
96
98
 
97
99
  ### MDM AI Tools Discovery
98
100
 
@@ -149,7 +151,7 @@ Alias: `unbound groups` works the same as `unbound user-groups`.
149
151
  | `unbound tools connect <type>` | Connect a tool |
150
152
  | `unbound tools approved` | List approved tool types |
151
153
 
152
- Supported tool types: `CLAUDE_CODE`, `CURSOR`, `COPILOT`, `ROO_CODE`, `CLINE`, `GEMINI_CLI`, `CODEX`, `KILO_CODE`, `CUSTOM_ACCESS`
154
+ Supported tool types: `CLAUDE_CODE`, `UNBOUND_CLAUDE_CODE`, `CURSOR`, `COPILOT`, `ROO_CODE`, `CLINE`, `GEMINI_CLI`, `CODEX`, `UNBOUND_CODEX`, `KILO_CODE`, `CUSTOM_ACCESS`
153
155
 
154
156
  ## Configuration
155
157
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unbound-cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "CLI tool for Unbound - AI Gateway management",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -11,7 +11,8 @@ const SETUP_TOOLS = [
11
11
  { label: 'Claude Code \u2014 subscription (hooks)', value: 'claude-sub', script: 'claude-code/hooks/setup.py', group: 'claude-code' },
12
12
  { label: 'Claude Code \u2014 gateway (gateway)', value: 'claude-gw', script: 'claude-code/gateway/setup.py', group: 'claude-code' },
13
13
  { label: 'Gemini CLI', value: 'gemini', script: 'gemini-cli/gateway/setup.py' },
14
- { label: 'Codex', value: 'codex', script: 'codex/gateway/setup.py' },
14
+ { label: 'Codex \u2014 subscription (hooks)', value: 'codex-sub', script: 'codex/hooks/setup.py', group: 'codex' },
15
+ { label: 'Codex \u2014 gateway (gateway)', value: 'codex-gw', script: 'codex/gateway/setup.py', group: 'codex' },
15
16
  ];
16
17
 
17
18
  const MDM_TOOLS = {
@@ -19,11 +20,12 @@ const MDM_TOOLS = {
19
20
  'claude-code-subscription': { label: 'Claude Code (subscription)', script: 'claude-code/hooks/mdm/setup.py' },
20
21
  'claude-code-gateway': { label: 'Claude Code (gateway)', script: 'claude-code/gateway/mdm/setup.py' },
21
22
  'gemini-cli': { label: 'Gemini CLI', script: 'gemini-cli/gateway/mdm/setup.py' },
22
- 'codex': { label: 'Codex', script: 'codex/gateway/mdm/setup.py' },
23
+ 'codex-subscription': { label: 'Codex (subscription)', script: 'codex/hooks/mdm/setup.py' },
24
+ 'codex-gateway': { label: 'Codex (gateway)', script: 'codex/gateway/mdm/setup.py' },
23
25
  };
24
26
 
25
- // Default tools for --all (uses subscription mode for Claude Code since only one can be active)
26
- const MDM_ALL_TOOLS = ['cursor', 'claude-code-subscription', 'gemini-cli', 'codex'];
27
+ // Default tools for --all (uses subscription mode for Claude Code and Codex since only one can be active)
28
+ const MDM_ALL_TOOLS = ['cursor', 'claude-code-subscription', 'gemini-cli', 'codex-subscription'];
27
29
 
28
30
  /**
29
31
  * Builds a shell command that curls a setup script and pipes it to python3.
@@ -143,7 +145,7 @@ Single-tool setup (downloads scripts, sets env vars, configures tool):
143
145
  $ unbound setup cursor # Download hooks, set env, restart Cursor
144
146
  $ unbound setup claude-code # Set up gateway + hooks for Claude Code
145
147
  $ unbound setup gemini-cli # Set GEMINI_API_KEY and base URL
146
- $ unbound setup codex # Set OPENAI_API_KEY and base URL
148
+ $ unbound setup codex # Set up gateway + hooks for Codex
147
149
 
148
150
  Instruction-only (shows API key and base URL to configure manually):
149
151
  $ unbound setup roo-code # Show Roo Code config values
@@ -309,15 +311,26 @@ Examples:
309
311
  setup
310
312
  .command('codex')
311
313
  .description(
312
- 'Set up Codex to use Unbound. Sets OPENAI_API_KEY and ' +
313
- 'OPENAI_BASE_URL environment variables.'
314
+ 'Set up Codex to use Unbound. Prompts whether to use your existing ' +
315
+ 'OpenAI subscription or use Unbound as the AI provider.'
314
316
  )
317
+ .option('--subscription', 'Use your existing OpenAI subscription (hooks only)')
318
+ .option('--gateway', 'Use Unbound as the AI provider (gateway mode)')
315
319
  .option('--clear', 'Remove Unbound configuration for Codex')
316
320
  .addHelpText('after', `
317
- What this does:
318
- 1. Sets OPENAI_API_KEY to your Unbound API key in your shell profile
319
- 2. Sets OPENAI_BASE_URL to the Unbound gateway endpoint
320
- 3. Codex will route all requests through Unbound
321
+ Modes:
322
+ Subscription (hooks only):
323
+ Keep your existing OpenAI subscription. Installs Unbound hooks for
324
+ policy enforcement (security guardrails, cost limits) without changing
325
+ the AI provider. Runs codex/hooks/setup.py.
326
+
327
+ Gateway:
328
+ Use Unbound as the AI provider. Routes all Codex requests through
329
+ the Unbound gateway for full policy enforcement and model management.
330
+ Runs codex/gateway/setup.py.
331
+
332
+ If neither --subscription nor --gateway is provided, an interactive
333
+ prompt will ask you to choose.
321
334
 
322
335
  Prerequisites:
323
336
  - Must be logged in (will auto-open browser to authenticate if not)
@@ -325,10 +338,45 @@ Prerequisites:
325
338
  - Codex must be installed
326
339
 
327
340
  Examples:
328
- $ unbound setup codex
329
- $ unbound setup codex --clear # Remove Unbound configuration
341
+ $ unbound setup codex # Interactive mode selection
342
+ $ unbound setup codex --subscription # Hooks only (keep your subscription)
343
+ $ unbound setup codex --gateway # Use Unbound as AI provider
344
+ $ unbound setup codex --clear # Remove Unbound configuration
330
345
  `)
331
- .action(makeAction('codex/gateway/setup.py'));
346
+ .action(async (opts) => {
347
+ try {
348
+ await ensureLoggedIn();
349
+ const apiKey = config.getApiKey();
350
+ const scriptOpts = { clear: opts.clear };
351
+
352
+ if (opts.subscription && opts.gateway) {
353
+ output.error('Cannot use both --subscription and --gateway. Choose one.');
354
+ process.exitCode = 1;
355
+ return;
356
+ }
357
+
358
+ let useSubscription = opts.subscription;
359
+ if (!opts.clear && !opts.subscription && !opts.gateway) {
360
+ const mode = await output.select('How do you want to use Codex with Unbound?', [
361
+ { label: 'Use my OpenAI subscription (hooks)', value: 'subscription' },
362
+ { label: 'Use Unbound as the AI provider (gateway)', value: 'gateway' },
363
+ ]);
364
+ useSubscription = mode === 'subscription';
365
+ }
366
+
367
+ if (opts.clear) {
368
+ runSetupScript('codex/hooks/setup.py', apiKey, scriptOpts);
369
+ runSetupScript('codex/gateway/setup.py', apiKey, scriptOpts);
370
+ } else if (useSubscription) {
371
+ runSetupScript('codex/hooks/setup.py', apiKey, scriptOpts);
372
+ } else {
373
+ runSetupScript('codex/gateway/setup.py', apiKey, scriptOpts);
374
+ }
375
+ } catch (err) {
376
+ output.error(err.message);
377
+ process.exitCode = 1;
378
+ }
379
+ });
332
380
 
333
381
  // --- Instruction-only tools ---
334
382
 
@@ -500,16 +548,18 @@ Available tools:
500
548
  claude-code-subscription Claude Code with your own subscription (hooks only)
501
549
  claude-code-gateway Claude Code with Unbound as AI provider
502
550
  gemini-cli Gemini CLI
503
- codex Codex CLI
551
+ codex-subscription Codex with your own subscription (hooks only)
552
+ codex-gateway Codex with Unbound as AI provider
504
553
 
505
554
  Note: claude-code-subscription and claude-code-gateway are mutually exclusive.
506
- When using --all, claude-code-subscription is used by default.
555
+ codex-subscription and codex-gateway are mutually exclusive.
556
+ When using --all, subscription mode is used by default for Claude Code and Codex.
507
557
 
508
558
  Examples:
509
559
  $ sudo unbound setup mdm --admin-api-key KEY cursor
510
- $ sudo unbound setup mdm --admin-api-key KEY cursor claude-code-subscription codex
560
+ $ sudo unbound setup mdm --admin-api-key KEY cursor claude-code-subscription codex-subscription
511
561
  $ sudo unbound setup mdm --admin-api-key KEY --all
512
- $ sudo unbound setup mdm --admin-api-key KEY --clear cursor codex
562
+ $ sudo unbound setup mdm --admin-api-key KEY --clear cursor codex-subscription
513
563
  `)
514
564
  .action(async (tools, opts) => {
515
565
  try {
@@ -547,6 +597,12 @@ Examples:
547
597
  return;
548
598
  }
549
599
 
600
+ if (toolNames.includes('codex-subscription') && toolNames.includes('codex-gateway')) {
601
+ output.error('Cannot use both codex-subscription and codex-gateway. Choose one.');
602
+ process.exitCode = 1;
603
+ return;
604
+ }
605
+
550
606
  const resolvedTools = toolNames.map(name => ({ name, ...MDM_TOOLS[name] }));
551
607
  console.log('');
552
608
 
@@ -11,6 +11,7 @@ const SUPPORTED_TOOL_TYPES = [
11
11
  'CLINE',
12
12
  'GEMINI_CLI',
13
13
  'CODEX',
14
+ 'UNBOUND_CODEX',
14
15
  'KILO_CODE',
15
16
  'CUSTOM_ACCESS',
16
17
  ];
package/src/index.js CHANGED
@@ -30,7 +30,9 @@ TOOL SETUP
30
30
  $ unbound setup claude-code --gateway Use Unbound as AI provider
31
31
  $ unbound setup claude-code --subscription Hooks only (keep your subscription)
32
32
  $ unbound setup gemini-cli Set up Gemini CLI
33
- $ unbound setup codex Set up Codex
33
+ $ unbound setup codex Set up Codex (interactive mode selection)
34
+ $ unbound setup codex --gateway Use Unbound as AI provider
35
+ $ unbound setup codex --subscription Hooks only (keep your subscription)
34
36
 
35
37
  Instruction-only (shows config values to set manually):
36
38
  $ unbound setup roo-code Show Roo Code config values
@@ -46,9 +48,9 @@ TOOL SETUP
46
48
 
47
49
  MDM SETUP (admin, requires root)
48
50
  $ sudo unbound setup mdm --admin-api-key KEY --all
49
- $ sudo unbound setup mdm --admin-api-key KEY cursor codex
50
- $ sudo unbound setup mdm --admin-api-key KEY claude-code-subscription gemini-cli
51
- $ sudo unbound setup mdm --admin-api-key KEY --clear cursor codex
51
+ $ sudo unbound setup mdm --admin-api-key KEY cursor codex-subscription
52
+ $ sudo unbound setup mdm --admin-api-key KEY claude-code-subscription codex-subscription gemini-cli
53
+ $ sudo unbound setup mdm --admin-api-key KEY --clear cursor codex-subscription
52
54
 
53
55
  MDM AI TOOLS DISCOVERY
54
56
  --domain defaults to https://backend.getunbound.ai