diff --git a/README.md b/README.md
index 775f618..6e972bb 100644
--- a/README.md
+++ b/README.md
@@ -20,9 +20,10 @@
- Lightweight & feature-rich Wayland clipboard "manager" with fast persistent history and
- robust multi-media support. Stores and previews clipboard entries (text, images)
- on the clipboard with a neat TUI and advanced scripting capabilities.
+ Lightweight & feature-rich Wayland clipboard "manager" with fast persistent
+ history and robust multi-media support. Stores and previews clipboard
+ entries (text, images) on the clipboard with a neat TUI and advanced
+ scripting capabilities.
@@ -52,6 +53,8 @@ with many features such as but not necessarily limited to:
- Drop-in replacement for `wl-clipboard` tools (`wl-copy` and `wl-paste`)
- Sensitive clipboard filtering via regex (see below)
- Sensitive clipboard filtering by application (see below)
+- Password manager hint filtering (`x-kde-passwordManagerHint`)
+- Optional at-rest encryption for database entries using age
on top of the existing features of Cliphist, which are as follows:
@@ -270,8 +273,8 @@ stash db stats
- `stash db vacuum`: Optimize the database using SQLite's VACUUM command,
reclaiming space and improving performance.
- `stash db stats`: Display database statistics including total/active/expired
- entry counts, storage size, and page information. This is provided purely for
- convenience and the rule of the cool.
+ entry counts, encrypted/undecryptable entry counts, storage size, and page
+ information.
### Watch clipboard for changes and store automatically
@@ -357,21 +360,36 @@ sensitive pattern, using a regular expression. This is useful for preventing
accidental storage of secrets, passwords, or other sensitive data. You don't
want sensitive data ending up in your persistent clipboard, right?
-The filter can be configured in one of three ways, as part of two separate
+The filter can be configured in several ways, as part of three separate
features.
#### Clipboard Filtering by Entry Regex
-This can be configured in one of two ways. You can use the **environment
-variable** `STASTH_SENSITIVE_REGEX` to a valid regex pattern, and if the
-clipboard text matches the regex it will not be stored. This can be used for
-trivial secrets such as but not limited to GitHub tokens or secrets that follow
-a rule, e.g. a prefix. You would typically set this in your `~/.bashrc` or
-similar but in some cases this might be a security flaw.
+This can be configured in several ways. The simplest is the **environment
+variable** `STASH_SENSITIVE_REGEX` set to a valid regex pattern; if the
+clipboard text matches, it will not be stored. Useful for trivial secrets such
+as GitHub tokens or secrets that follow a rule. You would typically set this in
+your `~/.bashrc` or similar, but in some cases this might be a security flaw.
-The safer alternative to this is using **Systemd LoadCrediental**. If Stash is
-running as a Systemd service, you can provide a regex pattern using a crediental
-file. For example, add to your `stash.service`:
+The less-insecure alternatives are:
+
+- `STASH_SENSITIVE_REGEX_FILE`: read the regex from a file path. Useful with
+ NixOS secrets managers like agenix or sops-nix.
+
+ ```bash
+ export STASH_SENSITIVE_REGEX_FILE=/run/secrets/stash/clipboard_filter
+ ```
+
+- `STASH_SENSITIVE_REGEX_COMMAND`: execute a shell command whose stdout is the
+ regex pattern. Works well with password managers.
+
+ ```bash
+ export STASH_SENSITIVE_REGEX_COMMAND="pass show stash/clipboard-filter"
+ ```
+
+The safest option is **Systemd LoadCredential**. If Stash is running as a
+Systemd service, you can provide a regex pattern using a credential file. For
+example, add to your `stash.service`:
```dosini
LoadCredential=clipboard_filter:/etc/stash/clipboard_filter
@@ -382,9 +400,9 @@ quotes). This is done automatically in the
[vendored Systemd service](./contrib/stash.service). Remember to set the
appropriate file permissions if using this option.
-The service will check the credential file first, then the environment variable.
-If a clipboard entry matches the regex, it will be skipped and a warning will be
-logged.
+The service will check the credential file first, then the command, then the
+file path, then the environment variable. If a clipboard entry matches the
+regex, it will be skipped and a warning will be logged.
> [!TIP]
> **Example regex to block common password patterns**:
@@ -415,6 +433,72 @@ be only copied to the clipboard.
>
> `stash --excluded-apps Bitwarden watch`
+#### Clipboard Filtering by Password Manager Hint
+
+Stash automatically skips entries whose clipboard offer includes the
+`x-kde-passwordManagerHint` MIME type. This is the convention used by KeePassXC
+and compatible password managers to signal that clipboard content is sensitive
+and should not be persisted.
+
+No configuration is required. If the hint is present in the clipboard offer, the
+entry is dropped before storage. The entry is still available in your clipboard
+— it is only excluded from the persistent database.
+
+> [!NOTE]
+> This filter only applies via the watch daemon (`stash watch`), where MIME type
+> metadata is available from the Wayland clipboard protocol. Manual
+> `stash store` invocations do not have this context and are not filtered.
+
+### Database Encryption
+
+Stash supports encrypting clipboard entries at rest using the
+[age](https://age-encryption.org/) encryption format.
+
+Encryption is **opt-in** and only activates when a passphrase is configured.
+When one is configured, all new entries are encrypted before storage and
+decrypted transparently on retrieval. Entries stored without encryption remain
+as plaintext. Only new entries written after configuring encryption are
+encrypted.
+
+> [!WARNING]
+> Removing the passphrase after encrypted entries have been stored leaves those
+> entries permanently unreadable. There is no migration path short of wiping the
+> database. `stash db stats` reports affected entries as Undecryptable.
+>
+> Full-text search (`stash delete --type query`, TUI search) operates on raw
+> database contents. Encrypted entries will not match any search query.
+
+#### Configuration
+
+Provide a passphrase in one of these ways (checked in order):
+
+1. **Systemd LoadCredential** (safest): add to `stash.service`:
+
+ ```dosini
+ LoadCredential=stash_encryption_passphrase:/etc/stash/encryption_passphrase
+ ```
+
+2. **Command** — stdout of a shell command:
+
+ ```bash
+ export STASH_ENCRYPTION_PASSPHRASE_COMMAND="pass show stash/encryption-key"
+ ```
+
+3. **File** — path to a file containing the passphrase:
+
+ ```bash
+ export STASH_ENCRYPTION_PASSPHRASE_FILE=/run/secrets/stash/encryption_passphrase
+ ```
+
+4. **Environment variable** (least secure):
+
+ ```bash
+ export STASH_ENCRYPTION_PASSPHRASE="your-secure-passphrase"
+ ```
+
+> [!TIP]
+> Back up your passphrase. Encrypted entries cannot be recovered without it.
+
## Motivation
I've been a long-time user of Cliphist. You can probably tell by the number of