Personal productivity system for task and capacity management. Create and organize tasks with rich attributes (priority, effort, complexity, tags), track time and streaks, manage capacity across projects and contexts, view Eisenhower Matrix prioritization, sync calendar subscriptions, handle delegation and follow-ups, and get AI-powered insights. Supports batch operations, multi-project workflows, and real-time capacity planning to prevent overcommitment. Security: v0.2.0 eliminates RCE vulnerability from v0.1.3 (shell/JSON injection in examples), adds endpoint verification, safe jq patterns throughout.
Interact with Yatta! task management system via API. Requires an API key from your Yatta! account.
This skill can perform DESTRUCTIVE operations on your Yatta! account:
Operation Types:
Read-Only Operations (✅ Safe):
Destructive Operations (⚠️ Modify or delete data):
Best Practices:
For detailed API operation documentation, see API-REFERENCE.md.
Your Yatta! API key provides FULL access to your account:
Security Best Practices:
yatta_... keyOption A: Environment Variables (Recommended)
# Add to your shell profile (~/.zshrc, ~/.bashrc)
export YATTA_API_KEY="yatta_your_key_here"
export YATTA_API_URL="https://zunahvofybvxpptjkwxk.supabase.co/functions/v1" # Default
Option B: 1Password CLI (Most Secure)
# Store key in 1Password
op item create --category=API_CREDENTIAL \
--title="Yatta API Key" \
api_key[password]="yatta_your_key_here"
# Use in commands
export YATTA_API_KEY=$(op read "op://Private/Yatta API Key/api_key")
The default API endpoint is hosted on Supabase:
https://zunahvofybvxpptjkwxk.supabase.co/functions/v1Why Supabase?
Verification steps:
Verify app ownership:
Check SSL certificate:
openssl s_client -connect zunahvofybvxpptjkwxk.supabase.co:443 \
-servername zunahvofybvxpptjkwxk.supabase.co < /dev/null 2>&1 \
| openssl x509 -noout -subject -issuer
Run verification script:
# Automated endpoint verification
bash scripts/verify-endpoint.sh
Contact support if uncertain:
Branded URL (Coming Soon):
https://api.yattadone.com/v1Security note: Only send your API key to endpoints you trust and have verified. If you prefer to wait for the branded API URL, that's a valid security choice.
curl -s "$YATTA_API_URL/tasks" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.[:3]' # Show first 3 tasks
⚠️ CRITICAL: This skill is vulnerable to shell and JSON injection if user input is not properly sanitized.
ALL examples in this skill use safe patterns:
jq -n --arg (prevents JSON injection)jq -sRr @uri (prevents shell injection)# ✅ SAFE: JSON construction
PAYLOAD=$(jq -n --arg title "$TITLE" '{title: $title}')
curl -d "$PAYLOAD" ...
# ✅ SAFE: URL encoding
TASK_ID_ENCODED=$(printf %s "$TASK_ID" | jq -sRr @uri)
curl "$API_URL/tasks/$TASK_ID_ENCODED" ...
# ✅ BEST: Use wrapper functions
source scripts/yatta-safe-api.sh
yatta_create_task "Finish report" "high"
Unsafe patterns can lead to:
See SECURITY.md for:
See scripts/yatta-safe-api.sh for:
This skill requires MANUAL invocation only.
Setting: disable-model-invocation: true
What this means:
Security rationale:
❌ Autonomous (NOT allowed):
User: "I should probably archive old tasks"
Agent: *silently archives tasks without confirmation*
✅ Manual (Required):
User: "Please archive tasks older than 30 days"
Agent: *executes explicit request, shows results*
How it works:
disable-model-invocation: trueVerification:
# Check package.json
jq '.openclaw["disable-model-invocation"]' package.json
# Should output: true
# Check SKILL.md frontmatter
grep "disable-model-invocation" SKILL.md
# Should show: "disable-model-invocation":true
If Yatta! operations happen without your explicit request:
This should never happen - manual invocation is a security requirement.
All tasks:
curl -s "$YATTA_API_URL/tasks" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
Filter by status:
# TODO tasks only
curl -s "$YATTA_API_URL/tasks?status=todo" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
# Doing (active) tasks
curl -s "$YATTA_API_URL/tasks?status=doing" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
# Completed tasks
curl -s "$YATTA_API_URL/tasks?status=done" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
Filter by priority:
# High priority tasks
curl -s "$YATTA_API_URL/tasks?priority=high" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.[] | {title, due_date, priority}'
Filter by project:
# Get project ID first
PROJECT_ID=$(curl -s "$YATTA_API_URL/projects" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq -r '.[] | select(.name=="Website Redesign") | .id')
# Get tasks for that project (URL-encode query parameter)
PROJECT_ID_ENCODED=$(printf %s "$PROJECT_ID" | jq -sRr @uri)
curl -s "$YATTA_API_URL/tasks?project_id=$PROJECT_ID_ENCODED" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
Filter by matrix state:
# Delegated tasks
curl -s "$YATTA_API_URL/tasks?matrix_state=delegated" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.[] | {title, delegated_to, follow_up_date}'
# Waiting tasks
curl -s "$YATTA_API_URL/tasks?matrix_state=waiting" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
Date range queries:
# Tasks due this week
WEEK_END=$(date -v+7d "+%Y-%m-%d")
curl -s "$YATTA_API_URL/tasks?due_date_lte=$WEEK_END" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.[] | {title, due_date}'
# Overdue tasks
TODAY=$(date "+%Y-%m-%d")
curl -s "$YATTA_API_URL/tasks?due_date_lte=$TODAY&status=todo" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.[] | {title, due_date}'
Pagination:
# First 50 tasks
curl -s "$YATTA_API_URL/tasks?limit=50&offset=0" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
# Next 50 tasks
curl -s "$YATTA_API_URL/tasks?limit=50&offset=50" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
Archived tasks:
curl -s "$YATTA_API_URL/tasks?archived=true" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
Simple task:
curl -s "$YATTA_API_URL/tasks" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Finish report",
"priority": "high"
}' \
| jq '.'
Task with full details:
curl -s "$YATTA_API_URL/tasks" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Review Q1 numbers",
"description": "Go through revenue, costs, and projections",
"priority": "high",
"due_date": "2026-02-15",
"effort_points": 5,
"project_id": "uuid-of-project",
"matrix_state": "active"
}' \
| jq '.'
Delegated task with follow-up:
curl -s "$YATTA_API_URL/tasks" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Website redesign",
"delegated_to": "Dev Team",
"matrix_state": "delegated",
"follow_up_schedule": {
"type": "weekly",
"day_of_week": "monday",
"next_follow_up": "2026-02-17"
}
}' \
| jq '.'
Recurring task:
curl -s "$YATTA_API_URL/tasks" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Team standup",
"recurrence_rule": {
"frequency": "daily",
"interval": 1,
"days_of_week": ["monday", "tuesday", "wednesday", "thursday", "friday"]
},
"effort_points": 1
}' \
| jq '.'
Update single task:
# ✅ SAFE: Use jq to build JSON payload
TASK_ID="uuid-of-task"
PAYLOAD=$(jq -n \
--arg id "$TASK_ID" \
--arg status "done" \
--arg completed_at "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
'{id: $id, status: $status, completed_at: $completed_at}')
curl -s -X PUT "$YATTA_API_URL/tasks" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" \
| jq '.'
Batch update tasks:
curl -s -X PUT "$YATTA_API_URL/tasks" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ids": ["uuid-1", "uuid-2", "uuid-3"],
"priority": "high",
"project_id": "project-uuid"
}' \
| jq '.'
# ✅ SAFE: Use jq to build JSON payload
TASK_ID="uuid-of-task"
PAYLOAD=$(jq -n --arg id "$TASK_ID" '{id: $id}')
curl -s -X DELETE "$YATTA_API_URL/tasks" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" \
| jq '.'
# All projects
curl -s "$YATTA_API_URL/projects" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
# With task counts
curl -s "$YATTA_API_URL/projects?with_counts=true" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.[] | {name, task_count, open_count}'
curl -s "$YATTA_API_URL/projects" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Website Redesign",
"description": "Complete overhaul of company site",
"color": "#3b82f6",
"icon": "🌐"
}' \
| jq '.'
# ✅ SAFE: Use jq to build JSON payload
PROJECT_ID="uuid-of-project"
PAYLOAD=$(jq -n \
--arg id "$PROJECT_ID" \
--arg name "Website Redesign v2" \
--argjson archived false \
'{id: $id, name: $name, archived: $archived}')
curl -s -X PUT "$YATTA_API_URL/projects" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" \
| jq '.'
# ✅ SAFE: URL-encode path parameter
PROJECT_ID="uuid-of-project"
PROJECT_ID_ENCODED=$(printf %s "$PROJECT_ID" | jq -sRr @uri)
curl -s "$YATTA_API_URL/projects/$PROJECT_ID_ENCODED/tasks" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
# All contexts
curl -s "$YATTA_API_URL/contexts" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
# With task counts
curl -s "$YATTA_API_URL/contexts?with_counts=true" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.[] | {name, task_count}'
curl -s "$YATTA_API_URL/contexts" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "@deep-focus",
"color": "#8b5cf6",
"icon": "🧠"
}' \
| jq '.'
# ✅ SAFE: Use jq to build JSON payload with arrays
TASK_ID="uuid-of-task"
CONTEXT_ID="uuid-of-context"
PAYLOAD=$(jq -n \
--arg task_id "$TASK_ID" \
--arg context_id "$CONTEXT_ID" \
'{task_id: $task_id, context_ids: [$context_id]}')
curl -s -X POST "$YATTA_API_URL/contexts/assign" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" \
| jq '.'
# ✅ SAFE: URL-encode path parameter
TASK_ID="uuid-of-task"
TASK_ID_ENCODED=$(printf %s "$TASK_ID" | jq -sRr @uri)
curl -s "$YATTA_API_URL/tasks/$TASK_ID_ENCODED/contexts" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
# ✅ SAFE: URL-encode path parameter
CONTEXT_ID="uuid-of-context"
CONTEXT_ID_ENCODED=$(printf %s "$CONTEXT_ID" | jq -sRr @uri)
curl -s "$YATTA_API_URL/contexts/$CONTEXT_ID_ENCODED/tasks" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
# ✅ SAFE: URL-encode path parameter
TASK_ID="uuid-of-task"
TASK_ID_ENCODED=$(printf %s "$TASK_ID" | jq -sRr @uri)
curl -s "$YATTA_API_URL/tasks/$TASK_ID_ENCODED/comments" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
# ✅ SAFE: URL-encode path + jq for JSON
TASK_ID="uuid-of-task"
TASK_ID_ENCODED=$(printf %s "$TASK_ID" | jq -sRr @uri)
PAYLOAD=$(jq -n \
--arg content "Waiting on client feedback before proceeding" \
'{content: $content}')
curl -s -X POST "$YATTA_API_URL/tasks/$TASK_ID_ENCODED/comments" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" \
| jq '.'
# ✅ SAFE: Use jq to build JSON payload
COMMENT_ID="uuid-of-comment"
PAYLOAD=$(jq -n \
--arg id "$COMMENT_ID" \
--arg content "Client responded, moving forward" \
'{id: $id, content: $content}')
curl -s -X PUT "$YATTA_API_URL/task-comments" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" \
| jq '.'
# ✅ SAFE: Use jq to build JSON payload
COMMENT_ID="uuid-of-comment"
PAYLOAD=$(jq -n --arg id "$COMMENT_ID" '{id: $id}')
curl -s -X DELETE "$YATTA_API_URL/task-comments" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" \
| jq '.'
curl -s "$YATTA_API_URL/follow-ups" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.[] | {title, delegated_to, follow_up_date}'
DATE="2026-02-15"
curl -s "$YATTA_API_URL/follow-ups?date=$DATE" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
# ✅ SAFE: URL-encode path parameter
TASK_ID="uuid-of-task"
TASK_ID_ENCODED=$(printf %s "$TASK_ID" | jq -sRr @uri)
curl -s -X POST "$YATTA_API_URL/tasks/$TASK_ID_ENCODED/follow-up" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{}' \
| jq '.'
# ✅ SAFE: URL-encode path + jq for JSON
TASK_ID="uuid-of-task"
TASK_ID_ENCODED=$(printf %s "$TASK_ID" | jq -sRr @uri)
PAYLOAD=$(jq -n \
--arg type "every_n_days" \
--argjson interval 3 \
--arg next_follow_up "2026-02-12" \
'{type: $type, interval: $interval, next_follow_up: $next_follow_up}')
curl -s -X PUT "$YATTA_API_URL/tasks/$TASK_ID_ENCODED/follow-up-schedule" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" \
| jq '.'
curl -s "$YATTA_API_URL/calendar/subscriptions" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
curl -s -X POST "$YATTA_API_URL/calendar/subscriptions" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Work Calendar",
"ical_url": "https://calendar.google.com/calendar/ical/...",
"default_context_id": "context-uuid"
}' \
| jq '.'
# ✅ SAFE: URL-encode path parameter
SUBSCRIPTION_ID="uuid-of-subscription"
SUBSCRIPTION_ID_ENCODED=$(printf %s "$SUBSCRIPTION_ID" | jq -sRr @uri)
curl -s -X POST "$YATTA_API_URL/calendar/subscriptions/$SUBSCRIPTION_ID_ENCODED/sync" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
# Events for date range
START="2026-02-10"
END="2026-02-17"
curl -s "$YATTA_API_URL/calendar/events?start=$START&end=$END" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
curl -s "$YATTA_API_URL/capacity/today" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '{date, utilization_percent, status, used_minutes, total_minutes}'
START="2026-02-10"
END="2026-02-17"
curl -s "$YATTA_API_URL/capacity?start=$START&end=$END" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.[] | {date, status, utilization_percent}'
curl -s -X POST "$YATTA_API_URL/capacity/compute" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
curl -s "$YATTA_API_URL/analytics/summary" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
curl -s "$YATTA_API_URL/analytics/velocity" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
curl -s "$YATTA_API_URL/analytics/distribution" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '{by_status, by_priority, by_matrix_state}'
curl -s "$YATTA_API_URL/analytics/streaks" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
curl -s "$YATTA_API_URL/analytics/insights" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '.'
curl -s "$YATTA_API_URL/tasks/matrix" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq '{do_first, schedule, delegate, eliminate}'
Morning briefing:
#!/bin/bash
echo "=== Today's Tasks ==="
curl -s "$YATTA_API_URL/tasks?status=todo&due_date_lte=$(date +%Y-%m-%d)" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq -r '.[] | "- [\(.priority)] \(.title)"'
echo ""
echo "=== Follow-Ups Due ==="
curl -s "$YATTA_API_URL/follow-ups" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq -r '.[] | "- \(.title) (delegated to: \(.delegated_to))"'
echo ""
echo "=== Capacity Status ==="
curl -s "$YATTA_API_URL/capacity/today" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq -r '"Utilization: \(.utilization_percent)% - \(.status)"'
#!/bin/bash
# Extract email subject and body
SUBJECT="$1"
BODY="$2"
curl -s "$YATTA_API_URL/tasks" \
-H "Authorization: Bearer $YATTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "'"$SUBJECT"'",
"description": "'"$BODY"'",
"priority": "medium",
"import_source": "email"
}' \
| jq -r '"Task created: \(.title)"'
#!/bin/bash
WEEK_START=$(date -v+mon "+%Y-%m-%d")
WEEK_END=$(date -v+sun "+%Y-%m-%d")
echo "=== Week of $WEEK_START ==="
curl -s "$YATTA_API_URL/capacity?start=$WEEK_START&end=$WEEK_END" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq -r '.[] | "\(.date): \(.status) (\(.utilization_percent)%)"'
echo ""
echo "=== Tasks Due This Week ==="
curl -s "$YATTA_API_URL/tasks?due_date_gte=$WEEK_START&due_date_lte=$WEEK_END" \
-H "Authorization: Bearer $YATTA_API_KEY" \
| jq -r '.[] | "[\(.due_date)] \(.title)"'
Check response status:
RESPONSE=$(curl -s -w "\n%{http_code}" "$YATTA_API_URL/tasks" \
-H "Authorization: Bearer $YATTA_API_KEY")
STATUS=$(echo "$RESPONSE" | tail -n1)
BODY=$(echo "$RESPONSE" | sed '$d')
if [ "$STATUS" -eq 200 ]; then
echo "$BODY" | jq '.'
else
echo "Error: HTTP $STATUS"
echo "$BODY" | jq '.error'
fi
Rate limit handling:
RESPONSE=$(curl -s -i "$YATTA_API_URL/tasks" \
-H "Authorization: Bearer $YATTA_API_KEY")
# Check X-RateLimit headers
REMAINING=$(echo "$RESPONSE" | grep -i "X-RateLimit-Remaining" | cut -d' ' -f2)
RESET=$(echo "$RESPONSE" | grep -i "X-RateLimit-Reset" | cut -d' ' -f2)
if [ "$REMAINING" -lt 10 ]; then
echo "Warning: Only $REMAINING requests remaining"
echo "Rate limit resets at: $(date -r $RESET)"
fi
jq for clean outputerror field with descriptionCurrently using the direct Supabase Edge Functions URL for reliability: