Metadata-Version: 2.4
Name: keyfort
Version: 1.1.0
Summary: Encrypt your secrets into one local file, injected as environment variables at launch — zero code changes, one command to enable.
Author: aiPublicProject
License: MIT
Project-URL: Homepage, https://github.com/aiPublicProject/keyfort
Project-URL: Issues, https://github.com/aiPublicProject/keyfort/issues
Keywords: env,dotenv,secrets,environment,encryption,aes-gcm
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: Software Development
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: cryptography>=41
Requires-Dist: keyring>=24
Dynamic: license-file

# keyfort

**English** | [简体中文](README.zh-CN.md)

> Encrypt your secrets into one local file, injected as environment variables at launch — zero code changes, one command to enable, no more leaked keys.

In 2026, xAI's Grok Build and Zhipu's ZCode were both caught **silently uploading users' entire codebases** — Git history, local records, and plaintext API keys, all packaged and shipped to the cloud. keyfort encrypts your secrets into a single `.keyfort` file: even if a tool packages it up and sends it away someday, what leaves your machine is ciphertext.

`DB_PASS`, `API_KEY` and other sensitive values no longer sit in plaintext inside your project. When you develop, entering the project directory automatically injects them as environment variables — `npm run dev` and `python main.py` run untouched, **not a single line of code changes**.

A purely local tool: no account, no server, no network requests of any kind. Built for individual developers.

## Quick Look

```console
$ pip install keyfort

$ cd my-project
$ keyfort .env.local my-password
Scope? [1] all (default) [2] partial — keep only the lines to encrypt, in your editor: 2
   ↳ your editor opens: keep the lines to encrypt, save & close
Original .env.local? [1] hide the secrets in place (default) ...: 1

$ npm run dev            # secrets are already in the environment

# ---- next session ----
$ cd my-project          # open a new terminal, cd in — auto-injected, nothing to type
```

In terminals without the integration installed, typing the single word `keyfort` also drops you into the injected environment (exit to return).

## Why keyfort

- **Purely local** — no account, no server, no network requests; fully usable offline
- **Zero code changes** — injection happens via environment variables (OS parent-to-child inheritance); works with node / python / any language
- **Type the password once** — stored in the OS credential manager (Windows Credential Manager / macOS Keychain / Linux Secret Service); no plaintext ever hits the disk
- **Secrets hidden in place** — `DB_PASS`'s value becomes a `<keyfort:DB_PASS>` placeholder (**the file is safe to commit to git**), while `PORT=3000` stays plaintext for frameworks to read
- **Auditable** — 3 core files, ~950 lines, readable in half an hour; only two dependencies: `cryptography` and `keyring`

## Installation

```console
$ pip install keyfort
```

Python ≥ 3.9; Windows / macOS / Linux.

> Note: interactive CLI messages are currently Chinese-only. Localization is on the [roadmap](ROADMAP.md).

## Quick Start

```console
$ cd your-project
$ keyfort .env.local your-password
```

It asks two things in order: the **encryption scope** (everything, or partial — an editor opens where you keep only the lines to encrypt; what you keep IS the selection, and editing line counts doesn't matter), and **what to do with the original file** (hide the secrets in place — values become placeholders, default / you handle it yourself). Then terminal integration installs automatically and you enter the injected environment.

Daily use is three actions:

```console
$ keyfort edit           # edit secrets; re-encrypts on every save (password required; -e code picks the editor)
$ keyfort set KEY value  # add a secret (no password)
$ keyfort restore        # one-click restore to plaintext; deletes .keyfort and the cached password
```

What ends up on your machine:

| Location | What it is |
|---|---|
| `.keyfort` in your project | The encrypted vault — **safe to commit to git**; teammates get it via clone |
| `.env.local` in your project | Secret values replaced with `<keyfort:name>` placeholders, the rest intact — **safe to commit to git** |
| `C:\Users\you\.keyfort\` (macOS/Linux: `~/.keyfort/`) | A tiny folder holding the cmd auto-activation script; removed by `keyfort uninit` |
| Your OS password manager | The encryption password — **not a file** |

## Team / New Machine

`.keyfort` is ciphertext — **commit it to git** directly (teammates get it via clone, no out-of-band file transfer):

```console
$ git add .keyfort && git commit      # after registration

# teammate / new machine, after clone:
$ pip install keyfort
$ keyfort                             # type the password once; cached in the local credential store
```

Daily use on that machine is zero-effort afterwards. After `keyfort passwd`, commit the re-encrypted
`.keyfort` again. Note: someone who left still holds their old copy — old copy + old password keeps
working on that copy; to cut them off completely, rotate the secret values themselves.

## Commands

| Command | What it does |
|---|---|
| `keyfort .env.local password` | Encrypt & register: choose scope → split & encrypt → install terminal integration → enter injected environment |
| `keyfort` | Enter the injected environment (in integrated terminals = in-place activation, no exit needed) |
| `keyfort edit` | Edit secrets in an editor (password required; **re-encrypts on every save**; `-e code` to pick, VS Code/Cursor terminals auto-detected) |
| `keyfort set KEY value` | Add/update a secret (no password needed) |
| `keyfort unset KEY` | Delete a secret |
| `keyfort get KEY` | Print a single secret's value (password required) |
| `keyfort list` | List secret names (no values) |
| `keyfort passwd` | Change the encryption password |
| `keyfort run <command>` | Run a single command with the injected environment (scripts/CI; set `KEYFORT_PASSWORD` for unattended use) |
| `keyfort create password` | Create an empty vault from scratch (no plaintext file needed; add secrets later with set/edit) |
| `keyfort restore` | Restore plaintext: merge secrets back into the env file, delete `.keyfort` and the cached password |
| `keyfort init` / `uninit` | Install / remove terminal integration (idempotent, fully reversible) |

The terminal integration adds a small marked script to the PowerShell 5.1/7 profiles and bash's `.bashrc` — **cd between projects in the same terminal and secrets follow automatically; leaving a project clears them**. cmd uses AutoRun, which only fires at startup — **no cd-following** (open a new terminal per project, or run `keyfort` manually). If PowerShell's execution policy is Restricted and profiles don't load: `Set-ExecutionPolicy -Scope CurrentUser RemoteSigned`.

## How It Works

**Encryption**. `.keyfort` stores the ciphertext of the selected `KEY=VALUE` lines:

```
KEYFORT1
<base64(salt 16B + nonce 12B + AES-256-GCM ciphertext)>
```

The encryption key is derived from your password via PBKDF2-HMAC-SHA256 (200,000 iterations) with a fresh random salt each time. AES-256-GCM is authenticated — a tampered file fails to decrypt rather than yielding fake values. Only raw bytes are stored; `KEY=VALUE` parsing happens only at injection time.

**Placeholders**. On registration, selected secret values in the original file are replaced with `<keyfort:same-name>` placeholders — the file now holds only placeholders and ordinary vars, and is **safe to commit** (config visible, values invisible). At injection time the real values are already set as same-named environment variables, and dotenv-family frameworks never overwrite existing env vars — so the placeholders are never read by your app.

**Injection**. Environment variables are the OS's parent-to-child mechanism — `keyfort` decrypts, spawns a child shell (bash / PowerShell / cmd auto-detected), and puts the variables into its environment block, so any language can read them. Terminal integration takes another path: a shell function calls `keyfort activate --emit` to get an assignment script and runs it in the **current** session (a shell function is not a child process, so it can modify the current environment); the `KEYFORT_ACTIVE_KEYS` marker prevents double injection and enables cleanup.

**New machine**. Copy `.keyfort` over and type the password once — the ciphertext is OS-independent, no re-encryption needed.

## Security

**Why these guarantees matter — two real incidents:**

- **July 2026: xAI's Grok Build caught silently uploading users' codebases.** Reverse engineering by an independent researcher showed the AI coding tool uploaded users' complete Git repositories and commit history to the cloud — even with privacy settings off. Musk later promised to delete the data and open-sourced Grok Build.
- **September 2026: Zhipu's ZCode caught silently uploading user workspaces.** After login it packaged and uploaded the entire workspace (including Git history and local operation records), with no working off switch in the UI. Zhipu later apologized and promised to open-source the code and accept third-party audits.

The common thread: users only learned what these tools uploaded from their own machines **through reverse engineering** — and a plaintext `.env` goes to the cloud along with the workspace. keyfort's answer works in both directions: `.keyfort` contains only ciphertext, so uploads can't hurt you; and keyfort makes zero network requests with open-source code — no reverse engineering needed to know what it does.

**What it guarantees:**

- No network requests of any kind: the code imports no network modules — no internet, no registration, no data collection
- Open source, quick to audit (MIT): core logic is ~950 lines across 3 files
- Plaintext exists in only two places: your terminal session, and `keyfort edit`'s temp file (deleted on close)

**What it does not protect against (honestly):**

- Same-user malware can read your injected environment variables and credential store — the same boundary as 1Password CLI, sops, and ssh-agent; keyfort protects against "secret files committed to git / copied away"
- Lose the password, lose the data — there is no backdoor; back the password up together with `.keyfort`

## Development

```console
$ git clone https://github.com/aiPublicProject/keyfort.git
$ cd keyfort && pip install -e .
$ python tests/cli_flow.py      # full-flow tests; all should PASS
$ python -m build               # build into dist/
```

Planned features and design trade-offs (placeholder model, proxy mode, explicit non-goals) are in [ROADMAP.md](ROADMAP.md) (currently Chinese).

## License

MIT © aiPublicProject
