<div align="center">

<img src="docs/assets/banner.svg" alt="Incredigo — guards your credentials in locked memory, leaves no trace on disk" width="760">

# Incredigo

**Guards your credentials in locked memory. Leaves no trace on disk.**

*Local-first, encrypted, RAM-only credential custody — shipped as the `incredigo` CLI.*

</div>

```
+------------------------------------------------------------+
|    /\      INCREDIGO                                       |
|   /<>\     in-CRED-i-GO : credentials, in Go               |
|   \<>/     Guards your credentials in locked memory.       |
|    \/      Leaves no trace on disk.                        |
+------------------------------------------------------------+
```

Incredigo finds credentials scattered across the usual places
(`~/.aws/credentials`, `.env` files, `~/.netrc`, SSH keys,
`~/.docker/config.json`, kubeconfig, …), migrates them into a
[gopass](https://www.gopass.pw/) (GPG-backed) store **without ever writing
plaintext to disk**, and tells you which ones are stale.

- 🔒 **No plaintext at rest.** Disk only ever holds GPG blobs (gopass) or
  openssl-sealed backups.
- 🧠 **RAM-only secrets.** Decrypted material lives in `mlock`'d, non-dumpable,
  zeroized memory ([memguard](https://github.com/awnumar/memguard)).
- 📴 **Offline.** v1 makes zero network calls.
- 👀 **Read-only discovery.** Scanners never touch your source files.
- 🧩 **Hackable.** A new source is one file; the backup format is an interface.

See [`DESIGN.md`](DESIGN.md) for the architecture and threat model.

## Why the name

**Incredigo** is one word hiding three:

```
  in · CRED · i · GO
        └┬─┘       └┬┘
   CREDentials   in GO
```

It manages your **CRED**entials, it's written in **GO**, and read aloud the whole
thing lands on *incredible* — which is the bar a credential tool that promises
"no plaintext on disk, ever" has to clear.

### The mark

The logo is **Strata** — nested diamonds tightening around a single bright core.
It's the whole tool in one glyph: each ring is a layer of custody (read-only
discovery → locked-memory vault → GPG/OpenSSL at rest), and the core is your
secret, held in RAM and never written out. The design is deliberately abstract and
geometric — no mascot, no metaphor to decode.

| What it does | How |
|---|---|
| **Finds, doesn't guess** | Real parsers per source — no blind grep, no false positives. |
| **Composes, doesn't invent** | Battle-tested GPG (via gopass) and OpenSSL; no home-rolled crypto to break. |
| **Holds, doesn't leak** | Read-only discovery, RAM-only custody, redacted audit log — plaintext never leaves the locked arena. |
| **Works, then vanishes** | No server, daemon, network, or temp files; it does its job and leaves nothing on disk. |

The brand is **Incredigo**, and so is the command: the CLI was renamed from its old
working title `credrot` so the tool and the project finally share a name.

## Status

v1 scope: **discover + migrate + expiry tracking**. Provider-driven rotation
(issue-new / verify / revoke-old) is planned for v2 behind a stable interface.

`export`/`import` are stubbed in this scaffold (see `cmd/incredigo/main.go`).

> **Rename in progress:** the Go package and binary are being renamed
> `credrot` → `incredigo`. Until that lands, substitute `./cmd/credrot` /
> `credrot` in the commands below.

## Build

Requires Go 1.22+.

```sh
go mod tidy
go build ./cmd/incredigo
```

## Usage

```sh
incredigo scan --dry-run                 # see what's out there (no secrets printed)
incredigo migrate --prefix imported/ --dedupe
incredigo status                         # age vs policy
incredigo export --out ~/incredigo-backup.enc   # (v1 stub)
```

## Layout

| Path | Purpose |
|---|---|
| `cmd/incredigo` | cobra CLI |
| `internal/vault` | RAM-only secret arena (memguard) |
| `internal/discover` | scanner registry + one file per source |
| `internal/sink` | gopass writer + Sealer interface + openssl impl |
| `internal/policy` | expiry rules |
| `internal/audit` | redacted append-only log |

## Contributing

Adding a source is intentionally easy — see
[`docs/ADDING_A_SCANNER.md`](docs/ADDING_A_SCANNER.md).
