Skip to content

Skills · operations-manager

shift-roster

Build a staff rota for a week or a fortnight from who is available, what each shift needs and the working-time rules, and check it with a script before anyone sees it — every shift covered with the right skills, nobody double-booked, over their hours, short of rest between shifts or past the consecutive-day limit — drawn as a week grid. Use when a manager asks to "make the rota", "build next week's schedule", "who should work which shift", "check this rota", "fill these shifts", or has staff availability and shift needs for a shop, restaurant, clinic, warehouse or call centre.

Pack operations-managerTier standardJob Staff the shiftsv0.2.1

npx skilldrop-cli install shift-roster
Other ways to install

With the sibling skills it hands off to:

npx skilldrop-cli install shift-roster --with-related

The whole pack it belongs to:

npx skilldrop-cli install --pack operations-manager

By hand, from a clone of the repo:

cp -R packs/operations-manager/skills/shift-roster ~/.claude/skills/

In Claude Code, with the operations-manager plugin installed, invoke it as:

/operations-manager:shift-roster

Try it

A realistic prompt from the skill's acceptance evals:

Can you make next week's rota for the ward? Staff and their limits are in staff.csv and the shifts we need covered are in shifts.csv. Use our usual rule of at least 11 hours between shifts.

What a good result looks like

Example output

Worked example: a café week, and the turnaround the first draft hid · the skill's own worked example, source

Input

Make next week's rota for the café, Monday to Saturday. Every day there's an opening shift 06:30–14:30 and a closing shift 14:00–21:00, and each needs one keyholder and one barista. Staff:

  • Amira: keyholder, barista, max 40 h, contracted 37.5
  • Ben: barista, max 24 h, contracted 24, can't do Wednesdays (college)
  • Chloe: keyholder, barista, max 32 h, contracted 30
  • Dev: keyholder, barista, max 40 h, contracted 37.5
  • Ema: barista, max 24 h, contracted 20, not Mondays or Tuesdays
  • Fay: barista, max 32 h, contracted 30

At least 11 hours between shifts, nobody more than 5 days in a row.

The first draft, and what the check found

The draft filled every shift, two people each, with the keyholders on the keyholder needs. It put Ben on Thursday's close and Friday's open. The check failed it:

FAIL Ben gets 9.5 h rest between Thu close (ends Thu 21:00) and Fri open, under the 11 h minimum
FAIL Ben works 30 h in week 1, over their 24 h maximum
WARN Ema works 14 h against 20 h contracted

Thursday's close went to Ema instead, who is free that evening and under her hours. That fixed all three. The reply never shows the draft: the manager sees the rota that passed.

Output

Rota, week of 9 November

MonTueWedThuFriSat
Amiraopen 06:30–14:30 (keys)open (keys)open (keys)open (keys)open (keys)
Benclose 14:00–21:00openopen
Chloeclose (keys)close (keys)close (keys)open (keys)
Devclosecloseclose (keys)close (keys)close (keys)
Emaclosecloseclose
Fayopenopenopenopen

Checked: every shift has a keyholder and a barista, and nobody is under 11 hours' rest, over their hours, on a day they can't work or more than 5 days in a row.

Hours: Amira 40 (contracted 37.5), Ben 23 (24), Chloe 29 (30), Dev 35 (37.5), Ema 21 (20), Fay 32 (30). Amira is at her 40-hour maximum, 2.5 over contract, because only three people hold keys and twelve shifts need one. A fourth keyholder would let her drop a shift.

Rules used, as you gave them: 11 hours between shifts, 5 days in a row. Assumed: at most 12 hours in a day.

The week grid is saved as rota-week-of-2026-11-09.svg, and the rota as roster.json, both in the working folder.

Why this is the oracle

  • The check passes before the rota is shown. The draft was covered, and still broke rest and a maximum. A glance at a grid doesn't show a 21:00 close followed by a 06:30 open.
  • Skills are matched, not heads counted. Every shift's keyholder is one of the three keyholders. Two baristas on an opening shift would look covered and be short.
  • The fix is the smallest change, one shift moved to the person with room in their week, and the reply explains the one hours figure over contract.

A cheaper pass fills the grid evenly, says it "looks balanced", and publishes the draft: Ben opens nine and a half hours after closing, and works six hours over his maximum.

The checked week

How it's checked

Admitted against plain Claude Code, on its third draft: on held-out evals written blind from its description, two judges preferred it in 2 of 4 and 2 of 4 pairs, and it met 100% of their checks, against 100% without it (RFC-0076). How skills are checked

70 assertions across 9 acceptance evals, and 9 trigger queries. Every skill's checks

What the output must do
  • Leads with the rota as a readable table of days and people (or shifts), not with a description of how it was made
  • Every Day and Evening shift on all seven days has one nurse and one healthcare assistant, or the reply names the shift it couldn't cover and why
  • Nobody is rostered on a day they can't work (Kwame at weekends, Lin on Monday, Owen on Thursday, Sofia on Wednesday, Priti on Friday evening)
  • No one gets less than 11 hours between an Evening shift ending at 22:00 and a Day shift starting at 07:30 the next morning
  • Nobody is over their maximum hours, and hours per person are shown against contracted hours
  • States any rule it assumed that the request didn't give, such as the days-in-a-row limit, with its value
  • Saves the week drawing in the working directory, not inside the skill's folder
  • Does not mention a script, a JSON file or the skill's name in the reply
  • Flags every short rest, 8 hours each: Priya Shah from Tuesday's late to Wednesday's early and from Thursday's late to Friday's early, and Tom Okafor from Wednesday's late to Thursday's early
  • Flags Tom Okafor on two overlapping Thursday shifts (Early 06:00-14:00 and Mid 10:00-18:00), and 40 hours against his 30-hour maximum
  • Flags Sam Reid filling the pharmacist role on Friday's early shift without being a pharmacist, leaving the shift without one
  • Gives each problem one line with a suggested fix, such as Nadia Haddad, who is free, taking Friday's early pharmacist shift
  • Does not rewrite or return a changed rota, since the person asked only for a check
  • Does not invent rules, staff or shifts that aren't in the files
  • Does not mention a script, a JSON file or the skill's name in the reply
  • Works out that two forklift drivers on five nights is 80 forklift hours, and Gus (40) and Hana (32) can give only 72
  • Says plainly that the week can't be fully covered with the forklift need, rather than publishing a rota that breaks a rule
  • Names the smallest change that would fix it, such as one more forklift-trained person or one night with a single driver agreed
  • Covers every picker need on all five nights
  • Gives the closest rota only if it is clearly marked with the one night that is short
  • Keeps everyone within 5 nights in a row and their maximum hours
  • Does not invent extra staff or change anyone's maximum hours
  • Builds the rota, runs the roster check script on it, and presents a rota only after a run with no failures
  • Fills all 35 shifts at the headcounts in the table (81 person-shifts in total), with only chefs in the kitchen shifts and only bar-trained staff (Rory Byrne, Mei Tan, Priya Nair, Alex Duarte, Grace Holloway) on the bar
  • Has a keyholder on every 08:00 AM Kitchen and every Bar shift: Marta Kowalczyk opens Monday (Joel Adeyemi would be on his 6th day in a row), Joel opens Saturday and Sunday (Marta is on holiday), Rory closes Monday and Tuesday (Grace unavailable) and Grace closes Wednesday (Rory unavailable); Dani Okafor is never put on the bar
  • Applies last week's carry-over: Joel and Imani Clarke are not rostered on Monday (it would be a 6th consecutive day), and neither Priya (closed the bar at midnight Sunday, 10 h rest) nor Luca Ferri (PM Floor to 23:30 Sunday, 10.5 h rest) is on Monday's 10:00 AM Floor
  • Leaves nobody with less than 11 hours between shifts within the week: no PM Floor (ends 23:30) or Bar (ends 00:00) followed by a next-day AM Floor (10:00), and no PM Kitchen (ends 23:00) followed by a next-day AM Kitchen (08:00)
  • Keeps everyone within their max hours, one shift a day, and no more than 5 days in a row, and never on a day marked Unavailable, Holiday or outside an AM-only / PM-only limit; Ellis Grant (17) gets only AM Floor shifts and at most two of them (16 h max), and Sana Iqbal at most two (16 h max)
  • Shows the result as a week grid (people or shifts by day, Mon 16 to Sun 22) with each person's weekly hours
  • Does not invent staff, agency cover, extra shifts or rules that are not in the export, the notes or the prompt
  • Runs the roster check script on the draft as supplied and reports what it fails before changing anything
  • Finds Owen Price double-booked on Sat 21/11, on both the Early (06:00-14:00) and the Mid (10:00-18:00)
  • Finds Ben Ashworth on the Late on Tue 24/11 (ends 22:00) and the Early on Wed 25/11 (starts 06:00): 8 hours' rest against the 11-hour rule
  • Finds Yasmin Khoury on 32 hours in week 2 (Mon 23 Early, Tue 24 Late, Wed 25 Late, Fri 27 Early) against her 24-hour contract
  • Says the Sun 29/11 Early has no FLT driver and none can be rostered: all four licence holders are out (Wojciech Nowak and Callum Reid on holiday, Abena Mensah does no Sundays, Delphine Moreau at a wedding); it leaves this as an open gap for the manager to decide (for example outside cover or moving the work) rather than rostering a licence holder who is on leave or calling it fixed
  • Does not flag correct entries as errors: Megan Doyle's six days in a row (Thu 19 to Tue 24) are within the limit, Late Friday into Mid Saturday (12 hours, Megan on 20-21/11 and Harpreet Gill on 27-28/11) is legal, and people at exactly their contracted hours are not over
  • Fixes the three fixable problems with named replacements who are available, keep each shift's headcount and FLT/first-aid cover, and break no other rule, then re-runs the check so only the Sunday 29 FLT gap remains
  • Does not invent staff, agency workers, licences or leave that are not in the two files
  • Fills all 24 shifts in rota_template.csv to the headcount asked (3 on each weekday Early and Late, 2 on each Saturday and Sunday, 68 places in all), and every shift has at least one team leader on it (Bethan Morgan, Dariusz Kowal or Amara Osei)
  • Every weekday Late and both Saturday shifts have at least one Welsh speaker (Bethan Morgan, Rhys Llewellyn or Catrin Hughes)
  • Keeps to the availability notes: Jade Whitlock only on Earlies or Sundays, Catrin Hughes never on a Tuesday or Thursday, Lewis Grant only on Friday Lates and weekends, Megan Doyle not on 25-27 Nov, Kwame Mensah never on a Sunday, Priya Nair not on a Monday Late, Rhys Llewellyn not on the Wed 18 Nov Early, Sofia Marchetti not on Fri 20 Nov, Amara Osei never on a Wednesday, and Dariusz Kowal never on a Wednesday Late
  • Nobody does a Late (ends 21:30) followed by the next day's Early (starts 07:30), which would leave only 10 hours' rest, and nobody has two shifts on one day
  • Nobody goes over their contracted hours in either Mon-Sun week (for example Amara Osei, Catrin Hughes and Jade Whitlock 24h at most, Lewis Grant 16h at most, Priya Nair 32h at most), and the weekly hours on the grid match the shifts given
  • Nobody works more than 5 days in a row, counting 14-15 Nov for Bethan Morgan, Tom Ashdown and Lewis Grant (so none of them works every day from Mon 16 to Thu 19 Nov) and counting across the weekend between the two weeks
  • Returns rota_template.csv filled in with its columns unchanged, plus a grid for each week with one row per person and their weekly hours
  • Does not roster Gareth Penry, who is a Welsh-speaking team leader but is marked as a Leaver (31/10/2026) in the export, and does not invent staff, agency cover or overtime that is not in the input
  • Flags that Ola Adebayo is down for both the Wed 2 Dec Early HCA shift (07:30-15:30) and the Wed phlebotomy clinic (08:00-12:00), and fixes it by giving the clinic to someone with phlebotomy who is free that morning (Nadia Fern, who does only the phlebotomy clinic and has hours to spare, fits)
  • Flags that Gwen Pryce has the Thu 3 Dec Late (ends 21:00) and then the Fri 4 Dec Early (starts 07:30), only 10.5 hours' rest, and fixes it without creating a new breach (for example Joel Ambrose or Lena Varga takes the Thursday Late, or Gwen and Marek Novak swap Friday shifts)
  • Flags that Hannah Brook is rostered 32 hours (Early Reception Mon to Thu) on a 24-hour contract, and moves one of those shifts to a receptionist who has spare hours and enough rest (Callum Reid on Thursday or Priti Desai on Monday or Tuesday work; Priti on Thursday does not, as she is on the Wednesday Late)
  • Flags that the Sat 5 Dec Minor Injuries prescriber slot has Fran Teale, who is not a prescriber, and says it cannot be filled from this staff list: the only prescribers are Joel Ambrose (Mon-Fri contract) and Lena Varga (on leave 4-6 Dec). It is left as a gap for the manager to decide on, not shown as fixed
  • Raises no false alarms: Gwen Pryce's five days in a row at exactly 40 hours, Aisha Rahman's Thursday Late followed by the Friday 08:00 phlebotomy clinic (exactly 11 hours), and Marek Novak's Friday Late followed by Saturday are all reported as fine or not raised
  • Returns rota_wc_30nov.csv in the same columns with only the rows that need to change altered and the changes marked, plus a list of who to tell, covering each person whose shifts changed
  • The returned rota, checked again, has no double-bookings, no rest gaps under 11 hours, nobody over contract and nobody past 5 days in a row, and the Saturday prescriber gap is the only problem left
  • Does not invent a bank or locum prescriber, or any member of staff who is not in staff_list.csv
  • Fills all 170 shift places implied by cover_requirements.csv for the fortnight (e.g. 3 lifeguards on every weekday early and late, 4 on every weekend AM and PM, 3 swim teachers on both Saturdays) with no place left empty
  • Every duty manager shift goes to one of the five staff holding the Duty Manager qualification (Fenella Orchard, Kwame Asante-Byrne, Marisol Penhale, Rhiannon Tull, Tadeusz Wren), every pool lifeguard place to an NPLQ holder, and every swim-lesson place to a Swim Teacher L2 holder
  • Nobody exceeds their contracted hours in either week: for example, the 16-hour casual lifeguards (Rory Venn, Theo Blackwood, Owen Garside) and Ifeoma Barrett (10 hours) stay at or under their totals
  • Nobody works a weekday Late lifeguard shift (ends 22:15) followed by a weekday Early (starts 06:00 or 06:15) the next day, and nobody goes from a Friday late (ends 22:00 or 22:15) to a Saturday AM shift (at most 9.75 hours' rest), since both break the 11-hour rest rule
  • Respects the availability form: no Rhiannon Tull shifts 30 Nov - 2 Dec, no Callum Feeney shifts 4 - 6 Dec, no weekday shifts starting before 15:00 for the casual lifeguards, Nikhil Rao only on Tuesdays, Thursdays and Saturdays, and no Sunday shifts for Fenella Orchard or Siobhan Daley
  • Nobody is given two shifts on the same day or more than 6 consecutive days
  • Presents the result as a week-by-week grid (one for each week) of staff against days that can be pinned up, and reports a check of the finished rota against the rules rather than just asserting it is fine
  • Does not invent staff, agency or relief workers not in staff_export.csv, and does not give anyone a qualification they do not hold in the export
  • Catches that Bronwen Tilsley is booked on both the Tue 08 Dec Early and the Late shift the same day (they overlap 14:00-14:30) and gives one of the two rows to someone else
  • Catches that Ravi Chaudhry works Fri 11 Dec Late (finishes 21:30) and then Sat 12 Dec Early (starts 07:00) - only 9.5 hours' rest - and fixes it
  • Catches that the Senior Carer on Thu 10 Dec Late is Bilal Qureshi, a Care Assistant who is not medication trained, and replaces them with a medication-trained senior
  • Catches that Patrice Delacroix is rostered for 25.5 hours against a 22.5-hour contract and brings them back within it
  • Flags the Sunday 13 Dec Night senior slot as one that cannot be covered from the staff list: Adaeze Moorcroft is on approved leave, Philippa Strand and Godfrey Achterberg are days only, Rosalind Ebo can't do Sunday nights, Declan Furness is on leave and Yasmin Okonedo-Hart can't do Sundays - and it does not leave Adaeze on it or put a non-medication-trained carer in the senior role
  • Every replacement it makes is itself legal: qualified, available per leave_and_restrictions.txt, within contracted hours, with 11 hours' rest either side and no second shift that day
  • Returns the rota in the same columns and row layout as rota_export_07-13Dec.csv (Date, Day, Shift, Start, End, Role, Staff ID, Staff Name), changing only the rows that needed fixing and listing each change
  • Does not invent agency or bank staff, names or staff IDs that are not in staff_list.csv to fill the Sunday night gap
When it should and shouldn't activate

Should activate:

  • make next week's rota for the shop, here's who's available
  • check this staff rota before I publish it
  • who should work which shift this weekend? we need two baristas and a keyholder each day
  • fill these night shifts for the warehouse team without breaking the 11-hour rest rule
  • build a fortnight schedule for our clinic nurses

Should leave to another skill:

  • write the weekly status update for the ops team
  • model how much our cloud capacity will cost next quarter
  • write a job ad for a shift supervisor
  • plan the sprint and assign stories to engineers

Source

SKILL.md · the whole folder on GitHub.