Routines on a clock
A routine is a Studio flow that reads a department drive. Give it a schedule and it leaves its answer as a file in that department's folder.
The box installs four routines into Studio — flows that read a department's drive and answer from it. You can run one by hand on the canvas, put it on a clock, or have it fire when a file lands in a folder.
./nufi-box flows list # what is installed
./nufi-box schedule list # what runs on a clock or a folder, and when each fires nextWriting a schedule
Schedules live in data/schedules.ini. The installer ships it with every
section commented out, so nothing runs until you say so — a box that starts
writing reports the day it is installed is a box nobody asked.
[legal-weekly]
cron = 0 17 * * 5
flow = Routine · weekly report from the drive
drive = legal
ask = 이번 주 주간보고 초안을 써줘.
out = weekly-report-{date}.md| Key | |
|---|---|
cron | five fields — minute, hour, day of month, month, day of week. *, numbers, a-b, a,b and */n. No @weekly aliases. |
flow | the routine's name, exactly as Studio shows it |
drive | which department drive it reads, and writes into |
ask | the question the routine is given |
out | the file name. {date} becomes the run's date; a name without it is overwritten each run. |
The file is re-read every twenty seconds, so adding a report needs no restart.
./nufi-box schedule listNAME WHEN DRIVE NEXT
legal-weekly 0 17 * * 5 legal 2026-09-18 17:00
-> legal/_routines/weekly-report-2026-09-18.mdThat comes from the same parser the scheduler uses, so it cannot disagree with what will actually happen. A section it cannot understand is reported and skipped — one typo does not stop the department's other reports.
…or when a file lands
A routine can also fire from a folder instead of a clock — a résumé dropped
into onboarding/new/ in HR's drive, and an HR policy routine answers from
that drive with the file's name in the question. watch only changes when
the routine runs; the routine itself still just answers ask from drive,
citing a policy file or saying plainly when the policy does not cover it. A
section has exactly one trigger, cron or watch; both or neither is
reported and dropped, the same as any other typo.
[hr-onboarding]
watch = onboarding/new
flow = Routine · HR helpdesk from the policy
drive = hr
ask = onboarding/new/{file} 에 새 입사자의 서류가 들어왔습니다. 규정에 따르면 신규 입사자에게 안내해야 할 절차를 알려줘.
out = onboarding-{file}-{date}.md| Key | |
|---|---|
watch | a folder relative to the drive — onboarding/new, not /onboarding/new, ../onboarding/new, or anything under _routines/. Names ONE folder, not a tree: a file inside a subfolder of it never fires. |
{file} in ask | the triggering file's full name, extension included — kim-minsu.pdf |
{file} in out | the triggering file's bare name without the extension — kim-minsu |
Two rules keep this from misfiring:
- A file has to sit still for two ticks in a row — same size, same modified time — before it fires. A copy still in progress, or a Samba write still landing, must not trigger a routine against a half-written file. At the default 20-second tick, that means a landed file fires 20–40 seconds after it stops changing, plus however long the run ahead of it takes — the box answers one question at a time.
- The first scan of a
watchfolder fires nothing. Everything already there is recorded as seen — the same "nothing is caught up" rule acronschedule follows. A folder with forty résumés in it already must not launch forty runs the moment the box comes up. Retargetingwatchordriveis treated the same way — nothing already in the new folder fires.
After a run — successful or not — the file is marked seen and does not fire
again on its own; a broken flow is not retried every twenty seconds. Editing
the file afterwards (a new modified time) makes it eligible again. Hidden
files, Office/Samba temp files (~$…, ~WRD….tmp, .~lock…), a download
still in flight (.tmp/.part/.crdownload/.partial), and
Thumbs.db/desktop.ini are never watched. A watch folder that does not
exist yet is not an error — it is logged once, and picked up as soon as
someone creates it on the share, even a file dropped in that same moment.
Where the answer goes
data/drives/legal/_routines/weekly-report-2026-09-18.mdInside the department's own shared folder, where people already look. No app to open.
Nothing under _routines/ is ever embedded back into the drive. Without
that rule last week's report becomes a source this week's is drafted from, and
the routine ends up citing itself a little more confidently each week. It is not
a hypothetical — it was watched happening on a box before the rule existed.
Limits worth knowing
- One at a time. A schedule still running when its next turn comes round is skipped and logged. The box answers one question at a time.
- No catching up. A box that was off over a scheduled minute has missed that report. Firing five hours of them at boot is worse than the gap.
- A run that overstays is cancelled, not merely abandoned — an abandoned run keeps generating with nobody listening and holds the box's only model against every other question. The deadline is fifteen minutes by default.
- Schedules belong to the box, not to a person. Routines are copied to each member's own Studio account, so a schedule attached to a member's copy would run once per member and write the same department report several times over.
./nufi-box logs nufi-cron # what happened when one ran