Files
pcli/.windsurf/skills/kanban/SKILL.md
T

6.8 KiB

name, description
name description
kanban Manage Planka project boards using the pcli CLI. Use when the user wants to interact with Planka boards, cards, lists, tasks, labels, or comments.

pcli - Planka CLI

CLI for the Planka project management API. All commands return JSON by default with envelope {"data": ..., "error": null}. Use jq to extract fields.

Prerequisites

Ensure environment variables are set:

export PLANKA_URL="https://planka.example.com"
export PLANKA_API_KEY="your-api-key"

Ensure jq and pcli are installed and in the path.

Global Flags

All commands accept: --format json|table, --url <url>, --api-key <key>, --log-level debug|info|warn|error

Commands

Status Overview

pcli status

Returns summary of all boards, lists, and card counts (open/closed per list).

Projects

pcli project list
pcli project get <project-id>

Boards

pcli board list
pcli board get <board-id>                    # includes lists and cards
pcli board actions <board-id> [--limit N]

Cards

# List (one of --board or --list required, mutually exclusive)
pcli card list --board <board-id> [--limit N]
pcli card list --list <list-id> [--limit N]

# CRUD
pcli card get <card-id>
pcli card create --list <list-id> --name "Name" [--description "..."] [--type project|story] [--position N] [--due-date "ISO8601"] [--due-completed]
pcli card update <card-id> [--name "..."] [--description "..."] [--type ...] [--position N] [--due-date "..."] [--due-completed]
pcli card delete <card-id>
pcli card duplicate <card-id> --name "Copy" [--position N]
pcli card move <card-id> --list <target-list-id> [--position N]

# Members
pcli card assign <card-id> --user <user-id>
pcli card unassign <card-id> --user <user-id>

# Labels
pcli card add-label <card-id> --label <label-id>
pcli card remove-label <card-id> --label <label-id>

# Actions
pcli card actions <card-id> [--limit N]

Comments

pcli comment list --card <card-id> [--limit N]
pcli comment create --card <card-id> --text "..."
pcli comment update <comment-id> --text "..."
pcli comment delete <comment-id>

Task Lists

pcli task-list create --card <card-id> --name "Checklist" [--position N] [--show-on-front] [--hide-completed]
pcli task-list get <task-list-id>
pcli task-list update <task-list-id> [--name "..."] [--position N] [--show-on-front] [--hide-completed]
pcli task-list delete <task-list-id>

Tasks

pcli task create --task-list <task-list-id> --name "Item" [--position N] [--completed]
pcli task update <task-id> [--name "..."] [--position N] [--completed]
pcli task delete <task-id>

Lists

pcli list create --board <board-id> --name "List Name" --position 65536 [--type active|closed]
pcli list get <list-id>
pcli list update <list-id> [--name "..."] [--position N] [--type active|closed] [--color "..."] [--board <board-id>]
pcli list delete <list-id>

Labels

pcli label create --board <board-id> --name "Bug" --color "berry-red" [--position N]
pcli label update <label-id> [--name "..."] [--color "..."] [--position N]
pcli label delete <label-id>

API Response Structure

Board Get Response

Board details include lists directly in .data.lists[], not in an included section:

pcli board get <board-id> | jq '.data.lists[] | {id, name, position}'

Card List Labels

Card list returns labels as plain strings, not objects:

# Labels are strings like "agent", NOT objects like {name: "agent"}
pcli card list --board <board-id> | jq '.data[] | select(.labels[]? == "agent")'

Card Get Response

Card get includes taskLists and tasks arrays (when they exist):

pcli card get <card-id> | jq '.data.taskLists[0].id'
pcli card get <card-id> | jq '.data.tasks[] | {name, isCompleted}'

Finding Boards in a Project

Use board list --project to find boards by project name:

pcli board list --project "<project-name>" | jq '.data[] | {id, name}'

Error Handling

Project Configuration

  • Always strip quotes from yq output: yq '.planka.project' project.yaml | tr -d '"'
  • Exit with error if configured project cannot be found or created
  • The project name in project.yaml is the authoritative source

Idempotent Operations

  • Use 2>/dev/null || true for create operations that should not fail if resources already exist
  • Check for empty results before attempting operations: if [ -z "$PROJECT_ID" ]; then

Extracting IDs from Output

All responses use {"data": ..., "error": null}. Extract IDs with jq:

# Single object
pcli card create --list <id> --name "X" | jq -r '.data.id'

# Array
pcli card list --board <id> | jq -r '.data[].id'

# With error checking
RESULT=$(pcli project list | jq -r --arg name "$PROJECT_NAME" '.data[] | select(.name == $name) | .id')
if [ -z "$RESULT" ]; then
  echo "Not found"
else
  echo "Found: $RESULT"
fi

Common Workflows

Bootstrap Project Infrastructure

# Read project configuration
PROJECT_NAME=$(yq '.planka.project' project.yaml | tr -d '"')
BOARD_NAME=$(yq '.planka.board' project.yaml | tr -d '"')

# Find or create project (exit with error if fails)
PROJECT_ID=$(pcli project list | jq -r --arg name "$PROJECT_NAME" '.data[] | select(.name == $name) | .id')
if [ -z "$PROJECT_ID" ]; then
  echo "Error: Project '$PROJECT_NAME' not found and creation failed"
  exit 1
fi

# Find or create board
BOARD_ID=$(pcli board list --project "$PROJECT_NAME" | jq -r --arg name "$BOARD_NAME" '.data[] | select(.name == $name) | .id')
if [ -z "$BOARD_ID" ]; then
  BOARD_ID=$(pcli board create --project $PROJECT_ID --name "$BOARD_NAME" | jq -r '.data.id')
fi

# Create required lists (skip if exists)
pcli list create --board $BOARD_ID --name "Backlog" --position 65536 2>/dev/null || true
pcli list create --board $BOARD_ID --name "To Do" --position 131072 2>/dev/null || true
pcli list create --board $BOARD_ID --name "Planning" --position 196608 2>/dev/null || true
pcli list create --board $BOARD_ID --name "In Progress" --position 262144 2>/dev/null || true
pcli list create --board $BOARD_ID --name "Review" --position 327680 2>/dev/null || true
pcli list create --board $BOARD_ID --name "Done" --position 393216 2>/dev/null || true

# Create agent label
pcli label create --board $BOARD_ID --name "agent" --color "berry-red" 2>/dev/null || true

Create a card with a checklist

CARD_ID=$(pcli card create --list <list-id> --name "Task" | jq -r '.data.id')
TL_ID=$(pcli task-list create --card $CARD_ID --name "Steps" | jq -r '.data.id')
pcli task create --task-list $TL_ID --name "Step 1"
pcli task create --task-list $TL_ID --name "Step 2"

Move all cards between lists

pcli card list --list <source-list-id> | jq -r '.data[].id' | while read id; do
  pcli card move $id --list <target-list-id>
done