From pm-tasks-asana
Asana adapter for the @llodev/pm-tasks-* family. Use when the user mentions Asana, asks to "create Asana task", "publish to Asana", "post to Asana", "publish", "add comment in Asana", or uses --publish-asana; OR for CRUD on existing tasks (check subtask, close task, change due-date, assign person, comment); OR when invoked autonomously by another agent with [autonomous] / --auto sentinel. Asana hierarchy: workspace > project > section > parent task > subtasks (one level), with custom fields and multi-assignee support. Modes: paste-ready (no MCP needed), MCP publish (via claude.ai Asana MCP), autonomous (write-through with allowlist). Implements 6 CRUD verbs (task.create, checklist.check, task.close, task.due-date.set, task.assignee.add, task.comment.add) from pm-tasks/pm-tasks-core/references/contract.md. Requires @llodev/pm-tasks-core installed.
How this skill is triggered — by the user, by Claude, or both
Slash command
/pm-tasks-asana:pm-tasks-asanaThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Adapter for Asana within the `@llodev/pm-tasks-*` family. Use the core skill's extraction phases, then apply Asana formatting and optionally publish/operate via the `claude.ai Asana` MCP server.
Adapter for Asana within the @llodev/pm-tasks-* family. Use the core skill's extraction phases, then apply Asana formatting and optionally publish/operate via the claude.ai Asana MCP server.
| Mode | Trigger | Path |
|---|---|---|
| Paste-only | "format as Asana task" without MCP intent | Phase 3 (core) → Phase 4 (this skill, format only) → output paste blocks |
| MCP publish | "publish to Asana", "create on Asana", "--publish-asana" | Phase 3 → Phase 4 → Phase 5 (publish via MCP) |
| Autonomous | [autonomous] or --auto in prompt OR LLODEV_PM_TASKS_AUTONOMOUS=1 | Phase 3 → Phase 4 → Phase 5b (write-through, no preview) |
| CRUD ops | "check subtask N on task X", "close task Y", "assign Alice to task Z", "comment on task X" | Phase 6 (operations, direct verb dispatch) |
Asana tasks have:
**Section** bold labels — ## headings render inconsistently).subtaskDefaults.inheritParentFields in .asana.json.task.assignee.add to add followers.Apply the generic card from core's ../pm-tasks-core/references/generic-card.md. Then map to Asana:
name.**Section** labels inside description (not ##)..asana.json customFields[]).due_on (YYYY-MM-DD).assignee GID resolved from .asana.json members[] or me at publish time.Prerequisites: Asana MCP server (claude.ai Asana) connected in your agent. The MCP handles OAuth; the adapter never sees tokens. Configuration steps differ per agent — register the same Asana MCP endpoint your agent supports:
claude mcp add asana -s project -- npx -y claude-ai-asana-mcp (or follow Anthropic's setup for the hosted claude.ai Asana connector).claude-ai-asana-mcp command (envelope identical to the Trello example in pm-tasks-trello/references/mcp-config.md).[mcp_servers.asana] in ~/.codex/config.toml.Strict order: 5.1 read .asana.json (full file) → 5.2.5 resolve assignee + custom fields + per-subtask field map → 5.2 preview & approval → 5.3 publish via MCP → 5.4 error handling.
MCP publish sequence:
create_tasks with name, notes (description), projects: [projectGid], memberships: [{ project, section }], assignee (resolved GID), due_on, custom_fields (JSON string of {fieldGid: optionGid}).create_tasks per subtask with parent: parentGid, name, assignee (inherited or per-subtask), custom_fields matching subtaskDefaults.inheritParentFields.addTag per tag GID.Skip 5.2 preview & approval. Apply autonomous-mode contract from ../pm-tasks-core/references/autonomous-mode.md. Audit log entries per ../pm-tasks-core/references/audit-log-format.md.
Asana-specific autonomous scope: autonomous.scope.projects[] + autonomous.scope.sections[] must include the target GIDs. Any custom-field write must be in autonomous.allow (task.create covers create-time field set; ongoing field changes are out of scope for v1.x).
For verbs other than task.create, jump directly to the operation. Verb → MCP tool mapping:
| Core verb | Asana MCP tool | Notes |
|---|---|---|
task.create | create_tasks | parent + subtasks per Phase 5 |
checklist.check | update_tasks | for subtasks: completed: true; emulates checklist via subtask model |
task.close | update_tasks | completed: true on parent |
task.due-date.set | update_tasks | due_on: "YYYY-MM-DD" |
task.assignee.add | update_tasks + addFollower | primary assignee replaces; additional are followers |
task.comment.add | add_comment (story) | adds a comment story to the task |
<task-ref> resolution: accept Asana permalinks (https://app.asana.com/0/<project>/<task>), bare GIDs, or aliases from .asana.json taskAliases[].
Every verb returns the core contract shape (see ../pm-tasks-core/references/contract.md §Result envelope):
{
"ok": true,
"verb": "task.create",
"tool": "asana",
"ref": { "id": "<gid>", "url": "https://app.asana.com/0/<project>/<gid>", "alias": "<optional>" },
"details": { /* Asana-specific (see table below) */ }
}
Asana-specific details per verb:
| Verb | details fields |
|---|---|
task.create | { parentGid, subtaskGids[], projectGid, sectionGid?, customFields[]? } |
checklist.check | { subtaskGid, completed: true } |
task.close | { parentGid, completed: true } |
task.due-date.set | { taskGid, due_on } |
task.assignee.add | { taskGid, assignee, followers[]? } (primary vs follower split) |
task.comment.add | { taskGid, storyGid } |
On failure: { ok: false, verb, tool, error: { code, message, retriable } }. Common codes: FORBIDDEN_VERB, OUT_OF_SCOPE, NOT_FOUND, RATE_LIMITED, PARTIAL_CREATE (subtask failed mid-create — see ../pm-tasks-core/references/contract.md §Partial-create recovery).
See anti-patterns/asana.md — paste health, custom-field rules, GID requirements, partial-create handling.
If @llodev/pm-tasks-core is not installed: ask the user for minimum input (title + subtask names) and produce a paste-ready Asana task body from this content alone. Quality is degraded — no scope/audience/fidelity inference. Print: "Install @llodev/pm-tasks-core for the full flow."
Lookup order: <git-root>/.asana.json → ~/.config/llodev/pm-tasks/asana.json → abort with init instructions. Schema: schemas/config.json. Secrets NEVER in JSON — Asana MCP holds OAuth; init uses LLODEV_PM_TASKS_ASANA_PAT env var only.
npx @llodev/pm-tasks-asana init
See ../pm-tasks-core/references/init-ux.md for the shared flow. Asana init reads workspaces / projects / sections / custom fields via the Asana REST API using a Personal Access Token (env LLODEV_PM_TASKS_ASANA_PAT).
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub llodev/skills --plugin pm-tasks-asana