{"skill":{"slug":"shortcut-skill","displayName":"Shortcut Epic and Story skill","summary":"Access and manage Shortcut.com (formerly Clubhouse) project management. Use when the user asks to: list stories, view backlog, search issues, check epics, up...","description":"---\nname: shortcut\ndescription: \"Access and manage Shortcut.com (formerly Clubhouse) project management. Use when the user asks to: list stories, view backlog, search issues, check epics, update story state, create stories or epics, add comments, wire story dependencies, or fetch/triage a story. Trigger keywords: shortcut, story, backlog, sc-XXXX, sprint, epic, ticket.\"\nmetadata:\n  {\n    \"openclaw\": {\n      \"emoji\": \"🎯\",\n      \"homepage\": \"https://developer.shortcut.com/api/rest/v3\",\n      \"requires\": {\n        \"bins\": [\"curl\", \"jq\"],\n        \"secrets\": [\"shortcut\"]\n      },\n      \"primaryEnv\": \"SHORTCUT_API_TOKEN\",\n      \"credentialNote\": \"Shortcut API token — stored at ~/.openclaw/secrets/shortcut. Generate at app.shortcut.com → Settings → API Tokens.\"\n    }\n  }\n---\n\n# Shortcut.com Skill 🎯\n\nRead and write Shortcut.com stories, epics, and workflows via the REST API v3.\n\n## Auth Setup\n\nToken is stored at `~/.openclaw/secrets/shortcut` (mode 600, readable only by your user).\n\n```bash\nSHORTCUT_API_TOKEN=$(cat ~/.openclaw/secrets/shortcut 2>/dev/null)\nBASE=\"https://api.app.shortcut.com/api/v3\"\n```\n\nIf empty, ask the user for their API token, then save it:\n```bash\nmkdir -p ~/.openclaw/secrets\necho -n \"<token>\" > ~/.openclaw/secrets/shortcut && chmod 600 ~/.openclaw/secrets/shortcut\n```\n\nGenerate a token at **app.shortcut.com → Settings → API Tokens**. Shortcut tokens have full member-level access — no scope restriction is available. Rotate or delete the token at any time from the same settings page.\n\n> If you prefer not to persist the token on disk, skip saving and export it for the session only:\n> `export SHORTCUT_API_TOKEN=\"<token>\"`\n\n---\n\n## ⚠️ JSON Construction Rule\n\n**Always use `jq -n --arg` / `--argjson` to build request bodies.** Never interpolate user-supplied values directly into shell strings — this prevents shell injection from values containing quotes, backticks, or `$()`.\n\n```bash\n# ✅ Safe — jq handles all escaping\nDATA=$(jq -n --arg name \"$TITLE\" --arg desc \"$DESCRIPTION\" \\\n  '{name: $name, description: $desc}')\ncurl -s -X POST -H \"Shortcut-Token: $SHORTCUT_API_TOKEN\" \\\n  -H \"Content-Type: application/json\" -d \"$DATA\" \"$BASE/stories\"\n\n# ❌ Unsafe — never do this\ncurl ... -d \"{\\\"name\\\": \\\"$TITLE\\\"}\"\n```\n\n---\n\n## Reading\n\n### Get a Story\n```bash\ncurl -s -H \"Shortcut-Token: $SHORTCUT_API_TOKEN\" \"$BASE/stories/<id>\" | \\\n  jq '{id, name, story_type, description, workflow_state_id, estimate, epic_id, labels: [.labels[].name]}'\n```\nStrip the `sc-` prefix from IDs (use the number only).\n\n### Search Stories\n```bash\ncurl -s -H \"Shortcut-Token: $SHORTCUT_API_TOKEN\" \\\n  \"$BASE/search/stories?$(jq -rn --arg q \"$QUERY\" 'query=\\($q|@uri)&page_size=10')\" | \\\n  jq '.data[] | {id, name, story_type, estimate}'\n```\n\n### List My Stories\n```bash\nME=$(curl -s -H \"Shortcut-Token: $SHORTCUT_API_TOKEN\" \"$BASE/member\" | jq -r '.id')\ncurl -s -H \"Shortcut-Token: $SHORTCUT_API_TOKEN\" \\\n  \"$BASE/search/stories?owner_id=${ME}&page_size=25\" | \\\n  jq '.data[] | {id, name, story_type, workflow_state_id}'\n```\n\n### List Workflows & States\n```bash\ncurl -s -H \"Shortcut-Token: $SHORTCUT_API_TOKEN\" \"$BASE/workflows\" | \\\n  jq '.[] | {workflow: .name, states: [.states[] | {id, name, type}]}'\n```\n\n### List Epics\n```bash\ncurl -s -H \"Shortcut-Token: $SHORTCUT_API_TOKEN\" \"$BASE/epics\" | \\\n  jq '.[] | {id, name, state, total_stories: .stats.num_stories_total}'\n```\n\n### Get Epic Stories\n```bash\ncurl -s -H \"Shortcut-Token: $SHORTCUT_API_TOKEN\" \"$BASE/epics/<epic_id>/stories\" | \\\n  jq '.[] | {id, name, story_type, workflow_state_id, estimate}'\n```\n\n### List Teams (Groups)\n```bash\ncurl -s -H \"Shortcut-Token: $SHORTCUT_API_TOKEN\" \"$BASE/groups\" | \\\n  jq '[.[] | {id, name, mention_name}]'\n```\n\n---\n\n## Writing\n\nAll write operations build JSON with `jq -n --arg` to safely handle user-supplied strings.\n\n### Create Story\n```bash\nDATA=$(jq -n \\\n  --arg name \"$STORY_TITLE\" \\\n  --arg description \"$STORY_DESCRIPTION\" \\\n  --arg story_type \"$STORY_TYPE\" \\\n  --argjson estimate \"$ESTIMATE\" \\\n  --argjson workflow_state_id \"$STATE_ID\" \\\n  --arg group_id \"$GROUP_ID\" \\\n  --argjson epic_id \"$EPIC_ID\" \\\n  '{name: $name, description: $description, story_type: $story_type,\n    estimate: $estimate, workflow_state_id: $workflow_state_id,\n    group_id: $group_id, epic_id: $epic_id}')\n\ncurl -s -X POST \\\n  -H \"Shortcut-Token: $SHORTCUT_API_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"$DATA\" \"$BASE/stories\" | jq '{id, name, app_url}'\n```\n\nStory types: `feature`, `bug`, `chore`\n\nTo add labels, extend the jq expression:\n```bash\nDATA=$(jq -n --arg name \"$TITLE\" --arg label \"mobile\" \\\n  '{name: $name, labels: [{name: $label}]}')\n```\n\n### Create Epic\n```bash\nDATA=$(jq -n \\\n  --arg name \"$EPIC_TITLE\" \\\n  --arg description \"$EPIC_DESCRIPTION\" \\\n  --arg group_id \"$GROUP_ID\" \\\n  '{name: $name, description: $description, group_id: $group_id}')\n\ncurl -s -X POST \\\n  -H \"Shortcut-Token: $SHORTCUT_API_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"$DATA\" \"$BASE/epics\" | jq '{id, name, app_url}'\n```\n\n### Update Story (state, estimate, title, etc.)\n```bash\nDATA=$(jq -n --argjson state \"$NEW_STATE_ID\" '{workflow_state_id: $state}')\n\ncurl -s -X PUT \\\n  -H \"Shortcut-Token: $SHORTCUT_API_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"$DATA\" \"$BASE/stories/$STORY_ID\" | jq '{id, name, workflow_state_id}'\n```\n\n### Add Comment\n```bash\nDATA=$(jq -n --arg text \"$COMMENT_TEXT\" '{text: $text}')\n\ncurl -s -X POST \\\n  -H \"Shortcut-Token: $SHORTCUT_API_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"$DATA\" \"$BASE/stories/$STORY_ID/comments\" | jq '{id, text}'\n```\n\n### Wire Story Dependencies (blocker links)\n```bash\nDATA=$(jq -n \\\n  --argjson object_id \"$BLOCKED_ID\" \\\n  --argjson subject_id \"$BLOCKER_ID\" \\\n  '{object_id: $object_id, subject_id: $subject_id, verb: \"blocks\"}')\n\ncurl -s -X POST \\\n  -H \"Shortcut-Token: $SHORTCUT_API_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"$DATA\" \"$BASE/story-links\" | jq '{id, verb}'\n```\n\n---\n\n## Workflow State Reference\n\nCommon default state IDs (verify with the workflows endpoint for your workspace):\n\n| State | Typical ID |\n|-------|-----------|\n| Backlog | 500000008 |\n| Ready for Development | 500000007 |\n| In Development | 500000006 |\n| Ready for Review | 500000010 |\n| Completed | 500000011 |\n\nAlways confirm state IDs by calling `/workflows` — they vary per account.\n\n---\n\n## Bulk Story Creation\n\nFor creating full epics with multiple dependent stories, see `references/create-stories.md`.\n\n---\n\n## Display Format\n\nStories:\n```\n🎯 sc-1234 — User Authentication Flow [feature, 5pts]\n   Status: In Development | Epic: Auth & Onboarding\n   Labels: backend, mobile\n\n   > Users should be able to log in with email/password...\n```\n\nBacklog list (table format):\n```\n| ID      | Story                    | Type    | Pts | State   |\n|---------|--------------------------|---------|-----|---------|\n| sc-1234 | User Auth Flow           | feature | 5   | In Dev  |\n| sc-1235 | Fix password reset email | bug     | 2   | Backlog |\n```\n\n---\n\n## Tips\n\n- Always check for API token before making requests\n- Strip `sc-` prefix from story IDs for API calls\n- Labels are auto-created by Shortcut if they don't exist — safe to pass new label names\n- Rate limit: 200 req/min — not a concern in normal usage\n- For exact story lookup always use `/stories/<id>` directly, not search\n","topics":["Project Management"],"tags":{"latest":"1.0.2"},"stats":{"comments":0,"downloads":896,"installsAllTime":34,"installsCurrent":0,"stars":1,"versions":3},"createdAt":1771928612443,"updatedAt":1778491624313},"latestVersion":{"version":"1.0.2","createdAt":1771952860345,"changelog":"**Major update: Adds mandatory safe JSON construction using jq for all API requests.**\n\n- All commands for creating or updating data now require using jq (`jq -n --arg/--argjson`) to build JSON, preventing shell injection and quoting errors.\n- Added a prominent section explaining and enforcing the safe JSON construction rule.\n- Updated all write and some read examples to demonstrate proper, secure variable handling with jq.\n- Improved comments and code samples for clarity and best security practices.\n- No functional API/interface changes; all updates reinforce secure scripting usage.","license":null},"metadata":{"setup":[],"os":null,"systems":null},"owner":{"handle":"incognos","userId":"s17466t8tmcm7e71fzmsvpy35h8849z8","displayName":"Sina Khelil","image":"https://avatars.githubusercontent.com/u/1743697?v=4"},"moderation":null}