Skip to content

feat(cli): keychain storage, encrypted offline cache, secret refs, watch, AI-agent guards#731

Merged
HugoRCD merged 3 commits into
mainfrom
feat/v5-cli-runtime-ux
Apr 20, 2026
Merged

feat(cli): keychain storage, encrypted offline cache, secret refs, watch, AI-agent guards#731
HugoRCD merged 3 commits into
mainfrom
feat/v5-cli-runtime-ux

Conversation

@HugoRCD
Copy link
Copy Markdown
Owner

@HugoRCD HugoRCD commented Apr 20, 2026

Stacked on #730 (`feat/v5-cli-subprocess`). Merge that one first; this PR's base will auto-retarget `main` afterwards.

Summary

Make `shelve run` the default secret-injection path so `.env` files no longer need to live on disk, then close every UX gap that previously made `run` painful.

OS keychain storage

  • The CLI now stores its API token in the OS keychain via `@napi-rs/keyring` (macOS Keychain, libsecret, Windows Credential Manager).
  • File fallback is XDG-compliant (`/.config/.shelve`, mode `0600`) and the legacy `/.shelve` is migrated automatically on first read.
  • Dropped deprecated `rc9.readUser` / `writeUser` for `readUserConfig` / `writeUserConfig`.
  • `shelve logout` clears both the keychain entry and the rc file.

Encrypted offline cache

  • After every successful pull, `shelve run` writes an AES-256-GCM cache at `~/.shelve/cache/<sha256(team:project:env)>.json.enc`. Key is HKDF-derived from the API token, so revoking the token makes the cache unreadable.
  • New flags: `--offline` (force cache, fail if absent), `--no-cache` (never read or write), `--cache-ttl 24h` (override freshness).
  • If the API call fails, `shelve run` falls back to a fresh-enough cache and prints a warning instead of crashing.

Secret references

  • `shelve run --template .env.template` resolves `shelve://///` references against the live or cached secrets, leaving literal values untouched. The template can be safely committed to Git.

Watch mode

  • `shelve run --watch` polls Shelve for variable changes and forwards `SIGHUP` to the child on update (Vite/Nuxt/Next handle the reload).
  • `--restart-on-change` instead kills and respawns the child.

AI-agent guards

  • New `shelve init` writes `.cursorignore`, `.aiderignore`, `.codeiumignore`, `.continueignore`, and a `# shelve-managed-block` in `.gitignore` to keep `.env` files out of model contexts.
  • `shelve pull` detects AI-agent environments (`CURSOR_TRACE_ID`, `AIDER_VERSION`, `CLAUDECODE`, …) and prompts before writing plaintext secrets to disk (skip with `--yes`).

Direct response to the Infisical post on AI agents siphoning `.env` files.

Test plan

  • Fresh login on macOS: token lands in Keychain Access (`Shelve` entry).
  • Existing `/.shelve` users: silent migration to `/.config/.shelve`, original file removed.
  • `shelve run -- pnpm dev` then unplug network → second run with `--offline` succeeds; `--no-cache` fails fast.
  • `.env.template` with `shelve://team/proj/dev/DATABASE_URL` → resolved at `run` time, file untouched on disk.
  • `shelve run --watch -- pnpm dev` → editing a secret in the dashboard triggers a SIGHUP and Vite picks it up.
  • Inside Cursor, `shelve pull` shows the agent warning; `shelve init` writes the ignore files.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
shelve-app Ready Ready Preview, Comment, Open in v0 Apr 20, 2026 2:38pm
shelve-lp Ready Ready Preview, Comment Apr 20, 2026 2:38pm
shelve-vault Ready Ready Preview, Comment Apr 20, 2026 2:38pm

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 20, 2026

Thank you for following the naming conventions! 🙏

HugoRCD added 2 commits April 20, 2026 12:30
…nt guard

Make shelve run the default secret-injection path so .env files don't
need to live on disk where AI agents will read them.

- Store CLI credentials in the OS keychain via @napi-rs/keyring with an
  XDG-compliant 0600 file fallback. Migrate the legacy ~/.shelve file
  silently on first read. Switch from rc9.readUser/writeUser to
  readUserConfig/writeUserConfig (the previous helpers are deprecated).
- Encrypt the offline cache with AES-256-GCM at
  ~/.shelve/cache/<sha256(team:project:env)>.json.enc. The key is derived
  from the API token via HKDF, so revoking the token also kills cached
  copies. Add --offline, --no-cache, --cache-ttl flags and a transparent
  cache fallback when the API is unreachable.
- Resolve shelve://<team>/<project>/<env>/<KEY> references from
  --template .env.template files; literal values pass through untouched
  so the template can be safely committed.
- --watch polls Shelve for variable changes and sends SIGHUP to the
  child (let Vite/Nuxt/Next reload), or use --restart-on-change to kill
  and respawn the child.
- shelve init writes .cursorignore / .aiderignore / .codeiumignore /
  .continueignore and a shelve-managed block in .gitignore. shelve pull
  detects AI-agent env (CURSOR_TRACE_ID, AIDER_VERSION, CLAUDECODE, ...)
  and prompts before writing plaintext secrets.
- spawnChild is now sync (matches cli-subprocess); update WatchOpts type
  and watch loop accordingly.
- Bail with handleCancel when no env can be resolved (was passing
  string | undefined into typed APIs).
- Add explicit return type on the keyring factory closure.
- Auto-fixed quote style in secret-refs.
@HugoRCD HugoRCD force-pushed the feat/v5-cli-runtime-ux branch from 211cc18 to a7b849e Compare April 20, 2026 11:41
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Apr 20, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@shelve/cli@731

commit: 6617c8b

Drop our hand-rolled `utils/agent.ts` (8 envvar heuristics + brittle
TERM_PROGRAM checks) in favor of `std-env` which already detects 11
agents (cursor, claude, devin, replit, gemini, codex, auggie,
opencode, kiro, goose, pi), is maintained by unjs, ships in our
transitive deps anyway, and supports `AI_AGENT=<name>` for explicit
override in tests/CI.
Base automatically changed from feat/v5-cli-subprocess to main April 20, 2026 15:35
@HugoRCD HugoRCD merged commit bca359e into main Apr 20, 2026
12 checks passed
@HugoRCD HugoRCD deleted the feat/v5-cli-runtime-ux branch April 20, 2026 15:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant