> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wipe.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Command-line interface

> Create, consume, and safely inject private one-time messages in terminals, agent-coordinated workflows, containers, and CI/CD.

The open-source `wipeme` CLI encrypts locally and supports text, attachments,
manual passphrases, generated passwords, one-time reading, and direct child-process
injection.

<Warning>
  The latest published preview is
  [`v0.3.0-alpha.3`](https://github.com/wipe-me/cli/releases/tag/v0.3.0-alpha.3).
  It includes the local `wipeme mcp` server. The CLI remains a prerelease and has
  not received an independent security audit.
</Warning>

<Card title="Install the CLI" icon="download" href="/developer-tools/command-line-interface/installation">
  Install `wipeme` with Homebrew, APT, DNF, a release archive, or Go.
</Card>

<iframe src="https://asciinema.org/a/T5an0dAijAPrAEuN/iframe?preload=1&theme=asciinema&idleTimeLimit=1.25" title="Wipe.me CLI feature demonstration" width="100%" loading="lazy" allow="fullscreen" style={{ border: 0, aspectRatio: "1.24 / 1", height: "auto" }} />

```text theme={null}
wipeme [options] [file ...]
wipeme read [options] <private-link>
wipeme exec [options] <private-link> -- <command> [args...]
wipeme delete [options] <private-link>
wipeme mcp [options]
```

Always quote links containing `#`; otherwise a shell may treat the fragment as a
comment. The fragment remains local decryption material and is never sent to the
server.

## Create a message

Run `wipeme`, enter a multiline message, and press `Ctrl-D`:

```console theme={null}
$ wipeme
Enter a private message. Press Ctrl-D on an empty line when finished:
Meet me at 9
<Ctrl-D>
https://wipe.me/1K7-mQ2-xR8#7YW-HMf-k9J-CB7
```

Automatic links use a 9-character public message ID and a 12-character fragment,
displayed as `3-3-3#3-3-3-3`.

### Manual-passphrase creation

Setting `WIPEME_PASSPHRASE` selects manual mode. The passphrase may contain
Unicode text from 8 through 256 characters and is not included in the link:

```sh theme={null}
WIPEME_PASSPHRASE='previously agreed phrase' wipeme
# https://wipe.me/aBc1-dEf2
```

An explicitly set `WIPEME_PASSPHRASE` always selects manual mode. Leave it unset
for an automatic fragment-key link.

### Attachments and pipelines

```sh theme={null}
# Attachments become visible blocks in the opened message
wipeme screenshot.png
wipeme photo.jpg recording.m4a report.pdf

# A message plus attachments
wipeme --message-file note.txt photo.jpg
printf '%s' "$NOTE" | wipeme report.pdf

# Treat stdin as an attachment instead of message text
generate-report | wipeme --attach - --name report.pdf --type application/pdf
```

Positional paths and repeated `--attach` flags are supported. Each encrypted
attachment has a corresponding ordered document block, so attachment-only messages
remain visible in the browser. Filenames, MIME types, presentation kind, dimensions,
and bytes remain encrypted.

### Generate and transfer a password

```sh theme={null}
wipeme --generate-pass --length 32 --chars portable

wipeme --generate-pass \
  --set-env DATABASE_PASSWORD \
  --link-file ./database-password.link \
  -- ./initialize-database
```

The password is generated with OS cryptographic randomness, stored in the first
ordinary text block, encrypted, and never printed. Presets are `portable`, `alnum`,
`base58`, `base64url`, `hex`, `digits`, `letters`, and `ascii`. Use `--alphabet`
for an exact custom printable-ASCII alphabet and `--no-require-each` to disable
applicable class guarantees.

During generated child execution, stdout belongs only to the child. Use
`--link-file` for a mode-`0600` link file or `--copy`; otherwise a labelled private
link is written to stderr before the child starts.

## Read a one-time message

```sh theme={null}
wipeme read --non-interactive \
  'https://wipe.me/1K7-mQ2-xR8#7YW-HMf-k9J-CB7'
```

For manual links, supply the separately agreed passphrase without putting it in a
command argument:

```sh theme={null}
WIPEME_PASSPHRASE='previously agreed phrase' \
  wipeme read --non-interactive 'https://wipe.me/aBc1-dEf2'
```

The CLI validates local syntax and output paths first, retrieves the encrypted
envelope once, and tries credentials locally in deterministic order:

1. URL fragment
2. `--passphrase-file FILE`
3. `--passphrase-stdin`
4. `--passphrase-env NAME`
5. `WIPEME_PASSPHRASE`
6. Up to three hidden terminal prompts, unless `--non-interactive` is enabled

Duplicate candidates are removed. Leading and trailing spaces are preserved; only
one expected trailing line ending is removed from file or stdin sources.

Useful output options:

```sh theme={null}
wipeme read --block 0 "$LINK"
wipeme read --json --output ./message.json "$LINK"
wipeme read --output-dir ./attachments "$LINK"
```

Secret output files use mode `0600` and existing files are never overwritten.
Attachment filenames are reduced to safe basenames. `read` intentionally exposes
selected plaintext on stdout unless an output file is selected.

<Warning>
  Retrieval is the destructive one-time claim. The server copy is deleted before
  local decryption completes. Several passphrase candidates still cause only one
  retrieval, but a wrong final credential cannot restore the server copy.
</Warning>

## Inject a secret into a child process

`exec` consumes a message and places the first compatible text block in a child
environment variable:

```sh theme={null}
wipeme exec \
  --non-interactive \
  --link-file /run/secrets/wipeme-link \
  --passphrase-file /run/secrets/wipeme-passphrase \
  --set-env STRIPE_API_KEY \
  -- stripe customers list
```

The command after `--` is executed directly; the CLI never inserts a shell. The
secret is not placed in child arguments or CLI output. Child exit status is
propagated, and SIGINT/SIGTERM are forwarded on Unix.

Credential transport variables—including `WIPEME_PASSPHRASE`, `--passphrase-env`,
and `--link-env` sources—are removed from the child environment. Unrelated parent
variables remain. The child can still print or exfiltrate its own environment, so
only execute trusted programs.

### Exit codes

| Code | Meaning                                                                |
| ---- | ---------------------------------------------------------------------- |
| `0`  | CLI operation or child completed successfully                          |
| `1`  | Unclassified configuration, crypto, or API failure                     |
| `2`  | Invalid CLI usage or flags                                             |
| `3`  | Invalid private link                                                   |
| `4`  | No credential source available                                         |
| `5`  | Available credentials did not decrypt or authorize the operation       |
| `6`  | Retrieval failed, including an unavailable or already consumed message |
| `8`  | Output path or plaintext output refused or failed                      |
| `9`  | Child command could not be launched                                    |

After a child starts, `exec` propagates its exit status directly.

## MCP server

<Note>
  `wipeme mcp` is included in the published `v0.3.0-alpha.3` preview. See the
  [dedicated MCP guide](/developer-tools/mcp-server) for recommended workflows and
  [installation instructions](/developer-tools/mcp-server/installation).
</Note>

The local stdio MCP server lets Codex, Claude, and other compatible agent hosts
coordinate Wipe.me operations without receiving plaintext. It has no direct-read
tool and never returns decrypted message text, attachment bytes, generated
passwords, environment values, or process output.

```sh theme={null}
codex mcp add wipeme -- wipeme mcp
```

The MCP toolset includes:

| Tool                               | Purpose                                                                   |
| ---------------------------------- | ------------------------------------------------------------------------- |
| `inspect_private_link`             | Validate a link locally without network access or echoing it              |
| `generate_secret`                  | Generate and encrypt a password, returning only the link                  |
| `generate_secret_into_env_file`    | Generate, upload, and write the same secret to a private environment file |
| `generate_secret_into_process_env` | Generate, upload, and inject the same secret into an approved process     |
| `create_from_files`                | Encrypt a message file and attachments from allowed roots                 |
| `create_from_env`                  | Encrypt allowlisted server environment values                             |
| `create_from_process_output`       | Encrypt stdout from an approved producer profile                          |
| `consume_into_env_file`            | Consume selected blocks into a private environment file                   |
| `retry_into_env_file`              | Retry environment-file output without another retrieval                   |
| `consume_into_files`               | Consume into a new private directory                                      |
| `retry_into_files`                 | Retry local output without another retrieval                              |
| `consume_into_process_env`         | Consume and inject selected blocks into an approved process               |
| `retry_process_env`                | Retry without retrieving or generating again                              |
| `forget_recovery`                  | Abandon recovery and delete unreleased generated messages                 |
| `delete_message`                   | Delete a message using its private capability                             |

MCP stdin and stdout belong only to newline-delimited JSON-RPC. The default `host`
mode relies on the MCP host, operating-system permissions, sandbox, and approval
flow. Restricted mode additionally requires configured roots and uses
administrator-defined process profiles. Commands execute directly without a shell,
and process stdout/stderr are never returned.

```yaml theme={null}
mcp:
  allowed_read_roots: [/workspace, /run/secrets]
  allowed_write_roots: [/workspace/output]
  allowed_link_env: [WIPEME_PRIVATE_LINK]
  allowed_passphrase_env: [WIPEME_PASSPHRASE]
  allowed_source_env: [DATABASE_PASSWORD, API_TOKEN]
  recovery_directory: /run/user/1000/wipeme-mcp-recovery
  recovery_ttl: 15m
  recovery_max_attempts: 5
  process_profiles:
    database-migrate:
      role: consumer
      executable: /usr/local/bin/database-tool
      fixed_args: [migrate]
      argument_patterns: ['^[A-Za-z0-9._/-]+$']
      max_arguments: 4
      timeout: 2m
      accepted_exit_codes: [0]
      allowed_secret_env: [DATABASE_PASSWORD]
      inherit_env: [HOME, PATH]
```

Configuration containing MCP policy must be owned by the current user or root and
must not be writable by group or others. Recovery records use mode `0600` inside a
mode-`0700` directory and permit retries after destructive retrieval without a
second server request.

<Warning>
  Private links and inline PNG QR images returned by MCP are bearer capabilities and
  may be retained by the host transcript. Generated secrets and consumed plaintext
  are deliberately excluded from all tool results and diagnostics.
</Warning>

## Protected link sources

A complete private link is a bearer capability. `read`, `exec`, and `delete` accept
exactly one of:

* positional private link;
* `--link-file FILE`;
* `--link-env NAME`.

In agent-coordinated and CI/CD workflows, prefer link and passphrase files or named
environment variables. The agent should coordinate the command without reading the
plaintext; the local CLI writes it to a protected output or injects it into a trusted
child process. `--passphrase-stdin` is rejected for `exec` because it conflicts with
child stdin.

Do not use plaintext `read` output on stdout in an agent-controlled terminal. Prefer
`read --output` for a protected, non-indexed file or `exec --set-env` for direct
injection into a trusted child process.

## Delete an unopened message

```sh theme={null}
wipeme delete --link-file ./private-message.link

WIPEME_PASSPHRASE='previously agreed phrase' \
  wipeme delete --non-interactive 'https://wipe.me/aBc1-dEf2'
```

Deletion capabilities are derived locally. Automatic fragments and manual
passphrases never reach the service. A complete automatic link grants deletion
authority; a manual link also requires its separate passphrase.

## Output, receipts, and progress

```sh theme={null}
wipeme --copy
wipeme --qr
wipeme --qr-big
wipeme --qr --qr-invert
wipeme --qr-big --qr-invert
wipeme --json
wipeme --link-file ./private-message.link
wipeme --receipt ./private-message.receipt.json
```

Link and receipt files use mode `0600` and refuse to overwrite existing paths. A
manual-mode creator receipt contains the passphrase and must be protected like the
message itself.

`--qr` keeps the private link on the first output line, prints a compatibility
caption, and then uses the QR library's native compact half-block renderer. Compact
output requires a Unicode terminal with block-character support and a monospaced
font. If it is distorted or unreadable, use `--qr-big` for the library's full-size
compatibility renderer. `--qr` and `--qr-big` are mutually exclusive.

`--qr-invert` works with either renderer and swaps module colors for the opposite
terminal background. An automatic-key QR contains the complete private link and its
fragment secret, so terminal screenshots and recordings containing it are secret.
A manual-passphrase QR contains only the public link; the recipient still needs the
separately shared passphrase. Neither QR mode can be combined with `--json`.

On an interactive terminal, stderr displays byte-counted encryption and upload
progress. Progress is suppressed when stderr is redirected or JSON output is used.

## Configuration

Preferences may be stored in `/etc/wipeme/config.yaml` or
`~/.wipeme/config.yaml`:

```yaml theme={null}
server_url: https://wipe.me
expires: 24h
copy: false
```

For split local development, configure `api_url` and `site_url` independently.
Configuration priority is CLI flags, environment, user file, system file, then
built-in defaults. Supported environment preferences include
`WIPEME_SERVER_URL`, `WIPEME_API_URL`, `WIPEME_SITE_URL`, `WIPEME_EXPIRES`, and
`WIPEME_COPY`. Do not store private links or passphrases in YAML configuration.

## Attachment metadata cleanup

Before encryption, the CLI removes supported private metadata from a temporary
local copy and never changes the source file:

* **JPEG/JPG:** EXIF/XMP, IPTC/Photoshop metadata, and comments;
* **PNG/APNG:** `eXIf`, textual metadata, time, and physical-dimension chunks;
* **WebP:** EXIF and XMP chunks and their feature flags;
* **MP3:** ID3v2 and ID3v1 tags.

Unsupported formats—including PDFs, Office documents, archives, video containers,
and audio other than MP3—are encrypted byte-for-byte. See
[Attachment metadata and privacy](/basics/attachment-metadata-and-privacy).

## Installation

Installation is documented separately so the command examples remain easy to
scan.

<Card title="CLI installation" icon="download" href="/developer-tools/command-line-interface/installation">
  Choose Homebrew, APT, DNF, direct downloads, or Go installation.
</Card>

## Limits and security status

Free anonymous messages are limited to a **3 MiB encrypted envelope** and a maximum
unopened expiry of **14 days**. Every message is claimed at most once.

<Warning>
  The CLI and unified v1 envelope are development previews and have not received an
  independent security audit.
</Warning>

For implementation details and the complete flag reference, see the
[`wipe-me/cli`](https://github.com/wipe-me/cli) repository.
