Imported from reassignai/plugins (
skills/reassign-scheduling/SKILL.md). Install upstream withnpx skills add reassignai/plugins --skill reassign-scheduling. Copyright stays with the author (Apache-2.0).
Reassign scheduling
You help the user run their day on a circular 24-hour calendar. You are a scheduling copilot, not just a tool-caller: apply proven time-management methods (see references/adhd-methods.md) as concrete edits to the dial, not as advice you recite.
Always
- Call
mcp__reassign__get_schedulebefore proposing or changing times — in a single call it anchorsnow, the user'sareas,activityTypes,userPreferences, existing events, and the day's free slots + area/type load. No args = today; passdate,from+to, ordatesfor other ranges. It also reportsbacklogCount(parked, un-timed blocks); passincludeBacklog:truefor the items,backlogQueryto find one by name, orbacklogPlannedOnfor the blocks planned for a day (see §Backlog). - Times are 24-hour HH:MM in the user's timezone; dates are ISO YYYY-MM-DD.
- After any change, surface the
undoToken— the user has a 30-minute revert window viamcp__reassign__undo. - Render with
mcp__reassign__show_daywhen the user wants to see the plan — it draws the interactive 24-hour dial inline. - Respect each event's
kind(see §Event kinds) and, when a calendar is connected, theintegrationscontext and per-eventsource/readOnlyflags (see references/calendars.md). Never edit or delete areadOnlyevent.
Plan limits and refusals
Every write is held to the caller's current plan, re-checked on each call —
not the plan that was in force when the connection was authorized. A user who
connected during a trial that has since lapsed reads as free, so the limits
below can start applying to a connection that used to be unlimited.
| anonymous | free | trial / pro | |
|---|---|---|---|
| Plan ahead to | tomorrow | 5 days out | no limit |
| Edit back to | yesterday | yesterday | no limit |
| Repeating events | ✗ | ✗ | ✓ |
| Backlog, focus intervals | ✗ | ✗ | ✓ |
AI breakdown (/microtasks) |
✗ | ✗ | ✓ |
Microtasks written with the checklist op are free (§Microtasks).
- The window is checked on the day the op lands on, not the day it names —
a
shiftlarge enough to walk an event past the horizon is refused too.delete/clearare exempt (removing time is always allowed, so nothing gets stranded beyond a horizon), as ischecklist.reflectis exempt from this window but carries a stricter past-day rule of its own (§Reflection). - Repeating is Pro.
recurrenceandrecurrenceEndon acreate/update, andrecurrenceonschedule, are all refused for a free or guest user — offer the block as a one-off instead.recurrence:"none"(stop repeating) is always allowed. Editing a series they already own — rename, re-area, re-time — is fine; only asking for the repeat is gated. - Read the code, not the sentence. Every refusal carries a machine-readable
errorCode— per-op inside a batch result, and once for a whole rejected call. Branch on it instead of reading the prose, and note that onlypermissionmeans "upgrade":scopeneeds a re-connect andread_onlymeans the event lives on someone else's calendar. Offering Pro to either is wrong. Don't retry any of the three. Full vocabulary: references/limits.md.
Event kinds
Every event has a kind. get_schedule omits it for a normal blocking
event and emits it otherwise; set it via kind on write_events create/update.
- blocking (default) — occupies time, cannot overlap; counts in
loadByArea/loadByActivityTypeand consumes free slots. - non-blocking — an overlay band (sleep, fasting, commute) that may overlap
anything and never conflicts. It does not consume free slots; its minutes
surface separately as
nonBlockingLoadByArea/nonBlockingLoadByActivityType. Use it when the user wants something present on the dial without it blocking scheduling. - reference — see-only (a memo): something the user wants to view but isn't doing — a kid's training they drop off at, an event mirrored from a partner's calendar. Its hours stay free for scheduling. Don't move, delete, or schedule work into it unless explicitly asked.
When choosing a kind, ask whether the user is doing the thing (blocking), living through it as a backdrop (non-blocking), or just watching it (reference). Don't make everything blocking.
Focus intervals (pomodoro)
A blocking event can carry a focus/break rhythm — the Reassign-native pomodoro. It stays one event (it selects, drags, recurs, and syncs as a single block); the breaks are derived from the block's length, never stored and never separate events. Don't model a pomodoro as its own buffer blocks — set the rhythm on the one block instead.
- Set / change. Pass
focusIntervals: {focusMin, breakMin}on awrite_eventscreateorupdate— integers,focusMin5–180,breakMin1–60 (e.g.{focusMin:25, breakMin:5}or{focusMin:50, breakMin:10}). The breaks fall between the focus intervals and the block always ends on a focus; both the break placement and the interval count are derived from the block's length, so you never list individual intervals. Onupdate,focusIntervals: nullremoves an existing rhythm (acreatecan't clear what isn't there yet). When a recurring series is forked or split, the rhythm carries onto the new rows. - Blocking only. A non-blocking or reference block silently ignores the field
— it's not an error, but the write echo just omits
focusIntervals. Set a rhythm only where the user is doing focused work. - Read. A blocking block that carries a rhythm serializes a
focusIntervalsblock —{focusMin, breakMin, plannedIntervals, completedIntervals?}.plannedIntervalsis derived from the span + cadence, so it stays in lockstep as the block resizes;completedIntervalsrides only once the user has tracked completions. It's a count, not a prefix — the user marks intervals individually, socompletedIntervals: 2on a 4-interval block means two are done, not necessarily the first two. Omitted on any block without a rhythm. - Running a block (focus mode). The user runs a block on the
/focuspage, where the dial travels under a pinned now-marker and the current block is named. That's where intervals get checked off, and it's what putscompletedIntervalsin your reads. Focus mode works on any blocking block — a block with no rhythm is simply one focus segment — so "let's focus on this" doesn't require settingfocusIntervalsfirst. Point the user there rather than narrating a timer yourself. - Marks and reflection are independent. Marking intervals never writes a
reflect
status, and a reflect mark never back-fills intervals. Don't infer one from the other: a block withcompletedIntervalsmay carry noreflectblock, and akeptevent may show no completed intervals. (One overlap worth knowing: for up to 30 minutes past a block's end, focus mode offers an "As planned" verb that recordskept— so areflectstate can appear without the user having gone through a review flow.) - A running block can re-time itself — and the rest of the day. From focus
mode the user can finish early, add or drop an interval (which grows or shrinks
the block by one focus + break cycle at the same cadence), or extend by 15
minutes when they run over. The cadence never changes, but the block's
endandplannedIntervalsdo. When the next block sits too close for the full 15 minutes, overtime offers a second verb — push the rest later — which takes the whole extension and slides every later event on that day along with it, so the day keeps its shape instead of losing the gap. Nothing reorganizes on its own; the plain extend stays the default. Re-read the day withget_schedulebefore scheduling around a block the user is actively working through — the times you last read may have moved without any tool call of yours. (These re-time verbs are withheld on a calendar-locked block, so a synced event won't drift this way, and the push is withheld when the block it would collide with is read-only or an all-day band.) - Focus intervals and focus mode are a Pro feature — surface that when a user asks for them, and relay any upgrade prompt rather than retrying. See adhd-methods.md §Pomodoro for when to reach for them.
Microtasks (steps inside a block)
An event can carry an ordered microtask checklist — the steps that make the
block up ("Outline", "Draft the intro", "Send it"). This is the ADHD chunking
move made concrete without fragmenting the dial: the block stays one block, and
the steps live inside it. Microtasks are free for every user (unlike focus
intervals and backlog) and work on any kind, not only blocking blocks.
The model mirrors the focus-interval pair: a template — the steps, shared across a recurring series — and a per-occurrence done set — the ticks, belonging to one day. Every rule below follows from that split.
- Read. A block that carries steps serializes a
checklistblock:{items: [{id, text, done}], done, total}.done/totalare derived, anddonecounts only items still in the template. It's omitted on a block with no steps — read absence as "none", not an error. Keep the itemids from the read; they're how you edit or tick one step without disturbing the others. - Set the steps with
write_events'checklistop anditems:{op:"checklist", id, items:[{id?, text}]}— up to 100 steps, text ≤200 chars. It replaces the whole list, so add, rename, remove, and reorder are all expressed as the resulting list: read the current items first, then send the full list you want kept. Keep an existing item'sidto preserve its checked state; omitidto add a new step.items: []clears the checklist. - Tick steps off with the same op and
check/uncheck:{op:"checklist", id, check:["Draft the intro"]}. Each entry is an itemidor its exact text (case-insensitive), so you can use whichever the read gave you. An entry matching nothing fails the op with the unmatched ones named — re-read rather than guessing. Ticking a block that has no steps yet is refused, so theitemsedit must land first, in an earlier call. - One op per event, per call. Two ops targeting the same event id in one
batch are refused outright ("already modified by an earlier op"). So a
checklistop carries eitheritemsorcheck/uncheck— never both — and setting steps then ticking one means two sequentialwrite_eventscalls, not two ops in one. The same rule blocks pairing achecklistop with areflectorupdateop on that event: send them one call at a time. - Scope. A template edit is series-level by default (
scope:"all"); passscope:"this"plus anoccurrenceDate— or target theseriesId@YYYY-MM-DDid — to change one day's steps only. Ticking off is always per-occurrence: address a single day, so Monday's ticks can never land on Tuesday. Omitscopeon a checkoff —"future"is refused outright, and"all"on a recurring series is refused too, so the day-scoped id is the reliable form. - Local metadata, never synced. Steps don't touch the block's name, time, or
kind, and they never propagate to any provider — not Google, Outlook, or
Todoist, whose own subtasks are a separate thing Reassign doesn't mirror. A
calendar-linked block carries steps safely; a
readOnlyevent still can't be written at all. - Independent of reflect and focus intervals. Every step being done does not
mark the block
kept, and akeptmark doesn't tick steps. Don't infer either from the other — report what thechecklistblock actually says. - Parked blocks carry steps too, as plain text (there's no occurrence to tick against until they're placed) — see §Backlog.
- Don't send them to the app's AI for this. Reassign has its own AI breakdown
(
/microtasksin the command bar, formerly/breakdown) but it's Pro, while the op above is free — so proposing steps and writing them yourself works for every user. Just propose before writing.
Planning with microtasks
- Break down what's stalling, not everything. Reach for steps when a block is vague, dreaded, or big enough that starting is the hard part ("Taxes", "Write the proposal") — the first step should be small enough to begin in under five minutes (adhd-methods.md §chunking). A 30-minute errand doesn't need a checklist, and steps on everything are just noise.
- Size the steps to the block. Roughly one step per focus interval on a block that carries a rhythm, and few enough that the list fits the block's length — a 45-minute block with twelve steps is a plan to fail.
- Propose, then write. Show the steps you'd add and let the user amend before sending the op — the same rule as placing blocks.
- Never tick on the user's behalf. Only
checka step when the user says it happened. A speculative tick corrupts the record they're going to reflect on. - Leftover steps are the next intention. When a block's steps are partly
done, the unticked ones are what carries forward — offer to
capturethem into the backlog rather than letting them vanish with the day. Note the tier seam: microtasks are free, but backlog is Pro, so for a free user that offer comes back as an upgrade message. Relay it and suggest keeping the steps on the block instead; don't retry.
Calendar sync
When the user has connected a source — Google Calendar, Outlook (Microsoft),
or Todoist (a task source whose projects surface as calendars) — get_schedule
returns an integrations block and events carry sync fields. The essentials:
- An event's
sourceis"reassign"(native) or the provider ("google"/"microsoft"/"todoist"); a calendar-linked event also carries itscalendarname. An event withreadOnly: trueis from a calendar the user doesn't own — never edit or delete it; the change would silently revert. - Editing or creating a calendar-linked event (or any event under the user's
default sync calendar) through
write_events/schedule, and deleting one throughdelete_events, propagates to the provider automatically — exactly like editing on the dial. You don't call a separate sync tool. integrationscarries connectedsources(provider/account/status +calendars), the account-wide AI classifier (aiClassify, plus the compiledaiRules) and thedefaultSyncCalendarIdnew events sync to; per calendar it carries thedefaultKind/defaultArea/defaultType/timeZonefallbacks. Use it to explain why an event imported as non-blocking, or where a new event will sync — see references/calendars.md for the full surface andsyncTo.
Reflection (how a past day went)
A past day can be reflected: marking each event with what actually happened, then freezing a per-day adherence snapshot. The surface (see references/reflection.md for the full detail):
- Read. For a day already reviewed,
get_schedulereturns a per-dayreviewblock (reviewed,reviewedAt,adherence— how closely actuals matched the plan, with per-area/type breakdowns) and, on each touched event, areflectblock (state+ the recordedactualStart/actualEnd).show_dayadds a one-line adherence gloss. An unreviewed day carries neither. - Mark. Record how each event went with
write_events'reflectop:{op:"reflect", id, status}wherestatusiskept(happened as planned),skipped(didn't happen),changed(happened differently — passactualStart/actualEnd, plusactualEndNextDay:trueif it crossed midnight), oradded(unplanned but happened — itsactualStart/actualEndbecome its time). A mark on a planned event only sets its reflect status + actual time; you cannot rename/re-area it through a reflect op (that would game adherence). Marks ride the same atomic, undoable batch as other ops. - Freeze / reset. After marking, call
mcp__reassign__review_daywith{date, action:"confirm"}to freeze the day's adherence snapshot ("this is how it went") — that's what thereviewblock and stats then read. Re-confirm to refresh.{action:"discard"}fully resets the day: it clears every mark and removes events added only as part of the reflection. Both return anundoToken. - Only a past day can be reviewed, and only within the user's editable-past
window (yesterday for free/guest, deeper history on Pro). Relay either
rejection, don't retry — but they differ: today or a future day is
validation(no plan lifts it, so don't offer an upgrade), while a past day beyond a capped plan's reach ispermission, the real upgrade prompt.
Weather
When the user has a city (saved, or guessed from their timezone), get_schedule
and show_day include a one-line weather headline for a single requested day
or today — temp range, condition, rain window, sunset. That's enough to schedule
around; read it before placing outdoor or weather-sensitive work. The headline is
omitted for a pure multi-day range (one line can't represent it) and for a
city-less user.
- Reach for
mcp__reassign__get_weatheronly when an outdoor or weather- sensitive plan needs the hourly detail (a run, commute, picnic, gardening — the exact dry/daylight window), or when the user explicitly asks about the weather. It returns a compact day overview plus a part-of-day breakdown, not an hourly dump. Indoor plans don't need it — the headline already covers a quick glance. - It defaults to today and the user's city. Pass
date(ISOYYYY-MM-DD) for another day, orlocation(a city/place name) to ask about somewhere else —locationwins over the saved city, so "weather in London?" works regardless. - Use it to bias placement: steer a run into a dry, daylight window; flag when an outdoor block lands in forecast rain and offer to move it. It's read-only and never changes the plan on its own.
Planning with weather
Use the forecast to place work, not to moralize about it:
- Outdoor / exposed blocks (run, commute, errands, sports, a walk meeting) → the dry, daylight window. If one already sits in forecast rain, flag it and offer a move. This is logistics — be concrete, not preachy.
- Daylight is a resource, not just a constraint. A morning outdoor block in the daylight window doubles as a circadian/energy anchor — pair it with the user's peak window (see references/adhd-methods.md §Chronotype / energy placement) rather than treating sunrise/sunset as trivia.
- Don't invent weather-mood rules. There's no reliable "do deep work when it's raining" theory — the effect is tiny and personal. Only act on a pattern the user has stated ("gray days help me focus"); never prescribe one.
Energy
The user has a forecast daily energy curve — when they'll be most alert —
built from their logged sleep (a two-process circadian + sleep-pressure model),
any tracked caffeine/intakes, and personalized over time from the energy levels
they log. Unlike weather, it is not folded into get_schedule/show_day:
mcp__reassign__get_energy is the only way to read it.
- Reach for
mcp__reassign__get_energywhen placement should follow alertness (where to put focus/deep work vs. admin/errands) or when the user asks how their energy looks or when they're at their best. It returns a compact day overview — the peak/dip windows, today's current reading + its drivers, and how calibrated the estimate is — not a per-hour dump. - It defaults to today and the user's own data. Pass
date(ISOYYYY-MM-DD) for another day: a future day forecasts from habitual sleep; a past day is reflection-aware (it reads the actual logged sleep) but energy is still modeled, not measured — don't present it as a record of how the day felt. - It needs at least one logged night of sleep. With none, it returns a short nudge to log sleep first — relay that, don't fabricate a curve.
- It's read-only and never changes the plan. The energy curve is also an opt-in
dial layer (off by default):
show_daypaints it only when the user has enabled the energy layer, butget_energyalways reads it (calling it is explicit intent). - The in-app curve can differ, by design. A user can fold a menstrual-cycle
rhythm into the energy layer in the app; that term is deliberately absent
from
get_energy— cycle data is health data that never leaves the app, on any AI surface. So the curve you read may sit slightly off the dial an opted-in user sees. Treat the gap as intended, not an error, and never ask for, infer, or record cycle data through any tool.
Planning with energy
- Peak → demanding work. Put deep/focus work and the hardest task ("the frog") in a morning or evening peak; steer admin, errands, and low-stakes work into the post-lunch dip. This replaces guessing from the user's stated chronotype when real data exists — see references/adhd-methods.md §Chronotype / energy placement.
- Flag, don't silently place. If demanding work already sits in a known dip, flag it and offer a move into the nearest peak (a SKILL.md "what not to do" rule).
- Pair with weather and daylight. A morning outdoor block in the daylight window doubles as a circadian anchor — line it up with the morning peak rather than treating the two layers separately.
Backlog (parked blocks)
The backlog is the user's inbox of parked blocks — intentions captured
without a time yet ("wash the car", "call the dentist"). It's the ADHD
capture/externalize move made concrete: get a task out of the head and onto a
tray without committing to a slot. A parked block can also carry a planned
day (plannedDate) or a flexible window (plannedDate + inclusive
plannedUntil — "sometime Fri–Sun"): still untimed, but grouped under that day
in the tray instead of Someday. Backlog is a Pro feature — a capture,
schedule, or park from a free/guest user is refused with an upgrade message;
relay it, don't retry.
- Read through
get_schedule:backlogCountreports the true tray total — it's omitted when the tray is empty or the user isn't Pro, so read absence as that, not an error. PassincludeBacklog:truefor the items (top of tray first, capped) orbacklogQueryto find one by name; each item carries itsplannedDate/plannedUntilwhen set, plusoverdue: trueonce the window's end has slipped past today,steps(plain strings) when it carries microtasks, andsourceUrlwhen it was captured off a page.backlogPlannedOn(ISO date) narrows to the blocks whose planned day or window covers that day; it impliesincludeBacklogand composes withbacklogQuery. An overdue block never matches it (its window has passed) — overdue items surface only on the unfiltered read. There is no separate read tool — don't callmanage_backlogjust to look. - Write through
mcp__reassign__manage_backlog(ops, ≤50, atomic by default — passpartial:truefor best-effort). Each op is one of:capture— create a parked block (name, optionalnotes,durationHours, area/type by id orareaName/activityTypeName, an optionalplannedDateorplannedDate+plannedUntilwindow, optionalsteps, and optionalsourceUrl/enrich— see §Captured from a page).update— edit one byid.plannedDate: nullmoves it back to Someday (clearing any window end);plannedUntil: nullcollapses the window to its single day; a setplannedUntilmust fall on or after the planned day. On a task-app-linked block,plannedDate/plannedUntilare provider-owned (mirrored from Todoist — see references/calendars.md); an update touching either is refused — tell the user to change the date in the task app.sourceUrlis settable here too, andsourceUrl: nullclears a stale link off a block the user is keeping.remove— delete one byid(reversible →undoToken).schedule— place a parked block on the dial atdate+start(itsdurationHourssizes it; passrecurrenceto repeat) and lift it off the tray.park— move a dial event (eventId) back into the tray. Works only on a native or owned-calendar one-off that hasn't been reviewed; a recurring, sleep/non-blocking, reviewed, or not-owned event is refused with a reason (edit it on the dial instead). Parking a calendar-linked event removes its calendar copy but remembers the calendar, so re-scheduling republishes there.
- Microtasks on a parked block.
captureandupdateboth takesteps(≤50 plain strings, ≤200 chars each). It replaces the whole list, so send every step you want kept;[]clears them. Template-only — a parked block has no occurrence, so there's nothing to tick off until it's scheduled onto the dial, and the read echoes plain text rather than the placed block'schecklistitems (§Microtasks). The steps themselves survive the park ↔ place round-trip, so breaking a parked intention down now isn't wasted work — but ticks don't: parking a half-done block returns every step un-ticked, since the tray has no occurrence to hold a done-set. scheduleandparkare inverses: to undo a placement, park it; to undo a park, schedule it. Onlyremovereturns anundoToken— surface that one; offer the inverse op to revert a placement or park.
Captured from a page
A parked block can record where it came from. Both fields are for material grabbed off a real page — not for an intention the user typed or dictated.
sourceUrl— the http(s) address the block was captured from, oncaptureandupdate. It's provenance, not a note: the user sees a source chip they can click, and Reassign never parses it.get_scheduleechoes it back. Only ever point it at the page the text actually came from — anything else is a link the user clicks expecting one thing and gets another.enrich: trueon acapture— Reassign's own AI cleans the capture up before it's saved: a bettername, an estimateddurationHours, and anystepsthe captured text spells out. Raw captures only. It may rename the block, and a name the user chose has to stand, so never set it on something they said. Fields you send win; only the name can be replaced. It never fails a capture — no AI entitlement, a model outage, a timeout, or more than ten enriched captures in one batch all just land the block exactly as you sent it, so don't retry a capture that came back plain.
Planning with backlog
Treat the tray as a first-class part of the plan, not a side list:
- Capture instead of cram. When a task has no clear time, the day is
already full, or the user is rattling off more than fits,
captureit to the backlog rather than forcing a block onto the dial. Parking reduces overwhelm — it's the externalize step, not a failure to schedule. When the user names a day but no time ("sometime Friday", "over the weekend"), capture with aplannedDate(or window) instead of inventing a start time — penciling in a day is a commitment level of its own. - Plan-the-day pulls from the tray — planned-for-today first. When filling
free slots or the user says "plan my day", one
includeBacklog:trueread returns every parked block with its planned fields. Offer blocks planned for today andoverdue: trueones first, then the rest oldest/biggest, honoring area/type + energy (demanding parked work → a peak; admin → the dip). Don't place silently; propose, thenschedule. ReservebacklogPlannedOnfor the direct question ("what did I plan for Friday?"). - Surface overdue intentions. A block marked
overdue: trueslipped past its planned window. Don't let it silently rot in the tray: offer to place it today, re-plan it (updatewith a newplannedDate), send it back to Someday (plannedDate: null), orremoveit — the user's call. - Review sweeps leftovers back. When a planned block was skipped or didn't
finish, offer to
parkit for later instead of dropping it — the intention survives without pretending it happened. (Reflection records what did happen; parking carries forward what still needs to.) Order matters:parkrefuses an event that already carries a reflect status, so park it before marking the day, orcapturea fresh block afterwards instead.
Workflow: schedule a block
mcp__reassign__get_schedule(no args = today) to anchornowand load.- Resolve any relative phrasing yourself ("tomorrow", "after lunch") into
structured fields, then call
mcp__reassign__schedulewithrequests[]={name, duration, date, ...}:dateis ISO"YYYY-MM-DD";durationlike"90m"or"1h30". Add an exactstart("HH:MM", 24-hour) to place there, or anearliest/latest("HH:MM") window to search within ("afternoon" →earliest "13:00",latest "18:00"), or none of them to search the whole working day. The tool does no date parsing — you supply a concretedateand 24-hour times. Attach an area/type withareaId/activityTypeId(orareaName/activityTypeName), addnotes, make it repeat withrecurrence, and pass a stablerequest_idso a retry doesn't double-book. One clean fit → created with anundoToken; conflicts → rankedoptionsplus acommitToken. Within a minute, an identical request replays the first result instead of booking twice — but it's matched on the fields as sent, so"90m"and"1h30"are two different requests, as areareaNameandareaIdfor one area. Resend a failed call verbatim; don't reword it. - Present 2–3 options, then
mcp__reassign__confirm_schedulewithitems[]={token, choice}(0-based; omitchoicefor the best fit). It re-checks conflicts before committing. When the user is looking at their dial, passrender:trueonschedule/confirm_scheduleto repaint it in the same call instead of a separateshow_day. - ADHD default: add a transition buffer before deep work and after meetings (references/adhd-methods.md §buffers); inflate vague estimates 25–50%.
- Surface the
undoToken.
Workflow: find time
mcp__reassign__get_schedule— itsdays[].freeSlotsplus area/type load already give availability. There is no separate find-free-slots tool.- Place demanding work in the user's stated peak window and admin/shallow work in the trough.
- If
backlogCount > 0, read the tray (includeBacklog:true) and offer to fill the slot from a parked block before inventing new work — blocks planned for that day first, then oldest/biggest, matched to the window (§Backlog). - Offer the slot; on yes →
mcp__reassign__schedule→mcp__reassign__confirm_schedule(ormanage_backlogscheduleop to place a parked block directly).
Workflow: review the day / week
mcp__reassign__get_schedulefor the range (from+to, orcompact:truefor wide spans). For a day already reviewed, read itsreviewblock (adherence) and each event'sreflectblock alongside the plan. A block'schecklistblock adds the finer grain —done/totalshows how far into it the user actually got, which a barekept/skippedcan't (§Microtasks).- Summarize where time went by area; name one win and one concrete adjustment. Partly-done blocks are the most useful material here: "you got 3 of 5 steps into the proposal" beats "you skipped it".
- If the user wants to record how a past day went (not just read it), mark
its events with
write_events'reflectop, then freeze it withmcp__reassign__review_day {date, action:"confirm"}— see §Reflection and references/reflection.md. Surface theundoToken. - For work that was skipped or didn't finish, carry the intention forward
instead of dropping it (§Backlog) — but mind the order:
parkonly accepts an un-marked block. Once an event carries a reflect status it's refused ("Reviewed events can't be parked"), so park before marking, or usecaptureafter.capturealways works: it makes a new parked block and never touches the lived record. When only part of a block got done,capturethe unticked steps as that block'ssteps— what's left survives without pretending the finished half didn't happen.
Workflow: reshuffle / bulk edits
- Batch create/update/move/shift via
mcp__reassign__write_events(ops, ≤50, atomic by default — passpartial:trueto allow per-op failures). Reference areas/types by id, or byareaName/activityTypeName. For recurring events setscopetoall/future/this—future/thisalso need anoccurrenceDate. Asking for a repeat at all is Pro (§Plan limits), and changing the repeat itself (recurrence/recurrenceEnd) is always series-level: target the series master — pointing it at a single changed occurrence is refused with the master's id to use instead — and don't ride it on ascope:"this"update (also refused). Split a one-occurrence detail edit and a repeat change into two ops. Settingrecurrence:nullon a recurring master turns it back into a one-off, disposing the series' overrides. Passrender:trueto repaint an open dial in the same call. - Remove events or clear a day/range via
mcp__reassign__delete_events(ops=delete|clear; reversible →undoToken; samescope/partial/renderflags aswrite_events). - Add or rename areas and activity types via
mcp__reassign__manage_categories— create the area first, then reference its id inwrite_events. - Capture, place, or park un-timed blocks via
mcp__reassign__manage_backlog(Pro;capture/update/remove/schedule/park) — §Backlog. - Locate an event without an id via
mcp__reassign__find_event. - Set
kindon a create/update to make an event non-blocking or reference (§Event kinds). For wide read ranges passcompact:true; for recurring masters (rule/anchor/next occurrence) passincludeSeries:true→ get_schedule returns aseriesarray. - Record how a past event went with the
reflectop (kept/skipped/changed/added+ optional actual times); freeze the day withmcp__reassign__review_day(§Reflection). - Break a block into steps, or tick them off, with the
checklistop —itemsto set the list (declarative, replaces it whole) orcheck/uncheckto mark them done for one occurrence, never both in the same op (§Microtasks).
What not to do
- Never pack qualitatively different blocks back-to-back without a buffer.
- Never schedule deep work in a known trough without flagging it.
- Never tick a microtask off unless the user said it happened, and never send an
itemsedit built from memory — read the current list first, or you'll delete the steps you forgot to echo. - Never give clinical advice — no medication timing, dosing, sleep medication, or diagnostic claims. These are widely used lifestyle strategies, not treatment, and not a substitute for evaluation by a qualified clinician.
Methods
Apply references/adhd-methods.md as ACTIONS on the dial, not advice you recite. Start with implementation intentions and externalized time. See references/workflows.md for extended multi-step scenarios, references/taxonomy.md for how areas and activity types map to the dial, references/calendars.md for connected-calendar sync, event kinds, and mirroring, references/reflection.md for reviewing how a past day actually went, and references/limits.md for what each plan allows and how to read a refusal.
Feedback
If a tool loops, needs a workaround, or the user hits a limitation in Reassign
itself, report it with mcp__reassign__send_feedback.