@r4security/cli 0.0.1 → 0.0.3
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 +20 -7
- package/bin/r4.js +5 -0
- package/lib/index.js +108 -28
- package/lib/index.js.map +1 -1
- package/package.json +13 -10
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @r4security/cli
|
|
2
2
|
|
|
3
|
-
Official R4 CLI -- manage vaults, projects, and secrets from the terminal.
|
|
3
|
+
Official R4 CLI -- manage vaults, projects, and secrets from the terminal using the zero-trust Node SDK path.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install -g
|
|
8
|
+
npm install -g @r4security/cli
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
Requires Node.js >= 18.0.0.
|
|
@@ -20,8 +20,8 @@ Manage API key authentication.
|
|
|
20
20
|
|
|
21
21
|
### `r4 vault`
|
|
22
22
|
Manage vault secrets.
|
|
23
|
-
- `r4 vault list` -- List
|
|
24
|
-
- `r4 vault get <name>` -- Get a specific
|
|
23
|
+
- `r4 vault list` -- List locally decrypted environment variables
|
|
24
|
+
- `r4 vault get <name>` -- Get a specific locally decrypted secret
|
|
25
25
|
|
|
26
26
|
### `r4 project`
|
|
27
27
|
Manage projects.
|
|
@@ -42,18 +42,31 @@ r4 run --prefix R4 -- docker compose up
|
|
|
42
42
|
| Flag | Description |
|
|
43
43
|
|--------------------|---------------------------------------------------|
|
|
44
44
|
| `--api-key <key>` | API key (overrides `R4_API_KEY` env var and config)|
|
|
45
|
-
| `--project-id <id>`|
|
|
45
|
+
| `--project-id <id>`| Optional project filter (overrides `R4_PROJECT_ID` env var) |
|
|
46
|
+
| `--dev` | Use `https://dev.r4.dev` unless an explicit base URL is set |
|
|
46
47
|
| `--base-url <url>` | API base URL (default: `https://r4.dev`) |
|
|
48
|
+
| `--private-key-path <path>` | Path to the local agent private key PEM |
|
|
49
|
+
| `--trust-store-path <path>` | Path to the local signer trust-store JSON |
|
|
47
50
|
| `--json` | Output as JSON for scripting and piping |
|
|
48
51
|
|
|
52
|
+
The CLI now follows the same zero-trust agent flow as `@r4security/sdk`, so it needs an
|
|
53
|
+
AGENT-scoped API key plus a local private key. Provide the key path via
|
|
54
|
+
`--private-key-path`, `R4_PRIVATE_KEY_PATH`, or `~/.r4/config.json`.
|
|
55
|
+
Set `R4_DEV=1` or save `dev: true` via `r4 auth login --dev` to default to
|
|
56
|
+
`https://dev.r4.dev`. Any explicit `--base-url`, `R4_BASE_URL`, or saved
|
|
57
|
+
`baseUrl` still wins over dev mode.
|
|
58
|
+
When the CLI is pointed at `https://dev.r4.dev`, it uses the dev API but skips
|
|
59
|
+
the public transparency witness anchor and falls back to local trust pins.
|
|
60
|
+
|
|
49
61
|
## Dependencies
|
|
50
62
|
|
|
51
|
-
Uses
|
|
63
|
+
Uses the published `@r4security/sdk` package under the hood for API communication. Built with Commander, Chalk, ora, and cli-table3.
|
|
52
64
|
|
|
53
65
|
## Development
|
|
54
66
|
|
|
55
67
|
```bash
|
|
56
68
|
pnpm run build # Build with tsup
|
|
57
69
|
pnpm run dev # Watch mode
|
|
70
|
+
pnpm run test # Run CLI runtime-config tests
|
|
58
71
|
pnpm run clean # Remove lib/
|
|
59
72
|
```
|
package/bin/r4.js
ADDED
package/lib/index.js
CHANGED
|
@@ -90,6 +90,63 @@ function withErrorHandler(fn) {
|
|
|
90
90
|
};
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
// src/lib/runtime-config.ts
|
|
94
|
+
var R4_DEFAULT_API_BASE_URL = "https://r4.dev";
|
|
95
|
+
var R4_DEV_API_BASE_URL = "https://dev.r4.dev";
|
|
96
|
+
function normalizeBaseUrl(baseUrl) {
|
|
97
|
+
return baseUrl.replace(/\/+$/, "");
|
|
98
|
+
}
|
|
99
|
+
function isTruthyEnvFlag(value) {
|
|
100
|
+
if (!value) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
return ["1", "true", "yes", "on"].includes(value.trim().toLowerCase());
|
|
104
|
+
}
|
|
105
|
+
function resolveRuntimeMode(sources) {
|
|
106
|
+
const explicitBaseUrl = sources.cliBaseUrl || sources.envBaseUrl || sources.configBaseUrl;
|
|
107
|
+
if (explicitBaseUrl) {
|
|
108
|
+
return {
|
|
109
|
+
baseUrl: explicitBaseUrl,
|
|
110
|
+
devMode: normalizeBaseUrl(explicitBaseUrl) === R4_DEV_API_BASE_URL
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const devMode = sources.cliDev === true || isTruthyEnvFlag(sources.envDev) || sources.configDev === true;
|
|
114
|
+
return {
|
|
115
|
+
baseUrl: devMode ? R4_DEV_API_BASE_URL : R4_DEFAULT_API_BASE_URL,
|
|
116
|
+
devMode
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function resolveRuntimeModeFromCli(opts, config) {
|
|
120
|
+
return resolveRuntimeMode({
|
|
121
|
+
cliBaseUrl: opts.baseUrl,
|
|
122
|
+
envBaseUrl: process.env.R4_BASE_URL,
|
|
123
|
+
configBaseUrl: config.baseUrl,
|
|
124
|
+
cliDev: opts.dev,
|
|
125
|
+
envDev: process.env.R4_DEV,
|
|
126
|
+
configDev: config.dev
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function applyGlobalRuntimeOptionsToConfig(config, opts) {
|
|
130
|
+
const nextConfig = { ...config };
|
|
131
|
+
if (opts.baseUrl) {
|
|
132
|
+
nextConfig.baseUrl = opts.baseUrl;
|
|
133
|
+
delete nextConfig.dev;
|
|
134
|
+
} else if (opts.dev === true) {
|
|
135
|
+
nextConfig.dev = true;
|
|
136
|
+
delete nextConfig.baseUrl;
|
|
137
|
+
}
|
|
138
|
+
if (opts.projectId) {
|
|
139
|
+
nextConfig.projectId = opts.projectId;
|
|
140
|
+
}
|
|
141
|
+
if (opts.privateKeyPath) {
|
|
142
|
+
nextConfig.privateKeyPath = opts.privateKeyPath;
|
|
143
|
+
}
|
|
144
|
+
if (opts.trustStorePath) {
|
|
145
|
+
nextConfig.trustStorePath = opts.trustStorePath;
|
|
146
|
+
}
|
|
147
|
+
return nextConfig;
|
|
148
|
+
}
|
|
149
|
+
|
|
93
150
|
// src/commands/auth/login.ts
|
|
94
151
|
function prompt(question) {
|
|
95
152
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -101,7 +158,7 @@ function prompt(question) {
|
|
|
101
158
|
});
|
|
102
159
|
}
|
|
103
160
|
function loginCommand() {
|
|
104
|
-
return new Command("login").description("Save your API key to the config file").action(
|
|
161
|
+
return new Command("login").description("Save your API key and runtime key paths to the config file").action(
|
|
105
162
|
withErrorHandler(async (_opts, cmd) => {
|
|
106
163
|
const globalOpts = cmd.optsWithGlobals();
|
|
107
164
|
let apiKey = globalOpts.apiKey || process.env.R4_API_KEY;
|
|
@@ -114,13 +171,13 @@ function loginCommand() {
|
|
|
114
171
|
if (!apiKey.includes(".")) {
|
|
115
172
|
warn("API key format is usually {accessKey}.{secret}");
|
|
116
173
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (globalOpts.baseUrl) {
|
|
120
|
-
config.baseUrl = globalOpts.baseUrl;
|
|
174
|
+
if (globalOpts.baseUrl && globalOpts.dev) {
|
|
175
|
+
warn("--base-url takes precedence over --dev and will be saved as the active runtime URL.");
|
|
121
176
|
}
|
|
177
|
+
const config = applyGlobalRuntimeOptionsToConfig(loadConfig(), globalOpts);
|
|
178
|
+
config.apiKey = apiKey;
|
|
122
179
|
saveConfig(config);
|
|
123
|
-
success(`
|
|
180
|
+
success(`Runtime settings saved to ${getConfigPath()}`);
|
|
124
181
|
})
|
|
125
182
|
);
|
|
126
183
|
}
|
|
@@ -148,8 +205,11 @@ function statusCommand() {
|
|
|
148
205
|
withErrorHandler(async (_opts, cmd) => {
|
|
149
206
|
const globalOpts = cmd.optsWithGlobals();
|
|
150
207
|
const config = loadConfig();
|
|
208
|
+
const runtimeMode = resolveRuntimeModeFromCli(globalOpts, config);
|
|
151
209
|
let source;
|
|
152
210
|
let apiKey;
|
|
211
|
+
const privateKeyPath = globalOpts.privateKeyPath || process.env.R4_PRIVATE_KEY_PATH || config.privateKeyPath;
|
|
212
|
+
const trustStorePath = globalOpts.trustStorePath || process.env.R4_TRUST_STORE_PATH || config.trustStorePath;
|
|
153
213
|
if (globalOpts.apiKey) {
|
|
154
214
|
source = "--api-key flag";
|
|
155
215
|
apiKey = globalOpts.apiKey;
|
|
@@ -169,7 +229,10 @@ function statusCommand() {
|
|
|
169
229
|
authenticated: !!apiKey,
|
|
170
230
|
source,
|
|
171
231
|
apiKey: apiKey ? maskKey(apiKey) : null,
|
|
172
|
-
baseUrl:
|
|
232
|
+
baseUrl: runtimeMode.baseUrl,
|
|
233
|
+
devMode: runtimeMode.devMode,
|
|
234
|
+
privateKeyPath: privateKeyPath || null,
|
|
235
|
+
trustStorePath: trustStorePath || null
|
|
173
236
|
},
|
|
174
237
|
null,
|
|
175
238
|
2
|
|
@@ -185,10 +248,10 @@ function statusCommand() {
|
|
|
185
248
|
[
|
|
186
249
|
["Source", source],
|
|
187
250
|
["API Key", maskKey(apiKey)],
|
|
188
|
-
[
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
]
|
|
251
|
+
["Mode", runtimeMode.devMode ? "dev" : "prod"],
|
|
252
|
+
["Base URL", runtimeMode.baseUrl],
|
|
253
|
+
["Private Key", privateKeyPath || chalk2.dim("(not set)")],
|
|
254
|
+
["Trust Store", trustStorePath || chalk2.dim("(default beside key file)")]
|
|
192
255
|
],
|
|
193
256
|
false
|
|
194
257
|
);
|
|
@@ -214,9 +277,11 @@ function whoamiCommand() {
|
|
|
214
277
|
withErrorHandler(async (_opts, cmd) => {
|
|
215
278
|
const globalOpts = cmd.optsWithGlobals();
|
|
216
279
|
const config = loadConfig();
|
|
280
|
+
const runtimeMode = resolveRuntimeModeFromCli(globalOpts, config);
|
|
217
281
|
const apiKey = globalOpts.apiKey || process.env.R4_API_KEY || config.apiKey;
|
|
218
282
|
const projectId = globalOpts.projectId || process.env.R4_PROJECT_ID || config.projectId;
|
|
219
|
-
const
|
|
283
|
+
const privateKeyPath = globalOpts.privateKeyPath || process.env.R4_PRIVATE_KEY_PATH || config.privateKeyPath;
|
|
284
|
+
const trustStorePath = globalOpts.trustStorePath || process.env.R4_TRUST_STORE_PATH || config.trustStorePath;
|
|
220
285
|
if (globalOpts.json) {
|
|
221
286
|
console.log(
|
|
222
287
|
JSON.stringify(
|
|
@@ -224,7 +289,10 @@ function whoamiCommand() {
|
|
|
224
289
|
authenticated: !!apiKey,
|
|
225
290
|
apiKey: apiKey ? maskKey2(apiKey) : null,
|
|
226
291
|
projectId: projectId || null,
|
|
227
|
-
baseUrl,
|
|
292
|
+
baseUrl: runtimeMode.baseUrl,
|
|
293
|
+
devMode: runtimeMode.devMode,
|
|
294
|
+
privateKeyPath: privateKeyPath || null,
|
|
295
|
+
trustStorePath: trustStorePath || null,
|
|
228
296
|
configPath: getConfigPath()
|
|
229
297
|
},
|
|
230
298
|
null,
|
|
@@ -247,7 +315,10 @@ function whoamiCommand() {
|
|
|
247
315
|
[
|
|
248
316
|
["API Key", maskKey2(apiKey)],
|
|
249
317
|
["Project ID", projectId || chalk3.dim("(not set)")],
|
|
250
|
-
["
|
|
318
|
+
["Mode", runtimeMode.devMode ? "dev" : "prod"],
|
|
319
|
+
["Base URL", runtimeMode.baseUrl],
|
|
320
|
+
["Private Key", privateKeyPath || chalk3.dim("(not set)")],
|
|
321
|
+
["Trust Store", trustStorePath || chalk3.dim("(default beside key file)")],
|
|
251
322
|
["Config File", getConfigPath()]
|
|
252
323
|
],
|
|
253
324
|
false
|
|
@@ -269,30 +340,39 @@ function registerAuthCommands(program2) {
|
|
|
269
340
|
// src/commands/vault/list.ts
|
|
270
341
|
import { Command as Command5 } from "commander";
|
|
271
342
|
import ora from "ora";
|
|
272
|
-
import R4 from "
|
|
343
|
+
import R4 from "@r4security/sdk";
|
|
273
344
|
|
|
274
345
|
// src/lib/resolve-auth.ts
|
|
275
346
|
function resolveAuth(opts) {
|
|
276
347
|
const config = loadConfig();
|
|
348
|
+
const runtimeMode = resolveRuntimeModeFromCli(opts, config);
|
|
277
349
|
const apiKey = opts.apiKey || process.env.R4_API_KEY || config.apiKey;
|
|
278
350
|
if (!apiKey) {
|
|
279
351
|
throw new Error(
|
|
280
352
|
"No API key found. Provide one via:\n --api-key <key> CLI flag\n R4_API_KEY environment variable\n r4 auth login save to config file"
|
|
281
353
|
);
|
|
282
354
|
}
|
|
283
|
-
const
|
|
284
|
-
if (!
|
|
355
|
+
const privateKeyPath = opts.privateKeyPath || process.env.R4_PRIVATE_KEY_PATH || config.privateKeyPath;
|
|
356
|
+
if (!privateKeyPath) {
|
|
285
357
|
throw new Error(
|
|
286
|
-
"No
|
|
358
|
+
"No private key path found. Provide one via:\n --private-key-path <path> CLI flag\n R4_PRIVATE_KEY_PATH environment variable\n ~/.r4/config.json config file (privateKeyPath field)"
|
|
287
359
|
);
|
|
288
360
|
}
|
|
289
|
-
const
|
|
290
|
-
|
|
361
|
+
const projectId = opts.projectId || process.env.R4_PROJECT_ID || config.projectId;
|
|
362
|
+
const trustStorePath = opts.trustStorePath || process.env.R4_TRUST_STORE_PATH || config.trustStorePath;
|
|
363
|
+
return {
|
|
364
|
+
apiKey,
|
|
365
|
+
projectId,
|
|
366
|
+
baseUrl: runtimeMode.baseUrl,
|
|
367
|
+
dev: runtimeMode.devMode,
|
|
368
|
+
privateKeyPath,
|
|
369
|
+
trustStorePath
|
|
370
|
+
};
|
|
291
371
|
}
|
|
292
372
|
|
|
293
373
|
// src/commands/vault/list.ts
|
|
294
374
|
function listCommand() {
|
|
295
|
-
return new Command5("list").description("List all
|
|
375
|
+
return new Command5("list").description("List all locally decrypted environment variables").action(
|
|
296
376
|
withErrorHandler(async (_opts, cmd) => {
|
|
297
377
|
const globalOpts = cmd.optsWithGlobals();
|
|
298
378
|
const config = resolveAuth(globalOpts);
|
|
@@ -320,9 +400,9 @@ function listCommand() {
|
|
|
320
400
|
// src/commands/vault/get.ts
|
|
321
401
|
import { Command as Command6 } from "commander";
|
|
322
402
|
import ora2 from "ora";
|
|
323
|
-
import R42 from "
|
|
403
|
+
import R42 from "@r4security/sdk";
|
|
324
404
|
function getCommand() {
|
|
325
|
-
return new Command6("get").description("Get a specific environment variable value").argument("<key>", "Environment variable key (SCREAMING_SNAKE_CASE)").action(
|
|
405
|
+
return new Command6("get").description("Get a specific locally decrypted environment variable value").argument("<key>", "Environment variable key (SCREAMING_SNAKE_CASE)").action(
|
|
326
406
|
withErrorHandler(
|
|
327
407
|
async (keyArg, _opts, cmd) => {
|
|
328
408
|
const globalOpts = cmd.optsWithGlobals();
|
|
@@ -350,7 +430,7 @@ function getCommand() {
|
|
|
350
430
|
// src/commands/vault/items.ts
|
|
351
431
|
import { Command as Command7 } from "commander";
|
|
352
432
|
import ora3 from "ora";
|
|
353
|
-
import R43 from "
|
|
433
|
+
import R43 from "@r4security/sdk";
|
|
354
434
|
function deriveItems(env) {
|
|
355
435
|
const keys = Object.keys(env).sort();
|
|
356
436
|
return keys.map((key) => ({
|
|
@@ -359,7 +439,7 @@ function deriveItems(env) {
|
|
|
359
439
|
}));
|
|
360
440
|
}
|
|
361
441
|
function itemsCommand() {
|
|
362
|
-
return new Command7("items").description("List all vault items
|
|
442
|
+
return new Command7("items").description("List all vault items represented in the locally decrypted env map").action(
|
|
363
443
|
withErrorHandler(async (_opts, cmd) => {
|
|
364
444
|
const globalOpts = cmd.optsWithGlobals();
|
|
365
445
|
const config = resolveAuth(globalOpts);
|
|
@@ -391,7 +471,7 @@ function itemsCommand() {
|
|
|
391
471
|
// src/commands/vault/search.ts
|
|
392
472
|
import { Command as Command8 } from "commander";
|
|
393
473
|
import ora4 from "ora";
|
|
394
|
-
import R44 from "
|
|
474
|
+
import R44 from "@r4security/sdk";
|
|
395
475
|
function searchCommand() {
|
|
396
476
|
return new Command8("search").description("Search vault items by name").argument("<query>", "Search query (case-insensitive match against key names)").action(
|
|
397
477
|
withErrorHandler(
|
|
@@ -631,7 +711,7 @@ function registerProjectCommands(program2) {
|
|
|
631
711
|
// src/commands/run/index.ts
|
|
632
712
|
import { spawn } from "node:child_process";
|
|
633
713
|
import ora8 from "ora";
|
|
634
|
-
import R45 from "
|
|
714
|
+
import R45 from "@r4security/sdk";
|
|
635
715
|
function registerRunCommand(program2) {
|
|
636
716
|
program2.command("run").description("Run a command with vault secrets injected as environment variables").argument("<command...>", "Command and arguments to execute").option("--prefix <prefix>", "Add prefix to all injected env var names").action(
|
|
637
717
|
withErrorHandler(
|
|
@@ -666,7 +746,7 @@ function registerRunCommand(program2) {
|
|
|
666
746
|
|
|
667
747
|
// src/index.ts
|
|
668
748
|
var program = new Command12();
|
|
669
|
-
program.name("r4").description("R4 CLI \u2014 manage vaults, projects, and secrets from the terminal").version("0.0.
|
|
749
|
+
program.name("r4").description("R4 CLI \u2014 manage vaults, projects, and secrets from the terminal").version("0.0.3").option("--api-key <key>", "API key (overrides R4_API_KEY env var and config file)").option("--project-id <id>", "Optional project ID filter (overrides R4_PROJECT_ID env var and config file)").option("--dev", "Use https://dev.r4.dev unless an explicit base URL override is set").option("--base-url <url>", "API base URL (default: https://r4.dev)").option("--private-key-path <path>", "Path to the agent private key PEM (overrides R4_PRIVATE_KEY_PATH env var and config file)").option("--trust-store-path <path>", "Path to the local signer trust-store JSON (overrides R4_TRUST_STORE_PATH env var and config file)").option("--json", "Output as JSON for scripting and piping", false);
|
|
670
750
|
registerAuthCommands(program);
|
|
671
751
|
registerVaultCommands(program);
|
|
672
752
|
registerProjectCommands(program);
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/auth/login.ts","../src/lib/config.ts","../src/lib/output.ts","../src/lib/errors.ts","../src/commands/auth/logout.ts","../src/commands/auth/status.ts","../src/commands/auth/whoami.ts","../src/commands/auth/index.ts","../src/commands/vault/list.ts","../src/lib/resolve-auth.ts","../src/commands/vault/get.ts","../src/commands/vault/items.ts","../src/commands/vault/search.ts","../src/commands/vault/index.ts","../src/commands/project/list.ts","../src/lib/client.ts","../src/commands/project/get.ts","../src/commands/project/create.ts","../src/commands/project/index.ts","../src/commands/run/index.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { registerAuthCommands } from './commands/auth/index.js'\nimport { registerVaultCommands } from './commands/vault/index.js'\nimport { registerProjectCommands } from './commands/project/index.js'\nimport { registerRunCommand } from './commands/run/index.js'\n\n/**\n * R4 CLI entry point.\n *\n * Sets up the commander program with global options and command groups:\n * - auth: Manage API key authentication\n * - vault: Manage vault secrets\n * - project: Manage projects\n * - run: Execute commands with vault secrets injected as env vars\n */\nconst program = new Command()\n\nprogram\n .name('r4')\n .description('R4 CLI — manage vaults, projects, and secrets from the terminal')\n .version('0.0.1')\n .option('--api-key <key>', 'API key (overrides R4_API_KEY env var and config file)')\n .option('--project-id <id>', 'Project ID (overrides R4_PROJECT_ID env var and config file)')\n .option('--base-url <url>', 'API base URL (default: https://r4.dev)')\n .option('--json', 'Output as JSON for scripting and piping', false)\n\nregisterAuthCommands(program)\nregisterVaultCommands(program)\nregisterProjectCommands(program)\nregisterRunCommand(program)\n\nprogram.parse()\n","import { Command } from 'commander'\nimport readline from 'node:readline'\nimport { loadConfig, saveConfig, getConfigPath } from '../../lib/config.js'\nimport { success, warn } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * Prompt the user for input via stdin.\n * Used when no --api-key flag is provided.\n */\nfunction prompt(question: string): Promise<string> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout })\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close()\n resolve(answer.trim())\n })\n })\n}\n\n/** r4 auth login — Save API key to config file */\nexport function loginCommand(): Command {\n return new Command('login')\n .description('Save your API key to the config file')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n\n let apiKey = globalOpts.apiKey || process.env.R4_API_KEY\n\n if (!apiKey) {\n apiKey = await prompt('Enter your R4 API key: ')\n }\n\n if (!apiKey) {\n throw new Error('No API key provided.')\n }\n\n if (!apiKey.includes('.')) {\n warn('API key format is usually {accessKey}.{secret}')\n }\n\n const config = loadConfig()\n config.apiKey = apiKey\n\n if (globalOpts.baseUrl) {\n config.baseUrl = globalOpts.baseUrl\n }\n\n saveConfig(config)\n success(`API key saved to ${getConfigPath()}`)\n }),\n )\n}\n","import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport type { R4ConfigFile } from '../types.js'\n\nconst CONFIG_DIR = path.join(os.homedir(), '.r4')\nconst CONFIG_PATH = path.join(CONFIG_DIR, 'config.json')\n\n/**\n * Load the R4 config file from ~/.r4/config.json.\n * Returns an empty object if the file does not exist or is invalid.\n */\nexport function loadConfig(): R4ConfigFile {\n try {\n const raw = fs.readFileSync(CONFIG_PATH, 'utf8')\n return JSON.parse(raw) as R4ConfigFile\n } catch {\n return {}\n }\n}\n\n/**\n * Save the R4 config file to ~/.r4/config.json.\n * Creates the ~/.r4 directory if it does not exist.\n */\nexport function saveConfig(config: R4ConfigFile): void {\n fs.mkdirSync(CONFIG_DIR, { recursive: true })\n fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + '\\n', 'utf8')\n}\n\n/**\n * Remove the R4 config file.\n */\nexport function clearConfig(): void {\n try {\n fs.unlinkSync(CONFIG_PATH)\n } catch {\n // File doesn't exist, nothing to do\n }\n}\n\n/**\n * Get the path to the config file (for display purposes).\n */\nexport function getConfigPath(): string {\n return CONFIG_PATH\n}\n","import chalk from 'chalk'\nimport Table from 'cli-table3'\n\n/**\n * Print data as a formatted table, or as JSON if --json flag is set.\n */\nexport function printTable(\n headers: string[],\n rows: string[][],\n jsonMode: boolean,\n jsonData?: unknown,\n): void {\n if (jsonMode) {\n console.log(JSON.stringify(jsonData ?? rows, null, 2))\n return\n }\n\n const table = new Table({\n head: headers.map((h) => chalk.cyan(h)),\n style: { head: [], border: [] },\n })\n for (const row of rows) {\n table.push(row)\n }\n console.log(table.toString())\n}\n\n/**\n * Print a key-value detail view.\n */\nexport function printDetail(\n entries: [string, string | null | undefined][],\n jsonMode: boolean,\n jsonData?: unknown,\n): void {\n if (jsonMode) {\n console.log(JSON.stringify(jsonData, null, 2))\n return\n }\n\n const maxLen = Math.max(...entries.map(([k]) => k.length))\n for (const [key, value] of entries) {\n const label = chalk.gray(key.padEnd(maxLen))\n const val = value ?? chalk.dim('(empty)')\n console.log(` ${label} ${val}`)\n }\n}\n\n/** Print a success message */\nexport function success(message: string): void {\n console.log(chalk.green('✓') + ' ' + message)\n}\n\n/** Print a warning */\nexport function warn(message: string): void {\n console.log(chalk.yellow('!') + ' ' + message)\n}\n\n/** Print an error message to stderr */\nexport function printError(message: string): void {\n console.error(chalk.red('✗') + ' ' + message)\n}\n","import { printError } from './output.js'\n\n/**\n * Wrap a command handler to catch errors and exit with proper codes.\n * Formats R4 API errors and auth errors with helpful messages.\n */\nexport function withErrorHandler<T extends unknown[]>(\n fn: (...args: T) => Promise<void>,\n): (...args: T) => Promise<void> {\n return async (...args: T) => {\n try {\n await fn(...args)\n } catch (err) {\n if (err instanceof Error) {\n printError(err.message)\n } else {\n printError('An unexpected error occurred')\n }\n process.exit(1)\n }\n }\n}\n","import { Command } from 'commander'\nimport { clearConfig, getConfigPath } from '../../lib/config.js'\nimport { success } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\n\n/** r4 auth logout — Remove saved credentials */\nexport function logoutCommand(): Command {\n return new Command('logout')\n .description('Remove saved API key from the config file')\n .action(\n withErrorHandler(async () => {\n clearConfig()\n success(`Config removed from ${getConfigPath()}`)\n }),\n )\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport { loadConfig, getConfigPath } from '../../lib/config.js'\nimport { printDetail } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/** Mask an API key for display, showing only the first 8 characters */\nfunction maskKey(key: string): string {\n if (key.length <= 8) return key\n return key.substring(0, 8) + '...'\n}\n\n/** r4 auth status — Show current auth status */\nexport function statusCommand(): Command {\n return new Command('status')\n .description('Show current authentication status')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = loadConfig()\n\n let source: string\n let apiKey: string | undefined\n\n if (globalOpts.apiKey) {\n source = '--api-key flag'\n apiKey = globalOpts.apiKey\n } else if (process.env.R4_API_KEY) {\n source = 'R4_API_KEY env var'\n apiKey = process.env.R4_API_KEY\n } else if (config.apiKey) {\n source = `config file (${getConfigPath()})`\n apiKey = config.apiKey\n } else {\n source = 'none'\n }\n\n if (globalOpts.json) {\n console.log(\n JSON.stringify(\n {\n authenticated: !!apiKey,\n source,\n apiKey: apiKey ? maskKey(apiKey) : null,\n baseUrl: globalOpts.baseUrl || process.env.R4_BASE_URL || config.baseUrl || 'https://r4.dev',\n },\n null,\n 2,\n ),\n )\n return\n }\n\n console.log()\n if (apiKey) {\n console.log(chalk.bold(' Authenticated'))\n console.log()\n printDetail(\n [\n ['Source', source],\n ['API Key', maskKey(apiKey)],\n [\n 'Base URL',\n globalOpts.baseUrl || process.env.R4_BASE_URL || config.baseUrl || 'https://r4.dev',\n ],\n ],\n false,\n )\n } else {\n console.log(chalk.bold(' Not authenticated'))\n console.log()\n console.log(' Run ' + chalk.cyan('r4 auth login') + ' to save your API key.')\n }\n console.log()\n }),\n )\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport { loadConfig, getConfigPath } from '../../lib/config.js'\nimport { printDetail } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/** Mask an API key for display, showing only the first 8 characters */\nfunction maskKey(key: string): string {\n if (key.length <= 8) return key\n return key.substring(0, 8) + '...'\n}\n\n/**\n * r4 auth whoami — Show the current authenticated identity.\n * Displays the resolved org context, project ID, and base URL\n * based on CLI flags, environment variables, and config file.\n */\nexport function whoamiCommand(): Command {\n return new Command('whoami')\n .description('Show current authenticated identity')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = loadConfig()\n\n const apiKey = globalOpts.apiKey || process.env.R4_API_KEY || config.apiKey\n const projectId = globalOpts.projectId || process.env.R4_PROJECT_ID || config.projectId\n const baseUrl =\n globalOpts.baseUrl || process.env.R4_BASE_URL || config.baseUrl || 'https://r4.dev'\n\n if (globalOpts.json) {\n console.log(\n JSON.stringify(\n {\n authenticated: !!apiKey,\n apiKey: apiKey ? maskKey(apiKey) : null,\n projectId: projectId || null,\n baseUrl,\n configPath: getConfigPath(),\n },\n null,\n 2,\n ),\n )\n return\n }\n\n console.log()\n if (!apiKey) {\n console.log(chalk.bold(' Not authenticated'))\n console.log()\n console.log(' Run ' + chalk.cyan('r4 auth login') + ' to save your API key.')\n console.log()\n return\n }\n\n console.log(chalk.bold(' Authenticated'))\n console.log()\n printDetail(\n [\n ['API Key', maskKey(apiKey)],\n ['Project ID', projectId || chalk.dim('(not set)')],\n ['Base URL', baseUrl],\n ['Config File', getConfigPath()],\n ],\n false,\n )\n console.log()\n }),\n )\n}\n","import type { Command } from 'commander'\nimport { loginCommand } from './login.js'\nimport { logoutCommand } from './logout.js'\nimport { statusCommand } from './status.js'\nimport { whoamiCommand } from './whoami.js'\n\n/** Register auth subcommands on the CLI program */\nexport function registerAuthCommands(program: Command): void {\n const auth = program.command('auth').description('Manage API key authentication')\n\n auth.addCommand(loginCommand())\n auth.addCommand(logoutCommand())\n auth.addCommand(statusCommand())\n auth.addCommand(whoamiCommand())\n}\n","import { Command } from 'commander'\nimport ora from 'ora'\nimport R4 from 'r4-sdk'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { printTable } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * r4 vault list — List all project environment variables as a table.\n * Uses the R4 SDK env endpoint to fetch a flat key-value map.\n */\nexport function listCommand(): Command {\n return new Command('list')\n .description('List all project environment variables')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n\n const spinner = ora('Fetching environment variables...').start()\n const r4 = await R4.create(config)\n spinner.stop()\n\n const env = r4.env\n const keys = Object.keys(env).sort()\n\n if (globalOpts.json) {\n console.log(JSON.stringify(env, null, 2))\n return\n }\n\n if (keys.length === 0) {\n console.log('\\n No environment variables found.\\n')\n return\n }\n\n const rows = keys.map((key) => [key, env[key]])\n\n console.log()\n printTable(['Key', 'Value'], rows, false)\n console.log()\n }),\n )\n}\n","import type { R4Config } from 'r4-sdk'\nimport type { GlobalOptions } from '../types.js'\nimport { loadConfig } from './config.js'\n\n/**\n * Resolve R4 SDK configuration from CLI flags, environment variables, and config file.\n *\n * Precedence (highest to lowest):\n * 1. CLI flags (--api-key, --base-url, --project-id)\n * 2. Environment variables (R4_API_KEY, R4_BASE_URL, R4_PROJECT_ID)\n * 3. Config file (~/.r4/config.json)\n * 4. Defaults (baseUrl: https://r4.dev)\n *\n * Throws if no API key or project ID is found from any source.\n */\nexport function resolveAuth(opts: GlobalOptions): R4Config {\n const config = loadConfig()\n\n const apiKey = opts.apiKey || process.env.R4_API_KEY || config.apiKey\n if (!apiKey) {\n throw new Error(\n 'No API key found. Provide one via:\\n' +\n ' --api-key <key> CLI flag\\n' +\n ' R4_API_KEY environment variable\\n' +\n ' r4 auth login save to config file',\n )\n }\n\n const projectId = opts.projectId || process.env.R4_PROJECT_ID || config.projectId\n if (!projectId) {\n throw new Error(\n 'No project ID found. Provide one via:\\n' +\n ' --project-id <id> CLI flag\\n' +\n ' R4_PROJECT_ID environment variable\\n' +\n ' ~/.r4/config.json config file (projectId field)',\n )\n }\n\n const baseUrl = opts.baseUrl || process.env.R4_BASE_URL || config.baseUrl || 'https://r4.dev'\n\n return { apiKey, projectId, baseUrl }\n}\n","import { Command } from 'commander'\nimport ora from 'ora'\nimport R4 from 'r4-sdk'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * r4 vault get <KEY> — Get a specific environment variable value.\n * Outputs the raw value, perfect for piping: r4 vault get PRODUCTION_DB_PASSWORD | pbcopy\n */\nexport function getCommand(): Command {\n return new Command('get')\n .description('Get a specific environment variable value')\n .argument('<key>', 'Environment variable key (SCREAMING_SNAKE_CASE)')\n .action(\n withErrorHandler(\n async (keyArg: string, _opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n\n const spinner = ora('Fetching environment variables...').start()\n const r4 = await R4.create(config)\n spinner.stop()\n\n const env = r4.env\n const key = keyArg.toUpperCase()\n const value = env[key]\n\n if (value === undefined) {\n const available = Object.keys(env).sort().join(', ') || '(none)'\n throw new Error(`Key \"${key}\" not found. Available keys: ${available}`)\n }\n\n if (globalOpts.json) {\n console.log(JSON.stringify({ key, value }, null, 2))\n return\n }\n\n // Raw output — perfect for piping: r4 vault get PRODUCTION_DB_PASSWORD | pbcopy\n process.stdout.write(value)\n },\n ),\n )\n}\n","import { Command } from 'commander'\nimport ora from 'ora'\nimport R4 from 'r4-sdk'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { printTable } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * Represents a vault item derived from environment variable keys.\n * Groups related fields that share the same item name prefix.\n */\ninterface VaultItem {\n name: string\n fields: { name: string; key: string }[]\n}\n\n/**\n * Derive vault items from a flat env map.\n *\n * Env keys follow the pattern: ITEM_NAME_FIELD_NAME (SCREAMING_SNAKE_CASE).\n * Since we only have the flat map, we group by common prefix heuristic:\n * - Each unique env key is treated as a single-field item\n * - The full key is the item name\n *\n * This provides a useful overview of all available secrets.\n */\nfunction deriveItems(env: Record<string, string>): VaultItem[] {\n const keys = Object.keys(env).sort()\n return keys.map((key) => ({\n name: key,\n fields: [{ name: key, key }],\n }))\n}\n\n/**\n * r4 vault items — List all vault items with their field names and types.\n * Uses the R4 SDK env endpoint to fetch variables and groups them by item.\n */\nexport function itemsCommand(): Command {\n return new Command('items')\n .description('List all vault items with their field names and types')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n\n const spinner = ora('Fetching vault items...').start()\n const r4 = await R4.create(config)\n spinner.stop()\n\n const env = r4.env\n const items = deriveItems(env)\n\n if (globalOpts.json) {\n console.log(JSON.stringify(items, null, 2))\n return\n }\n\n if (items.length === 0) {\n console.log('\\n No vault items found.\\n')\n return\n }\n\n const rows = items.map((item) => [\n item.name,\n 'secret',\n item.fields.map((f) => f.name).join(', '),\n ])\n\n console.log()\n printTable(['Name', 'Type', 'Fields'], rows, false)\n console.log()\n }),\n )\n}\n","import { Command } from 'commander'\nimport ora from 'ora'\nimport R4 from 'r4-sdk'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { printTable } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * r4 vault search <query> — Search vault items by name (case-insensitive).\n * Matches env variable keys that contain the search query.\n * Useful for finding secrets when you know part of the name.\n */\nexport function searchCommand(): Command {\n return new Command('search')\n .description('Search vault items by name')\n .argument('<query>', 'Search query (case-insensitive match against key names)')\n .action(\n withErrorHandler(\n async (query: string, _opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n\n const spinner = ora('Searching vault items...').start()\n const r4 = await R4.create(config)\n spinner.stop()\n\n const env = r4.env\n const lowerQuery = query.toLowerCase()\n\n const matches = Object.keys(env)\n .filter((key) => key.toLowerCase().includes(lowerQuery))\n .sort()\n\n if (globalOpts.json) {\n const result = matches.map((key) => ({ key, value: env[key] }))\n console.log(JSON.stringify(result, null, 2))\n return\n }\n\n if (matches.length === 0) {\n console.log(`\\n No items matching \"${query}\" found.\\n`)\n return\n }\n\n const rows = matches.map((key) => [key, env[key]])\n\n console.log()\n printTable(['Key', 'Value'], rows, false)\n console.log()\n },\n ),\n )\n}\n","import type { Command } from 'commander'\nimport { listCommand } from './list.js'\nimport { getCommand } from './get.js'\nimport { itemsCommand } from './items.js'\nimport { searchCommand } from './search.js'\n\n/** Register vault subcommands on the CLI program */\nexport function registerVaultCommands(program: Command): void {\n const vault = program.command('vault').description('Manage vault secrets')\n\n vault.addCommand(listCommand())\n vault.addCommand(getCommand())\n vault.addCommand(itemsCommand())\n vault.addCommand(searchCommand())\n}\n","import { Command } from 'commander'\nimport ora from 'ora'\nimport { CliClient } from '../../lib/client.js'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { printTable } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/** r4 project list — List all projects as a table */\nexport function listCommand(): Command {\n return new Command('list')\n .description('List all projects')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n const client = new CliClient(config.apiKey, config.baseUrl || 'https://r4.dev')\n\n const spinner = ora('Fetching projects...').start()\n const response = await client.listProjects()\n spinner.stop()\n\n const rows = response.projects.map((p) => [\n p.id,\n p.name,\n p.externalId || '-',\n String(p.vaultsCount),\n String(p.licensesCount),\n String(p.licenseGroupsCount),\n ])\n\n console.log()\n printTable(\n ['ID', 'Name', 'External ID', 'Vaults', 'Licenses', 'License Groups'],\n rows,\n !!globalOpts.json,\n response.projects,\n )\n console.log()\n }),\n )\n}\n","import type {\n ProjectListResponse,\n ProjectDetail,\n CreateProjectRequest,\n CreateProjectResponse,\n} from '../types.js'\n\n/**\n * HTTP client for machine API endpoints not covered by the r4-sdk.\n * Follows the same fetch + X-API-Key pattern as the SDK's R4Client.\n */\nexport class CliClient {\n private apiKey: string\n private baseUrl: string\n\n constructor(apiKey: string, baseUrl: string) {\n this.apiKey = apiKey\n this.baseUrl = baseUrl.replace(/\\/$/, '')\n }\n\n /**\n * Make an authenticated request to the machine API.\n * Handles error responses consistently with the SDK pattern.\n */\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`\n\n const response = await fetch(url, {\n method,\n headers: {\n 'X-API-Key': this.apiKey,\n 'Content-Type': 'application/json',\n },\n body: body ? JSON.stringify(body) : undefined,\n })\n\n if (!response.ok) {\n const errorBody = (await response.json().catch(() => ({}))) as Record<string, unknown>\n const error = errorBody?.error as Record<string, unknown> | undefined\n const errorMessage = error?.message || `HTTP ${response.status}: ${response.statusText}`\n throw new Error(`R4 API Error: ${errorMessage}`)\n }\n\n return response.json() as Promise<T>\n }\n\n /** List all projects. GET /api/v1/machine/project */\n async listProjects(): Promise<ProjectListResponse> {\n return this.request<ProjectListResponse>('GET', '/api/v1/machine/project')\n }\n\n /** Get project details. GET /api/v1/machine/project/:id */\n async getProject(id: string): Promise<ProjectDetail> {\n return this.request<ProjectDetail>('GET', `/api/v1/machine/project/${id}`)\n }\n\n /** Create a new project. POST /api/v1/machine/project */\n async createProject(data: CreateProjectRequest): Promise<CreateProjectResponse> {\n return this.request<CreateProjectResponse>('POST', '/api/v1/machine/project', data)\n }\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport ora from 'ora'\nimport { CliClient } from '../../lib/client.js'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { printDetail, printTable } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/** r4 project get <id> — Show project details with associated resources */\nexport function getCommand(): Command {\n return new Command('get')\n .description('Get project details')\n .argument('<id>', 'Project ID')\n .action(\n withErrorHandler(async (id: string, _opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n const client = new CliClient(config.apiKey, config.baseUrl || 'https://r4.dev')\n\n const spinner = ora('Fetching project...').start()\n const project = await client.getProject(id)\n spinner.stop()\n\n if (globalOpts.json) {\n console.log(JSON.stringify(project, null, 2))\n return\n }\n\n console.log()\n console.log(chalk.bold(` ${project.name}`))\n console.log()\n\n printDetail(\n [\n ['ID', project.id],\n ['External ID', project.externalId],\n ['Description', project.description],\n ['Created At', project.createdAt],\n ['Vaults', String(project.vaultsCount)],\n ['Licenses', String(project.licensesCount)],\n ['License Groups', String(project.licenseGroupsCount)],\n ],\n false,\n )\n\n if (project.vaults.length > 0) {\n console.log()\n console.log(chalk.bold(' Vaults'))\n console.log()\n printTable(\n ['ID', 'Name', 'Encrypted'],\n project.vaults.map((v) => [v.id, v.name, v.isEncrypted ? 'Yes' : 'No']),\n false,\n )\n }\n\n if (project.licenses.length > 0) {\n console.log()\n console.log(chalk.bold(' Licenses'))\n console.log()\n printTable(\n ['ID', 'Name', 'Type'],\n project.licenses.map((l) => [l.id, l.name || '-', l.type]),\n false,\n )\n }\n\n if (project.licenseGroups.length > 0) {\n console.log()\n console.log(chalk.bold(' License Groups'))\n console.log()\n printTable(\n ['ID', 'Name'],\n project.licenseGroups.map((lg) => [lg.id, lg.name]),\n false,\n )\n }\n\n console.log()\n }),\n )\n}\n","import { Command } from 'commander'\nimport readline from 'node:readline'\nimport ora from 'ora'\nimport { CliClient } from '../../lib/client.js'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { success } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/** Prompt the user for input via stdin */\nfunction prompt(question: string): Promise<string> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout })\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close()\n resolve(answer.trim())\n })\n })\n}\n\n/** r4 project create — Create a new project */\nexport function createCommand(): Command {\n return new Command('create')\n .description('Create a new project')\n .option('--name <name>', 'Project name')\n .option('--description <description>', 'Project description')\n .option('--external-id <externalId>', 'External identifier')\n .action(\n withErrorHandler(async (opts: { name?: string; description?: string; externalId?: string }, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n const client = new CliClient(config.apiKey, config.baseUrl || 'https://r4.dev')\n\n let name = opts.name\n if (!name) {\n name = await prompt('Project name: ')\n }\n if (!name) {\n throw new Error('Project name is required.')\n }\n\n const spinner = ora('Creating project...').start()\n const response = await client.createProject({\n name,\n description: opts.description,\n externalId: opts.externalId,\n })\n spinner.stop()\n\n if (globalOpts.json) {\n console.log(JSON.stringify(response, null, 2))\n return\n }\n\n success(`Project created with ID: ${response.id}`)\n }),\n )\n}\n","import type { Command } from 'commander'\nimport { listCommand } from './list.js'\nimport { getCommand } from './get.js'\nimport { createCommand } from './create.js'\n\n/** Register project subcommands on the CLI program */\nexport function registerProjectCommands(program: Command): void {\n const project = program.command('project').description('Manage projects')\n\n project.addCommand(listCommand())\n project.addCommand(getCommand())\n project.addCommand(createCommand())\n}\n","import { Command } from 'commander'\nimport { spawn } from 'node:child_process'\nimport ora from 'ora'\nimport R4 from 'r4-sdk'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * r4 run <command...> — Run a command with vault secrets injected as environment variables.\n *\n * Env var naming: SCREAMING_SNAKE_CASE keys from the project env endpoint.\n *\n * Examples:\n * r4 run --project-id abc123 node deploy.js\n * r4 run --prefix R4 -- docker compose up\n */\nexport function registerRunCommand(program: Command): void {\n program\n .command('run')\n .description('Run a command with vault secrets injected as environment variables')\n .argument('<command...>', 'Command and arguments to execute')\n .option('--prefix <prefix>', 'Add prefix to all injected env var names')\n .action(\n withErrorHandler(\n async (commandParts: string[], opts: { prefix?: string }, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n\n // 1. Fetch project env vars via the R4 SDK\n const spinner = ora('Loading vault secrets...').start()\n const r4 = await R4.create(config)\n spinner.stop()\n\n const env = r4.env\n\n // 2. Build environment variable map (optionally with prefix)\n const secretEnv: Record<string, string> = {}\n\n for (const key of Object.keys(env)) {\n const envName = opts.prefix\n ? `${opts.prefix.toUpperCase()}_${key}`\n : key\n secretEnv[envName] = env[key]\n }\n\n // 3. Spawn the child process with merged environment\n const [command, ...args] = commandParts\n const child = spawn(command, args, {\n stdio: 'inherit',\n env: { ...process.env, ...secretEnv },\n shell: true,\n })\n\n // 4. Forward the child's exit code\n child.on('close', (code) => {\n process.exit(code ?? 1)\n })\n\n child.on('error', (err) => {\n throw new Error(`Failed to execute command \"${command}\": ${err.message}`)\n })\n },\n ),\n )\n}\n"],"mappings":"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","names":["Command","Command","Command","Command","chalk","Command","chalk","Command","chalk","maskKey","Command","chalk","program","Command","Command","Command","ora","R4","Command","ora","R4","Command","ora","R4","Command","ora","R4","Command","ora","R4","Command","ora","R4","program","Command","ora","path","listCommand","Command","ora","Command","chalk","ora","getCommand","Command","ora","chalk","Command","readline","ora","prompt","readline","Command","ora","program","listCommand","getCommand","ora","R4","program","ora","R4","Command"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/auth/login.ts","../src/lib/config.ts","../src/lib/output.ts","../src/lib/errors.ts","../src/lib/runtime-config.ts","../src/commands/auth/logout.ts","../src/commands/auth/status.ts","../src/commands/auth/whoami.ts","../src/commands/auth/index.ts","../src/commands/vault/list.ts","../src/lib/resolve-auth.ts","../src/commands/vault/get.ts","../src/commands/vault/items.ts","../src/commands/vault/search.ts","../src/commands/vault/index.ts","../src/commands/project/list.ts","../src/lib/client.ts","../src/commands/project/get.ts","../src/commands/project/create.ts","../src/commands/project/index.ts","../src/commands/run/index.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { registerAuthCommands } from './commands/auth/index.js'\nimport { registerVaultCommands } from './commands/vault/index.js'\nimport { registerProjectCommands } from './commands/project/index.js'\nimport { registerRunCommand } from './commands/run/index.js'\n\n/**\n * R4 CLI entry point.\n *\n * Sets up the commander program with global options and command groups:\n * - auth: Manage API key authentication\n * - vault: Manage vault secrets\n * - project: Manage projects\n * - run: Execute commands with vault secrets injected as env vars\n */\nconst program = new Command()\n\nprogram\n .name('r4')\n .description('R4 CLI — manage vaults, projects, and secrets from the terminal')\n .version('0.0.3')\n .option('--api-key <key>', 'API key (overrides R4_API_KEY env var and config file)')\n .option('--project-id <id>', 'Optional project ID filter (overrides R4_PROJECT_ID env var and config file)')\n .option('--dev', 'Use https://dev.r4.dev unless an explicit base URL override is set')\n .option('--base-url <url>', 'API base URL (default: https://r4.dev)')\n .option('--private-key-path <path>', 'Path to the agent private key PEM (overrides R4_PRIVATE_KEY_PATH env var and config file)')\n .option('--trust-store-path <path>', 'Path to the local signer trust-store JSON (overrides R4_TRUST_STORE_PATH env var and config file)')\n .option('--json', 'Output as JSON for scripting and piping', false)\n\nregisterAuthCommands(program)\nregisterVaultCommands(program)\nregisterProjectCommands(program)\nregisterRunCommand(program)\n\nprogram.parse()\n","import { Command } from 'commander'\nimport readline from 'node:readline'\nimport { loadConfig, saveConfig, getConfigPath } from '../../lib/config.js'\nimport { success, warn } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport { applyGlobalRuntimeOptionsToConfig } from '../../lib/runtime-config.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * Prompt the user for input via stdin.\n * Used when no --api-key flag is provided.\n */\nfunction prompt(question: string): Promise<string> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout })\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close()\n resolve(answer.trim())\n })\n })\n}\n\n/** r4 auth login — Save runtime auth settings to the config file */\nexport function loginCommand(): Command {\n return new Command('login')\n .description('Save your API key and runtime key paths to the config file')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n\n let apiKey = globalOpts.apiKey || process.env.R4_API_KEY\n\n if (!apiKey) {\n apiKey = await prompt('Enter your R4 API key: ')\n }\n\n if (!apiKey) {\n throw new Error('No API key provided.')\n }\n\n if (!apiKey.includes('.')) {\n warn('API key format is usually {accessKey}.{secret}')\n }\n\n if (globalOpts.baseUrl && globalOpts.dev) {\n warn('--base-url takes precedence over --dev and will be saved as the active runtime URL.')\n }\n\n const config = applyGlobalRuntimeOptionsToConfig(loadConfig(), globalOpts)\n config.apiKey = apiKey\n\n saveConfig(config)\n success(`Runtime settings saved to ${getConfigPath()}`)\n }),\n )\n}\n","import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport type { R4ConfigFile } from '../types.js'\n\nconst CONFIG_DIR = path.join(os.homedir(), '.r4')\nconst CONFIG_PATH = path.join(CONFIG_DIR, 'config.json')\n\n/**\n * Load the R4 config file from ~/.r4/config.json.\n * Returns an empty object if the file does not exist or is invalid.\n */\nexport function loadConfig(): R4ConfigFile {\n try {\n const raw = fs.readFileSync(CONFIG_PATH, 'utf8')\n return JSON.parse(raw) as R4ConfigFile\n } catch {\n return {}\n }\n}\n\n/**\n * Save the R4 config file to ~/.r4/config.json.\n * Creates the ~/.r4 directory if it does not exist.\n */\nexport function saveConfig(config: R4ConfigFile): void {\n fs.mkdirSync(CONFIG_DIR, { recursive: true })\n fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + '\\n', 'utf8')\n}\n\n/**\n * Remove the R4 config file.\n */\nexport function clearConfig(): void {\n try {\n fs.unlinkSync(CONFIG_PATH)\n } catch {\n // File doesn't exist, nothing to do\n }\n}\n\n/**\n * Get the path to the config file (for display purposes).\n */\nexport function getConfigPath(): string {\n return CONFIG_PATH\n}\n","import chalk from 'chalk'\nimport Table from 'cli-table3'\n\n/**\n * Print data as a formatted table, or as JSON if --json flag is set.\n */\nexport function printTable(\n headers: string[],\n rows: string[][],\n jsonMode: boolean,\n jsonData?: unknown,\n): void {\n if (jsonMode) {\n console.log(JSON.stringify(jsonData ?? rows, null, 2))\n return\n }\n\n const table = new Table({\n head: headers.map((h) => chalk.cyan(h)),\n style: { head: [], border: [] },\n })\n for (const row of rows) {\n table.push(row)\n }\n console.log(table.toString())\n}\n\n/**\n * Print a key-value detail view.\n */\nexport function printDetail(\n entries: [string, string | null | undefined][],\n jsonMode: boolean,\n jsonData?: unknown,\n): void {\n if (jsonMode) {\n console.log(JSON.stringify(jsonData, null, 2))\n return\n }\n\n const maxLen = Math.max(...entries.map(([k]) => k.length))\n for (const [key, value] of entries) {\n const label = chalk.gray(key.padEnd(maxLen))\n const val = value ?? chalk.dim('(empty)')\n console.log(` ${label} ${val}`)\n }\n}\n\n/** Print a success message */\nexport function success(message: string): void {\n console.log(chalk.green('✓') + ' ' + message)\n}\n\n/** Print a warning */\nexport function warn(message: string): void {\n console.log(chalk.yellow('!') + ' ' + message)\n}\n\n/** Print an error message to stderr */\nexport function printError(message: string): void {\n console.error(chalk.red('✗') + ' ' + message)\n}\n","import { printError } from './output.js'\n\n/**\n * Wrap a command handler to catch errors and exit with proper codes.\n * Formats R4 API errors and auth errors with helpful messages.\n */\nexport function withErrorHandler<T extends unknown[]>(\n fn: (...args: T) => Promise<void>,\n): (...args: T) => Promise<void> {\n return async (...args: T) => {\n try {\n await fn(...args)\n } catch (err) {\n if (err instanceof Error) {\n printError(err.message)\n } else {\n printError('An unexpected error occurred')\n }\n process.exit(1)\n }\n }\n}\n","import type { GlobalOptions, R4ConfigFile } from '../types.js'\n\nexport const R4_DEFAULT_API_BASE_URL = 'https://r4.dev'\nexport const R4_DEV_API_BASE_URL = 'https://dev.r4.dev'\n\ntype RuntimeModeSources = {\n cliBaseUrl?: string\n envBaseUrl?: string\n configBaseUrl?: string\n cliDev?: boolean\n envDev?: string\n configDev?: boolean\n}\n\nexport type ResolvedRuntimeMode = {\n baseUrl: string\n devMode: boolean\n}\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n return baseUrl.replace(/\\/+$/, '')\n}\n\nfunction isTruthyEnvFlag(value?: string): boolean {\n if (!value) {\n return false\n }\n\n return ['1', 'true', 'yes', 'on'].includes(value.trim().toLowerCase())\n}\n\n/**\n * Resolve the effective API base URL and dev-mode state.\n * Any explicit base URL override wins over dev mode.\n */\nexport function resolveRuntimeMode(sources: RuntimeModeSources): ResolvedRuntimeMode {\n const explicitBaseUrl = sources.cliBaseUrl || sources.envBaseUrl || sources.configBaseUrl\n\n if (explicitBaseUrl) {\n return {\n baseUrl: explicitBaseUrl,\n devMode: normalizeBaseUrl(explicitBaseUrl) === R4_DEV_API_BASE_URL,\n }\n }\n\n const devMode =\n sources.cliDev === true ||\n isTruthyEnvFlag(sources.envDev) ||\n sources.configDev === true\n\n return {\n baseUrl: devMode ? R4_DEV_API_BASE_URL : R4_DEFAULT_API_BASE_URL,\n devMode,\n }\n}\n\n/**\n * Resolve the effective runtime mode from CLI flags, env vars, and config file.\n */\nexport function resolveRuntimeModeFromCli(\n opts: GlobalOptions,\n config: R4ConfigFile,\n): ResolvedRuntimeMode {\n return resolveRuntimeMode({\n cliBaseUrl: opts.baseUrl,\n envBaseUrl: process.env.R4_BASE_URL,\n configBaseUrl: config.baseUrl,\n cliDev: opts.dev,\n envDev: process.env.R4_DEV,\n configDev: config.dev,\n })\n}\n\n/**\n * Apply runtime-related global options to the persisted CLI config.\n * Saving an explicit base URL clears persisted dev mode, and saving dev mode\n * clears any persisted base URL so the dev host actually takes effect.\n */\nexport function applyGlobalRuntimeOptionsToConfig(\n config: R4ConfigFile,\n opts: Pick<GlobalOptions, 'baseUrl' | 'dev' | 'projectId' | 'privateKeyPath' | 'trustStorePath'>,\n): R4ConfigFile {\n const nextConfig: R4ConfigFile = { ...config }\n\n if (opts.baseUrl) {\n nextConfig.baseUrl = opts.baseUrl\n delete nextConfig.dev\n } else if (opts.dev === true) {\n nextConfig.dev = true\n delete nextConfig.baseUrl\n }\n\n if (opts.projectId) {\n nextConfig.projectId = opts.projectId\n }\n\n if (opts.privateKeyPath) {\n nextConfig.privateKeyPath = opts.privateKeyPath\n }\n\n if (opts.trustStorePath) {\n nextConfig.trustStorePath = opts.trustStorePath\n }\n\n return nextConfig\n}\n","import { Command } from 'commander'\nimport { clearConfig, getConfigPath } from '../../lib/config.js'\nimport { success } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\n\n/** r4 auth logout — Remove saved credentials */\nexport function logoutCommand(): Command {\n return new Command('logout')\n .description('Remove saved API key from the config file')\n .action(\n withErrorHandler(async () => {\n clearConfig()\n success(`Config removed from ${getConfigPath()}`)\n }),\n )\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport { loadConfig, getConfigPath } from '../../lib/config.js'\nimport { printDetail } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport { resolveRuntimeModeFromCli } from '../../lib/runtime-config.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/** Mask an API key for display, showing only the first 8 characters */\nfunction maskKey(key: string): string {\n if (key.length <= 8) return key\n return key.substring(0, 8) + '...'\n}\n\n/** r4 auth status — Show current auth status */\nexport function statusCommand(): Command {\n return new Command('status')\n .description('Show current authentication status')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = loadConfig()\n const runtimeMode = resolveRuntimeModeFromCli(globalOpts, config)\n\n let source: string\n let apiKey: string | undefined\n const privateKeyPath =\n globalOpts.privateKeyPath ||\n process.env.R4_PRIVATE_KEY_PATH ||\n config.privateKeyPath\n const trustStorePath =\n globalOpts.trustStorePath ||\n process.env.R4_TRUST_STORE_PATH ||\n config.trustStorePath\n\n if (globalOpts.apiKey) {\n source = '--api-key flag'\n apiKey = globalOpts.apiKey\n } else if (process.env.R4_API_KEY) {\n source = 'R4_API_KEY env var'\n apiKey = process.env.R4_API_KEY\n } else if (config.apiKey) {\n source = `config file (${getConfigPath()})`\n apiKey = config.apiKey\n } else {\n source = 'none'\n }\n\n if (globalOpts.json) {\n console.log(\n JSON.stringify(\n {\n authenticated: !!apiKey,\n source,\n apiKey: apiKey ? maskKey(apiKey) : null,\n baseUrl: runtimeMode.baseUrl,\n devMode: runtimeMode.devMode,\n privateKeyPath: privateKeyPath || null,\n trustStorePath: trustStorePath || null,\n },\n null,\n 2,\n ),\n )\n return\n }\n\n console.log()\n if (apiKey) {\n console.log(chalk.bold(' Authenticated'))\n console.log()\n printDetail(\n [\n ['Source', source],\n ['API Key', maskKey(apiKey)],\n ['Mode', runtimeMode.devMode ? 'dev' : 'prod'],\n ['Base URL', runtimeMode.baseUrl],\n ['Private Key', privateKeyPath || chalk.dim('(not set)')],\n ['Trust Store', trustStorePath || chalk.dim('(default beside key file)')],\n ],\n false,\n )\n } else {\n console.log(chalk.bold(' Not authenticated'))\n console.log()\n console.log(' Run ' + chalk.cyan('r4 auth login') + ' to save your API key.')\n }\n console.log()\n }),\n )\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport { loadConfig, getConfigPath } from '../../lib/config.js'\nimport { printDetail } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport { resolveRuntimeModeFromCli } from '../../lib/runtime-config.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/** Mask an API key for display, showing only the first 8 characters */\nfunction maskKey(key: string): string {\n if (key.length <= 8) return key\n return key.substring(0, 8) + '...'\n}\n\n/**\n * r4 auth whoami — Show the current authenticated identity.\n * Displays the resolved org context, project ID, and base URL\n * based on CLI flags, environment variables, and config file.\n */\nexport function whoamiCommand(): Command {\n return new Command('whoami')\n .description('Show current authenticated identity')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = loadConfig()\n const runtimeMode = resolveRuntimeModeFromCli(globalOpts, config)\n\n const apiKey = globalOpts.apiKey || process.env.R4_API_KEY || config.apiKey\n const projectId = globalOpts.projectId || process.env.R4_PROJECT_ID || config.projectId\n const privateKeyPath =\n globalOpts.privateKeyPath ||\n process.env.R4_PRIVATE_KEY_PATH ||\n config.privateKeyPath\n const trustStorePath =\n globalOpts.trustStorePath ||\n process.env.R4_TRUST_STORE_PATH ||\n config.trustStorePath\n\n if (globalOpts.json) {\n console.log(\n JSON.stringify(\n {\n authenticated: !!apiKey,\n apiKey: apiKey ? maskKey(apiKey) : null,\n projectId: projectId || null,\n baseUrl: runtimeMode.baseUrl,\n devMode: runtimeMode.devMode,\n privateKeyPath: privateKeyPath || null,\n trustStorePath: trustStorePath || null,\n configPath: getConfigPath(),\n },\n null,\n 2,\n ),\n )\n return\n }\n\n console.log()\n if (!apiKey) {\n console.log(chalk.bold(' Not authenticated'))\n console.log()\n console.log(' Run ' + chalk.cyan('r4 auth login') + ' to save your API key.')\n console.log()\n return\n }\n\n console.log(chalk.bold(' Authenticated'))\n console.log()\n printDetail(\n [\n ['API Key', maskKey(apiKey)],\n ['Project ID', projectId || chalk.dim('(not set)')],\n ['Mode', runtimeMode.devMode ? 'dev' : 'prod'],\n ['Base URL', runtimeMode.baseUrl],\n ['Private Key', privateKeyPath || chalk.dim('(not set)')],\n ['Trust Store', trustStorePath || chalk.dim('(default beside key file)')],\n ['Config File', getConfigPath()],\n ],\n false,\n )\n console.log()\n }),\n )\n}\n","import type { Command } from 'commander'\nimport { loginCommand } from './login.js'\nimport { logoutCommand } from './logout.js'\nimport { statusCommand } from './status.js'\nimport { whoamiCommand } from './whoami.js'\n\n/** Register auth subcommands on the CLI program */\nexport function registerAuthCommands(program: Command): void {\n const auth = program.command('auth').description('Manage API key authentication')\n\n auth.addCommand(loginCommand())\n auth.addCommand(logoutCommand())\n auth.addCommand(statusCommand())\n auth.addCommand(whoamiCommand())\n}\n","import { Command } from 'commander'\nimport ora from 'ora'\nimport R4 from '@r4security/sdk'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { printTable } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * r4 vault list — List all locally decrypted environment variables as a table.\n */\nexport function listCommand(): Command {\n return new Command('list')\n .description('List all locally decrypted environment variables')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n\n const spinner = ora('Fetching environment variables...').start()\n const r4 = await R4.create(config)\n spinner.stop()\n\n const env = r4.env\n const keys = Object.keys(env).sort()\n\n if (globalOpts.json) {\n console.log(JSON.stringify(env, null, 2))\n return\n }\n\n if (keys.length === 0) {\n console.log('\\n No environment variables found.\\n')\n return\n }\n\n const rows = keys.map((key) => [key, env[key]])\n\n console.log()\n printTable(['Key', 'Value'], rows, false)\n console.log()\n }),\n )\n}\n","import type { R4Config } from 'r4-sdk'\nimport type { GlobalOptions } from '../types.js'\nimport { loadConfig } from './config.js'\nimport { resolveRuntimeModeFromCli } from './runtime-config.js'\n\n/**\n * Resolve R4 SDK configuration from CLI flags, environment variables, and config file.\n *\n * Precedence (highest to lowest):\n * 1. CLI flags (--api-key, --base-url, --dev, --project-id, --private-key-path, --trust-store-path)\n * 2. Environment variables (R4_API_KEY, R4_BASE_URL, R4_DEV, R4_PROJECT_ID, R4_PRIVATE_KEY_PATH, R4_TRUST_STORE_PATH)\n * 3. Config file (~/.r4/config.json)\n * 4. Defaults (baseUrl: https://r4.dev)\n *\n * Explicit baseUrl overrides dev mode. Throws if no API key or private-key\n * path is found from any source.\n */\nexport function resolveAuth(opts: GlobalOptions): R4Config {\n const config = loadConfig()\n const runtimeMode = resolveRuntimeModeFromCli(opts, config)\n\n const apiKey = opts.apiKey || process.env.R4_API_KEY || config.apiKey\n if (!apiKey) {\n throw new Error(\n 'No API key found. Provide one via:\\n' +\n ' --api-key <key> CLI flag\\n' +\n ' R4_API_KEY environment variable\\n' +\n ' r4 auth login save to config file',\n )\n }\n\n const privateKeyPath =\n opts.privateKeyPath ||\n process.env.R4_PRIVATE_KEY_PATH ||\n config.privateKeyPath\n\n if (!privateKeyPath) {\n throw new Error(\n 'No private key path found. Provide one via:\\n' +\n ' --private-key-path <path> CLI flag\\n' +\n ' R4_PRIVATE_KEY_PATH environment variable\\n' +\n ' ~/.r4/config.json config file (privateKeyPath field)',\n )\n }\n\n const projectId = opts.projectId || process.env.R4_PROJECT_ID || config.projectId\n const trustStorePath =\n opts.trustStorePath ||\n process.env.R4_TRUST_STORE_PATH ||\n config.trustStorePath\n\n return {\n apiKey,\n projectId,\n baseUrl: runtimeMode.baseUrl,\n dev: runtimeMode.devMode,\n privateKeyPath,\n trustStorePath,\n }\n}\n","import { Command } from 'commander'\nimport ora from 'ora'\nimport R4 from '@r4security/sdk'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * r4 vault get <KEY> — Get a specific locally decrypted environment variable value.\n * Outputs the raw value, perfect for piping: r4 vault get PRODUCTION_DB_PASSWORD | pbcopy\n */\nexport function getCommand(): Command {\n return new Command('get')\n .description('Get a specific locally decrypted environment variable value')\n .argument('<key>', 'Environment variable key (SCREAMING_SNAKE_CASE)')\n .action(\n withErrorHandler(\n async (keyArg: string, _opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n\n const spinner = ora('Fetching environment variables...').start()\n const r4 = await R4.create(config)\n spinner.stop()\n\n const env = r4.env\n const key = keyArg.toUpperCase()\n const value = env[key]\n\n if (value === undefined) {\n const available = Object.keys(env).sort().join(', ') || '(none)'\n throw new Error(`Key \"${key}\" not found. Available keys: ${available}`)\n }\n\n if (globalOpts.json) {\n console.log(JSON.stringify({ key, value }, null, 2))\n return\n }\n\n // Raw output — perfect for piping: r4 vault get PRODUCTION_DB_PASSWORD | pbcopy\n process.stdout.write(value)\n },\n ),\n )\n}\n","import { Command } from 'commander'\nimport ora from 'ora'\nimport R4 from '@r4security/sdk'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { printTable } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * Represents a vault item derived from environment variable keys.\n * Groups related fields that share the same item name prefix.\n */\ninterface VaultItem {\n name: string\n fields: { name: string; key: string }[]\n}\n\n/**\n * Derive vault items from a flat env map.\n *\n * Env keys follow the pattern: ITEM_NAME_FIELD_NAME (SCREAMING_SNAKE_CASE).\n * Since we only have the flat map, we group by common prefix heuristic:\n * - Each unique env key is treated as a single-field item\n * - The full key is the item name\n *\n * This provides a useful overview of all available secrets.\n */\nfunction deriveItems(env: Record<string, string>): VaultItem[] {\n const keys = Object.keys(env).sort()\n return keys.map((key) => ({\n name: key,\n fields: [{ name: key, key }],\n }))\n}\n\n/**\n * r4 vault items — List all vault items with their field names and types.\n * Uses the zero-trust SDK env map and groups keys heuristically by item prefix.\n */\nexport function itemsCommand(): Command {\n return new Command('items')\n .description('List all vault items represented in the locally decrypted env map')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n\n const spinner = ora('Fetching vault items...').start()\n const r4 = await R4.create(config)\n spinner.stop()\n\n const env = r4.env\n const items = deriveItems(env)\n\n if (globalOpts.json) {\n console.log(JSON.stringify(items, null, 2))\n return\n }\n\n if (items.length === 0) {\n console.log('\\n No vault items found.\\n')\n return\n }\n\n const rows = items.map((item) => [\n item.name,\n 'secret',\n item.fields.map((f) => f.name).join(', '),\n ])\n\n console.log()\n printTable(['Name', 'Type', 'Fields'], rows, false)\n console.log()\n }),\n )\n}\n","import { Command } from 'commander'\nimport ora from 'ora'\nimport R4 from '@r4security/sdk'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { printTable } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * r4 vault search <query> — Search vault items by name (case-insensitive).\n * Matches locally decrypted env variable keys that contain the search query.\n * Useful for finding secrets when you know part of the name.\n */\nexport function searchCommand(): Command {\n return new Command('search')\n .description('Search vault items by name')\n .argument('<query>', 'Search query (case-insensitive match against key names)')\n .action(\n withErrorHandler(\n async (query: string, _opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n\n const spinner = ora('Searching vault items...').start()\n const r4 = await R4.create(config)\n spinner.stop()\n\n const env = r4.env\n const lowerQuery = query.toLowerCase()\n\n const matches = Object.keys(env)\n .filter((key) => key.toLowerCase().includes(lowerQuery))\n .sort()\n\n if (globalOpts.json) {\n const result = matches.map((key) => ({ key, value: env[key] }))\n console.log(JSON.stringify(result, null, 2))\n return\n }\n\n if (matches.length === 0) {\n console.log(`\\n No items matching \"${query}\" found.\\n`)\n return\n }\n\n const rows = matches.map((key) => [key, env[key]])\n\n console.log()\n printTable(['Key', 'Value'], rows, false)\n console.log()\n },\n ),\n )\n}\n","import type { Command } from 'commander'\nimport { listCommand } from './list.js'\nimport { getCommand } from './get.js'\nimport { itemsCommand } from './items.js'\nimport { searchCommand } from './search.js'\n\n/** Register vault subcommands on the CLI program */\nexport function registerVaultCommands(program: Command): void {\n const vault = program.command('vault').description('Manage vault secrets')\n\n vault.addCommand(listCommand())\n vault.addCommand(getCommand())\n vault.addCommand(itemsCommand())\n vault.addCommand(searchCommand())\n}\n","import { Command } from 'commander'\nimport ora from 'ora'\nimport { CliClient } from '../../lib/client.js'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { printTable } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/** r4 project list — List all projects as a table */\nexport function listCommand(): Command {\n return new Command('list')\n .description('List all projects')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n const client = new CliClient(config.apiKey, config.baseUrl || 'https://r4.dev')\n\n const spinner = ora('Fetching projects...').start()\n const response = await client.listProjects()\n spinner.stop()\n\n const rows = response.projects.map((p) => [\n p.id,\n p.name,\n p.externalId || '-',\n String(p.vaultsCount),\n String(p.licensesCount),\n String(p.licenseGroupsCount),\n ])\n\n console.log()\n printTable(\n ['ID', 'Name', 'External ID', 'Vaults', 'Licenses', 'License Groups'],\n rows,\n !!globalOpts.json,\n response.projects,\n )\n console.log()\n }),\n )\n}\n","import type {\n ProjectListResponse,\n ProjectDetail,\n CreateProjectRequest,\n CreateProjectResponse,\n} from '../types.js'\n\n/**\n * HTTP client for machine API endpoints not covered by the r4-sdk.\n * Follows the same fetch + X-API-Key pattern as the SDK's R4Client.\n */\nexport class CliClient {\n private apiKey: string\n private baseUrl: string\n\n constructor(apiKey: string, baseUrl: string) {\n this.apiKey = apiKey\n this.baseUrl = baseUrl.replace(/\\/$/, '')\n }\n\n /**\n * Make an authenticated request to the machine API.\n * Handles error responses consistently with the SDK pattern.\n */\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`\n\n const response = await fetch(url, {\n method,\n headers: {\n 'X-API-Key': this.apiKey,\n 'Content-Type': 'application/json',\n },\n body: body ? JSON.stringify(body) : undefined,\n })\n\n if (!response.ok) {\n const errorBody = (await response.json().catch(() => ({}))) as Record<string, unknown>\n const error = errorBody?.error as Record<string, unknown> | undefined\n const errorMessage = error?.message || `HTTP ${response.status}: ${response.statusText}`\n throw new Error(`R4 API Error: ${errorMessage}`)\n }\n\n return response.json() as Promise<T>\n }\n\n /** List all projects. GET /api/v1/machine/project */\n async listProjects(): Promise<ProjectListResponse> {\n return this.request<ProjectListResponse>('GET', '/api/v1/machine/project')\n }\n\n /** Get project details. GET /api/v1/machine/project/:id */\n async getProject(id: string): Promise<ProjectDetail> {\n return this.request<ProjectDetail>('GET', `/api/v1/machine/project/${id}`)\n }\n\n /** Create a new project. POST /api/v1/machine/project */\n async createProject(data: CreateProjectRequest): Promise<CreateProjectResponse> {\n return this.request<CreateProjectResponse>('POST', '/api/v1/machine/project', data)\n }\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport ora from 'ora'\nimport { CliClient } from '../../lib/client.js'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { printDetail, printTable } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/** r4 project get <id> — Show project details with associated resources */\nexport function getCommand(): Command {\n return new Command('get')\n .description('Get project details')\n .argument('<id>', 'Project ID')\n .action(\n withErrorHandler(async (id: string, _opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n const client = new CliClient(config.apiKey, config.baseUrl || 'https://r4.dev')\n\n const spinner = ora('Fetching project...').start()\n const project = await client.getProject(id)\n spinner.stop()\n\n if (globalOpts.json) {\n console.log(JSON.stringify(project, null, 2))\n return\n }\n\n console.log()\n console.log(chalk.bold(` ${project.name}`))\n console.log()\n\n printDetail(\n [\n ['ID', project.id],\n ['External ID', project.externalId],\n ['Description', project.description],\n ['Created At', project.createdAt],\n ['Vaults', String(project.vaultsCount)],\n ['Licenses', String(project.licensesCount)],\n ['License Groups', String(project.licenseGroupsCount)],\n ],\n false,\n )\n\n if (project.vaults.length > 0) {\n console.log()\n console.log(chalk.bold(' Vaults'))\n console.log()\n printTable(\n ['ID', 'Name', 'Encrypted'],\n project.vaults.map((v) => [v.id, v.name, v.isEncrypted ? 'Yes' : 'No']),\n false,\n )\n }\n\n if (project.licenses.length > 0) {\n console.log()\n console.log(chalk.bold(' Licenses'))\n console.log()\n printTable(\n ['ID', 'Name', 'Type'],\n project.licenses.map((l) => [l.id, l.name || '-', l.type]),\n false,\n )\n }\n\n if (project.licenseGroups.length > 0) {\n console.log()\n console.log(chalk.bold(' License Groups'))\n console.log()\n printTable(\n ['ID', 'Name'],\n project.licenseGroups.map((lg) => [lg.id, lg.name]),\n false,\n )\n }\n\n console.log()\n }),\n )\n}\n","import { Command } from 'commander'\nimport readline from 'node:readline'\nimport ora from 'ora'\nimport { CliClient } from '../../lib/client.js'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { success } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/** Prompt the user for input via stdin */\nfunction prompt(question: string): Promise<string> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout })\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close()\n resolve(answer.trim())\n })\n })\n}\n\n/** r4 project create — Create a new project */\nexport function createCommand(): Command {\n return new Command('create')\n .description('Create a new project')\n .option('--name <name>', 'Project name')\n .option('--description <description>', 'Project description')\n .option('--external-id <externalId>', 'External identifier')\n .action(\n withErrorHandler(async (opts: { name?: string; description?: string; externalId?: string }, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n const client = new CliClient(config.apiKey, config.baseUrl || 'https://r4.dev')\n\n let name = opts.name\n if (!name) {\n name = await prompt('Project name: ')\n }\n if (!name) {\n throw new Error('Project name is required.')\n }\n\n const spinner = ora('Creating project...').start()\n const response = await client.createProject({\n name,\n description: opts.description,\n externalId: opts.externalId,\n })\n spinner.stop()\n\n if (globalOpts.json) {\n console.log(JSON.stringify(response, null, 2))\n return\n }\n\n success(`Project created with ID: ${response.id}`)\n }),\n )\n}\n","import type { Command } from 'commander'\nimport { listCommand } from './list.js'\nimport { getCommand } from './get.js'\nimport { createCommand } from './create.js'\n\n/** Register project subcommands on the CLI program */\nexport function registerProjectCommands(program: Command): void {\n const project = program.command('project').description('Manage projects')\n\n project.addCommand(listCommand())\n project.addCommand(getCommand())\n project.addCommand(createCommand())\n}\n","import { Command } from 'commander'\nimport { spawn } from 'node:child_process'\nimport ora from 'ora'\nimport R4 from '@r4security/sdk'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * r4 run <command...> — Run a command with vault secrets injected as environment variables.\n *\n * Env var naming: SCREAMING_SNAKE_CASE keys built from locally decrypted vault items.\n *\n * Examples:\n * r4 run --project-id abc123 node deploy.js\n * r4 run --prefix R4 -- docker compose up\n */\nexport function registerRunCommand(program: Command): void {\n program\n .command('run')\n .description('Run a command with vault secrets injected as environment variables')\n .argument('<command...>', 'Command and arguments to execute')\n .option('--prefix <prefix>', 'Add prefix to all injected env var names')\n .action(\n withErrorHandler(\n async (commandParts: string[], opts: { prefix?: string }, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n\n // 1. Fetch and locally decrypt env vars via the R4 SDK\n const spinner = ora('Loading vault secrets...').start()\n const r4 = await R4.create(config)\n spinner.stop()\n\n const env = r4.env\n\n // 2. Build environment variable map (optionally with prefix)\n const secretEnv: Record<string, string> = {}\n\n for (const key of Object.keys(env)) {\n const envName = opts.prefix\n ? `${opts.prefix.toUpperCase()}_${key}`\n : key\n secretEnv[envName] = env[key]\n }\n\n // 3. Spawn the child process with merged environment\n const [command, ...args] = commandParts\n const child = spawn(command, args, {\n stdio: 'inherit',\n env: { ...process.env, ...secretEnv },\n shell: true,\n })\n\n // 4. Forward the child's exit code\n child.on('close', (code) => {\n process.exit(code ?? 1)\n })\n\n child.on('error', (err) => {\n throw new Error(`Failed to execute command \"${command}\": ${err.message}`)\n })\n },\n ),\n )\n}\n"],"mappings":"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","names":["Command","Command","Command","Command","chalk","Command","chalk","Command","chalk","maskKey","Command","chalk","program","Command","Command","Command","ora","R4","Command","ora","R4","Command","ora","R4","Command","ora","R4","Command","ora","R4","Command","ora","R4","program","Command","ora","path","listCommand","Command","ora","Command","chalk","ora","getCommand","Command","ora","chalk","Command","readline","ora","prompt","readline","Command","ora","program","listCommand","getCommand","ora","R4","program","ora","R4","Command"]}
|
package/package.json
CHANGED
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@r4security/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Official R4 CLI — manage vaults, projects, and secrets from the terminal",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"r4": "./
|
|
7
|
+
"r4": "./bin/r4.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
|
-
"lib"
|
|
10
|
+
"lib",
|
|
11
|
+
"bin"
|
|
11
12
|
],
|
|
12
|
-
"scripts": {
|
|
13
|
-
"build": "tsup",
|
|
14
|
-
"clean": "rm -rf lib",
|
|
15
|
-
"dev": "tsup --watch"
|
|
16
|
-
},
|
|
17
13
|
"keywords": [
|
|
18
14
|
"r4",
|
|
19
15
|
"cli",
|
|
@@ -30,7 +26,7 @@
|
|
|
30
26
|
"node": ">=18.0.0"
|
|
31
27
|
},
|
|
32
28
|
"dependencies": {
|
|
33
|
-
"
|
|
29
|
+
"@r4security/sdk": "0.0.3",
|
|
34
30
|
"commander": "^12.0.0",
|
|
35
31
|
"chalk": "^5.3.0",
|
|
36
32
|
"cli-table3": "^0.6.4",
|
|
@@ -38,7 +34,14 @@
|
|
|
38
34
|
},
|
|
39
35
|
"devDependencies": {
|
|
40
36
|
"@types/node": "^20.11.24",
|
|
37
|
+
"tsx": "^4.20.6",
|
|
41
38
|
"tsup": "8.2.4",
|
|
42
39
|
"typescript": "5.5.3"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsup",
|
|
43
|
+
"clean": "rm -rf lib",
|
|
44
|
+
"dev": "tsup --watch",
|
|
45
|
+
"test": "tsx --test src/**/*.test.ts"
|
|
43
46
|
}
|
|
44
|
-
}
|
|
47
|
+
}
|