Install
openclaw skills install openclaw-yatta-skillPersonal productivity system for task and capacity management. Create and organize tasks with rich attributes (priority, effort, complexity, tags), track tim...
openclaw skills install openclaw-yatta-skillInteract 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:
https://zunahvofybvxpptjkwxk.supabase.co/functions/v1
Branded URLs (yattadone.com/api) will be available in a future release once proxy configuration is resolved with the hosting provider.