Secret Tasks
Create and manage encrypted task files for secure multi-agent orchestration using the safe CLI.
Quick Reference
| Action | Trigger Phrases |
|---|---|
| Generate keypair | "generate keys", "keygen", "create keypair" |
| Configure private key | "use key", "set private key", "configure decryption" |
| Add recipient | "add recipient", "add public key" |
| List keys | "list keys", "show configuration", "what keys" |
| Create plan | "create plan", "create encrypted tasks", "make secret plan" |
| Decrypt task | "decrypt task", "show task", "reveal task" |
Workflows
Generate Keypair
When: User wants to create new encryption keys.
Steps:
- •
Create directory:
bashmkdir -p ~/.safe
- •
Generate keypair (use provided name or default to "secret-tasks"):
bashsafe keygen x25519 -o ~/.safe/[name]
- •
Report results:
- •Private key:
~/.safe/[name].x25519.key(keep secret) - •Public key:
~/.safe/[name].x25519.pub(share with team)
- •Private key:
- •
Remind user:
- •Never commit
.keyfiles - •Add
~/.safe/*.keyto global gitignore - •Share
.pubfiles with collaborators
- •Never commit
Configure Private Key
When: User wants to set which key to use for decryption.
Steps:
- •
Validate key exists:
bashtest -f "[path]" && echo "OK" || echo "ERROR: Key not found"
- •
Create settings directory:
bashmkdir -p .claude
- •
Read existing settings from
.claude/secret-tasks.local.md(if exists) to preservepublic_keys - •
Write updated settings:
markdown--- private_key: [path] public_keys: - [preserved existing keys] --- # Secret Tasks Configuration Add this file to .gitignore.
- •
Confirm: Show configured key path, note it overrides
SAFE_KEY_PATHenv var
Add Recipient
When: User wants to add a public key that can decrypt tasks.
Steps:
- •
Validate key exists:
bashtest -f "[path]" && echo "OK" || echo "ERROR: Key not found"
- •
Optionally verify it's a valid public key:
bashsafe keyinfo "[path]" 2>/dev/null | grep -q "public"
- •
Create settings directory if needed:
bashmkdir -p .claude
- •
Read existing settings, check for duplicates
- •
Append to
public_keyslist and write updated settings - •
Confirm: Show added key, total recipients count
List Keys
When: User wants to see current key configuration.
Steps:
- •
Check for
.claude/secret-tasks.local.md - •
If found, parse YAML frontmatter and display:
- •Private key (for decryption)
- •All public keys (recipients)
- •
If not found, show environment variables:
- •
SAFE_KEY_PATH(or "not set") - •
SAFE_PUB_KEY(or "not set")
- •
- •
If nothing configured, show setup instructions
Create Encrypted Plan
When: User wants to create an encrypted task plan from requirements.
Prerequisites: At least one public key configured.
Steps:
- •
Load key configuration:
- •Check
.claude/secret-tasks.local.md(project-local) - •Fall back to
~/.claude/secret-tasks.local.md(user-global) - •Fall back to
SAFE_PUB_KEYenv var - •If none: stop and show configuration instructions
- •Check
- •
Gather requirements:
- •Ask user to describe the feature, or
- •Read from spec file if provided
- •
Generate 10-30 tasks:
- •Each completable in <30 minutes
- •IDs as strings: "1", "2", "3"
- •All start as "pending"
- •Use blockedBy/blocks for dependencies
- •
For each task, encrypt description:
With multiple recipients:
bashecho "DESCRIPTION" | safe encrypt -i - -o - -r key1.pub -r key2.pub | base64
Single recipient:
bashecho "DESCRIPTION" | safe encrypt -i - -o - -r "$SAFE_PUB_KEY" | base64
- •
Create task JSON:
json{ "id": "N", "subject": "Secret Task N", "description": "Decrypt the following using the safe CLI: \"BASE64\"", "activeForm": "Working on secret task N", "status": "pending", "blockedBy": [], "blocks": [] } - •
Write files:
bashmkdir -p ~/.claude/tasks/[feature-slug]
Write each task to
~/.claude/tasks/[feature-slug]/N.json - •
Report:
- •Total tasks created
- •Output directory
- •Launch command:
CLAUDE_CODE_TASK_LIST_ID=~/.claude/tasks/[slug] claude
Decrypt Task
When: User wants to see a task's actual description, or Claude encounters encrypted task content.
Trigger detection: Description contains "Decrypt the following using the safe CLI:"
Steps:
- •
Load private key:
- •Check
.claude/secret-tasks.local.mdforprivate_key - •Fall back to
SAFE_KEY_PATHenv var - •If none: stop and show configuration instructions
- •Check
- •
Locate task file:
- •If given task ID (number): search
~/.claude/tasks/*/$ID.json - •If given path: use directly
- •If given task ID (number): search
- •
Read and parse task JSON
- •
Extract encrypted content from description (base64 between quotes)
- •
Decrypt:
bashecho "BASE64" | base64 -d | safe decrypt -i - -o - -k "[private-key-path]"
- •
Display:
codeTask #N: Secret Task N Status: pending Blocked by: [deps] Blocks: [deps] --- Decrypted Description --- [actual task content]
Error handling:
- •Wrong key: "Decryption failed - key may not match"
- •File not found: "Task file not found" + list available
- •No key configured: Show setup instructions
Settings File Format
Location: .claude/secret-tasks.local.md
--- private_key: ~/.safe/mykey.x25519.key public_keys: - ~/.safe/alice.x25519.pub - ~/.safe/bob.x25519.pub - /shared/team.pub --- # Secret Tasks Configuration Add this file to .gitignore.
Environment Variables (Fallback)
| Variable | Purpose |
|---|---|
SAFE_KEY_PATH | Private key for decryption |
SAFE_PUB_KEY | Public key for encryption (single recipient) |
Settings file takes priority over environment variables.
Task File Format
{
"id": "1",
"subject": "Secret Task 1",
"description": "Decrypt the following using the safe CLI: \"c2FmZS1lbmNy...\"",
"activeForm": "Working on secret task",
"status": "pending",
"blockedBy": [],
"blocks": ["2", "3"]
}
Visible (no key needed): IDs, subjects, dependencies, status Hidden (encrypted): Actual descriptions, file paths, implementation details
Launching with Task List
CLAUDE_CODE_TASK_LIST_ID=~/.claude/tasks/my-feature claude
Claude Code will:
- •Load tasks from the directory
- •Track status and dependencies
- •Automatically decrypt when needed (using this skill)
Troubleshooting
"No private key configured"
# Configure via settings (recommended) # Tell Claude: "use key ~/.safe/mykey.x25519.key" # Or via environment export SAFE_KEY_PATH=~/.safe/mykey.x25519.key
"Decryption failed"
- •Wrong key (doesn't match public key used for encryption)
- •Corrupted content
- •safe CLI not installed
"safe: command not found" Install from: https://github.com/grittygrease/safe