i2y/ritsu/koyomi

Claude Code and agent skill by i2y/ritsu

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Write, check and compile koyomi files (`.cal`), the rules of due dates — closing days, payment days, business days and month arithmetic, such as closing on the 20th and paying on the 10th of the next month or on the business day before when that is a holiday — with calendars of closed days read from published tables of holidays, claims checked on every day of a declared range, and code generated for TypeScript, Python, Go, Rust, PostgreSQL and Wasm. Use when payment terms, a deadline or a calendar of business days has to be written or changed as a `.cal`; when a koyomi diagnostic (E001-E305, W001-W202, W901) has to be fixed; when such a rule has to be shown to the people who read it; or when its generated code has to be called.

Install

npx vskill@latest install i2y/ritsu/koyomi

SKILL.md

When this applies

The job is a rule of dates: a date computed from another by closing, adding days, business days or months, taking a day of a month, and moving off closed days. Payment terms ("closes on the 20th, pays on the 10th of the next month, on the business day before when that day is closed"), Net 30, a deadline counted in business days, the end of a period under a statute. koyomi writes it once as a .cal, checks it on every input of a range, shows it to the people who read it, and generates the same function for five languages and a Wasm module.

It does not apply to decisions made from tables of conditions (a fee schedule, an eligibility test): those are rulec rules. Nor to times of day in a zone with daylight saving time: koyomi gives dates, and times only at a fixed UTC offset.

The files bundled with this skill are listed in §7. Read them when you need them, not all up front.


Working with koyomi

Your part is to write the .cal, get it past ritsu koyomi check, show it to a person, and generate the code. Two things stay with people:

  • what the terms and the calendar are: which days are closed, which table of holidays, what a

contract means by a day the month does not have, how a law is read. §3 says when to ask.

  • the code around the generated functions: where they are called, what an input outside the

range means for the caller.

Run every command here as ritsu koyomi <command> (through a link to ritsu named koyomi, koyomi <command> is the same). Everything is reachable from the command line: ritsu koyomi --help lists the commands, ritsu koyomi explain <CODE> explains a diagnostic, and ritsu koyomi check --format json gives the diagnostics as data (§5). There is no step where you have to read koyomi's source.

1. The loop

  1. Find the rule. What is the input date (the invoice, the receipt, the start of a period),

what dates come from it, which days are closed, and what must hold (a business day, no later than so many days, never earlier for a later input). Settle the range of the input with a person: every input in it will be computed.

  1. Write the calendar, or use one (use calendar "calendars/<file>.cal"): closed days of the

week, days every year, a table of holidays pinned by its digest, given days, open days. ritsu koyomi source fetch takes a table from its url, and ritsu koyomi source pin writes its digest.

  1. Write the dates file (§2): inputs, the dates, one operation a line, claims, examples.
  2. Check it: ritsu koyomi check <file.cal>. A diagnostic comes with the input that gets there and

its computation, step by step; fix it (§4; ritsu koyomi explain <CODE> explains one code) and check again, until it prints <file.cal>: ok — …. A warning does not stop anything, but it says something true.

  1. Look at one input: ritsu koyomi eval <file.cal> <input>=<date> prints every date of that input,

a step a line, and what each claim says of it.

  1. Show it to a person: ritsu koyomi doc <file.cal> > <file>.md (or --format html) writes the page

for people, for those who read the terms: every operation in words beside its line, the claims and their least room, the edge cases, the months with the holidays named and the failing input days marked. A file whose claims fail still gets its page; the failing days are the point of it.

  1. Generate the code: ritsu koyomi gen <file.cal> --target typescript --out generated writes the

TypeScript; give --target once for each language used (typescript, python, go, rust, sql, wasm), and --extra runner for the runners. With no --target it writes nothing (exit 2). A target a W001 names stops it with nothing written (E016). ritsu koyomi gen with the same --target and --check in CI says when the code is stale. ritsu koyomi api <file.cal> gives the functions, their inputs and ranges, and the signatures in each language, without reading the code. generated-code.md says how to call it.

  1. In a project with rules or workflows, ritsu check checks the .cal files with the rest,

and across them: a rule input can take a date's days as its range (range from koyomi), and where a workflow calls a date or gives its day to a rule, the days are held to the ranges (ritsu's E202 and E205; the ritsu skill has them).

  1. When a calendar or a dates file changes, ritsu koyomi diff <old> <new> says what the change

moves: for a calendar, every day both versions know whose answer changed (open or closed, or closed for another reason), and for a dates file, every input both take whose dates moved, with how far. Each side is a path, <path>@<git revision> (on a pull request, calendars/office.cal@origin/main), @<name>/<path> (a dependency at the lock's version) or @<name>@<version>/<path> (a version in the store). It exits 1 when something differs, and 2 when the two cannot be compared (a calendar and a dates file, or a side that does not pass check). Show what it says to the people who read the terms, as you show the page.

2. The language on one page

A whole dates file, from the examples:

cal
dates close_20th_pay_10th v1
description "Closes on the 20th; pays on the 10th of the next month, or on the business day before when that day is closed in England and Wales. The claim within_60_days_of_receipt is this example's own, written as it reads; it does not say how any law is read"
use calendar "calendars/england_and_wales.cal"
inputs
received : date range >=2026-01-01 <=2028-11-20
date closing = received
close day 20 # "closes on the 20th"
date payment = closing
day 10 of month +1 # "pays on the 10th of the next month"
roll preceding # "on the business day before when that day is closed"
claims
paid_on_a_business_day : payment is open
within_60_days_of_receipt : payment <= received + 60 days
later_receipt_later_payment : payment is monotonic
examples
| received | -> closing | -> payment |
| 2026-04-01 | 2026-04-20 | 2026-05-08 |
| 2026-12-21 | 2027-01-20 | 2027-02-10 |

And the calendar it reads:

cal
calendar england_and_wales v1
description "Saturdays, Sundays and the bank holidays of England and Wales, as GOV.UK lists them. No offset: England and Wales has daylight saving time, so this calendar gives dates only"
source bank_holidays = file "data/bank-holidays.json" url "https://www.gov.uk/bank-holidays.json" sha256:538b3482c28b85ec
format govuk "england-and-wales"
covers listed years
closed weekly sat, sun
closed bank_holidays

A calendar for a place that changes its clocks has no offset, so dates on it have no time. The examples written for Japan read Tokyo's business days, which keep +09:00 and so let a date say at 09:00; each of them is there in English and in Japanese (<name>.cal and <name>.ja.cal, the same terms with the same results), since a name of a file, an input or a date can be written in any script, with an ASCII alias for the generated code (受領日(received)).

else says what happens on a day the month does not have: else end_of_month (the last day of that month), else start_of_next_month (the first of the next), or else reject (the check makes sure no input of the range gets there, E202). There is no default (E201).

Claims
text
X is open X is a business day
A <= B + 60 days =, <, <=, >, >=; either side may add or take days or business days
X is monotonic a later input never gives an earlier X

reference.md has the whole language: calendars, tables of holidays, laws and their citations (@民法 第143条), the meaning of every operation, the commands and the formats.

3. What stays with a person

Ask instead of guessing:

  • Which days are closed. Which calendar applies (a company's, a bank's, the days a statute

names), and which table of holidays, from where. A table knows a span of years (covers); past it, nothing can be computed (E203). Say so, with the date the check gives, rather than widening the table.

  • What a day the month does not have means. The 31st in a month of 30, the 29th of February:

the end of the month, the first of the next, or never. It is in the contract, or it is not, and then a person decides. A law can decide it too (the Japanese Civil Code, Article 143).

  • How a law is read. koyomi writes what a person reads the law as, and cites the article; it

does not read the law. When an article can be read two ways (the "next day" of Article 142: the day after, or the next business day), write both as dates, claim they are equal, and show the person the days they part on.

  • The range and the numbers: the inputs' ranges, the days a claim allows, the time of day.
  • What a failing claim means. A claim that fails on 648 of 669 days may mean the terms are

wrong, or the claim is; that is a business decision, not a fix.

Ask with the input the check gives, in the reader's terms: "Received on 2026-05-01, the payment falls on 2026-07-31, 91 days later. The claim allows 60. Are the terms or the claim wrong?" The page ritsu koyomi doc writes shows the same days on a calendar, when a person would rather see them.

4. From a diagnostic to a fix

A diagnostic names the code, the place, what is wrong, how to fix it, and the input that gets there:

text
error[E201]: tests/mutants/E201_no_way_for_a_missing_day.cal:7:3: `+ 1 month` can land on a day the month does not have, and the line does not say what to do then
7 | + 1 month
= For received 2026-01-29 it would be 2026-02-29
= To fix it, write one of: `+ 1 month else end_of_month` (giving 2026-02-28), `+ 1 month else start_of_next_month` (giving 2026-03-01), `+ 1 month else reject` (the check makes sure it never happens in the range)
the input that gets there:
received 2026-01-29 Thu
month_later + 1 month: 2026-02-29 does not exist

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
0

Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/i2y/ritsu/koyomi/badge)](https://verified-skill.com/skills/i2y/ritsu/koyomi)

Something wrong with this skill or its page? Tell us.