Clone any repo, get it running, and fill its
.env— in seconds.
KeyForge is a local, offline-first CLI for the local dev onboarding problem: you copy a repo URL, clone it, hunt through the README, guess the install command, find the .env.example, and chase down API keys across four browser tabs before the app will even start.
KeyForge collapses that into one command:
kf https://github.com/owner/repoIt asks where to clone, clones the repo, detects the tech stack(s), installs the dependencies, and then fills in .env from your encrypted vault — auto-injecting keys you've used before and prompting only for the ones it's never seen.
Status: Phase 4 complete (v0.4.0). KeyForge now ships a desktop GUI (a lightweight Tauri app) on top of the same Core Engine + vault, backed by a
kf daemonthat unlocks the vault once per session. All vault data stays on your machine — no cloud, no telemetry.
The CLI is still the single source of truth; the GUI is a visual face over the exact same logic (it shells out to kf --json and a local vault daemon — no reimplemented crypto or detection).
- 🖥️ Tauri desktop app (
gui/) — ~10–20MB, native OS webview, not a 150MB Electron bundle. - 🔓 Unlock once per launch — a new
kf daemonholds the derived key (never the password) in memory and serves vault operations over a local-only socket (Unix domain socket / Windows named pipe), so you type your master password once. - 🧙 Redesigned Clone Wizard — copy from clipboard, pick a folder, and view repository metadata (description, stars, language via the GitHub CLI
gh) alongside required env vars pre-scanned and checked against your vault. - 🤖 Agent-like Setup Progress — watch active agent tasks (cloning, package installs, key injection) in real-time with an active progress bar, key-filling micro-animations, and a toggleable developer log console.
- 🗂️ Visual vault — browse by category, reveal masked values on demand, validate keys, set defaults, add/edit/delete, and bulk-import variables from local
.envfiles using a "Fetch from directory" review modal. - 📋 Clipboard detection — copy a GitHub/GitLab/Bitbucket URL and the dashboard or wizard offers to instantly use it.
- 🔐 Optional Master Password — disable the master password in Settings to unlock GUI and CLI automatically using machine-derived keys only.
- 🗑️ Lockscreen Reset — click "Forgot password" to completely wipe and reset the vault to start fresh.
- 🛠️ Two additive CLI commands power the GUI and scripting:
kf write-env(writes.envfrom a name→value payload on stdin) andkf <clone|run> --no-vault-match(returns the required env var names instead of resolving them).
Setup pipeline (Phase 1, still here)
- One-command setup —
kf <repo-url>runs the whole clone → detect → install →.envpipeline. - Interactive destination — clone into
./<repo-name>or any directory you choose. - Multi-stack detection — handles repos with more than one stack (e.g. a Node frontend + Python backend) in a single pass.
- Smart package-manager selection — picks
npm/yarn/pnpm/bunfrom the lockfile present. - npm audit fix — after a clean
npm install, checks for vulnerabilities and runsnpm audit fix(never the breaking--force). - Python environment choice — for pip projects: a local
.venv(recommended), globally, a conda env, or a uv env, with tool-availability checks. - Open when done — launch the project in VS Code or a new terminal.
Vault (Phase 2, new)
- Encrypted, offline, local — values are only ever written encrypted; the master password is never stored or cached between commands;
.envis protected via.gitignore. - Smart classification — name + value heuristics detect the category, provider, and whether a value is a secret to mask.
- Auto-inject on clone — matched env vars are filled from the vault (exact name → provider alias → provider match); only genuine unknowns are prompted.
- Provider validity checks — OpenAI, Anthropic, GitHub.
- Multiple keys per type — name them (
work,personal), set a default, and the default is whatkf cloneinjects. - Security-first input — secret values are never accepted as CLI arguments (they'd leak into shell history); they're always entered at a hidden prompt.
| Command | What it does |
|---|---|
kf <repo-url> |
Clone, detect, install, and fill .env from the vault |
kf run [path] |
Same pipeline on an existing local project (merges into any current .env) |
kf add [type] |
Add a key / URL / id / config / path to the vault (value entered at a hidden prompt) |
kf fetch |
Scan the current project's .env files and import the values into the vault |
kf vault [category] |
Browse and manage the vault (view, set default, validate, edit, delete) |
kf keys add|list|remove|check |
Shortcuts for managing API keys |
Add --dry-run to kf clone/kf run to preview without writing, or --json to clone, run, vault, keys list, keys check, and fetch for machine-readable output.
-d, --dest <path> Destination directory (skips the prompt)
--open <target> Open after setup: vscode | terminal | none
--no-install Detect stacks but skip running install commands
--dry-run Preview what KeyForge would do without writing anything
--json Machine-readable JSON output (no prompts, no colour)
-v, --version Print the version
-h, --help Show help
--open <target> Open after setup: vscode | terminal | none
--no-install Skip dependency installation (only fill .env)
--no-env Skip .env injection (only run installs)
--dry-run Preview without writing anything
--json Machine-readable JSON output
kf vault [category] --list Print entries non-interactively (no browser)
kf vault [category] --json Machine-readable entries (never includes values)
kf fetch --dir <path> Scan a specific project directory (defaults to cwd)
kf fetch --json Scan + classify only (no import, no values)
kf keys list --json Stored keys as JSON
kf keys check --json Per-key validation results as JSON
$ kf https://github.com/owner/some-api
▸ Cloning some-api
✓ Cloned into /home/you/some-api
▸ Detecting tech stack
✓ Node.js (pnpm) (package.json)
▸ Installing dependencies
...
▸ Setting up .env
✓ OPENAI_API_KEY → matched vault (openai › work) will inject
✓ DATABASE_URL → matched vault (supabase) will inject
· STRIPE_SECRET_KEY → not in vault will prompt
1 value needs your input:
STRIPE_SECRET_KEY (api-keys — stripe)
Enter value: ********
Save to vault? (Y/n)
✓ Wrote .env (3 values)
✓ Added .env to .gitignore
▸ Done
✓ some-api is ready at /home/you/some-apiIf a project has no .env.example, the env step is skipped silently. If you have no vault yet, KeyForge doesn't force you to create one just to clone — every var is simply prompted.
# Add a key — value is typed at a hidden prompt, never as an argument
kf add openai
# Import everything from a project you've already set up
cd my-existing-project
kf fetch
# Browse, validate, and manage
kf vault
kf keys check # validate all stored API keysRequires Node.js 20+ and git on your PATH.
git clone https://github.com/Developerr86/keyforge
cd keyforge
npm install
npm run build
npm link # makes `kf` and `keyforge` available globallyUndo the global link anytime with npm unlink -g keyforge. Run the test suite with npm test.
The GUI lives in gui/ and depends on the built CLI. It additionally needs the Rust toolchain (rustup), the platform webview (WebView2 on Windows, WebKitGTK on Linux — preinstalled on macOS), and a C/C++ build toolchain.
# from the repo root, with the CLI already built (npm run build)
npm link # so the app can find `kf` (or set KEYFORGE_CLI)
cd gui
npm install
npm run tauri dev # run the app in development
npm run tauri build # produce an installer (e.g. NSIS .exe on Windows)The app never reimplements vault or detection logic — it calls the same kf CLI and a local kf daemon.
| Marker file | Stack | Install |
|---|---|---|
package.json |
Node.js | npm / yarn / pnpm / bun (from lockfile) |
requirements.txt |
Python (pip) | venv / global / conda / uv |
pyproject.toml |
Python | uv sync / poetry install / pip |
Pipfile |
Python | pipenv install |
pom.xml |
Java | mvn install |
build.gradle |
Java | Gradle wrapper or gradle build |
Cargo.toml |
Rust | cargo build |
go.mod |
Go | go mod download |
composer.json |
PHP | composer install |
Gemfile |
Ruby | bundle install |
mix.exs |
Elixir | mix deps.get |
pubspec.yaml |
Dart / Flutter | flutter pub get |
Dockerfile / docker-compose.yml |
Docker | Detected, not auto-run |
Makefile |
Make | Detected; relevant targets surfaced |
- Values are never CLI arguments — pass
kf add openai, then type the value at the hidden prompt. A value passed as an argument is detected and discarded. - The vault is always encrypted — AES-256-GCM; only the salt and a non-secret config file are stored in the clear.
- The master password is never stored — not in config, not cached between commands. (Skip it and KeyForge falls back to a machine-derived key — less secure, but no prompt.)
.envis always protected — after writing,.envis added to.gitignore.- No cloud, no telemetry — the only outbound calls are user-initiated key-validation pings, which send nothing but the key in the auth header.
KeyForge keeps all business logic in a Core Engine and a Vault layer, both with zero CLI/GUI dependencies, so the same logic can power the planned desktop GUI without drift.
src/
├── cli/ # presentation only — Commander, Inquirer, Chalk/Ora
│ ├── commands/ # clone · run · add · fetch · vault · keys
│ ├── ui/ # prompts + output helpers (+ dry-run preview, JSON emit)
│ ├── envResolve.ts # shared vault match + prompt + machine-local + merge
│ ├── setupHooks.ts pythonPrompt.ts commandUtil.ts jsonView.ts version.ts
│ └── vaultSession.ts # master-password unlock / first-run setup
├── core/ # Core Engine — clone, detect, install logic
│ ├── setup.ts # shared detect → install → env → launch pipeline (clone + run)
│ ├── clone.ts detect.ts install.ts python.ts tools.ts launch.ts
│ ├── env.ts # API key detection (detect-only)
│ ├── envFiles.ts # read real .env files + .env.example names
│ ├── envWriter.ts # write .env (merge, not clobber) + .gitignore protect
│ └── providers.ts # provider registry (value + name + alias patterns)
├── vault/ # the Vault — zero CLI imports
│ ├── store.ts # AES-256-GCM encrypted persistence + CRUD
│ ├── classify.ts # classification engine (pure)
│ ├── match.ts # match env var names → vault entries
│ └── validate.ts # provider key validators
└── shared/ # typed errors + shared interfaces
Built with TypeScript (strict mode), Commander, Inquirer (@inquirer/prompts + @inquirer/search), Ora, Chalk, Execa, and simple-git. Encryption and UUIDs use Node's built-in crypto. Tests use Node's built-in node:test.
KeyForge is built in phases:
- Phase 1 — CLI MVP ✅ — clone, detect, install, report required keys.
- Phase 2 — Keychain Core ✅ — encrypted local vault; classify/store/validate; auto-inject
.envon clone;add/fetch/vault/keys. - Phase 3 — Polish + Integration ✅ —
kf runfor already-local projects,--dry-run,--json, machine-local path warning, Python not-on-path probing. (Profiles and optional.keyforge.jsonproject config deferred to a later pass.) - Phase 4 — GUI ✅ — a Tauri desktop app (
gui/) wrapping the same Core Engine + Vault, talking to the CLI via--jsonand a localkf daemon. (Tauri replaces the originally-planned Electron — same React/TS frontend, a fraction of the footprint.) - Phase 5 — AI Agent Layer (future) — read setup docs to fill gaps detection can't.
See KEYFORGE_PLAN.md for the full design document.
MIT
