macOS Keychain helpers (list/get/set/delete) via the security CLI. Trigger this skill when the user needs to inspect, store, update, or remove generic passwo...
---
name: keychain-access
description: "macOS Keychain helpers (list/get/set/delete) via the security CLI. Trigger this skill when the user needs to inspect, store, update, or remove generic passwords from the Keychain with explicit confirmation on destructive ops and guarded secret disclosure."
metadata:
openclaw:
emoji: "🔐"
requires:
bins:
- security
---
# Keychain Access Skill
Manage macOS Keychain items in a safe, scriptable way. Use the bundled `keychain-access/keychain-access.sh` helper for all operations: it wraps `security` calls, enforces confirmations for updates and deletions, masks secrets unless explicitly requested, and supports dry-run previews.
## Safety Constraints
- Never print secrets unless the user explicitly asks to reveal them (`--raw`). Routine `get` calls only report metadata with the password hidden.
- Ask the user to confirm before modifying or deleting existing entries. The script prompts by default and accepts `--yes` to skip the prompt for automation.
- Support a `--dry-run` mode so agents can preview the `security` command without touching the Keychain.
- Supply secrets via `--password-stdin`, `--password-env`, or the hidden interactive prompt. The legacy `--password` option leaves values in shell history and process listings (the helper warns when it's used), so prefer the safer inputs; `--password-env VAR` reads the var and unsets it immediately to keep the secret out of the environment.
- Operate on a specific keychain when provided (`--keychain`); otherwise, the default search list is used. Avoid leaking system passwords by defaulting to explicit service/account filters.
## Supported Operations
1. **list** – Summaries of matching entries.
```bash
./skills/keychain-access/keychain-access.sh list \
[--keychain /path/to/keychain] [--service NAME] [--account NAME]
```
- Scans the chosen keychain via `security dump-keychain` and prints service/account/label rows.
- Filters can target a specific service or account (substring match).
- Use `--dry-run` to review the `security dump-keychain` invocation without running it.
2. **get** – Display metadata for a generic password.
```bash
./skills/keychain-access/keychain-access.sh get \
--service SERVICE --account ACCOUNT [--keychain PATH] [--raw] [--dry-run]
```
- Requires both `--service` and `--account` to avoid ambiguity.
- Password output is masked by default; add `--raw` only when the user explicitly needs the secret value.
- Returns command diagnostics even if the password is hidden (e.g., matching record, keychain path).
- Use `--dry-run` to review the `security find-generic-password` invocation without reaching into the keychain.
3. **set** – Create or update a generic password entry.
```bash
printf '<SERVICE_SECRET>' | ./skills/keychain-access/keychain-access.sh set --service SERVICE --account ACCOUNT --password-stdin [--keychain PATH] [--yes] [--dry-run]
```
- Supply the password via `--password-stdin`, `--password-env VAR`, or the hidden interactive prompt that runs when stdin is a terminal and no source is provided. The legacy `--password` flag still works but is insecure because its value appears in shell history and process listings, so the helper prints a warning if it is used.
- `--password-env VAR` reads the named env var, unsets it immediately after reading, and keeps the secret out of the command line and environment dumps.
- When a matching service/account already exists, the helper announces the pending update and prompts for confirmation before overwriting (use `--yes` to skip the prompt once you have authorized the change).
- `--dry-run` prints the `security add-generic-password ...` invocation with the password redacted and exits before checking for an existing entry or prompting.
4. **delete** – Remove a matching generic password.
```bash
./skills/keychain-access/keychain-access.sh delete \
--service SERVICE --account ACCOUNT [--keychain PATH] [--yes] [--dry-run]
```
- Always prompts before deletion; `--yes` bypasses the prompt if the user already authorized removing the credential.
- The helper verifies the entry exists before asking for confirmation.
- Combine with `--dry-run` to preview the `security delete-generic-password` invocation while keeping the keychain untouched; the helper exits before verifying the entry or prompting.
## Request Examples
- "Store a new API token for `terraform` under account `ci-bot`." → run `set` for that service/account, pipe `<TERRAFORM_TOKEN>` into `--password-stdin` (or set `TERRAFORM_TOKEN` and pass `--password-env TERRAFORM_TOKEN`), then confirm the update if prompted.
- "Show everything stored for `smtp` credentials." → run `list --service smtp` and then `get` with `--raw` only if the user explicitly needs to read the password.
- "Rotate the password for `deploy-bot` and remove the old entry." → use `set` with `--service deploy` and `--account deploy-bot`, supply the new secret through one of the safe input options, allow the helper to prompt for confirmation, then `delete` the old credential with confirmation when the rotation is complete.
- "Preview the delete command for the app key without running it." → use `delete --service app-key --account release-bot --dry-run`.
## Testing Transcript (safe context)
```bash
# Prepare a disposable keychain (password = <KEYCHAIN_PASSWORD>)
security create-keychain -p <KEYCHAIN_PASSWORD> /tmp/keychain-access-test.keychain
security unlock-keychain -p <KEYCHAIN_PASSWORD> /tmp/keychain-access-test.keychain
# 1) List entries (empty keychain)
./skills/keychain-access/keychain-access.sh list --keychain /tmp/keychain-access-test.keychain
# Output:
No matching entries found.
# 2) Set a credential (confirms before update)
printf '<SERVICE_SECRET>' | ./skills/keychain-access/keychain-access.sh set --service test-service --account test-user --password-stdin --keychain /tmp/keychain-access-test.keychain --yes
# Output:
Stored credential for 'test-service' / 'test-user'.
# 3) Get the credential (masked by default, raw only when asked)
./skills/keychain-access/keychain-access.sh get --service test-service --account test-user --keychain /tmp/keychain-access-test.keychain --raw
# Output:
password: "<SERVICE_SECRET>"
keychain: "/private/tmp/keychain-access-test.keychain"
version: 256
class: "genp"
attributes:
0x00000007 <blob>="test-service"
0x00000008 <blob>=<NULL>
"acct"<blob>="test-user"
... (remaining metadata omitted for brevity)
# 4) Delete the credential (prompts confirmation)
./skills/keychain-access/keychain-access.sh delete --service test-service --account test-user --keychain /tmp/keychain-access-test.keychain --yes
# Output:
Deleted credential for 'test-service' / 'test-user'.
# Cleanup
security delete-keychain /tmp/keychain-access-test.keychain
```
Include this transcript in reports so the main agent knows the commands and their expected output shape.
don't have the plugin yet? install it then click "run inline in claude" again.
added explicit inputs section documenting keychain access requirements and password sourcing options, expanded decision points to cover all conditional branches including locked keychains and empty result sets, formalized output contract with exit codes and format specifications, and added outcome signal section describing success indicators for each operation.
manage macOS Keychain items safely via the security CLI. use this skill when the user needs to list, retrieve, store, update, or delete generic passwords. the helper wraps security calls with confirmation gates on destructive ops, masks secrets by default, and supports dry-run previews so you can inspect commands before they touch the keychain.
./skills/keychain-access/keychain-access.sh (bundled).security binary present on PATH (standard on macOS 10.6+).--password-env VAR, the variable must be set in the calling shell. the helper reads and unsets it immediately after use.set operations if using --password-stdin; otherwise the helper prompts interactively if stdin is a TTY.list operations but full exact matches are required for get, set, and delete.list credentials: invoke ./skills/keychain-access/keychain-access.sh list [--keychain PATH] [--service NAME] [--account NAME] [--dry-run]. the helper scans the target keychain (or default search list if not specified) via security dump-keychain, filters by service/account if provided (substring match), and prints matching entries as service/account/label rows. use --dry-run to preview the dump command without executing it. output is human-readable summary or "no matching entries found" if the result set is empty.
get a credential: invoke ./skills/keychain-access/keychain-access.sh get --service SERVICE --account ACCOUNT [--keychain PATH] [--raw] [--dry-run]. both --service and --account are required to avoid ambiguity. the helper queries via security find-generic-password and returns metadata (keychain path, version, class, attributes). password is masked by default; add --raw only when the user explicitly requests the secret value. use --dry-run to preview the find command without querying the keychain. if no matching entry exists, the helper reports "credential not found" and exits with status 1.
set a credential: invoke printf '<PASSWORD>' | ./skills/keychain-access/keychain-access.sh set --service SERVICE --account ACCOUNT --password-stdin [--keychain PATH] [--yes] [--dry-run]. password source options: pipe via stdin (preferred, --password-stdin), read from env var and unset it immediately (--password-env VAR), or let the helper prompt interactively if stdin is a TTY and no source is provided. the legacy --password flag is supported but insecure; the helper warns if it is used. if a matching service/account already exists, the helper announces the pending update and prompts for confirmation before overwriting (use --yes to skip the prompt). use --dry-run to print the security add-generic-password invocation with the password redacted; the helper exits before checking for an existing entry or prompting.
delete a credential: invoke ./skills/keychain-access/keychain-access.sh delete --service SERVICE --account ACCOUNT [--keychain PATH] [--yes] [--dry-run]. the helper verifies the entry exists and always prompts before deletion; use --yes to skip the prompt once the user has authorized removal. use --dry-run to preview the security delete-generic-password invocation; the helper exits before verifying the entry or prompting. if the entry does not exist, the helper reports "credential not found" and exits with status 1 without prompting.
get --raw. without --raw, the password is masked in output. secrets are never printed unless explicitly requested.--yes to bypass confirmation prompts on set and delete. manual confirmation is the default for safety.--dry-run with any operation. the helper prints the security invocation with secrets redacted and exits without modifying the keychain.--password-env VAR instead of --password. the helper reads the var and unsets it immediately, preventing the secret from remaining in the environment. do not use --password VALUE in production; it leaves the secret in shell history and process listings.--keychain /path/to/keychain. the helper operates on the default search list if not specified. if the keychain is locked, the system prompts for the unlock password.security CLI will prompt for the keychain password. if running non-interactively and the keychain is locked, the operation will fail. pre-unlock the keychain or use an unlocked keychain.list first if certainty is required.security does the escaping internally.--dry-run, prints the security dump-keychain command instead of executing it.--dry-run, prints the security find-generic-password command and exits without executing it.--yes is not set, prompts the user for confirmation before proceeding. exit status 0 on success, 1 if the operation is cancelled or fails. if --dry-run, prints the redacted security add-generic-password command and exits without touching the keychain.--yes is provided. exit status 0 on success, 1 if the credential does not exist, the user cancels the prompt, or the operation fails. if --dry-run, prints the security delete-generic-password command and exits without touching the keychain.get or list --service X --account Y.get or list on that service/account afterward should return no results.# prepare a disposable keychain (password = testpass123)
security create-keychain -p testpass123 /tmp/keychain-access-test.keychain
security unlock-keychain -p testpass123 /tmp/keychain-access-test.keychain
# 1) list entries (empty keychain)
./skills/keychain-access/keychain-access.sh list \
--keychain /tmp/keychain-access-test.keychain
# output:
# No matching entries found.
# 2) set a credential (with --yes to skip confirmation)
printf 'super-secret-token-xyz' | ./skills/keychain-access/keychain-access.sh set \
--service test-service --account test-user \
--password-stdin --keychain /tmp/keychain-access-test.keychain --yes
# output:
# Stored credential for 'test-service' / 'test-user'.
# 3) get the credential (masked by default)
./skills/keychain-access/keychain-access.sh get \
--service test-service --account test-user \
--keychain /tmp/keychain-access-test.keychain
# output:
# password: (masked)
# keychain: "/private/tmp/keychain-access-test.keychain"
# version: 256
# class: "genp"
# attributes: ...
# 4) get the credential (raw, secret revealed)
./skills/keychain-access/keychain-access.sh get \
--service test-service --account test-user \
--keychain /tmp/keychain-access-test.keychain --raw
# output:
# password: "super-secret-token-xyz"
# keychain: "/private/tmp/keychain-access-test.keychain"
# version: 256
# class: "genp"
# attributes: ...
# 5) preview a delete command without executing
./skills/keychain-access/keychain-access.sh delete \
--service test-service --account test-user \
--keychain /tmp/keychain-access-test.keychain --dry-run
# output:
# security delete-generic-password -s 'test-service' -a 'test-user' /tmp/keychain-access-test.keychain
# 6) delete the credential (with --yes to skip confirmation)
./skills/keychain-access/keychain-access.sh delete \
--service test-service --account test-user \
--keychain /tmp/keychain-access-test.keychain --yes
# output:
# Deleted credential for 'test-service' / 'test-user'.
# 7) verify deletion
./skills/keychain-access/keychain-access.sh get \
--service test-service --account test-user \
--keychain /tmp/keychain-access-test.keychain
# output:
# credential not found.
# (exit status 1)
# cleanup
security delete-keychain /tmp/keychain-access-test.keychain
include this transcript in reports so the calling agent knows the commands and expected output shapes.
credits: original skill authored for clawhub. enriched and standardized for Implexa.