Dailybot Labels
Requires
dailybot-cli >= 3.9.0(pack baseline). That release ships the fulldailybot labelsurface:entitlement/list/get/create/update/archive/delete/assign/batch. Confirm withdailybot label assign --help. If missing, ask the developer to rundailybot upgrade(orpip install --upgrade 'dailybot-cli>=3.9.0').
Organization Labels are a shared taxonomy for Forms, Check-ins, and
Workflows (Automations) — the same chips on the web settings page and row
picker. They are not private Featured stars (dailybot featured →
../featured/SKILL.md).
The web picker on a form / check-in / automation row is a replace-set.
Match that with dailybot label assign. Bulk add/remove/replace across many
entities uses dailybot label batch.
When to Use
- List, search, or inspect organization Labels
- Create, update, archive, or hard-delete Labels (when entitled)
- Attach / replace / clear Labels on one form, check-in, or workflow
- Bulk add / remove / replace Labels on many entities
- Check Labels entitlement before building automations that depend on tags
Do not use for:
| Intent | Route instead |
|---|---|
| Private per-user stars | dailybot-featured |
| Form response workflow states named “labels” (Draft → Review → …) | dailybot-forms transitions |
| Creating the form / check-in / workflow itself | forms / checkin / workflow skills — then come back here to assign |
Auth
Same session as the rest of the CLI (dailybot login or DAILYBOT_API_KEY /
.dailybot/env.json). See ../shared/auth.md.
Point at a non-prod API with the global flag when needed:
dailybot --api-url <your-api-url> label entitlement
# Example placeholder: https://staging-api.example.com
Step 1 — Entitlement (always first)
Server entitlement is the source of truth. Do not assume Labels are (or are not) a paid-only feature — plans differ.
dailybot status --auth 2>&1
dailybot label entitlement
dailybot label entitlement --json
JSON shape (stable fields):
{
"entitled": true,
"feature": "LABELS",
"reason": null,
"is_guest": false,
"can_create": true,
"can_manage_all": true,
"can_hard_delete": true,
"can_manage": true
}
| Flag | Meaning |
|---|---|
entitled |
Org may use Labels at all |
can_create |
Caller may create Labels |
can_manage_all |
Caller may edit/archive Labels they did not create |
can_hard_delete |
Caller may hard-delete (elevated; fails when Label is in use) |
is_guest |
Guest identity — usually cannot manage |
If entitled is false, warn briefly (feature_not_available /
paid_plan_required), surface any upgrade hint, and continue the primary
task without looping.
Step 2 — List / search / get
dailybot label list
dailybot label list --search sprint --json
dailybot label list --archived --limit 50 --offset 0
dailybot label get <label-uuid>
dailybot label get <label-uuid> --json
| Flag | Notes |
|---|---|
--search |
Case-insensitive name search |
--archived |
Include archived Labels |
--limit / --offset |
Pagination (limit default 20, max 100) |
--json |
Machine-readable {count, results:[…]} |
Copy UUIDs from label list / --json — assign/batch need Label UUIDs, not
names.
List rows include usage / usage_count (forms / automations / checkins).
Counters can lag briefly after assign; trust the assign/batch response and
form list / workflow list enrichment when verifying.
Step 3 — Create / update
dailybot label create --name "Sprint" --color "#4A90E2"
dailybot label create --name "Release" --color "#2ECC71" --description "Release train" --json
dailybot label update <label-uuid> --name "Sprint 42" --color "#C0392B"
dailybot label update <label-uuid> --description "Updated copy"
# Clear description:
dailybot label update <label-uuid> --description ""
| Flag | Notes |
|---|---|
--name |
Required on create; unique per org |
--color |
Hex, e.g. #4A90E2 |
--description |
Optional; empty string on update clears it |
--json |
Prefer for scripting |
Duplicate names are rejected — pick another name or update the existing Label.
Step 4 — Assign to one entity (web picker parity)
assign replaces the full set of Labels on that entity (same as the web
chip picker). Pass every Label that should remain.
# Forms
dailybot label assign <form-uuid> --type forms --label <label-uuid>
dailybot label assign <form-uuid> --type forms --label <uuid-a> --label <uuid-b>
dailybot label assign <form-uuid> --type forms --label <uuid-a>,<uuid-b>
# Check-ins (use the check-in UUID from create --json → .uuid or .id)
dailybot label assign <checkin-uuid> --type checkins --label <label-uuid>
# Workflows / Automations (same API; --type automations is an alias)
dailybot label assign <workflow-uuid> --type workflows --label <label-uuid>
dailybot label assign <workflow-uuid> --type automations --label <label-uuid>
Clear every Label on an entity:
dailybot label assign <form-uuid> --type forms --clear
| Flag | Notes |
|---|---|
--type |
Required. forms | checkins | workflows (automations alias) |
--label |
Repeatable or comma-separated Label UUIDs (replace-set) |
--clear |
Replace with an empty set (mutually exclusive with attaching labels) |
--json |
Returns {uuid, labels:[…]} for the entity |
After authoring forms / check-ins
dailybot form create and dailybot checkin create do not take
--labels. Create first, then assign:
# Forms expose .uuid
FID=$(dailybot form create -n "Retro" --questions-file q.json --active --json | jq -r '.uuid')
dailybot label assign "$FID" --type forms --label "$LABEL_UUID"
# Check-ins: prefer .uuid (CLI >= 3.9.x also aliases API `id` → `uuid` on --json)
CID=$(dailybot checkin create -n "Standup" --user <user-uuid> \
--questions-file q.json --time 09:00 --days 1,2,3,4,5 --json | jq -r '.uuid // .id')
dailybot label assign "$CID" --type checkins --label "$LABEL_UUID"
Workflows are created in the web app only — list UUIDs with
dailybot workflow list --json, then label assign --type workflows.
Verify on list APIs
dailybot form list --limit 20 --json | jq '.[] | {name, labels}'
# or paginated envelope: .results[]
dailybot workflow list --limit 20 --json | jq '.[] | {name, labels}'
checkin show may omit labels even when assign succeeded — use the assign
--json response or list enrichment where available.
Step 5 — Batch (many entities)
dailybot label batch --type forms --uuids <uuid1>,<uuid2> --label <label-uuid> --mode add
dailybot label batch --type checkins --uuids <uuid> --label <label-uuid> --mode remove
dailybot label batch --type workflows --uuids <uuid1>,<uuid2> --label <l1>,<l2> --mode replace
dailybot label batch --type automations --uuids <uuid> --label <label-uuid> --mode add --json
| Flag | Notes |
|---|---|
--type |
forms | checkins | workflows (automations alias) |
--uuids |
Comma-separated entity UUIDs (required, at least one) |
--label |
Repeatable or comma-separated Label UUIDs |
--mode |
add (default) | remove | replace |
--json |
{mode, updated_count, entity_uuids, labels} |
Use batch for bulk add/remove; use assign when the web picker replace-set semantics for a single row matter.
Step 6 — Archive / delete
# Soft-archive (idempotent). Archived Labels cannot be newly assigned
# (code: archived_label).
dailybot label archive <label-uuid>
dailybot label archive <label-uuid> --json
# Hard-delete — elevated only; fails when the Label is still attached
# (code: label_in_use).
dailybot label delete <label-uuid> -y
dailybot label delete <label-uuid> -y --json
If delete fails because the Label is in use (label_in_use): clear or
reassign entities (label assign … --clear / label batch --mode remove),
then delete again — or leave it archived.
Worked end-to-end flow
# 0. Gate
dailybot label entitlement --json | jq '.entitled, .can_create'
# 1. Create taxonomy
L1=$(dailybot label create --name "Sprint" --color "#4A90E2" --json | jq -r '.uuid')
L2=$(dailybot label create --name "Platform" --color "#2ECC71" --json | jq -r '.uuid')
# 2. Author entities (questions required on create)
cat > /tmp/db-q.json <<'EOF'
[{"question": "What shipped?", "short_question": "Shipped", "question_type": "text"}]
EOF
FID=$(dailybot form create -n "Sprint Retro" --questions-file /tmp/db-q.json --active --json | jq -r '.uuid')
CID=$(dailybot checkin create -n "Daily Standup" --user <user-uuid> \
--questions-file /tmp/db-q.json --time 09:00 --days 1,2,3,4,5 --json | jq -r '.uuid // .id')
WID=$(dailybot workflow list --limit 1 --json | jq -r 'if type=="array" then .[0].uuid else .results[0].uuid end')
# 3. Attach (replace-set on one row; batch for many)
dailybot label assign "$FID" --type forms --label "$L1" --label "$L2" --json
dailybot label assign "$CID" --type checkins --label "$L1" --json
[ -n "$WID" ] && dailybot label assign "$WID" --type workflows --label "$L2" --json
dailybot label batch --type forms --uuids "$FID" --label "$L1" --mode add --json
# 4. Inspect
dailybot label get "$L1" --json | jq '{name, usage, usage_count}'
dailybot form list --limit 5 --json | jq 'map({name, labels})'
Error codes (match on code, never detail)
See also ../shared/list-query-and-errors.md.
code |
HTTP | When | What to do |
|---|---|---|---|
feature_not_available |
403 | Org not entitled to Labels | Stop Labels work; tell the developer; do not retry |
paid_plan_required |
403 | Plan lacks Feature.LABELS | Surface upgrade path if present; do not retry |
guest_not_allowed |
403 | Guest caller hit a Labels endpoint | Stop; Labels require a non-guest member |
permission_denied |
403 | Caller lacks permission for this Labels action | Ask an admin/manager; do not retry blindly |
org_admin_required / insufficient_role |
403 | Caller cannot manage/delete | Ask an admin/manager |
archived_label |
400 | Assign/batch used an archived Label | Create a new Label or stop assigning that UUID; do not force |
invalid_color |
400 | Create/update color is not valid hex | Fix --color (e.g. #4A90E2) |
label_limit_exceeded |
400 | Assign/batch would exceed per-entity Label limit | Remove a Label first, then retry |
duplicate_name |
409 | Label name already exists in the org | Pick another --name or update the existing UUID |
label_in_use |
409 | Hard-delete while the Label still has attachments | Clear/reassign entities, then delete — or archive instead |
not_found |
404 | Unknown Label or entity UUID | Verify UUID via label list / entity list |
Frozen public codes: Errors
(Labels & personalization). Match on code from CLI --json (server value
forwarded unchanged).
A 403 is never “session expired” — only 401 is. Re-login will not fix a plan/role 403.
HTTP fallback
When the CLI is unavailable, call /v1/labels/ and the per-entity assign
paths under /v1/forms/…/labels/, /v1/checkins/…/labels/, or
/v1/workflows/…/labels/ with Bearer or X-API-KEY.
See ../shared/http-fallback.md and
Labels API docs.
Non-Blocking Rule
If auth fails or Labels are not entitled, warn once and continue the developer's primary task. Never block coding work on Labels availability.