<!--
  This file is generated. Do not edit by hand.
  Run scripts/regenerate-llms-full.sh after updating README.md,
  docs/llm-usage.md, or other source documents.
-->

# klef — full documentation for LLM consumption

This file concatenates README + LLM usage guide + condensed architectural notes
for one-shot LLM context loading. For navigation, see `llms.txt`.

---

## Project overview

# klef

[![CI](https://github.com/slewinus/klef/actions/workflows/ci.yml/badge.svg)](https://github.com/slewinus/klef/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![Rust 1.85+](https://img.shields.io/badge/rust-1.85%2B-orange.svg)](https://www.rust-lang.org)
[![Platforms](https://img.shields.io/badge/platforms-macOS%20%7C%20Linux-lightgrey)](#statut)

Un coffre local pour tes clés API et secrets — pour arrêter de les perdre dans Dashlane, Notes, ou des `.env` éparpillés.

## Le problème

Tu as 15 clés API (Stripe, Anthropic, OpenAI, Gemini, Telnyx, etc.). Tu les notes dans Dashlane, dans des fichiers texte, dans des `.env` perdus. Quand tu démarres un projet, tu passes 10 minutes à les retrouver — et le pire, tu copies-colles la valeur dans le `.env` du projet, donc elle traîne en clair sur ton disque.

## La solution

Un CLI local qui :
- **Stocke** tes clés dans le Keychain de l'OS — chiffrement géré par Apple/GNOME, pas par nous.
- **Récupère** une clé en une commande : `klef get stripe`.
- **Injecte** les valeurs dans tes projets via des **références** dans le `.env` plutôt que des valeurs en clair :
  ```
  STRIPE_KEY=klef:stripe          # référence — résolue au runtime
  ANTHROPIC_KEY=klef:anthropic    # idem
  ```
  Puis `klef run -- npm start` résout tout ça et exécute ta commande avec les bonnes vars d'env.
- **Reste 100% local** — pas de serveur, pas de cloud, pas de télémétrie.

## Démo

```bash
# Tu as un .env qui traîne avec des secrets en clair :
$ cat .env
STRIPE_API_KEY=sk_live_xyz
ANTHROPIC_API_KEY=sk-ant-zzz
PORT=3000

# Une commande pour tout importer dans le Keychain et réécrire le .env en références :
$ klef import .env --rewrite
ENV VAR             KLEF NAME             VALUE
STRIPE_API_KEY      stripe-api-key        sk_l*** (16 chars)
ANTHROPIC_API_KEY   anthropic-api-key     sk-a*** (12 chars)
PORT                port                  *** (4 chars)
Import 3 key(s)? [y/N] y
✓ STRIPE_API_KEY → klef:stripe-api-key
✓ ANTHROPIC_API_KEY → klef:anthropic-api-key
✓ PORT → klef:port
Imported 3 key(s).
Rewrote .env (3 reference(s) replaced).

$ cat .env
STRIPE_API_KEY=klef:stripe-api-key
ANTHROPIC_API_KEY=klef:anthropic-api-key
PORT=klef:port

# Maintenant lance ton app comme avant — klef résout les références à la volée :
$ klef run -- node app.js
Server on port 3000, Stripe wired ✓
```

> 🎬 _Asciinema cast en cours d'enregistrement — voir [examples/quickstart/](./examples/quickstart/) pour le scénario complet en attendant._

## Install

### Depuis les sources (Rust ≥ 1.85)

```bash
cargo install --git https://github.com/slewinus/klef
```

### Homebrew (macOS / Linux desktop)

```bash
brew tap slewinus/tap
brew install klef
```

_Disponible dès la release v0.2.0 (tag à venir)._

### Binaires pré-compilés

À venir, voir [#11](https://github.com/slewinus/klef/issues/11).

### Auto-complétion shell

```bash
# zsh
klef completions zsh > ~/.zfunc/_klef

# bash
klef completions bash > /usr/local/etc/bash_completion.d/klef

# fish
klef completions fish > ~/.config/fish/completions/klef.fish
```

> La complétion statique des sous-commandes et des flags fonctionne dès aujourd'hui. La complétion dynamique des noms de clés (ex. `klef get <TAB>`) est suivie dans [#28](https://github.com/slewinus/klef/issues/28) et pas encore implémentée.

## Commandes

| Commande | Rôle |
|---|---|
| `klef add <name>` | Ajouter une clé (prompt TTY ou stdin). Avec `--value-from-file <FILE>` pour les secrets multi-lignes (PEM, JSON). |
| `klef get <name>` | Afficher la valeur (pipeable). |
| `klef show <name>` | Valeur + métadonnées. |
| `klef list [--format table\|json] [-v\|--verbose] [--filter PATTERN]` | Lister les clés (jamais les valeurs). `--verbose` ajoute la date d'ajout, `--filter` cherche en sous-chaîne. |
| `klef rm <name>` (alias `remove`) | Supprimer une clé. |
| `klef edit <name>` | Changer la valeur ou les métadonnées. `--value-from-file` accepté ici aussi. |
| `klef set-note <name> <text>` | Raccourci pour `edit --note`. |
| `klef rename <old> <new>` | Renommer une clé. |
| `klef export <name>... [--format shell\|dotenv]` | Émettre des lignes `export`. |
| `klef import <file.env> [--prefix P] [--dry-run] [--rewrite] [--yes]` | Bulk-import depuis un `.env` existant. `--rewrite` remplace les valeurs littérales par des références `klef:` dans le fichier source. |
| `klef run [--env-file FILE] -- <cmd>` | Résoudre `klef:<name>` dans `.env` et exec `<cmd>`. |
| `klef status [--format text\|json]` | Diagnostic : version, backend, index path, nombre de clés, désync. Exit 1 si désync. |
| `klef completions <shell>` | Générer le script d'auto-complétion. |

`klef --help` ou `klef <cmd> --help` pour les détails de chaque option.

## Stack

- **Langage** : Rust (édition 2024)
- **Stockage** : Keychain natif via [`keyring`](https://crates.io/crates/keyring) — Apple Security framework sur macOS, Secret Service sur Linux.
- **CLI** : [`clap`](https://crates.io/crates/clap) (derive)
- **Pas de serveur, pas de cloud, pas de compte, pas de télémétrie.**

## Dev

```bash
# Setup hooks (à faire une fois après le clone)
./scripts/setup-dev.sh

# Build / test
cargo build
cargo test --all-features      # 86 tests : unit + E2E
cargo run -- --help
```

Les hooks git (`fmt`, `clippy`, `tests`, line-cap < 300 lignes/fichier) sont versionnés dans `.githooks/`. CI sur macOS + Ubuntu via GitHub Actions (`.github/workflows/ci.yml`).

## Documentation

- **Quickstart** : [examples/quickstart/](./examples/quickstart/) — `.env` + script consommateur, smoke test bout-en-bout.
- **Changelog** : [CHANGELOG.md](./CHANGELOG.md)

## Statut

✅ **v0.2.0** taggé (2026-05-06) — distribution prête : 13 commandes, binaires pré-compilés pour macOS (Intel + Apple Silicon) + Linux (x86_64 + ARM), formule Homebrew, complétion zsh dynamique des noms de clés.

Highlights ajoutés depuis v0.1 :
- `klef import .env` pour onboarder un projet existant en une commande
- `klef status` pour le diagnostic
- `klef set-note` raccourci
- `klef list --verbose` (date d'ajout) + `--filter` (recherche)
- `--value-from-file` pour les secrets multi-lignes (PEM, certs, JSON)
- Hints actionnables quand le Keychain n'est pas disponible (Linux + macOS)
- Alias `klef remove` pour `klef rm`
- Complétion zsh dynamique : `klef show str<Tab>` → `stripe`

- **Plateformes supportées** : macOS (Keychain natif) + Linux desktop (Secret Service via gnome-keyring / KWallet).
- **Hors-scope v0.2** : Linux headless / WSL sans desktop, Windows, synchro multi-machines, GUI.
- **Roadmap** : voir [issues by milestone](https://github.com/slewinus/klef/milestones). v0.3+ trackée sous le [headless umbrella #26](https://github.com/slewinus/klef/issues/26), backend chiffré [#12](https://github.com/slewinus/klef/issues/12), MCP server [#24](https://github.com/slewinus/klef/issues/24), GUI [#18](https://github.com/slewinus/klef/issues/18).

## Licence

[MIT](./LICENSE) — © 2026 Oscar R.

---

## LLM usage patterns

# Using klef from an LLM agent

This document teaches an LLM agent (Claude Code, Cursor, ChatGPT) how to drive `klef` to manage user secrets without leaking values.

## Mental model in one paragraph

`klef` is a local CLI that stores secrets in the OS keychain (macOS Keychain, Linux Secret Service). It maps human-friendly names (`stripe`, `anthropic-api-key`) to opaque values. The killer trick: instead of writing the secret value into a project's `.env`, you write a reference (`STRIPE_KEY=klef:stripe`), and `klef run -- <cmd>` resolves it at runtime so the secret never touches disk in plaintext.

## Decision table

| User intent | klef command |
|---|---|
| "Save my Stripe key" | `echo -n "<value>" \| klef add stripe` (or interactive: just `klef add stripe`) |
| "Show me my Stripe key" | `klef get stripe` (prints the value, pipeable) |
| "What keys do I have?" | `klef list` |
| "Find my keys related to billing" | `klef list --filter billing` |
| "When did I add this key?" | `klef list --verbose` (adds an `ADDED` column) |
| "Delete this key" | `klef rm <name>` (prompts) or `klef rm <name> --yes` |
| "Update the value" | `klef edit <name>` (re-prompts) |
| "Update only the note" | `klef set-note <name> "<text>"` |
| "Rename this key" | `klef rename <old> <new>` |
| "Bulk-import an existing `.env`" | `klef import path/to/.env` (interactive) or `klef import path/to/.env --yes --rewrite` to also rewrite the source `.env` with klef references |
| "Run my dev server with secrets injected" | `klef run -- npm start` (assuming `.env` has `klef:` references; non-default file: `klef run --env-file .env.dev -- npm start`) |
| "Pull a key into my shell" | `eval $(klef export <name>)` |
| "Diagnostics: how is klef configured?" | `klef status` (or `klef status --format json` for parsing) |
| "Add a multi-line secret (e.g. a PEM)" | `klef add <name> --value-from-file path/to/cert.pem` |

## Exit codes (parse them programmatically)

- `0`: success.
- `1`: generic error.
- `2`: `KeyNotFound`. The user named a key that doesn't exist; suggest `klef list` to check.
- `3`: `BrokenReference`. A `klef:<name>` in the user's `.env` doesn't match any stored key.
- `4`: `BackendUnavailable` / `BackendDenied`. The OS keychain isn't reachable. On Linux, suggest installing `gnome-keyring` or `KWallet`. On macOS, the user may need to unlock their login keychain via Keychain Access.app.
- `64`: bad CLI usage (sysexits.h EX_USAGE). Re-read the help.

## JSON output for parsing

Two commands have stable JSON output:

```bash
klef list --format json
# {
#   "stripe": { "env_var": "STRIPE_API_KEY", "note": "...", "added_at": "...", "updated_at": "..." }
# }

klef status --format json
# {
#   "klef_version": "0.2.0",
#   "backend": "KeychainBackend",
#   "index_path": "...",
#   "keys": 3,
#   "desync": []
# }
```

The `desync` field is a list of key names that are in the index but missing from the backend. Empty list = healthy.

## Critical: never print secret values back to the user without their explicit ask

`klef get` and `klef show` print the value to stdout. If the user said "what is my Stripe key?", a literal `klef get stripe` is correct. But if the user said "wire up my Stripe key in this script", DON'T capture the output and embed it in code — use the reference pattern (`STRIPE_KEY=klef:stripe` in `.env`, then `klef run -- node app.js`).

## When `klef` is not installed

Suggest `cargo install --git https://github.com/slewinus/klef --tag v0.2.0` (Rust toolchain required) or `brew tap slewinus/tap && brew install klef` (macOS / Linux desktop, after the Homebrew tap is published).

## Common pitfalls

- The user expects `klef add stripe sk_live_xyz` to work because that's how `aws configure` and others work. It doesn't — klef reads values from stdin or an interactive prompt to keep them out of shell history. The error message hints at the right form.
- Tab-completion on key names works in zsh after `klef completions zsh > ~/.zfunc/_klef` and a `compinit` reload. Bash and fish only get static completion (subcommands and flags) for now (issue #28).
- `klef run` uses Unix `execvp` so klef itself disappears from the process tree once the child starts. Signals (SIGINT, SIGTERM) reach the child directly.

---

## Architectural overview (condensed)

klef is a Rust 2024 crate built as bin + lib. The CLI (`src/cli.rs`, clap derive)
parses arguments and dispatches to `src/commands/<name>.rs` modules. Each command
consumes a `Store` (`src/store/mod.rs`) which combines a `Backend` trait impl
(Keychain, File, or in-memory) with an `IndexFile` for metadata.

Errors flow through `KlefError` (`src/error.rs`), with deterministic exit codes:

- 0: success
- 1: generic error
- 2: KeyNotFound
- 3: BrokenReference (klef run couldn't resolve a klef:<name>)
- 4: BackendUnavailable / BackendDenied
- 64: bad CLI usage (sysexits.h EX_USAGE)

`klef run` uses Unix `execvp` to replace itself with the child process. Signals
propagate naturally; no zombie process.

The OS keychain is the default backend on macOS (Apple Security framework via
the `keyring` crate) and Linux desktop (Secret Service via `keyring`,
gnome-keyring or KWallet at runtime). Linux headless / CI / Docker support via
an encrypted file backend is the v0.3 roadmap (issue #12, umbrella #26).

---

## Configuration

- Index file: `~/Library/Application Support/klef/index.json` (macOS),
  `${XDG_CONFIG_HOME:-~/.config}/klef/index.json` (Linux). Override with
  `KLEF_INDEX_PATH`.
- OS keychain entries: service `klef`, account `<key>`.
- `KLEF_TEST_BACKEND=file:/path` switches to plaintext file backend in DEBUG
  builds only. Release binaries ignore it.

---

## Privacy / security

- 100% local: no network, no telemetry, no cloud, no master password.
- `get`, `show`, `export`, `run` are exfiltration-by-design surfaces.
- `list`, `status`, `completions`, hidden `_names` never print values.
