Clickup
Portable collection of Cursor agent and Claude Code agent skills. Paste the repo URL into agent chat to install on any machine
npx -y skills add timi-ty/agent-forge --skill clickupAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Set up ClickUp integration for AI coding agents. Provisions credentials, links a ClickUp view to the current project, and provides direct API query tools for fetching tasks, comments, and attachments. Works with both Cursor and Claude Code. TRIGGER on "set up clickup", "configure clickup", "link clickup", "connect clickup", "clickup setup". Also handles sub-commands: "change clickup view", "reconfigure clickup", "remove clickup from this project".
SKILL.md
12.5 KB, ~3.3k tokens by cl100k_base, as published. Nobody here has run it
ClickUp Integration
Connects your AI coding agent to ClickUp so you can query tasks, comments, and attachments directly from the IDE during development — no need to open ClickUp at all. Works with both Cursor and Claude Code.
How it works once set up:
- A local query helper provides direct ClickUp API access
- You give the agent a task reference (e.g. "work on PROJ-123" or "what's left in this sprint")
- The agent calls the query helper to fetch tasks from the linked view, inspect individual tasks, read comments, and download attachments
- No MCP server, no external dependencies — just Node.js and the ClickUp REST API v2
Dispatch
Read the user's intent and jump to the appropriate section:
| User says | Go to |
|---|---|
| "set up clickup", "configure clickup", "clickup setup", "connect clickup", "link clickup view" | SETUP |
| "change clickup view", "link a different view" | CHANGE VIEW |
| "reconfigure clickup", "update clickup token", "refresh clickup credentials" | RECONFIGURE |
| "remove clickup from this project", "unlink clickup" | REMOVE VIEW |
SETUP
Run this full flow when the user invokes the skill without a more specific intent.
Step 0: Detect platform and resolve paths
Detect the host tool:
- Cursor: Your system prompt identifies you as a Cursor agent, or you have access to the
AskQuestiontool. - Claude Code: Your system prompt identifies you as Claude Code, or you have access to the
AskUserQuestiontool.
Set $TOOL to cursor or claude-code.
Resolve the skill install path:
node -p "require('os').homedir()"
Set $NATIVE_HOME to the output.
Set paths based on $TOOL:
| Variable | Cursor | Claude Code |
|---|---|---|
$SKILL_DIR | $NATIVE_HOME/.cursor/skills/clickup | $NATIVE_HOME/.claude/commands/clickup |
$CLICKUP_ENV_FILE | $NATIVE_HOME/.clickup/.env | $NATIVE_HOME/.clickup/.env |
$SETUP_SCRIPT | $SKILL_DIR/setup/index.mjs | $SKILL_DIR/setup/index.mjs |
$QUERY_SCRIPT | $SKILL_DIR/query/index.mjs | $SKILL_DIR/query/index.mjs |
Also check the workspace-local path (.cursor/skills/clickup or .claude/commands/clickup). If the skill exists there, prefer it over the global path.
Resolve the project root:
git rev-parse --show-toplevel
If this fails: "Could not find a git repository root. Please run this from inside a git project." Then stop.
Set $PROJECT_ROOT to the output.
Step 1: Provision ClickUp API token
Check for existing token:
node -e "
const fs = require('fs');
const p = process.argv[1];
if (!fs.existsSync(p)) { console.log('MISSING'); process.exit(0); }
const content = fs.readFileSync(p, 'utf8');
const match = content.match(/^CLICKUP_API_TOKEN=(.+)$/m);
console.log(match ? match[1].trim() : 'MISSING');
" "$CLICKUP_ENV_FILE"
If output is not MISSING, set $CLICKUP_TOKEN to the value and skip to the [Validate] check.
If MISSING — ask the user:
"To connect to ClickUp, I need your Personal API Token.
Generate one at: ClickUp avatar (upper-right) → Settings → Apps → Generate (under API Token)
Paste your token:"
Set $CLICKUP_TOKEN to the user's input.
[Validate] — call the ClickUp API to confirm the token works:
node "$SETUP_SCRIPT" validate-token "$CLICKUP_TOKEN"
Parse the JSON output:
- If
ok: true: printAuthenticated as {name} ({email}). Continue. - If
ok: false: show the error message and re-ask. Retry up to 3 times. If all fail, stop.
Save token to $CLICKUP_ENV_FILE:
node -e "
const fs = require('fs'), path = require('path');
const envFile = process.argv[1];
const token = process.argv[2];
fs.mkdirSync(path.dirname(envFile), { recursive: true });
let content = '';
try { content = fs.readFileSync(envFile, 'utf8'); } catch {}
if (content.includes('CLICKUP_API_TOKEN=')) {
content = content.replace(/^CLICKUP_API_TOKEN=.+$/m, 'CLICKUP_API_TOKEN=' + token);
} else {
content = content.trimEnd();
content = (content ? content + '\n' : '') + 'CLICKUP_API_TOKEN=' + token + '\n';
}
fs.writeFileSync(envFile, content);
console.log('saved');
" "$CLICKUP_ENV_FILE" "$CLICKUP_TOKEN"
Step 2: Link a ClickUp view
Ask the user:
"Paste your ClickUp URL. This can be:
- A view URL (e.g.
app.clickup.com/9014734012/v/l/8cn3v5w-634) — links directly- A workspace URL (e.g.
app.clickup.com/9014734012) — lets you browse and pick a view"
Parse the URL:
node "$SETUP_SCRIPT" parse-url "<pasted_url>"
If type: "view":
- Set
$CHOSEN_TEAM_IDfromteamIdand$CHOSEN_VIEW_IDfromviewId. - Verify the view is accessible:
node "$SETUP_SCRIPT" validate-view "$CHOSEN_VIEW_ID" "$CLICKUP_TOKEN" - If ok: print
View accessible ({taskCount} tasks found). Skip to Step 3. - If error: show error, re-ask.
If type: "workspace":
- Set
$CHOSEN_TEAM_IDfromteamId. - Enumerate views:
node "$SETUP_SCRIPT" get-views "$CHOSEN_TEAM_ID" "$CLICKUP_TOKEN" - Format a numbered list grouped by space and folder:
[Space Name] [Folder Name] 1. View Name (list: List Name, type: list) 2. Another View (list: Other List, type: board) (no folder) 3. Direct View (list: Folderless List, type: list) - Ask: "Which view should I link to this project? Enter a number (or Q to quit):"
- Set
$CHOSEN_VIEW_IDfrom the selection.
If type: "task":
- Print: "That looks like a task URL. I need a view URL to link to this project. Open the view you want, then paste its URL."
- Re-ask.
If ok: false: Show error, re-ask.
Step 3: Write configuration to CLAUDE.md
Check if $PROJECT_ROOT/CLAUDE.md exists. Read it if so.
If a ## ClickUp section already exists:
Extract the current Team ID and View ID.
Ask: "This project already has a ClickUp view linked (View {current view ID}). Replace with {CHOSEN_VIEW_ID}? (y/N)"
If N: stop.
Write or update the section:
If CLAUDE.md does not exist, create it with:
## ClickUp
Team ID: `{CHOSEN_TEAM_ID}`
View ID: `{CHOSEN_VIEW_ID}`
If CLAUDE.md exists but has no ## ClickUp section, append:
## ClickUp
Team ID: `{CHOSEN_TEAM_ID}`
View ID: `{CHOSEN_VIEW_ID}`
If CLAUDE.md exists and has a ## ClickUp section, replace the Team ID: and View ID: lines with the new values.
Step 4: Done
Print:
ClickUp is configured for this project.
Team ID: {CHOSEN_TEAM_ID}
View ID: {CHOSEN_VIEW_ID}
Credentials: {CLICKUP_ENV_FILE}
Query tool: {QUERY_SCRIPT}
From now on, when you reference tasks or ask about project state,
I will automatically query ClickUp to get accurate, up-to-date information.
CHANGE VIEW
Use when the user wants to link a different ClickUp view without touching credentials.
- Resolve paths (Step 0).
- Read
$CLICKUP_TOKENfrom$CLICKUP_ENV_FILE. If missing, redirect to SETUP. - Ask: "Paste a ClickUp view URL, or a workspace URL to browse views:"
- If they paste a view URL: parse with
parse-url, follow the view branch from Step 2. - If they paste a workspace URL: parse, run
get-views, present the picker.
- If they paste a view URL: parse with
- Run Step 3 (write config to CLAUDE.md).
- Print confirmation.
RECONFIGURE
Use when the user wants to re-enter credentials.
- Resolve paths (Step 0).
- Ask: "What do you want to reconfigure? (1) API token, (2) Both token and view"
- Based on choice: run Step 1 and/or Step 2, forcing the prompts even if values exist.
- Print confirmation. No restart needed — the query helper reads credentials fresh on every call.
REMOVE VIEW
Remove the ClickUp association from the current project's CLAUDE.md.
- Resolve
$PROJECT_ROOT. - Read
$PROJECT_ROOT/CLAUDE.md. If no## ClickUpsection exists, print "No ClickUp view is linked to this project." and stop. - Extract and show the current view ID.
- Ask: "Remove the ClickUp association from this project? Global credentials are kept. (y/N)"
- If y: remove the entire
## ClickUpsection from CLAUDE.md. Print confirmation.
How to use ClickUp during development
Once set up, use this workflow whenever you need to understand, reference, or act on project tasks. Do this proactively — if the project has ClickUp config in CLAUDE.md and the user references a task, ticket, or asks about project state, always query ClickUp first without being asked.
Query helper
All ClickUp data is fetched via the query helper:
node "$QUERY_SCRIPT" <command> [args...]
Where $QUERY_SCRIPT is the path resolved in Step 0:
- Cursor:
~/.cursor/skills/clickup/query/index.mjs - Claude Code:
~/.claude/commands/clickup/query/index.mjs
The helper automatically reads the API token from ~/.clickup/.env and the Team/View IDs
from the nearest CLAUDE.md. All output is JSON on stdout.
Commands
| Command | Usage | Description |
|---|---|---|
tasks | tasks [--status X] [--assignee X] [--fresh] | List tasks in the linked view. Cached for 5 min. --status and --assignee filter client-side. |
task | task <task_id> | Full details for a single task: description, status, dates, assignees, custom fields, subtasks, attachments, checklists. |
comments | comments <task_id> | Comment thread with author and timestamps. |
search | search <query> | Search tasks by name across the workspace (client-side filtering, up to 300 tasks scanned). |
download-attachment | download-attachment <url> <path> | Download an attachment to a local path (sends auth for private-link workspaces). |
statuses | statuses | Available statuses for the linked list — useful for understanding task state vocabulary. |
Recommended workflow
- Overview:
tasksto see all tasks in the linked view with their statuses and assignees. - Filter:
tasks --status "in progress"ortasks --assignee "John"to narrow down. - Inspect:
task <task_id>to read the full description, acceptance criteria, and context. - Context:
comments <task_id>to read the discussion thread for additional context. - Find:
search <query>when the user references a task not in the current view. - Assets:
download-attachment <url> <path>for any attached images or files. - Vocabulary:
statusesto understand what states are available before discussing task transitions.
When to query proactively
- User says "work on PROJ-123" → call
taskto understand the requirement before coding. - User says "what's left in the sprint" → call
tasksto show current state. - User says "check the comments on that task" → call
comments. - User pastes a ClickUp URL containing a task ID → extract and call
task. - User asks about project status, blockers, or priorities → call
taskswith relevant filters.
Attachment downloads
ClickUp attachment URLs are publicly accessible by default, but workspaces can enable
"Private Attachment Links" which makes them auth-gated. The download-attachment command
always sends the API token, so it works in both cases. Use it for images, PDFs, and any
other files attached to tasks.
Rate limiting
The helper retries automatically on 429 with exponential backoff (up to 3 retries). If ClickUp returns a wait longer than 60 seconds, it fails fast with an actionable error message. ClickUp's rate limit is 100 requests per minute per token.
Cache behavior
The tasks command caches view results for 5 minutes (tasks change state frequently).
Use --fresh to bypass the cache. All other commands are uncached and always fetch live data.
Example
# Resolve the query script path for your platform first (see Step 0)
Q="$QUERY_SCRIPT"
# 1. See all tasks in the view
node "$Q" tasks
# 2. Filter by status
node "$Q" tasks --status "in progress"
# 3. Get full task details
node "$Q" task "abc123"
# 4. Read comments
node "$Q" comments "abc123"
# 5. Search across workspace
node "$Q" search "billing page"
# 6. Download an attachment
node "$Q" download-attachment "https://t.clickup.com/..." "./assets/mockup.png"
# 7. Check available statuses
node "$Q" statuses