cursor-keys 1.2.1 → 1.2.2
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 +4 -1
- package/bin/cursor-keys.mjs +7 -3
- package/package.json +4 -2
- package/scripts/postinstall.mjs +22 -0
- package/src/ansi.mjs +14 -4
- package/src/commands.mjs +73 -1
package/README.md
CHANGED
|
@@ -102,10 +102,13 @@ Settings flow one way, main to profiles: `sync` re-copies your main `settings.js
|
|
|
102
102
|
| `sync [name]` | Re-copy main Cursor settings into profiles |
|
|
103
103
|
| `doctor [name]` | Health checks: key row, base URL, subagent overrides |
|
|
104
104
|
| `wrap [--install]` | zsh function so plain `cursor <path>` auto-picks the profile |
|
|
105
|
-
| `aliases [--install]` | Per-project shell aliases
|
|
105
|
+
| `aliases [--install]` | Per-project shell aliases (also `ck` shortcut + tab completion) |
|
|
106
|
+
| `completion` | Print zsh tab completion (auto-sourced by `aliases --install`) |
|
|
106
107
|
| `install-extension` | Link the Cursor extension into `~/.cursor/extensions` |
|
|
107
108
|
| `rm <name> [--delete]` | Unregister (optionally delete the profile) |
|
|
108
109
|
|
|
110
|
+
`cursor-keys ls` prints registered project names one per line for scripts and tab completion; it is hidden from `--help`.
|
|
111
|
+
|
|
109
112
|
## Config
|
|
110
113
|
|
|
111
114
|
`~/.config/cursor-keys/config.json`:
|
package/bin/cursor-keys.mjs
CHANGED
|
@@ -9,12 +9,13 @@ const BANNER = `
|
|
|
9
9
|
${yellow}██║ ██║ ██║██████╔╝███████╗██║ ██║██████╔╝ █████╔╝ █████╗ ╚████╔╝ ███████╗
|
|
10
10
|
${yellow}██║ ██║ ██║██╔══██╗╚════██║██║ ██║██╔══██╗ ██╔═██╗ ██╔══╝ ╚██╔╝ ╚════██║
|
|
11
11
|
${yellow}╚██████╗╚██████╔╝██║ ██║███████║╚██████╔╝██║ ██║ ██║ ██╗███████╗ ██║ ███████║
|
|
12
|
-
${yellow} ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝${reset}
|
|
12
|
+
${yellow} ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝${reset}
|
|
13
|
+
${dim}per-project Cursor API keys${reset}
|
|
13
14
|
`;
|
|
14
15
|
|
|
15
16
|
function printHelp() {
|
|
16
17
|
console.log(BANNER);
|
|
17
|
-
console.log(`${bold}Usage:${reset} cursor-keys <command> [options]\n`);
|
|
18
|
+
console.log(`${bold}Usage:${reset} cursor-keys (or ck, ckeys) <command> [options]\n`);
|
|
18
19
|
console.log(`${bold}Commands:${reset}`);
|
|
19
20
|
console.log(
|
|
20
21
|
" init [--root DIR] [--all] Scan for git repos and register projects",
|
|
@@ -42,7 +43,10 @@ function printHelp() {
|
|
|
42
43
|
console.log(
|
|
43
44
|
" doctor [name] Verify setup for one or all projects",
|
|
44
45
|
);
|
|
45
|
-
console.log(" aliases [--install]
|
|
46
|
+
console.log(" aliases [--install] Shell aliases (incl. 'ck' + tab completion)");
|
|
47
|
+
console.log(
|
|
48
|
+
" completion Print zsh tab completion (auto-sourced by aliases)",
|
|
49
|
+
);
|
|
46
50
|
console.log(
|
|
47
51
|
" wrap [--install] Make plain `cursor <path>` auto-pick profile",
|
|
48
52
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cursor-keys",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
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": {
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"files": [
|
|
14
14
|
"bin",
|
|
15
15
|
"src",
|
|
16
|
-
"extension"
|
|
16
|
+
"extension",
|
|
17
|
+
"scripts"
|
|
17
18
|
],
|
|
18
19
|
"keywords": [
|
|
19
20
|
"cursor",
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
},
|
|
32
33
|
"scripts": {
|
|
33
34
|
"test": "node --test",
|
|
35
|
+
"postinstall": "node scripts/postinstall.mjs",
|
|
34
36
|
"prepublishOnly": "npm test"
|
|
35
37
|
}
|
|
36
38
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Postinstall hint: prints once on global install, never breaks the install.
|
|
2
|
+
// Quiet installs: CURSOR_KEYS_NO_POSTINSTALL=1
|
|
3
|
+
try {
|
|
4
|
+
if (process.env.CURSOR_KEYS_NO_POSTINSTALL) process.exit(0);
|
|
5
|
+
const yellow = "\x1b[33m";
|
|
6
|
+
const dim = "\x1b[2m";
|
|
7
|
+
const reset = "\x1b[0m";
|
|
8
|
+
console.log(`
|
|
9
|
+
${yellow}cursor-keys installed${reset}
|
|
10
|
+
|
|
11
|
+
cursor-keys --help commands
|
|
12
|
+
cursor-keys aliases --install aliases, 'ck' shortcut, tab completion
|
|
13
|
+
cursor-keys wrap --install plain 'cursor <path>' picks the profile
|
|
14
|
+
|
|
15
|
+
Inside Cursor: Cmd+Shift+P then "cursor-keys: Open Project..." after
|
|
16
|
+
'cursor-keys install-extension' (or install 'cursor-keys' from Open VSX).
|
|
17
|
+
|
|
18
|
+
${dim}Quiet installs: CURSOR_KEYS_NO_POSTINSTALL=1${reset}
|
|
19
|
+
`);
|
|
20
|
+
} catch {
|
|
21
|
+
/* postinstall must never break install */
|
|
22
|
+
}
|
package/src/ansi.mjs
CHANGED
|
@@ -26,15 +26,25 @@ export function err(text) {
|
|
|
26
26
|
return colorize(text, red);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
const ANSI_RE = /\x1b\[[0-9;]*m/g;
|
|
30
|
+
|
|
31
|
+
export function stripAnsi(s) {
|
|
32
|
+
return String(s).replace(ANSI_RE, "");
|
|
33
|
+
}
|
|
34
|
+
|
|
29
35
|
export function padEnd(str, len) {
|
|
30
36
|
const s = String(str);
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
const vis = stripAnsi(s).length;
|
|
38
|
+
if (vis >= len) return s;
|
|
39
|
+
return s + " ".repeat(len - vis);
|
|
33
40
|
}
|
|
34
41
|
|
|
35
42
|
export function printTable(headers, rows) {
|
|
36
43
|
const widths = headers.map((h, i) =>
|
|
37
|
-
Math.max(
|
|
44
|
+
Math.max(
|
|
45
|
+
h.length,
|
|
46
|
+
...rows.map((r) => stripAnsi(String(r[i] ?? "")).length),
|
|
47
|
+
),
|
|
38
48
|
);
|
|
39
49
|
const line = widths.map((w) => "-".repeat(w)).join("-+-");
|
|
40
50
|
console.log(widths.map((w, i) => padEnd(headers[i], w)).join(" | "));
|
|
@@ -51,5 +61,5 @@ export function blockSwatch(hex) {
|
|
|
51
61
|
const r = parseInt(hex.slice(1, 3), 16);
|
|
52
62
|
const g = parseInt(hex.slice(3, 5), 16);
|
|
53
63
|
const b = parseInt(hex.slice(5, 7), 16);
|
|
54
|
-
return
|
|
64
|
+
return `\x1b[48;2;${r};${g};${b}m ${reset}`;
|
|
55
65
|
}
|
package/src/commands.mjs
CHANGED
|
@@ -93,6 +93,10 @@ export async function runCommand(argv) {
|
|
|
93
93
|
return cmdClone(rest);
|
|
94
94
|
case "rm":
|
|
95
95
|
return cmdRm(rest);
|
|
96
|
+
case "ls":
|
|
97
|
+
return cmdLs(rest);
|
|
98
|
+
case "completion":
|
|
99
|
+
return cmdCompletion(rest);
|
|
96
100
|
default:
|
|
97
101
|
throw new Error(`Unknown command: ${cmd}. Run cursor-keys --help`);
|
|
98
102
|
}
|
|
@@ -569,7 +573,13 @@ async function cmdAliases(args) {
|
|
|
569
573
|
const lines = names.map(
|
|
570
574
|
(n) => `alias ${sanitizeAlias(n)}='cursor-keys open ${shellEscapeName(n)}'`,
|
|
571
575
|
);
|
|
572
|
-
const block = [
|
|
576
|
+
const block = [
|
|
577
|
+
ZSHRC_MARKER_START,
|
|
578
|
+
"alias ck='cursor-keys'",
|
|
579
|
+
'eval "$(cursor-keys completion)" # tab completion',
|
|
580
|
+
...lines,
|
|
581
|
+
ZSHRC_MARKER_END,
|
|
582
|
+
].join("\n");
|
|
573
583
|
|
|
574
584
|
if (!flags.install) {
|
|
575
585
|
console.log(block);
|
|
@@ -591,6 +601,13 @@ async function cmdAliases(args) {
|
|
|
591
601
|
}
|
|
592
602
|
fs.writeFileSync(zshrc, content, "utf8");
|
|
593
603
|
console.log(ok(`Updated ${zshrc}`));
|
|
604
|
+
if (!content.includes("compinit")) {
|
|
605
|
+
console.log(
|
|
606
|
+
warn(
|
|
607
|
+
"Note: `compinit` not found in ~/.zshrc. Tab completion needs it; add this line: autoload -Uz compinit && compinit",
|
|
608
|
+
),
|
|
609
|
+
);
|
|
610
|
+
}
|
|
594
611
|
}
|
|
595
612
|
|
|
596
613
|
function sanitizeAlias(name) {
|
|
@@ -601,6 +618,54 @@ function shellEscapeName(name) {
|
|
|
601
618
|
return name.replace(/'/g, `'\\''`);
|
|
602
619
|
}
|
|
603
620
|
|
|
621
|
+
const COMPLETION_COMMANDS =
|
|
622
|
+
"init add clone set-key open status current config sync doctor aliases wrap install-extension completion ls rm";
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Pure builder for the zsh completion script. Sourced via
|
|
626
|
+
* `eval "$(cursor-keys completion)"` from the aliases/wrap zshrc blocks,
|
|
627
|
+
* so updates ship with `npm update` and never go stale on disk.
|
|
628
|
+
*/
|
|
629
|
+
export function completionScript() {
|
|
630
|
+
return `#compdef cursor-keys ckeys ck
|
|
631
|
+
_cursor_keys() {
|
|
632
|
+
local -a projects
|
|
633
|
+
if (( CURRENT == 3 )) && [[ \${words[2]} == (open|clone|set-key|doctor|sync|rm) ]]; then
|
|
634
|
+
projects=(\${(f)"$(cursor-keys ls 2>/dev/null)"})
|
|
635
|
+
_describe 'project' projects
|
|
636
|
+
else
|
|
637
|
+
_arguments '1:command:(${COMPLETION_COMMANDS})'
|
|
638
|
+
fi
|
|
639
|
+
}
|
|
640
|
+
compdef _cursor_keys cursor-keys ckeys ck
|
|
641
|
+
`;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
function cmdCompletion(args) {
|
|
645
|
+
const { flags } = parseFlags(args);
|
|
646
|
+
if (flags.help) {
|
|
647
|
+
console.log("Usage: cursor-keys completion");
|
|
648
|
+
console.log("Prints the zsh tab completion script to stdout.");
|
|
649
|
+
console.log("Auto-sourced by `cursor-keys aliases --install`; no separate install needed.");
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
process.stdout.write(completionScript());
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* Hidden command: bare project names, one per line, for completion/scripts.
|
|
657
|
+
*/
|
|
658
|
+
function cmdLs(args) {
|
|
659
|
+
const { flags } = parseFlags(args);
|
|
660
|
+
if (flags.help) {
|
|
661
|
+
console.log("Usage: cursor-keys ls");
|
|
662
|
+
console.log("Prints registered project names, one per line (for scripts and tab completion).");
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
const config = loadConfig();
|
|
666
|
+
console.log(Object.keys(config.projects).sort().join("\n"));
|
|
667
|
+
}
|
|
668
|
+
|
|
604
669
|
function installZshrcBlock(startMarker, endMarker, block) {
|
|
605
670
|
const zshrc = path.join(os.homedir(), ".zshrc");
|
|
606
671
|
let content = fs.existsSync(zshrc) ? fs.readFileSync(zshrc, "utf8") : "";
|
|
@@ -615,6 +680,13 @@ function installZshrcBlock(startMarker, endMarker, block) {
|
|
|
615
680
|
content = content.trimEnd() + "\n\n" + block + "\n";
|
|
616
681
|
}
|
|
617
682
|
fs.writeFileSync(zshrc, content, "utf8");
|
|
683
|
+
if (!content.includes("compinit")) {
|
|
684
|
+
console.log(
|
|
685
|
+
warn(
|
|
686
|
+
"Note: `compinit` not found in ~/.zshrc. Tab completion needs it; add this line: autoload -Uz compinit && compinit",
|
|
687
|
+
),
|
|
688
|
+
);
|
|
689
|
+
}
|
|
618
690
|
return zshrc;
|
|
619
691
|
}
|
|
620
692
|
|