agentsclimarketplace

Sprawl

Skill ultrakorne/sprawl_cli/skills/sprawl

Collaborate on shared tasks, checklists, and notes with the human and other agents via the sprawl CLI. Use this skill whenever the user asks you to look at "my tasks", "the backlog", "what's assigned to me", to check off a checklist item, leave a note for another agent, create a task, or coordinate work with another agent — anything that reads or writes the sprawl task space.From its SKILL.md

Install
npx -y skills add ultrakorne/sprawl_cli --skill sprawl

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 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 file declares

Copied from the file, not written here

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

20.3 KB, ~5.1k tokens by cl100k_base, as published. Nobody here has run it

sprawl

Shared task space for the human owner and their agents. Every agent has its own secret; the server resolves per-agent permissions so you only see and touch what you're allowed to. The CLI is a thin HTTP client — the server is the source of truth for validation and permissions, so trust its error codes.

When to use this skill

  • The user refers to tasks, checklists, notes, or the backlog in sprawl.
  • The user asks you to coordinate with another agent or leave them context.
  • You need durable state that survives beyond this conversation (a todo, a hand-off note, a status update another agent can pick up).
  • The user mentions sprawl directly, or points at a task id.

Do not use this skill for one-off in-conversation todos — use TaskCreate for those. sprawl is for collaboration across sessions and agents.

Preflight

For reads, skip it. task list / task <id> / checklist / note show are already filtered server-side to what your key can see, so just run them. Probing first only burns tokens and a round-trip.

For writes, run sprawl whoami once. Before the first task create, task update, checklist add, note set, or any other mutation in this session, check your scope — see Before you write. A wasted 403 on a write is fine; a wasted chained write is the trap, because && swallows the error and the follow-up commands run with empty inputs.

Only diagnose other failures when a real call hits one. Map the failure, then act:

  • sprawl: command not found — not installed. Read SETUP.md in this skill's directory and walk the user through it.
  • SPRAWL_AGENT_SECRET not set (or similar pre-flight error from the CLI) — ask the user to export it in this shell or pass -s <value> per command. If they don't have one, point them at SETUP.md.
  • HTTP 401 — token bad or missing. Ask the user to re-run sprawl login (interactive — don't try it yourself).
  • HTTP 403 — secret is scoped out of this action. Don't retry; tell the user which action you lack permission for. See Permission model.
  • Anything ambiguousthen run sprawl whoami --format=json to separate "CLI/network broken" from "auth broken". A 200 also tells you which agent and scope the server thinks you are.

Never write the secret to a file, commit it, echo it back to the user, or print it in a command you run. If you show a command using -s, redact the value.

Before you write — check your scope

Run sprawl whoami once at the start of a write session. Reads don't need this (the server already filters them), but writes need to know your scope upfront — otherwise you'll learn it the hard way through a 403, and any chained follow-up commands will run with empty inputs and produce a confusing partial state.

sprawl whoami
# agent:
#   default_permission: write              # ← projectless `task create` needs write_create
#   ...
# project_permissions[1]{level,name,project_id}:
#   write_create,Sprawl,1                  # ← projects you can create/edit in

What each scope unlocks: read → list/show only · write → edit existing tasks/items in scope · write_create → also create new ones.

For a task create:

  • Projectless (sprawl task create --title ...) — needs agent.default_permission = write_create.
  • Inside a project (--project-id N) — needs an entry in project_permissions with level = write_create for that id.

If neither holds, don't try. Tell the user you lack write_create and on which project they'd need to grant it. The server will reject the call anyway; surfacing it from whoami saves the wasted round-trip and the confusing partial state from chained follow-ups.

For edits (task update, checklist check/uncheck/update, note set), write is enough on the target's project. You can usually skip the whoami check for edits if you've already established scope earlier in the session — but if this is the first write of the session, just check.

Don't chain writes with && to capture the new id. Run task create on its own, read the id from its output, then add checklist items. If the create returns 403, an && chain blows past it with an empty id and the next command silently no-ops on stderr — exactly the failure mode that surfaces as "(no output)".

# Right — split so each step's outcome is visible:
sprawl task create --title "quick reminders"
# → note the id from the output
sprawl checklist add <id> --title "print something"
sprawl checklist add <id> --title "talk to Antti about AI tools"

# Wrong — masks 403 on create, follow-ups run on empty id:
task_json=$(sprawl task create --title "quick reminders" --format=json) \
  && id=$(printf '%s' "$task_json" | jq -r '.task.id') \
  && sprawl checklist add "$id" --title "..."

Credential model

Two credentials, resolved per request:

  1. Token — user's device-flow token, managed by sprawl login. You don't touch this. Lives in ~/.config/sprawl/config.toml (mode 0600) or SPRAWL_TOKEN.
  2. Agent secretSPRAWL_AGENT_SECRET env var (preferred) or -s <value> / --agent-secret <value> flag. Never persisted by sprawl. Prefer the env var for long-lived shells; the flag leaks via ps auxe and shell history.

If either is missing the CLI fails before making the HTTP call.

Permission model (how to read errors)

Your agent secret resolves one of four scopes per task / project: none · read · write · write_create. Resolution order on read/write is task override → project override → agent_keys.default_permission.

HTTPMeaningWhat to do
200SuccessCarry on.
401Token bad / missingAsk user to re-run sprawl login.
403Your key is scoped out of this actionDon't retry. Tell the user you lack permission and which action.
404Not visible to you, or genuinely goneTreat as "not available to me". Don't assume it exists and retry.
422Validation (e.g. empty search query)Fix the input.

Non-owner agents only see tasks their key resolves at least :read on, so task list is already filtered. Do not loop retrying on 403 — the server won't change its mind.

Output formats

--format is a persistent flag: text | json | toon (default toon). SPRAWL_OUTPUT sets a session default.

Default to omitting --format for your own reads. Toon is 30–60 % fewer tokens than json and lossless, so when the output is just coming back into your context for you to eyeball (list, show, checklist, search), let it default. Passing --format=json to read a task list is pure token waste.

Only override when you have a specific reason:

  • --format=json — only when you're actually piping to jq or another parser. Not for "I want to read it myself".
  • --format=text — when you're showing the output to the user (tabwriter tables, multi-line detail views).

Errors in json / toon come as a structured envelope:

{"status": "error", "error": "<message>", "http_status": 403}

http_status is omitted for pre-flight errors (e.g. missing secret).

Task shape (house style)

The owner's convention for this task space. Follow it unless the user says otherwise — it's what makes the board readable across agents and sessions.

  • Everything is a checklist item. The task is a lightweight container; the actual work is the items underneath it.
  • Title: short. Server cap is 30 characters (enforced — longer fails with a 422). Aim well under that: a handful of words, no punctuation filler. If you can't say it in a title, the thing is probably two tasks.
  • Skip the description. Default to no --description. Don't summarise the task there — summarise it in the checklist.
  • If you must use a description, keep it brief. Server cap is 255 characters (enforced at the DB layer — longer currently surfaces as a 500, not a clean 422).
  • Itemize work as checklist items, titles kept short like task titles. One discrete thing per item. If an item reveals subwork, add a new item, don't cram it into the title.
  • Long context → item notes. When something needs paragraphs — a rationale, a block of status, a link dump, a hand-off — attach it as a note on the relevant checklist item via sprawl note set. Notes are free-form and unbounded; that's the channel for anything that won't fit in a title.

So the usual create flow is: task create --title "..." (no description), then one or more checklist add <task_id> --title "...", then note set <item_id> only on items that need the extra context.

Command reference

All /api/v1/* commands honour --format and the credential model above. login is interactive and always plain text.

Discovery (reads)

Omit --format — default toon is what you want here (see Output formats).

sprawl task list
sprawl task <id>                               # show one task (no `show` subcommand)
sprawl task <id> --full                        # task + its checklist items + notes, one call
sprawl task search "<query>"                   # case-insensitive substring on title
sprawl checklist <task_id>                     # list checklist items for a task
sprawl checklist <task_id> --full              # items with their notes inline, one call
sprawl note show <item_id>                     # raw notes blob; empty is valid
sprawl activity                                # completed tasks + items for today
sprawl activity --days-ago 1                   # yesterday
sprawl activity --date 2026-04-29              # specific day

--full is the read-before-work shortcut. When you're about to work a task, sprawl task <id> --full (or sprawl checklist <task_id> --full) pulls the items and their notes in one call — prefer it over listing the checklist and then running note show per item. Reach for plain note show only for a single item's notes in isolation.

Daily activity: sprawl activity returns the calling agent's completed tasks + completed checklist items for a single day, scoped by the same key cascade as task list. Default is today in the user's timezone. --date (YYYY-MM-DD) and --days-ago (0..365, 0=today) are mutually exclusive — passing both is a local error before any HTTP call. Empty days return an empty result, not an error. Useful for daily standup write-ups, weekly summaries (loop over --days-ago 0..6), and answering "what did I get done yesterday?".

Reading note content into a shell variable or another command — use --format=text, not json + a parser.

The text format on note show emits the notes body verbatim with no envelope, which is exactly what you want when capturing or piping the content. Reaching for --format=json | jq -r '.notes' works but is unnecessary; reaching for --format=json | python3 -c "import json,sys; print(json.load(sys.stdin)['notes'])" is pure overhead — don't do it.

# Right — raw content straight out:
body=$(sprawl note show 203 --format=text)
sprawl note show 203 --format=text | less
sprawl note show 203 --format=text > note.md

# Wrong — toon envelope leaks into the variable ("notes: \"...\""):
body=$(sprawl note show 203)

# Overkill — only justified if you're extracting *other* fields too:
sprawl note show 203 --format=json | jq -r '.notes'

Writes — tasks

Wire body: {"task": {...}}. Accept explicit flags or --from-json <path|->; explicit flags override fields parsed from JSON. Title max 30 chars, description max 255 chars — see Task shape for why you usually skip description entirely.

# Create (projectless — needs default_permission=write_create):
sprawl task create --title "draft spec"

# Create attached to a project (needs write_create at project scope):
sprawl task create --title "wire up CI" --project-id 42

# Create from a JSON template, tweak one field:
echo '{"title":"draft","project_id":42}' \
  | sprawl task create --from-json - --title "final"

# Update title (server ignores project_id on update):
sprawl task update 17 --title "renamed"
sprawl task update 17 --description ""        # explicit clear (not "flag unset")

# Set / clear due date (separate route — `task update` ignores due_date).
# Only do this when the user asked for it — see Guardrails below.
sprawl task due 17 today                      # set due date (resolved in user TZ)
sprawl task due 17 yesterday                  # backdate by one day
sprawl task due 17 week                       # owner's configured week-end
sprawl task due 17 none                       # clear due date

sprawl task delete 17                         # soft-delete; 404 from server treated as success (idempotent)

task due takes a preset (yesterday|today|week|none) and the server resolves it against the user's timezone and week_end_day setting. Reads return the resolved ISO date in due_date — there's no echo of which preset is currently set, so if you need that, compute it locally by comparing the date against today / yesterday / the user's week-end.

Writes — checklists

Wire body: {"checklist_item": {...}}. Server assigns position on add. Permission is checked on the parent task, not per item.

sprawl checklist add <task_id> --title "write migration"
sprawl checklist add <task_id> --title "deploy" --notes "run after backfill"

sprawl checklist check <item_id>              # idempotent
sprawl checklist uncheck <item_id>            # idempotent
sprawl checklist update <item_id> --title "renamed"
sprawl checklist delete <item_id>             # hard-delete; idempotent on 404

Use check / uncheck for completion — update doesn't mutate it. The split avoids a GET-then-PATCH race when you don't know current state.

Writes — notes (hand-off channel)

Notes are per-checklist-item free-form blobs, addressed separately so list responses stay small. This is the primary place to leave context for another agent or the human.

sprawl note show <item_id>                    # read
sprawl note set <item_id> "blocked on PR #418"
sprawl note set <item_id> ""                  # clears notes
cat status.md | sprawl note set <item_id> --stdin

--stdin and the positional arg are mutually exclusive — passing both is a local error before any HTTP call.

Misc

sprawl version                                # prints version + baked-in API URL
sprawl whoami                                 # who am I + elevated project permissions (also a liveness probe)
sprawl theme get                              # read active UI theme
sprawl theme set tokyo-night                  # owner-only; unknown id → 404

Collaboration patterns

These are the common shapes of work the skill exists for.

1. Pick up assigned work

sprawl task list
# inspect output, pick tasks you can act on
sprawl task <id> --full        # the task plus every item and its notes, one call

Filter by what's visible — your key already scopes the list server-side.

Read the notes before you start. Notes are where the previous agent or the human left hand-off context — skipping them is how you redo work someone already did or miss a blocker they flagged. sprawl task <id> --full already includes every item's notes inline, so prefer it when picking up a task; use sprawl checklist <task_id> --full if you only need the checklist. Fall back to sprawl note show <item_id> only for a single item's notes in isolation:

sprawl task <id> --full        # preferred: task + items + notes together
sprawl checklist <id> --full   # just the checklist, notes inline
sprawl note show <item_id>     # one item's notes, when that's all you need

A plain sprawl checklist <id> (no --full) still shows a has_notes marker per item without the bodies — fine for a quick glance, but --full is the one-call way to actually read them.

When you finish an item, check it off immediately — see §2. Don't wait until the end of the task: other agents and the human are watching the board live, and an unchecked item reads as "still to do".

2. Make progress on a checklist

Mark items as you finish them; don't batch. Other agents and the human see the state live.

sprawl checklist check 203

If an item reveals subwork, add a child item rather than stuffing it into the note:

sprawl checklist add <task_id> --title "backfill legacy rows"

3. Leave context for another agent or the human

Use the item's notes blob. Append by reading first if you need to preserve prior content (note set is a full replace):

prev=$(sprawl note show 203 --format=text)
printf '%s\n\n---\n\n%s\n' "$prev" "blocked on PR #418" \
  | sprawl note set 203 --stdin

Don't sign your edits. No "done by <agent-name>", no "— claude". The server already records the last actor on each note / checklist item, and sprawl whoami resolves any agent secret to its identity. Manual signatures just add noise the human has to skim past.

4. Create a new task on behalf of the user

Only if the user asked, and only if your key resolves write_create for the target scope (projectless or the specific --project-id). Run sprawl whoami first if you haven't this session — that's the cheap way to find out before round-tripping. If you get a 403 anyway, surface it — don't retry.

Create the task on its own, then add checklist items in separate calls so each step's outcome is visible — see the chaining warning in Before you write.

sprawl task create --title "flaky deploy" --project-id 42
# → note the task id from the output
sprawl checklist add <task_id> --title "repro on staging"
sprawl checklist add <task_id> --title "check #ops logs"

5. Hand off

Finishing your slice and passing to another agent or the human:

  1. checklist check the items you finished.
  2. note set on the next item with a short status + what you couldn't do and why (permission, missing info, blocker).
  3. Do not task update the title / description just to log status — that rewrites the task. Status belongs in notes or new checklist items.

Guardrails

  • Never echo, log, commit, or persist SPRAWL_AGENT_SECRET. If you must show a command to the user, redact the value.
  • Never attempt sprawl login — it's interactive; ask the user instead.
  • Never retry 403 responses. Permission won't flip mid-session.
  • Don't use task update as a status channel. Use notes / checklist items.
  • Don't delete tasks or checklist items the user didn't ask you to remove. task delete is a soft-delete and can only be undone via the LiveView trash bin (no API to restore). checklist delete is a hard delete and has no undo. When in doubt, leave a note on the item instead.
  • Don't set due dates the user didn't ask for. task due is for when the human explicitly tells you to schedule something (or you're acting out a clearly scheduled instruction — "remind me about this Friday"). Don't infer due dates from urgency cues, don't backfill them on existing tasks, and don't add them when creating a task on the user's behalf unless they specified one. The due date is the owner's planning channel, not an agent housekeeping field — leaving it blank is the correct default.
  • Don't --from-json with untrusted input without reading it first — the file / stdin is parsed as the full task/item attrs map.
  • Empty strings matter: --description "" and note set X "" are explicit clears, distinct from "flag unset". Use them deliberately.
  • Write only what the user asked for. The task space is shared with the human and other agents; spurious tasks or notes are noise for everyone.

What ships with it: 1 file

4.8 KB alongside SKILL.md

Keep looking

Skills are one crate of 326,401. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.