secret-tasks
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:
mkdir -p ~/.safe -
Generate keypair (use provided name or default to "secret-tasks"):
safe 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:
test -f "[path]" && echo "OK" || echo "ERROR: Key not found" -
Create settings directory:
mkdir -p .claude -
Read existing settings from
.claude/secret-tasks.local.md(if exists) to preservepublic_keys -
Write updated settings:
--- 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:
test -f "[path]" && echo "OK" || echo "ERROR: Key not found" -
Optionally verify it's a valid public key:
safe keyinfo "[path]" 2>/dev/null | grep -q "public" -
Create settings directory if needed:
mkdir -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:
echo "DESCRIPTION" | safe encrypt -i - -o - -r key1.pub -r key2.pub | base64Single recipient:
echo "DESCRIPTION" | safe encrypt -i - -o - -r "$SAFE_PUB_KEY" | base64 -
Create task 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:
mkdir -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:
echo "BASE64" | base64 -d | safe decrypt -i - -o - -k "[private-key-path]" -
Display:
Task #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