karasu is a text modeling language for system architecture, inspired by the C4 model.
You describe your system in .krs files and karasu draws the views: system, deployment, and team structure.
I haven't written its code by hand; everything goes through Claude Code.

This is the sixth weekly update.
It covers changes merged from November 8 to 13.
Starting this week the update comes out on Saturday instead of Sunday, so this one covers six days instead of seven.

This week in numbers: 72 PRs merged (14 of them Dependabot) and 9 decisions recorded as ADRs.
All 9 ADRs came in ADR-only PRs.
No monthly release this week.
On November 11 the second weekly prerelease of the Visual Studio Code extension came out (0.5.2026111101).

What I learned building with agents this week

This week I changed how PRs get merged, in two places.
For Low PRs, whose diffs I don't read, the merge moved from the Claude session to a GitHub workflow.
For High PRs, which I do read, the checks before I merge became a skill.

Take the merge out of the agent's session

karasu sorts each PR into one of four risk tiers by the paths it changes.
The lowest tier, Low, covers PRs like ADR-only changes and the regenerated ADR index, and I merge them without reading the diff.
Until now, the Claude session that opened the PR ran gh pr merge --auto and left the merge to GitHub's auto-merge.

That had two problems.
The first is that the merge depended on the session.
In my local session records, 3 out of 128 --auto calls were denied by Claude Code's auto mode classifier.
When a call is denied or the session stops, the merge stops too.
One PR took about 7 hours to merge.
The second is that GitHub's auto-merge doesn't wait for the check that decides the tier (Review tier).
One PR merged 16 seconds after that check failed.

Now a workflow handles Low PRs in two jobs.
The judge job has read-only permissions and runs the tier script from main against the PR's head commit.
It doesn't put the PR's files on disk or run the PR's code.
Only the merge job holds a GitHub App key, and it merges with the commit it judged pinned.
The key lives in an environment that only workflows running from main can use.

This adds a key.
The previous design counted needing no new key as one of its reasons.
A leaked key could merge any PR that passes CI, not only Low ones.
I accepted that and created the GitHub App.
The workflow checks the conditions for merging, not whether the change is good.
The local review record is still self-reported by the agent.

The move is split into three stages.
In the first stage, the workflow only judges the open Low PRs and writes down the verdicts.
It merges and comments on nothing; the session's --auto still does the merging.
The PR for that stage ran the same judge script from my machine against real PRs.
It said "wait" while the required checks were running and "merge" once they finished.
In the second stage, the workflow merges according to its verdicts.
In the last stage, --auto comes out of the session's procedure and auto-merge gets turned off for the repository.

On November 13 the workflow merged a PR for the first time.
The first run failed because the private key I had registered in the environment couldn't be read.
After I registered the key again and re-ran it, it merged as low-pr-merger[bot].
Once five PRs in a row merge through the workflow alone, the last stage starts.

When a procedure keeps growing cases, make it a script

In the second stage, sessions were still running --auto.
Then GitHub's auto-merge merged a few seconds after the last required check passed, and the workflow never got its turn.
So I wrote a procedure into the session rules: leave Low PRs to the workflow and wait.
The first version was prose, and every review round found a gap in it.
There were too many cases.
The session has to decide whether to turn off auto-merge, fix a rejected PR, or re-run a stuck check.
If nothing moves for 30 minutes, it goes back to --auto.
In the end the waiting went into a tested script, and the rule kept only the command and a table of what to do for each outcome.

Last week's block on gh pr ready went the same way: listing the loopholes from the command string never ended.
This week the cases couldn't be written out in prose either, and things settled once they became a script that runs.
Next time I write a procedure for sessions, if it has many cases, I'll first ask whether it can be a script from the start.

Let a skill do the checks before I merge, and record videos

I still read and merge High PRs myself.
Before merging, I read the PR description, check CodeRabbit's findings and CI, and open the preview to try the acceptance items by hand.
The descriptions are long and in English.
Trying app changes by hand took the most time.

/pr-verify <PR number> is a skill that takes over the mechanical part:

  • If there is an unresolved CodeRabbit finding, a failed required check, or a conflict with the base, it stops there and writes a request in English to paste into the session that implemented the PR.
  • Otherwise it summarizes the PR, and the points that need my decision, in Japanese.
  • For a PR that changes acceptance tests or e2e tests, it drives the preview with Playwright, takes screenshots of the items to check by hand, records videos of the changed e2e tests, and publishes a report page.
  • It ends with an opinion on whether to merge. It merges only when I say OK in the session.

On the skill's own PR, three rounds of agent review plus CodeRabbit raised 41 findings.
The ones that stood out were gaps where a failed read from GitHub, or a check with no result yet, came out as "go ahead".
Now a failed read counts as "stop" or "wait".
It merges with --match-head-commit, so a push after the check makes the merge fail.
I evaluated the skill with skill-creator on three PRs.
With the skill, 97% of the assertions passed; without it, 87%.

Since it merged, I've been using it on High PRs.
The report puts the points that need my decision first, so I can spend my attention on what I actually need to check.
Recording the behavior checks as Playwright videos turned out well too.
In the videos, it's easier to spot what the agent probably didn't check.
A passing test doesn't tell you which parts of the screen it never looked at.
I think a video helps because it also shows the parts the test doesn't look at.

PRs by tier

Of the 72 PRs merged this week, 42 were High (14 of them Dependabot), 10 Design, 7 Medium and 13 Low.
73 PRs were closed; the one that wasn't merged was a spike for an experiment.
I merged the 13 Low PRs without reading their diffs, an auto-merge rate of 18% (24% last week).
They were 9 ADR PRs, 2 regenerations of the ADR and TPL indices, and 2 cleanups of TPL documents.

Getting ready for teams to try karasu: a payroll subject, a session script, and a feedback form

Last week's "coming next" mentioned a PR that walks the guide on a second subject. It has merged.
The "Design a service split" guide on karasu.kompiro.dev walks you through splitting an online shop into services in five steps.
On its first step you can now switch to doing the same five steps on a payroll system, and switch back.
Going back and forth reuses a copy you haven't edited, so it doesn't pile up projects.

Whether to add this subject at all was my call at the design stage.
Adding it means a sample, its text, a gallery page, and two new public constants in @karasu-tools/core.
Removing a public constant later is a breaking change.
The app has no usage tracking, so nothing will tell me whether anyone uses it.
The design doc recommended adding it because the first-run requirements document lists a second subject.
I went with adding it.

The first-run work is split into phases, and this PR finished the work of the second.
The third is about finding out, with real teams, whether looking at one shared model as a team is worth it.
This week two things went in to prepare for that.

A script for a 60-minute karasu trial session with a team.
It is in the guides on the docs site, in English and Japanese.
The session has three parts:

  1. Each participant walks the "Design a service split" guide in a private browser window.
  2. The team looks at a model of its own system. Before looking, they predict how the parts connect, then look and talk.
  3. A retrospective.

The agent drafted the Japanese version first and I revised it with it.
The revisions: fewer parts with room to spare, a short survey afterwards instead of an interview during the session, and a retrospective at the end.
The survey is four questions the same day and two more two weeks later.

A place for feedback, in GitHub Discussions.
It's a category called Feedback, and a new post there comes with a form.
The last step of every guide on karasu.kompiro.dev links to it ("Tell us what you thought ↗").
That is the only place in the app with this link.

The form starts with a warning and a required checkbox, so that nobody pastes a share link to a model of a non-public system.
A karasu share link carries the whole model after the # in the URL.
Browsers don't send that part to karasu's server, so the model isn't stored there.
But anyone who has the link can see the model.

I'm looking for teams to try it.
You don't need to follow the script.
If you walk one guide and tell me in Feedback where you got stuck, and whether your team could use karasu (or why not), that already helps a lot.
For now the script assumes Chrome or Edge.
In a private window of another browser, the app may fail because it can't use the browser storage it saves files to, and I haven't checked that yet.

Other changes this week

Fixed several cases where karasu misread the model you wrote.

  • With two edges whose node names contain ->, such as a -> "b->c" and "a->b" -> c, the color and direction of the edge written later applied to both. The key that told edges apart was the endpoints joined as plain text. The released 0.10.0 has this bug.
  • With both x -> y and x -> "y#sync", color rules and direction: up applied to both edges or to neither, depending on the order you wrote them. No diagnostic said so.
  • When the line after an edge started with an edge whose source name was quoted, that name was read as the label of the edge on the previous line. Inside a node block, this produced a wrong label and an edge you never wrote, with no error.
  • When two files @imported the same style sheet, karasu reported a circular import. A .krs file in a subdirectory had its @import resolved from the entry file's directory instead of its own.

All of these should reach the stable CLI and Visual Studio Code extension on the next monthly train (planned for November 29).

Diagnostics now have short IDs.
Every diagnostic has an ID from KRS001 to KRS114, and the CLI prints it like Warning[KRS041]: ....
karasu check --format json gives scripts and agents the same findings as JSON.
The skills in karasu-skills used to grep the diagnostic messages to decide whether a model was broken.
The messages are translated, so the grep could find nothing, and a broken model could pass the point where a skill should stop.
They now decide by the code in the JSON.
Showing the IDs in the app and the Visual Studio Code extension comes next.

Redaction in karasu-nest could get extremely slow on some inputs.
karasu-nest is a gallery where you can post and publish a .krs you generated from your own repository.
Every post is checked for secrets such as passwords and keys.
Three of those patterns took time proportional to the square of the input length.
On a 1 MiB input on Node.js 24 on my machine, the connection-string password check took 277 seconds; after the fix, the whole check takes 260 milliseconds.
On Cloudflare Workers each request is limited to 5 seconds of CPU time, and I haven't seen a request killed in production.

Decided on a design that puts my approval before anything reaches npm.
karasu ships three packages on npm.
Today the release workflow publishes straight to latest.
That will move to staged publishing, which npm made generally available in May.
CI only puts versions into an approval queue, and I approve them after comparing them against a build on my machine.
The security review of the implementation found that the queue doesn't show a version's manifest (what package.json becomes on npm).
So the design was revised before the implementation merged.
The job that installs dependencies and builds is split from the job that holds the npm token and stages the versions.
The implementation will be redone on the revised design.

Dependencies.
The 14 Dependabot PRs were triaged together and merged.
No new packages came in, and there were no known vulnerability advisories.

Coming next

  • Redo the staged publishing implementation on the revised design, and rehearse it again.
  • See whether five Low PRs in a row merge through the workflow alone. If they do, take --auto out of the session's procedure.
  • Show diagnostic IDs in the app and the Visual Studio Code extension too.
  • The next monthly train is planned for November 29. This week's fixes and the diagnostic IDs should reach the stable CLI and Visual Studio Code extension on it.