@lllanyard/cli 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -56
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -34,9 +34,9 @@ export OPENAI_BASE_URL=http://127.0.0.1:3000/openai/v1
|
|
|
34
34
|
export OPENAI_API_KEY=lly_...
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
Compatibility notes
|
|
38
|
-
- Claude Code reads its base URL and key from these environment variables; if `ANTHROPIC_AUTH_TOKEN` is also set it may take precedence, so unset it. Only API-key mode is proxied, not subscription logins. The Claude Desktop app
|
|
39
|
-
- Cursor makes some model calls from its own servers, so a localhost base URL may not work there.
|
|
37
|
+
Compatibility notes:
|
|
38
|
+
- Claude Code reads its base URL and key from these environment variables; if `ANTHROPIC_AUTH_TOKEN` is also set it may take precedence, so unset it. Only API-key mode is proxied, not subscription logins. The Claude Desktop app ignores these variables; for Desktop (and subscription use generally) see [Claude Desktop](#3-claude-desktop-and-subscription-chat-apps) below.
|
|
39
|
+
- Cursor makes some model calls from its own servers, so a localhost base URL may not work there.
|
|
40
40
|
|
|
41
41
|
## Commands
|
|
42
42
|
|
|
@@ -47,7 +47,7 @@ Compatibility notes (verify against each tool's own docs):
|
|
|
47
47
|
| `exec <command> [args…]` | Run a script with the keys it uses: `lllanyard exec pwsh -File ./Onboard-Client.ps1 -DryRun`. LLLanyard reads the script, and the helper files it loads (quoted paths, `source`/`.` lines, Python imports), for your keys' variable names and passes only those, for that run only. Keys in the output are redacted; each run is logged and shown by `usage`. `exec --keys trmm,itflow -- <command>` names the keys yourself (needed for programs that aren't scripts). Run from a terminal, the script gets a real terminal of its own (prompts like `Read-Host`, colours and window size work) on macOS, Linux and Windows, and its output is still redacted. |
|
|
48
48
|
| `list`, `remove`, `rotate`, `status` | Manage keys; `status` shows rotation due dates and exits 1 if anything is overdue (cron/CI friendly). |
|
|
49
49
|
| `agent create <name> [--client N] [--providers a,b]` / `list` / `revoke` | Placeholder tokens. `--client acme` pins an agent to the `acme` key; `--providers` limits which APIs it may reach (least privilege). |
|
|
50
|
-
| `provider add <id> --upstream https://… [--auth bearer\|header --header NAME --prefix TXT]` / `list` / `remove` | Teach the proxy a new API host (GitHub, Slack, your own service). Built-ins: openai, anthropic, gemini, openrouter, github, slack, stripe, notion
|
|
50
|
+
| `provider add <id> --upstream https://… [--auth bearer\|header --header NAME --prefix TXT]` / `list` / `remove` | Teach the proxy a new API host (GitHub, Slack, your own service). Built-ins: openai, anthropic, gemini, openrouter, github, slack, stripe, notion. |
|
|
51
51
|
| `tool add <name> --env VAR=provider[:label] [--allow-host H] [--kill-on-leak] [--pass-env V] [--inherit-env] [--no-scrub] -- <command> [args…]` / `list` / `remove` | Approve a command (e.g. an MCP server) to receive keys as environment variables, with the safeguards below. |
|
|
52
52
|
| `run <name> [-- args…]` | Run an approved tool with its keys injected and scrubbed from its output. Extra args are appended only if the tool was approved with `--allow-args`. For script tools (python, node, sh, pwsh…) the script file is pinned by hash at approval and `run` refuses if it has changed since; `--allow-args` is refused for bare interpreters (`python3 -c`, `-m`) and launchers (`env`, `xargs`, `sudo`, `npx`). `run --env … -- <cmd>` is a one-off that needs a human to confirm at a terminal. |
|
|
53
53
|
| `scan [paths] [--import --apply [--redact]]` | Find plaintext keys in `.env` files, MCP/IDE configs and shell profiles, then move them into the keychain. Dry run unless `--apply`. |
|
|
@@ -155,11 +155,9 @@ lllanyard doctor # reports whether a sandbox works on this machine
|
|
|
155
155
|
- Run it from the project folder: only the current directory is writable, and running from your home directory is refused.
|
|
156
156
|
Credential folders (`~/.ssh`, `~/.aws`, `~/.gnupg`, ...) cannot be shared even with `--share-ro/--share-rw`.
|
|
157
157
|
- Linux needs `sudo apt install bubblewrap`. Ubuntu 24.04+ restricts unprivileged user namespaces; `doctor` explains the fix.
|
|
158
|
-
- **Windows:** no sandbox
|
|
159
|
-
- **
|
|
160
|
-
|
|
161
|
-
can reach only allowlisted hosts through the bridge. **Not yet run against a real `bwrap` or on macOS** (neither was
|
|
162
|
-
available where this was built). Treat the first release as beta on those paths and run `lllanyard doctor` first.
|
|
158
|
+
- **Windows:** no sandbox. Use WSL2 (Debian/Ubuntu) to get the Linux one.
|
|
159
|
+
- **Beta.** The sandbox is tested in CI on Linux and macOS, but it is the newest part of LLLanyard. Run `lllanyard doctor`
|
|
160
|
+
first.
|
|
163
161
|
|
|
164
162
|
Honest limits:
|
|
165
163
|
|
|
@@ -183,7 +181,7 @@ git; prompt-injected agents echoing their "key" (it is only a placeholder); runa
|
|
|
183
181
|
|
|
184
182
|
**Does NOT protect against:** malicious code running *as your OS user*. A fully compromised agent that can run shell
|
|
185
183
|
commands can ask the OS keychain for the key directly (macOS prompts; Windows and Linux generally do not). For
|
|
186
|
-
untrusted agents, run the proxy under a separate OS user or on another machine (
|
|
184
|
+
untrusted agents, run the proxy under a separate OS user or on another machine (see [Sharing with a team](#sharing-with-a-team-pro)).
|
|
187
185
|
|
|
188
186
|
Built-in hardening:
|
|
189
187
|
- Zero runtime dependencies in the proxy (Node built-ins only); the only native dependency is `@napi-rs/keyring`.
|
|
@@ -211,10 +209,10 @@ Keys that sat in plaintext should be treated as exposed: after `scan --import`,
|
|
|
211
209
|
- **Debian/Ubuntu:** needs a Secret Service: `sudo apt install gnome-keyring libsecret-1-0`, inside a desktop/D-Bus session.
|
|
212
210
|
Headless servers are not supported yet.
|
|
213
211
|
|
|
214
|
-
## Tiers
|
|
212
|
+
## Tiers
|
|
215
213
|
|
|
216
|
-
Free: up to 10 keys, local only. Pro
|
|
217
|
-
and
|
|
214
|
+
Free: up to 10 keys and 5 agent tokens, local only. Pro and Team ([pricing](https://lllanyard.app/pricing)) raise the key
|
|
215
|
+
limit and add the shared proxy for a team and the usage dashboard.
|
|
218
216
|
|
|
219
217
|
### Desktop app and rotation assistant
|
|
220
218
|
|
|
@@ -231,7 +229,6 @@ tokens, usage, proxy start/stop, license, and the **rotation assistant**.
|
|
|
231
229
|
nonce. All text is inserted with `textContent`, never as HTML.
|
|
232
230
|
- Honest limits: any program running as your user could still read the session secret from the process list or the printed
|
|
233
231
|
link, as it could read your keychain; this protects against web pages and other websites, not against local malware.
|
|
234
|
-
The Tauri shell has not been compiled yet (see `apps/desktop/README.md`).
|
|
235
232
|
|
|
236
233
|
### MCP server for agents
|
|
237
234
|
|
|
@@ -267,7 +264,7 @@ Teammates point their tools at `https://keys.example.com:3443/openai/v1` and use
|
|
|
267
264
|
| Per-person scope | Each token is limited to a client (`--client`), optionally to providers, and can expire (`--expires`) |
|
|
268
265
|
| Audit trail | Every request is logged with agent name and caller address; `lllanyard usage` breaks it down by agent and client |
|
|
269
266
|
| Rate limits + kill switch | Per token, as before |
|
|
270
|
-
| Seats | Free: 5 agent tokens. Licensed: 3 tokens per seat
|
|
267
|
+
| Seats | Free: 5 agent tokens. Licensed: 3 tokens per seat |
|
|
271
268
|
|
|
272
269
|
Put it behind a VPN (Tailscale, WireGuard) or a firewall if you can; the lockout and TLS are a second layer, not a reason to
|
|
273
270
|
expose it to the whole internet. `X-Forwarded-For` is deliberately ignored, so a reverse proxy in front shows as one address.
|
|
@@ -285,8 +282,8 @@ lllanyard add openai --stdin < key.txt && lllanyard serve --host 0.0.0.0 ...
|
|
|
285
282
|
|
|
286
283
|
On a terminal with no passphrase file you are prompted instead (hidden). Under systemd use `LoadCredential=` and point
|
|
287
284
|
`LLLANYARD_VAULT_PASSPHRASE_FILE` at `$CREDENTIALS_DIRECTORY/pass`. Honest limit: it protects the vault at rest (backups,
|
|
288
|
-
disk images, other users); someone who can read both the vault and the passphrase file as your user can open it.
|
|
289
|
-
|
|
285
|
+
disk images, other users); someone who can read both the vault and the passphrase file as your user can open it. The
|
|
286
|
+
passphrase can't be changed once the vault is created.
|
|
290
287
|
|
|
291
288
|
### Usage and dashboard
|
|
292
289
|
|
|
@@ -316,13 +313,8 @@ this off; each renewed key is also emailed.
|
|
|
316
313
|
Pro lifts the key cap to 250, Team to 500 (`TIER_LIMITS` in `packages/core/src/license.ts`). An expired license drops
|
|
317
314
|
back to free: existing keys keep working, you just can't add past the free cap.
|
|
318
315
|
|
|
319
|
-
**
|
|
320
|
-
|
|
321
|
-
`node tools/issue-license.mjs issue --key ~/lly-keys/license-private.pem --tier pro --days 365 --sub order-123`.
|
|
322
|
-
Until `LICENSE_PUBLIC_KEY` is set, no license validates.
|
|
323
|
-
|
|
324
|
-
**Honest limit:** a local check can be patched in private. The BSL license (see License) forbids it and makes such use
|
|
325
|
-
unlicensed, but the features worth paying for (shared proxy, cloud sync) should also live where a local patch can't reach.
|
|
316
|
+
**Honest limit:** a local check can be patched in private. The license (see License) forbids it and makes such use
|
|
317
|
+
unlicensed.
|
|
326
318
|
|
|
327
319
|
## License
|
|
328
320
|
|
|
@@ -337,42 +329,16 @@ In plain words (the license text is what counts):
|
|
|
337
329
|
- You may not resell it as a hosted/embedded competing product.
|
|
338
330
|
- Each version converts to Apache 2.0 four years after its release.
|
|
339
331
|
|
|
340
|
-
|
|
341
|
-
commercial remedy), but cannot physically stop someone doing it in private. Keep the genuinely valuable features (shared
|
|
342
|
-
proxy operations, cloud sync, support, updates) where only you can provide them.
|
|
343
|
-
|
|
344
|
-
Before publishing: fill in the licensing contact email in `LICENSE.md`, and have a lawyer review the **Additional Use Grant**
|
|
345
|
-
(it is my drafting, not boilerplate) and the Change License choice. The BSL body text was taken from a published BSL 1.1 copy
|
|
346
|
-
(HashiCorp's) because the official page was unreachable; compare it with mariadb.com/bsl11, which also includes a
|
|
347
|
-
"Covenants of Licensor" section you should keep if you use the name "Business Source License". PolyForm Shield and
|
|
348
|
-
Noncommercial texts remain in `docs/license-options/` as alternatives; note Shield does **not** forbid patching out checks.
|
|
332
|
+
Licensing questions: sales@lllanyard.co.uk.
|
|
349
333
|
|
|
350
334
|
## Verifying on your machine
|
|
351
335
|
|
|
352
336
|
`node tools/smoke.mjs` (add `--keychain` to also test your real OS keychain once) runs the real CLI, proxy, UI and MCP server
|
|
353
|
-
against a throwaway vault and prints PASS/FAIL plus a one-line report for bug reports.
|
|
354
|
-
pre-launch checklist.
|
|
337
|
+
against a throwaway vault and prints PASS/FAIL plus a one-line report for bug reports.
|
|
355
338
|
|
|
356
339
|
## Tests
|
|
357
340
|
|
|
358
|
-
`npm test` (tsx + node:test
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
agent scoping, log hygiene). A manual end-to-end pass of the CLI, a custom provider and the live proxy also succeeded using
|
|
363
|
-
a file-backed stand-in for the keychain.
|
|
364
|
-
CI (`.github/workflows/ci.yml`) runs the suite on Linux, macOS and Windows with Node 22 and 24, installs bubblewrap on Linux so
|
|
365
|
-
the real-sandbox test runs, and does a full type-check and `npm audit`. Not covered locally: real keychains on each OS, real provider endpoints, and the Windows shell path for `npx` (logic is unit-tested
|
|
366
|
-
with a simulated platform, not on Windows).
|
|
367
|
-
|
|
368
|
-
## Roadmap
|
|
369
|
-
|
|
370
|
-
1. Compile and sign the Tauri app; bundle Node as a sidecar so no separate install is needed.
|
|
371
|
-
2. E2E-encrypted cloud sync; vault passphrase change; KMS/hardware-token vault backends.
|
|
372
|
-
3. Docker sandbox mode (Windows).
|
|
373
|
-
4. Auto-rotation via provider admin APIs. Honeytoken keys need a hosted callback service, so they belong in a paid cloud tier.
|
|
374
|
-
|
|
375
|
-
## Naming
|
|
376
|
-
|
|
377
|
-
The name is a placeholder pending a trademark check. To rename: edit `packages/core/src/constants.ts` and the `@lllanyard`
|
|
378
|
-
package scope. Changing `SERVICE` orphans keys already stored under the old name.
|
|
341
|
+
`npm test` runs the suite (tsx + node:test): storage, tokens, scanner and redaction, rotation, provider and tool validation,
|
|
342
|
+
the output scrubber, the `run` engine with real child processes, the egress proxy, the sandbox, and proxy integration tests
|
|
343
|
+
against a fake upstream. CI (`.github/workflows/ci.yml`) runs it on Linux, macOS and Windows with Node 22 and 24, with a full
|
|
344
|
+
type-check and `npm audit`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lllanyard/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Keep API keys out of AI agents: keys live in your OS keychain and agents only see placeholder tokens.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
"dist"
|
|
11
11
|
],
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@lllanyard/core": "^0.1.
|
|
14
|
-
"@lllanyard/proxy": "^0.1.
|
|
15
|
-
"@lllanyard/ui": "^0.1.
|
|
13
|
+
"@lllanyard/core": "^0.1.1",
|
|
14
|
+
"@lllanyard/proxy": "^0.1.1",
|
|
15
|
+
"@lllanyard/ui": "^0.1.1"
|
|
16
16
|
},
|
|
17
17
|
"license": "BUSL-1.1",
|
|
18
18
|
"engines": {
|