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). Routinegetcalls 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
--yesto skip the prompt for automation. - Support a
--dry-runmode so agents can preview thesecuritycommand without touching the Keychain. - Supply secrets via
--password-stdin,--password-env, or the hidden interactive prompt. The legacy--passwordoption leaves values in shell history and process listings (the helper warns when it's used), so prefer the safer inputs;--password-env VARreads 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
list – Summaries of matching entries.
./skills/keychain-access/keychain-access.sh list \ [--keychain /path/to/keychain] [--service NAME] [--account NAME]- Scans the chosen keychain via
security dump-keychainand prints service/account/label rows. - Filters can target a specific service or account (substring match).
- Use
--dry-runto review thesecurity dump-keychaininvocation without running it.
- Scans the chosen keychain via
get – Display metadata for a generic password.
./skills/keychain-access/keychain-access.sh get \ --service SERVICE --account ACCOUNT [--keychain PATH] [--raw] [--dry-run]- Requires both
--serviceand--accountto avoid ambiguity. - Password output is masked by default; add
--rawonly 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-runto review thesecurity find-generic-passwordinvocation without reaching into the keychain.
- Requires both
set – Create or update a generic password entry.
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--passwordflag 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 VARreads 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
--yesto skip the prompt once you have authorized the change). --dry-runprints thesecurity add-generic-password ...invocation with the password redacted and exits before checking for an existing entry or prompting.
- Supply the password via
delete – Remove a matching generic password.
./skills/keychain-access/keychain-access.sh delete \ --service SERVICE --account ACCOUNT [--keychain PATH] [--yes] [--dry-run]- Always prompts before deletion;
--yesbypasses the prompt if the user already authorized removing the credential. - The helper verifies the entry exists before asking for confirmation.
- Combine with
--dry-runto preview thesecurity delete-generic-passwordinvocation while keeping the keychain untouched; the helper exits before verifying the entry or prompting.
- Always prompts before deletion;
Request Examples
- "Store a new API token for
terraformunder accountci-bot." → runsetfor that service/account, pipe<TERRAFORM_TOKEN>into--password-stdin(or setTERRAFORM_TOKENand pass--password-env TERRAFORM_TOKEN), then confirm the update if prompted. - "Show everything stored for
smtpcredentials." → runlist --service smtpand thengetwith--rawonly if the user explicitly needs to read the password. - "Rotate the password for
deploy-botand remove the old entry." → usesetwith--service deployand--account deploy-bot, supply the new secret through one of the safe input options, allow the helper to prompt for confirmation, thendeletethe 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)
# 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.