# Redcee for agents

Redcee stores secrets in a config. An access token selects exactly one config, so commands never accept an organization, project, environment, or config selector.

Use the CLI unless your runtime cannot execute a process. The CLI is a thin client over the same JSON API described at [https://www.redcee.com/openapi.json](https://www.redcee.com/openapi.json).

## Non-negotiable rules

1. Never put an access token or secret value in argv, a URL, source code, logs, or chat output.
2. Supply a token with `REDCEE_TOKEN`, `--token-file`, or `--token-stdin`.
3. Supply a mutation value with `--value-file` or `--value-stdin`. There is no `--value` argument.
4. Before every mutation, run `redcee config show` and use its `config_revision` as `--expected-config-revision`.
5. On `revision_conflict`, inspect the config again. Never retry a write blindly.
6. A mutation may be retried only with the same UUIDv7 operation ID and the exact same request. Reusing an operation ID for different input fails.
7. Automation tokens start with `rc_at_`, are config-scoped, expire after 1, 7, or 30 days, and can read/create/replace/view history/rollback/restore. They cannot delete, purge, manage access, or issue tokens.
8. Read-only service tokens start with `rc_st_`. They can retrieve secrets but cannot mutate them.

## Install the CLI

Release artifacts are immutable, signed Linux musl archives for x86_64 and arm64. Set the exact Redcee version you intend to install; there is deliberately no `latest` URL.

```sh
REDCEE_VERSION=v0.1.0
REDCEE_ARCH=x86_64-unknown-linux-musl
curl --fail --silent --show-error --location --remote-name \
  "https://downloads.redcee.com/cli/${REDCEE_VERSION}/redcee-${REDCEE_VERSION}-${REDCEE_ARCH}.tar.gz"
curl --fail --silent --show-error --location --remote-name \
  "https://downloads.redcee.com/cli/${REDCEE_VERSION}/redcee-${REDCEE_VERSION}-${REDCEE_ARCH}.tar.gz.sha256"
curl --fail --silent --show-error --location --remote-name \
  "https://downloads.redcee.com/cli/${REDCEE_VERSION}/redcee-${REDCEE_VERSION}-${REDCEE_ARCH}.tar.gz.sig"
curl --fail --silent --show-error --location --remote-name \
  "https://downloads.redcee.com/cli/${REDCEE_VERSION}/release-signing-public-key.pem"
sha256sum --check "redcee-${REDCEE_VERSION}-${REDCEE_ARCH}.tar.gz.sha256"
cosign verify-blob \
  --key release-signing-public-key.pem \
  --signature "redcee-${REDCEE_VERSION}-${REDCEE_ARCH}.tar.gz.sig" \
  "redcee-${REDCEE_VERSION}-${REDCEE_ARCH}.tar.gz"
tar --extract --gzip --file "redcee-${REDCEE_VERSION}-${REDCEE_ARCH}.tar.gz"
install -m 0755 redcee "$HOME/.local/bin/redcee"
redcee --version
```

For arm64, set `REDCEE_ARCH=aarch64-unknown-linux-musl`. Pin the release-signing public-key fingerprint through an independently trusted channel before installing in a privileged environment.

## Authenticate

Create an automation token in the Redcee web app: open the config, choose **Access tokens**, create an **Automation token**, and copy the credential immediately. It is shown once.

Environment variable:

```sh
export REDCEE_TOKEN='rc_at_REDACTED'
```

Token file:

```sh
install -m 0600 /dev/null "$HOME/.config/redcee/token"
printf '%s\n' 'rc_at_REDACTED' >"$HOME/.config/redcee/token"
redcee --token-file "$HOME/.config/redcee/token" config show
```

`REDCEE_URL` is optional and defaults to `https://redcee.com`. Set it only for an explicit alternate deployment or loopback development server.

## Inspect the config

```sh
redcee config show
```

Example output:

```json
{"config_id":"019c2a50-1234-7abc-8123-0123456789ab","config_revision":"7","protected":true}
```

`config_revision` is a canonical decimal string, not a JSON number.

## Read secrets

Read one value exactly:

```sh
redcee secrets get DATABASE_URL
```

Read several values as JSON:

```sh
redcee secrets get DATABASE_URL API_TOKEN --format json
```

Download the effective config as JSON:

```sh
redcee secrets download --format json
```

Create a mode-0600 dotenv file without overwriting an existing path:

```sh
redcee secrets download --format env --out .env.redcee
```

Run a process with secrets in its environment. Existing variables fail closed unless `--replace-existing` is explicit:

```sh
redcee run -- ./server --listen 127.0.0.1:8080
```

## Create a secret

Read the revision, generate one operation ID, and keep that ID if transport failure makes a retry necessary.

```sh
REVISION=$(redcee config show | jq -er '.config_revision')
OPERATION_ID=$(uuidgen --time-v7)
printf %s 'the exact secret value' | redcee secrets create API_TOKEN \
  --type opaque \
  --value-stdin \
  --expected-config-revision "$REVISION" \
  --operation-id "$OPERATION_ID"
```

The CLI generates a UUIDv7 operation ID when `--operation-id` is omitted. Supplying it explicitly makes retry behavior visible to an agent.

## Replace a secret

Omitting `--type` preserves the current secret type.

```sh
REVISION=$(redcee config show | jq -er '.config_revision')
redcee secrets replace API_TOKEN \
  --value-file ./new-api-token.txt \
  --expected-config-revision "$REVISION"
```

## Inspect version history

```sh
redcee secrets versions API_TOKEN --page-size 25
```

For the next page, pass the returned `next_before_version_number`:

```sh
redcee secrets versions API_TOKEN \
  --page-size 25 \
  --before-version-number 42
```

History returns metadata only. It never returns an old plaintext value.

## Roll back or restore

Use rollback when the secret is active. Use restore when the current version is a tombstone. Both append a new version; neither rewrites history.

```sh
REVISION=$(redcee config show | jq -er '.config_revision')
redcee secrets rollback API_TOKEN 019c2a50-5678-7abc-8123-0123456789ab \
  --expected-config-revision "$REVISION"
```

```sh
REVISION=$(redcee config show | jq -er '.config_revision')
redcee secrets restore API_TOKEN 019c2a50-5678-7abc-8123-0123456789ab \
  --expected-config-revision "$REVISION"
```

## Output and failure contract

- Successful metadata and mutation commands write one compact JSON object plus a trailing newline to stdout.
- `secrets get` writes exact plaintext by default. `secrets download` and `run` also handle plaintext. Treat their stdout and child environment as sensitive.
- Diagnostics go to stderr and start with a stable code such as `RC_CLI_API_FAILURE`.
- Success exits 0. Any validation, authorization, conflict, network, decoding, output, or child-exec failure exits nonzero.
- The client rejects redirects, non-JSON API responses, unknown response fields, oversized bodies, non-UUIDv7 identifiers, and malformed revisions.

API errors always have this shape:

```json
{"error":{"code":"revision_conflict","message":"The config revision does not match. Read the config and retry explicitly.","request_id":"019c2a50-9abc-7abc-8123-0123456789ab"}}
```

Stable error codes include `invalid_request`, `validation_error`, `invalid_token`, `insufficient_scope`, `not_found`, `read_conflict`, `revision_conflict`, `idempotency_conflict`, `lifecycle_conflict`, `service_unavailable`, and `internal_error`.

## Raw API

Use `Authorization: Bearer TOKEN` and `Accept: application/json`. Mutation bodies also require `Content-Type: application/json`.

| Method | Path | Token | Purpose |
| --- | --- | --- | --- |
| GET | `/api/v1/config` | Either | Config ID, revision, protection state |
| GET | `/api/v1/secrets` | Either | Effective config plaintext |
| GET | `/api/v1/secrets/{name}` | Either | One current plaintext value |
| POST | `/api/v1/secrets` | Automation | Create |
| PUT | `/api/v1/secrets/{name}` | Automation | Replace |
| GET | `/api/v1/secrets/{name}/versions` | Automation | History metadata |
| POST | `/api/v1/secrets/{name}/versions/{version_id}/rollback` | Automation | Append rollback version |
| POST | `/api/v1/secrets/{name}/versions/{version_id}/restore` | Automation | Append restore version |

There is no machine API for delete, purge, organization management, grants, invitations, or token issuance. Those operations require a human browser session and, where applicable, fresh password-plus-MFA reauthentication.

## Minimal agent loop

```text
1. Obtain one config-scoped token through an approved secret channel.
2. Run `redcee config show`.
3. Read only the values needed for the task.
4. Before a write, capture the current config revision.
5. Generate one UUIDv7 operation ID.
6. Submit exactly one mutation with value input from a file or stdin.
7. If the outcome is unknown because transport failed, retry the exact request with the same operation ID.
8. If Redcee returns revision_conflict, stop, inspect current state, and form a new explicit request with a new operation ID.
9. Never log plaintext or the token. Revoke the token when the task ends.
```
