cursor-keys 1.1.0 → 1.2.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 CHANGED
@@ -1,27 +1,42 @@
1
- # cursor-keys
1
+ <div align="center">
2
2
 
3
- > Per-project Cursor profiles so every window automatically uses the right BYOK API key. Two windows, two projects, two keys, zero switching.
3
+ ```
4
+ ██████╗██╗ ██╗██████╗ ███████╗ ██████╗ ██████╗ ██╗ ██╗███████╗██╗ ██╗███████╗
5
+ ██╔════╝██║ ██║██╔══██╗██╔════╝██╔═══██╗██╔══██╗ ██║ ██╔╝██╔════╝╚██╗ ██╔╝██╔════╝
6
+ ██║ ██║ ██║██████╔╝███████╗██║ ██║██████╔╝ █████╔╝ █████╗ ╚████╔╝ ███████╗
7
+ ██║ ██║ ██║██╔══██╗╚════██║██║ ██║██╔══██╗ ██╔═██╗ ██╔══╝ ╚██╔╝ ╚════██║
8
+ ╚██████╗╚██████╔╝██║ ██║███████║╚██████╔╝██║ ██║ ██║ ██╗███████╗ ██║ ███████║
9
+ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝
10
+ ```
4
11
 
5
- Cursor stores your OpenAI-compatible API key (Bonzai, LiteLLM, AI Gateway, ...) **once per profile**, not per repo. If you bill five client projects, you either babysit Settings all day or bill the wrong project. `cursor-keys` gives each project its own isolated profile and makes opening, switching, and checking keys automatic.
12
+ **Per-project Cursor profiles so every window uses the right BYOK API key.**
6
13
 
7
- ```
8
- ╔═╗┬ ┬┬─┐┌─┐┌─┐┬─┐ ┬┌─┌─┐┬ ┬┌─┐
9
- │ │ │├┬┘└─┐│ │├┬┘ ├┴┐├┤ └┬┘└─┐
10
- └─┘└─┘┴└─└─┘└─┘┴└─ ┴ ┴└─┘ ┴ └─┘ per-project Cursor API keys
14
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
15
+ [![Node](https://img.shields.io/badge/node-%E2%89%A518-5FA04E.svg)](https://nodejs.org)
16
+ [![Runtime dependencies](https://img.shields.io/badge/runtime%20deps-0-brightgreen.svg)](#development)
17
+
18
+ [Website](https://l-ubu.github.io/cursor-keys/) · [Install](#install) · [Commands](#commands) · [Config](#config)
19
+
20
+ </div>
21
+
22
+ ---
11
23
 
24
+ Cursor stores your OpenAI-compatible API key (LiteLLM, Vercel AI Gateway, corporate proxy, ...) **once per profile**, not per repo. If you bill five client projects, you either babysit Settings all day or bill the wrong project. `cursor-keys` gives each project its own isolated profile and makes opening, switching, and checking keys automatic.
25
+
26
+ ```
12
27
  $ cursor-keys status
13
28
 
14
- Project | Color | Windows | Key | Repo
15
- --------------------+----------+---------+-----+-------------------------
16
- famework-platform-1 | #339af0 | 1 | yes | ~/Projects/famework-platform-1
17
- jlr_mss | #4f8cff | 0 | no | ~/Projects/jlr_mss
18
- nokia | #845ef7 | 1 | yes | ~/Projects/nokia-main-cs
29
+ Project | Color | Windows | Key | Repo
30
+ ----------+----------+---------+-----+------------------
31
+ acme | #4f8cff | 1 | yes | ~/Projects/acme
32
+ client-a | #51cf66 | 0 | no | ~/Projects/client-a
33
+ client-b | #845ef7 | 1 | yes | ~/Projects/client-b
19
34
 
20
- $ cursor-keys doctor nokia
35
+ $ cursor-keys doctor acme
21
36
 
22
- ✓ OpenAI/Bonzai API key row present
37
+ ✓ OpenAI API key row present
23
38
  ✓ Explore subagent overrides present
24
- ✓ Base URL (connect.iobonzai.com/cursor) in profile state
39
+ ✓ Base URL (gateway.example.com/v1) in profile state
25
40
  ```
26
41
 
27
42
  ## Install
@@ -36,8 +51,8 @@ Requires Node ≥18, the Cursor CLI (`Shell Command: Install 'cursor' in PATH`),
36
51
  ## Quick start
37
52
 
38
53
  ```bash
39
- # one-time, only if your gateway is not the Bonzai default
40
- cursor-keys config baseUrl https://your-gateway.example.com/v1
54
+ # one-time: point at your OpenAI-compatible gateway
55
+ cursor-keys config baseUrl https://gateway.example.com/v1
41
56
 
42
57
  # one-time per project
43
58
  cursor-keys add acme --path ~/Projects/acme # register + create profile
@@ -64,7 +79,7 @@ One window, one profile, one key. Each project gets an isolated `--user-data-dir
64
79
 
65
80
  Settings flow one way, main to profiles: `sync` re-copies your main `settings.json` into every profile and re-applies that profile's title bar color on top. `open` does this automatically before every launch, and open windows hot-reload the file, so tweaks in your main Cursor show up everywhere. Changes made inside a profile window are overwritten on the next sync.
66
81
 
67
- `clone` copies your main Cursor state (SQLite backup) so profiles open signed-in with your theme and model config. `set-key` encrypts your project key with Cursor's own safeStorage (Chromium OSCrypt, key from the "Cursor Safe Storage" Keychain item) and writes it into the profile's secret store, round-trip verified. macOS asks for Keychain permission once; click Always Allow.
82
+ `clone` copies your main Cursor state (SQLite backup) so profiles open signed-in with your theme and model config. `set-key` encrypts your project key with Cursor's own safeStorage (Chromium OSCrypt, key from the "Cursor Safe Storage" macOS Keychain item) and writes it into the profile's secret store, round-trip verified. macOS asks for Keychain permission once; click Always Allow.
68
83
 
69
84
  ## "Which key am I on?" in three layers
70
85
 
@@ -83,7 +98,7 @@ Settings flow one way, main to profiles: `sync` re-copies your main `settings.js
83
98
  | `open [name]` | Launch Cursor with the profile (auto-detect from cwd) |
84
99
  | `status` | Projects, colors, running windows, key configured |
85
100
  | `current` | Mapping for the current directory |
86
- | `config [baseUrl [URL]]` | Show or set the gateway base URL |
101
+ | `config [get <key> · baseUrl [URL]]` | Show summary, print one value, or set the gateway base URL |
87
102
  | `sync [name]` | Re-copy main Cursor settings into profiles |
88
103
  | `doctor [name]` | Health checks: key row, base URL, subagent overrides |
89
104
  | `wrap [--install]` | zsh function so plain `cursor <path>` auto-picks the profile |
@@ -98,14 +113,21 @@ Settings flow one way, main to profiles: `sync` re-copies your main `settings.js
98
113
  ```json
99
114
  {
100
115
  "profilesRoot": "~/.cursor-profiles",
101
- "baseUrl": "https://connect.iobonzai.com/cursor",
116
+ "baseUrl": "https://gateway.example.com/v1",
102
117
  "projects": {
103
118
  "acme": { "path": "~/Projects/acme", "color": "#4f8cff" }
104
119
  }
105
120
  }
106
121
  ```
107
122
 
108
- `baseUrl` is your gateway's OpenAI-compatible endpoint (Bonzai default; point it at LiteLLM, Vercel AI Gateway, ...). `doctor` verifies it per profile.
123
+ `baseUrl` is your gateway's OpenAI-compatible endpoint. `doctor` verifies it per profile.
124
+
125
+ Read a single value for scripts (stdout only, exit 1 on unknown keys):
126
+
127
+ ```bash
128
+ cursor-keys config get baseUrl
129
+ cursor-keys config get profilesRoot
130
+ ```
109
131
 
110
132
  ## Security
111
133
 
@@ -1,12 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { runCommand } from "../src/commands.mjs";
4
- import { bold, cyan, dim, reset } from "../src/ansi.mjs";
4
+ import { bold, dim, reset, yellow } from "../src/ansi.mjs";
5
5
 
6
6
  const BANNER = `
7
- ${cyan}╔═╗┬ ┬┬─┐┌─┐┌─┐┬─┐ ┬┌─┌─┐┬ ┬┌─┐
8
- ${cyan}│ │ │├┬┘└─┐│ │├┬┘ ├┴┐├┤ └┬┘└─┐
9
- ${cyan}└─┘└─┘┴└─└─┘└─┘┴└─ ┴ ┴└─┘ ┴ └─┘${dim} per-project Cursor API keys
7
+ ${yellow} ██████╗██╗ ██╗██████╗ ███████╗ ██████╗ ██████╗ ██╗ ██╗███████╗██╗ ██╗███████╗
8
+ ${yellow}██╔════╝██║ ██║██╔══██╗██╔════╝██╔═══██╗██╔══██╗ ██║ ██╔╝██╔════╝╚██╗ ██╔╝██╔════╝
9
+ ${yellow}██║ ██║ ██║██████╔╝███████╗██║ ██║██████╔╝ █████╔╝ █████╗ ╚████╔╝ ███████╗
10
+ ${yellow}██║ ██║ ██║██╔══██╗╚════██║██║ ██║██╔══██╗ ██╔═██╗ ██╔══╝ ╚██╔╝ ╚════██║
11
+ ${yellow}╚██████╗╚██████╔╝██║ ██║███████║╚██████╔╝██║ ██║ ██║ ██╗███████╗ ██║ ███████║
12
+ ${yellow} ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝${reset}${dim} per-project Cursor API keys
10
13
  `;
11
14
 
12
15
  function printHelp() {
@@ -31,7 +34,7 @@ function printHelp() {
31
34
  );
32
35
  console.log(" current Show mapping for cwd");
33
36
  console.log(
34
- " config [baseUrl [URL]] Show or set config (gateway base URL)",
37
+ " config [get <key>|baseUrl [URL]] Show, read, or set config values",
35
38
  );
36
39
  console.log(
37
40
  " sync [name] Re-copy main Cursor settings into profiles",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursor-keys",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Per-project Cursor profiles so each window uses the correct BYOK API key. Zero dependencies.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -19,7 +19,6 @@
19
19
  "cursor",
20
20
  "cli",
21
21
  "api-key",
22
- "bonzai",
23
22
  "byok",
24
23
  "developer-tools",
25
24
  "productivity"
package/src/commands.mjs CHANGED
@@ -8,8 +8,10 @@ import {
8
8
  baseUrlFragment,
9
9
  collapseHome,
10
10
  CONFIG_FILE,
11
+ CONFIG_GETTABLE_KEYS,
11
12
  expandHome,
12
13
  findProjectByPath,
14
+ getConfigValue,
13
15
  getProject,
14
16
  loadConfig,
15
17
  pickColorForName,
@@ -177,12 +179,30 @@ function ask(question) {
177
179
  async function cmdConfig(args) {
178
180
  const { flags, positional } = parseFlags(args);
179
181
  if (flags.help) {
180
- console.log("Usage: cursor-keys config [baseUrl [URL]]");
182
+ console.log(
183
+ "Usage: cursor-keys config Show config summary",
184
+ );
185
+ console.log(
186
+ " cursor-keys config get <key> Print one value (baseUrl, profilesRoot)",
187
+ );
188
+ console.log(
189
+ " cursor-keys config baseUrl <URL> Set gateway base URL",
190
+ );
181
191
  return;
182
192
  }
183
193
  const config = loadConfig();
184
194
  const [key, value] = positional;
185
195
 
196
+ if (key === "get") {
197
+ if (!value) {
198
+ throw new Error(
199
+ `Missing config key. Usage: cursor-keys config get <${CONFIG_GETTABLE_KEYS.join("|")}>`,
200
+ );
201
+ }
202
+ console.log(getConfigValue(config, value));
203
+ return;
204
+ }
205
+
186
206
  if (!key) {
187
207
  const count = Object.keys(config.projects).length;
188
208
  console.log(
@@ -295,7 +315,7 @@ async function cmdInit(args) {
295
315
  }
296
316
  saveConfig(config);
297
317
  console.log(
298
- `\nNext: cursor-keys add <name> --clone main (creates profile + copies Bonzai settings)`,
318
+ `\nNext: cursor-keys add <name> --clone main (creates profile + copies main Cursor settings)`,
299
319
  );
300
320
  }
301
321
 
@@ -516,7 +536,7 @@ async function cmdDoctor(args) {
516
536
  if (fs.existsSync(db)) {
517
537
  const hasKey = stateDbHasKey(db, SECRET_OPENAI_KEY);
518
538
  console.log(
519
- ` ${hasKey ? ok("✓") : warn("✗")} OpenAI/Bonzai API key row present`,
539
+ ` ${hasKey ? ok("✓") : warn("✗")} OpenAI API key row present`,
520
540
  );
521
541
  if (hasKey) {
522
542
  const mainDb = path.join(
package/src/config.mjs CHANGED
@@ -98,6 +98,21 @@ export function baseUrlFragment(config) {
98
98
  return String(config.baseUrl || "").replace(/^https?:\/\//, "");
99
99
  }
100
100
 
101
+ export const CONFIG_GETTABLE_KEYS = ["baseUrl", "profilesRoot"];
102
+
103
+ /**
104
+ * @param {ReturnType<typeof loadConfig>} config
105
+ * @param {string} key
106
+ */
107
+ export function getConfigValue(config, key) {
108
+ if (!CONFIG_GETTABLE_KEYS.includes(key)) {
109
+ throw new Error(
110
+ `Unknown config key: ${key}. Known keys: ${CONFIG_GETTABLE_KEYS.join(", ")}`,
111
+ );
112
+ }
113
+ return config[key];
114
+ }
115
+
101
116
  const COLOR_PALETTE = [
102
117
  "#4f8cff",
103
118
  "#ff6b6b",
package/src/profile.mjs CHANGED
@@ -145,17 +145,16 @@ export function needsFirstRunChecklist(profileDir) {
145
145
 
146
146
  export function printFirstRunChecklist(
147
147
  projectName,
148
- baseUrl = "https://connect.iobonzai.com/cursor",
148
+ baseUrl = "https://gateway.example.com/v1",
149
149
  ) {
150
150
  console.log(`
151
151
  First-time setup for "${projectName}" in this Cursor profile:
152
152
 
153
153
  1. Cursor Settings → Models → API keys
154
- 2. Paste your project Bonzai API key under OpenAI API Key
154
+ 2. Paste your project API key under OpenAI API Key (or run: cursor-keys set-key ${projectName})
155
155
  3. Enable "Use OpenAI API Key" and "Override OpenAI Base URL"
156
156
  4. Base URL: ${baseUrl}
157
- 5. Explore Subagent Model: Composer 2.5
158
- 6. Add custom Bonzai models and disable non-Bonzai models
157
+ 5. Add your gateway models and disable models you do not use
159
158
 
160
159
  Then run: cursor-keys doctor ${projectName}
161
160
  `);