Summary#
osy clock advance 1d moves the app on your local platform one day ahead. Everything that asks the time follows:
a function's DateTime.UtcNow, the instant a query compares against, the CreatedAt a new row is stamped with, and the
time a workflow arms its reminders, deadlines and expiries from. Whatever the move made due is woken at once, so a
48-hour expiry fires the moment the clock passes it.
It is the clock a test moves with TestClock.Advance, put on the app you are clicking
through instead of on a test's throwaway copy.
Signature#
osy clock # where the app's clock stands
osy clock advance <span> # 30m · 2h · 1d · 1w — and -1d to go back
osy clock set <instant> # 2026-11-03T09:00, read as UTC — or with its offset, 2026-11-03T09:00+01:00
osy clock reset # back to the machine's time--json prints { now, offsetSeconds, moved, description, woke }. --path and --devname pick the project and the
instance as every local verb does.
Description#
What moves#
The app's own reads of the time, on the server and in the browser:
| reads the moved clock | |
|---|---|
| a function body, a page action, a workflow body | DateTime.UtcNow, DateTime.Today, DateTime.Now |
| a query | the instant Where(o => o.Due < DateTime.UtcNow) compares against |
| a write | CreatedAt / ModifiedAt, and any field defaulted to DateTime.UtcNow |
| a workflow | when a reminder, a deadline or an Expire is armed — and when it falls due |
| a schedule | when its next occurrence is due |
| the page | its Now and DateTime.UtcNow, once you reload it |
What does not move is the platform's own bookkeeping about the machine — the sign-in that osy and the dev page
hold keeps working across a move, so you can advance two days and go on querying the app.
It runs#
The clock keeps going from wherever you put it: set 2026-11-03T09:00 and a minute later the app reads 09:01. A move
is an offset from the machine's time, and osy clock shows how far ahead (or behind) it is. reset puts it back.
What a move wakes#
A move wakes the app's timer sweep and its schedule sweep straight away — the same two the platform runs when a
reminder or an occurrence falls due on its own — so anything the jump made due fires within a moment. Read the outcome
the way you read anything else on the app, with osy query or the page.
using Osysharp.Workflow;
enum TicketStatus { Open, TimedOut }
entity Ticket {
[Required, MaxLength(100)] string Title;
TicketStatus Status;
security { allow read, create, update when IsAnonymous || IsAuthenticated; }
}
workflow TicketFlow {
Tracks = Ticket.Status; Autostart = true; Initial = Open;
state Open {
Expire = TimeSpan.FromHours(48);
on Expire { goto TimedOut; }
}
terminal success TimedOut { }
}
void OpenOne() { new Ticket { Title = "Leaking tap" }; UnitOfWork.Commit(); }osy run OpenOne
osy query 'Ticket.Count(t => t.Status == TicketStatus.TimedOut)' # 0 — it is due in two days
osy clock advance 49h
osy query 'Ticket.Count(t => t.Status == TicketStatus.TimedOut)' # 1 — the move made it due, and it fired
osy clock resetA move only ever goes forward through what is due: moving the clock BACK does not un-fire a reminder that already ran.
On the dev page#
osy launch --dev opens the app's dev page, whose Clock section shows the app's time
and moves it — +1 hour, +1 day, +7 days, a date and time to set, and Back to the machine's time once it
has moved. It is the same clock osy clock moves. Reload the app's own tab afterwards to see the new time there.
Only on a local platform#
The clock exists only on a platform osyrin dev started for you — osy launch, osy compile, osy test and the
rest start one on demand. A deployed app has no such clock and no way to be given one: osy clock refuses there, and
the dev page and its clock controls do not exist on any deployed host. A reminder in production falls due when its
time comes, and nothing an app or a visitor sends can change that.
Examples#
osy clock advance 1d # see tomorrow's reminders go out
osy clock set 2026-12-31T23:59 && osy clock advance 2m # step across the year's end
osy clock --json # { "now": "...", "offsetSeconds": 86400, "moved": true, ... }
osy clock resetSee also#
TestClock.Advance and TestClock.Set — the same clock inside a test, where TestClock.Set and TestClock.Advance move it.
Dev seeds: a fixture you can load into the running app — put the app in a known world first, then move its time.
Remind (milestone reminders) — the reminders a move makes due.