Work Done (/wd)
Setup required before use. See README.md for all prerequisite IDs and keys.
Fixed IDs — configure once, never look up again
Replace all <PLACEHOLDER> values with your own before using this skill.
| Resource |
Placeholder |
| Trello sprint board ID |
<TRELLO_BOARD_ID> |
| Trello "In Progress" list ID |
<TRELLO_IN_PROGRESS_LIST_ID> |
| Your Trello member ID |
<YOUR_TRELLO_MEMBER_ID> |
| Slack announce channel ID |
<SLACK_CHANNEL_ID> |
| Primary CC Slack user ID |
<SLACK_CC_USER_ID> |
Clockify Fixed IDs — configure once, never look up again
| Resource |
Placeholder |
| Clockify API Key |
<CLOCKIFY_API_KEY> |
| Clockify Workspace ID |
<CLOCKIFY_WORKSPACE_ID> |
| Project: web.admin (or equivalent) |
<PROJECT_ID_WEB_ADMIN> |
| Project: app.partners (or equivalent) |
<PROJECT_ID_APP_PARTNERS> |
| Project: web.customer (or equivalent) |
<PROJECT_ID_WEB_CUSTOMER> |
| Project: web.partner (or equivalent) |
<PROJECT_ID_WEB_PARTNER> |
| Project: app.customer (or equivalent) |
<PROJECT_ID_APP_CUSTOMER> |
| Project: AI / agents |
<PROJECT_ID_AI> |
| Project: Miscellaneous / fallback |
<PROJECT_ID_MISC> |
Project detection rules (first match wins)
Map keywords found in repo names or the task title to a Clockify project ID. Adapt to your project naming.
| Keyword in repos/title |
Maps to |
web.admin / helpdesk / bff |
<PROJECT_ID_WEB_ADMIN> |
app.partner |
<PROJECT_ID_APP_PARTNERS> |
web.customer |
<PROJECT_ID_WEB_CUSTOMER> |
web.partner |
<PROJECT_ID_WEB_PARTNER> |
app.customer |
<PROJECT_ID_APP_CUSTOMER> |
carowl / ai / agent / leaderboard |
<PROJECT_ID_AI> |
| anything else |
<PROJECT_ID_MISC> |
Mode flags (parsed from args before doing anything)
Three shorthand modes — pick one, or use no flag for the full package:
| Flag |
Alias |
What runs |
| (none) |
|
Full package: git PRs + Slack/Trello + Clockify |
--time-only |
--to |
Time only — just log to Clockify. Skip everything else. |
--pr-only |
--pro |
PRs only — run git workflow only. Skip Slack, Trello, Clockify. |
--post-only |
--po |
Post only — Slack + Trello only. Skip git and Clockify. |
--time <duration> |
--t <duration> |
Pre-supply Clockify duration (e.g. --t 3h, --t 1.5h, --t 45m). Works with any mode. |
--range-time [range] |
--rt [range] |
Bulk Clockify backfill — see --rt flow below. |
Git workflow (runs in full package and --pr-only mode only)
Per repo: create feature/<slug> from develop → stage named files → commit (conventional, ≤72 char header) → push → find existing integration branch (git branch -r | grep integration, pick highest suffix) → open 2 PRs: --base develop and --base integration/<branch>.
Normal flow (full package — no mode flag)
Gather from context — title, 1–2 line summary, PRs grouped by repo (base + URL), existing Trello card URL if any, bullet list of changes, extra CC names if specified.
Trello card (skip in --to / --pro) — if card exists in context: use its ID (from URL slug). If not: create_card → idList: <TRELLO_IN_PROGRESS_LIST_ID>, idMembers: <YOUR_TRELLO_MEMBER_ID>. Save card ID + URL.
Trello attachments (skip in --to / --pro) — one add_attachment per PR not already attached. Name: <repo> → <base-branch>.
Slack main message (skip in --to / --pro) → channel <SLACK_CHANNEL_ID>:
<emoji> **<Title>**\n\n<1–2 line summary>\n\n<Trello URL>
Emoji: :shield: security · :rocket: features · :white_check_mark: fixes · :tools: infra
Save returned message_ts.
Slack thread — per repo (skip in --to / --pro):
:white_check_mark: **<repo>** — <one-line summary>\n- → \`: `
Slack thread — what changed (skip in --to / --pro):
**What changed:**\n- <change>\n- <change> — one line per change, no descriptions.
Slack thread — CC (skip in --to / --pro) (always last): cc <@SLACK_CC_USER_ID> + any extras on the same line.
Clockify time entry (skip in --po / --pro) — if --time/--t was passed, use that duration directly. Otherwise ask: "Clockify: how long did this take? (e.g. 2h, 1.5h, 45m — or 'skip')". If not skipped:
- Detect
projectId from repo/title context using the project detection rules above. Default to <PROJECT_ID_MISC>.
- Compute
end = current UTC datetime in ISO 8601 (date -u +"%Y-%m-%dT%H:%M:%SZ"). Compute start = end minus duration.
- Run via Bash:
curl -s -X POST \
-H "X-Api-Key: <CLOCKIFY_API_KEY>" \
-H "Content-Type: application/json" \
-d "{\"start\":\"<start>\",\"end\":\"<end>\",\"description\":\"<title>\",\"projectId\":\"<projectId>\",\"billable\":true}" \
"https://api.clockify.me/api/v1/workspaces/<CLOCKIFY_WORKSPACE_ID>/time-entries"
- Verify response contains
"id" field. Report project name + duration logged.
Return Trello card URL + Slack message link + Clockify entry confirmation (or "skipped").
--range-time / --rt flow (bulk backfill)
Use case: forgot to log time for a period. Scans your Slack announcements and batch-logs them to Clockify.
Range parsing (step 1)
Parse the optional string after --rt. If absent, default to "this month".
| Input |
oldest |
latest |
(none) / "this month" |
First second of current month (UTC) |
Now |
"this week" |
Last Monday 00:00:00 UTC |
Now |
"last week" |
Monday of previous week 00:00:00 UTC |
Last Sunday 23:59:59 UTC |
"last two weeks" / "last 2 weeks" |
14 days ago 00:00:00 UTC |
Now |
"last N weeks" / "last N days" |
N×7 days (or N days) ago 00:00:00 UTC |
Now |
"last month" |
First second of previous calendar month UTC |
Last second of previous calendar month UTC |
"YYYY-MM-DD to YYYY-MM-DD" |
Given start date 00:00:00 UTC |
Given end date 23:59:59 UTC |
Compute timestamps via Bash date commands. Always confirm resolved range before fetching: "Scanning: 2026-05-01 → 2026-05-24".
Steps
Compute range — parse range string → compute oldest + latest UTC Unix timestamps. Print resolved dates for confirmation.
Fetch all channel messages — read <SLACK_CHANNEL_ID> with oldest set, paginate until exhausted. Collect only top-level messages from your user ID that look like work announcements: has a Trello link, a bold title (*text*), or a work emoji at start (:rocket:, :white_check_mark:, :tools:, :shield:, :ladybug:). Skip casual messages. If a single message contains multiple entries each with their own Trello link, split into individual items.
Present numbered list:
#1 [YYYY-MM-DD] <title> — Project: <detected-project-name>
#2 [YYYY-MM-DD] <title> — Project: <detected-project-name>
Ask for durations in one shot:
"Enter durations comma-separated in order. Use 'skip' to skip. Example: 2h, 1.5h, skip, 3h"
Log each non-skipped item — for each with a duration:
- Detect
projectId from title/content using project detection rules.
- Use the message's actual date for
start (09:00:00 UTC). Chain same-day entries (second starts where first ends). Compute end = start + duration.
- POST to Clockify with
"billable": true (same curl as normal flow).
Report summary:
Logged N entries to Clockify:
✓ [YYYY-MM-DD] <title> — 2h → web.admin
- [YYYY-MM-DD] <title> — skipped
Rules
- Use
thread_ts for all thread replies (steps 5–7).
- Do not post if no PRs or deliverables — ask what to announce instead.
- Primary Slack user is always CC'd. Never look up IDs at runtime — use the configured values above.
--rt never posts to Slack or Trello — read-only on those systems.
- All Clockify entries are always
"billable": true.
1---2name: wd3description: Post a work-done announcement to a Slack channel and create/update a Trello card, then log time to Clockify. Use after completing any task that produces PRs, fixes, or deployable changes. Supports --skip-time, --skip-post, --time <duration>, and --range-time for bulk backfill.4---56# Work Done (/wd)78> **Setup required before use.** See `README.md` for all prerequisite IDs and keys.910## Fixed IDs — configure once, never look up again1112Replace all `<PLACEHOLDER>` values with your own before using this skill.1314| Resource | Placeholder |15|---|---|16| Trello sprint board ID | `<TRELLO_BOARD_ID>` |17| Trello "In Progress" list ID | `<TRELLO_IN_PROGRESS_LIST_ID>` |18| Your Trello member ID | `<YOUR_TRELLO_MEMBER_ID>` |19| Slack announce channel ID | `<SLACK_CHANNEL_ID>` |20| Primary CC Slack user ID | `<SLACK_CC_USER_ID>` |2122## Clockify Fixed IDs — configure once, never look up again2324| Resource | Placeholder |25|---|---|26| Clockify API Key | `<CLOCKIFY_API_KEY>` |27| Clockify Workspace ID | `<CLOCKIFY_WORKSPACE_ID>` |28| Project: web.admin (or equivalent) | `<PROJECT_ID_WEB_ADMIN>` |29| Project: app.partners (or equivalent) | `<PROJECT_ID_APP_PARTNERS>` |30| Project: web.customer (or equivalent) | `<PROJECT_ID_WEB_CUSTOMER>` |31| Project: web.partner (or equivalent) | `<PROJECT_ID_WEB_PARTNER>` |32| Project: app.customer (or equivalent) | `<PROJECT_ID_APP_CUSTOMER>` |33| Project: AI / agents | `<PROJECT_ID_AI>` |34| Project: Miscellaneous / fallback | `<PROJECT_ID_MISC>` |3536### Project detection rules (first match wins)3738Map keywords found in repo names or the task title to a Clockify project ID. Adapt to your project naming.3940| Keyword in repos/title | Maps to |41|---|---|42| `web.admin` / `helpdesk` / `bff` | `<PROJECT_ID_WEB_ADMIN>` |43| `app.partner` | `<PROJECT_ID_APP_PARTNERS>` |44| `web.customer` | `<PROJECT_ID_WEB_CUSTOMER>` |45| `web.partner` | `<PROJECT_ID_WEB_PARTNER>` |46| `app.customer` | `<PROJECT_ID_APP_CUSTOMER>` |47| `carowl` / `ai` / `agent` / `leaderboard` | `<PROJECT_ID_AI>` |48| anything else | `<PROJECT_ID_MISC>` |4950---5152## Mode flags (parsed from args before doing anything)5354Three shorthand modes — pick one, or use no flag for the full package:5556| Flag | Alias | What runs |57|---|---|---|58| _(none)_ | | **Full package**: git PRs + Slack/Trello + Clockify |59| `--time-only` | `--to` | **Time only** — just log to Clockify. Skip everything else. |60| `--pr-only` | `--pro` | **PRs only** — run git workflow only. Skip Slack, Trello, Clockify. |61| `--post-only` | `--po` | **Post only** — Slack + Trello only. Skip git and Clockify. |62| `--time <duration>` | `--t <duration>` | Pre-supply Clockify duration (e.g. `--t 3h`, `--t 1.5h`, `--t 45m`). Works with any mode. |63| `--range-time [range]` | `--rt [range]` | Bulk Clockify backfill — see `--rt` flow below. |6465---6667## Git workflow (runs in full package and `--pr-only` mode only)6869Per repo: create `feature/<slug>` from `develop` → stage named files → commit (conventional, ≤72 char header) → push → find existing integration branch (`git branch -r | grep integration`, pick highest suffix) → open 2 PRs: `--base develop` and `--base integration/<branch>`.7071---7273## Normal flow (full package — no mode flag)74751. **Gather from context** — title, 1–2 line summary, PRs grouped by repo (base + URL), existing Trello card URL if any, bullet list of changes, extra CC names if specified.76772. **Trello card** _(skip in `--to` / `--pro`)_ — if card exists in context: use its ID (from URL slug). If not: `create_card` → `idList: <TRELLO_IN_PROGRESS_LIST_ID>`, `idMembers: <YOUR_TRELLO_MEMBER_ID>`. Save card ID + URL.78793. **Trello attachments** _(skip in `--to` / `--pro`)_ — one `add_attachment` per PR not already attached. Name: `<repo> → <base-branch>`.80814. **Slack main message** _(skip in `--to` / `--pro`)_ → channel `<SLACK_CHANNEL_ID>`:82 `<emoji> **<Title>**\n\n<1–2 line summary>\n\n<Trello URL>`83 Emoji: `:shield:` security · `:rocket:` features · `:white_check_mark:` fixes · `:tools:` infra84 Save returned `message_ts`.85865. **Slack thread — per repo** _(skip in `--to` / `--pro`)_:87 `:white_check_mark: **<repo>** — <one-line summary>\n- → \`<branch>\`: <PR URL>`88896. **Slack thread — what changed** _(skip in `--to` / `--pro`)_:90 `**What changed:**\n- <change>\n- <change>` — one line per change, no descriptions.91927. **Slack thread — CC** _(skip in `--to` / `--pro`)_ (always last): `cc <@SLACK_CC_USER_ID>` + any extras on the same line.93948. **Clockify time entry** _(skip in `--po` / `--pro`)_ — if `--time`/`--t` was passed, use that duration directly. Otherwise ask: `"Clockify: how long did this take? (e.g. 2h, 1.5h, 45m — or 'skip')"`. If not skipped:95 - Detect `projectId` from repo/title context using the project detection rules above. Default to `<PROJECT_ID_MISC>`.96 - Compute `end` = current UTC datetime in ISO 8601 (`date -u +"%Y-%m-%dT%H:%M:%SZ"`). Compute `start` = `end` minus duration.97 - Run via Bash:98 ```bash99 curl -s -X POST \100 -H "X-Api-Key: <CLOCKIFY_API_KEY>" \101 -H "Content-Type: application/json" \102 -d "{\"start\":\"<start>\",\"end\":\"<end>\",\"description\":\"<title>\",\"projectId\":\"<projectId>\",\"billable\":true}" \103 "https://api.clockify.me/api/v1/workspaces/<CLOCKIFY_WORKSPACE_ID>/time-entries"104 ```105 - Verify response contains `"id"` field. Report project name + duration logged.1061079. Return Trello card URL + Slack message link + Clockify entry confirmation (or "skipped").108109---110111## `--range-time` / `--rt` flow (bulk backfill)112113Use case: forgot to log time for a period. Scans your Slack announcements and batch-logs them to Clockify.114115### Range parsing (step 1)116117Parse the optional string after `--rt`. If absent, default to `"this month"`.118119| Input | `oldest` | `latest` |120|---|---|---|121| _(none)_ / `"this month"` | First second of current month (UTC) | Now |122| `"this week"` | Last Monday 00:00:00 UTC | Now |123| `"last week"` | Monday of previous week 00:00:00 UTC | Last Sunday 23:59:59 UTC |124| `"last two weeks"` / `"last 2 weeks"` | 14 days ago 00:00:00 UTC | Now |125| `"last N weeks"` / `"last N days"` | N×7 days (or N days) ago 00:00:00 UTC | Now |126| `"last month"` | First second of previous calendar month UTC | Last second of previous calendar month UTC |127| `"YYYY-MM-DD to YYYY-MM-DD"` | Given start date 00:00:00 UTC | Given end date 23:59:59 UTC |128129Compute timestamps via Bash `date` commands. Always confirm resolved range before fetching: `"Scanning: 2026-05-01 → 2026-05-24"`.130131### Steps1321331. **Compute range** — parse range string → compute `oldest` + `latest` UTC Unix timestamps. Print resolved dates for confirmation.1341352. **Fetch all channel messages** — read `<SLACK_CHANNEL_ID>` with `oldest` set, paginate until exhausted. Collect only top-level messages from your user ID that look like work announcements: has a Trello link, a bold title (`*text*`), or a work emoji at start (`:rocket:`, `:white_check_mark:`, `:tools:`, `:shield:`, `:ladybug:`). Skip casual messages. If a single message contains multiple entries each with their own Trello link, split into individual items.1361373. **Present numbered list**:138 ```139 #1 [YYYY-MM-DD] <title> — Project: <detected-project-name>140 #2 [YYYY-MM-DD] <title> — Project: <detected-project-name>141 ```1421434. **Ask for durations in one shot**:144 `"Enter durations comma-separated in order. Use 'skip' to skip. Example: 2h, 1.5h, skip, 3h"`1451465. **Log each non-skipped item** — for each with a duration:147 - Detect `projectId` from title/content using project detection rules.148 - Use the message's actual date for `start` (09:00:00 UTC). Chain same-day entries (second starts where first ends). Compute `end` = `start` + duration.149 - POST to Clockify with `"billable": true` (same curl as normal flow).1501516. **Report summary**:152 ```153 Logged N entries to Clockify:154 ✓ [YYYY-MM-DD] <title> — 2h → web.admin155 - [YYYY-MM-DD] <title> — skipped156 ```157158---159160## Rules161162- Use `thread_ts` for all thread replies (steps 5–7).163- Do not post if no PRs or deliverables — ask what to announce instead.164- Primary Slack user is always CC'd. Never look up IDs at runtime — use the configured values above.165- `--rt` never posts to Slack or Trello — read-only on those systems.166- All Clockify entries are always `"billable": true`.