Article

Loops, Precisely: What to Automate, What to Queue, and What It Costs You

Author

Oleksandr Kotliarov

Date

July 22, 2026

Reading Time

19 min

A loop is worth building exactly where the work recurs on a schedule and a machine can tell you whether it worked. Everywhere else you are building a queue, not a loop — a machine that produces work items faster than your team can absorb them, and calls that progress.

That is the whole argument. The rest is the taxonomy, the evidence, and a setup you can run against your own repo this afternoon. The occasion is a fireside chat: Boris Cherny, head of Claude Code, at a Meta dev-infra event. His mental model is good and worth repeating. Source code is a statement. An agent writing the code is a function. A loop is a higher-order function. He puts loops roughly where agents were eighteen months ago — early, working in patches, about 30% of his code on an average day, by his own account. The step up is real.

It is also a vendor’s framing delivered from a stage, and what it leaves out is the condition under which the step pays. That condition is the difference between a loop that quietly removes a chore from your week and a loop that hands your senior engineers a pile of pull requests nobody has the hours to read.

The taxonomy, because “loops” is five things

Before any argument, separate what the word covers. In the talk, “loops” is an umbrella. In the product, it is five distinct primitives with different runtimes, lifetimes, and blast radii. Confusing them is how teams end up believing they have unattended automation when what they have is a terminal window that stops working when the laptop lid closes.

/loopCloud RoutinesDynamic workflowsAuto modeCo-work
What it isA bundled skill that re-fires a prompt on a timer inside an open sessionA saved config (prompt + repos + connectors) running on Anthropic’s infraA JS script Claude writes to orchestrate subagents at scaleA permission mode where a classifier adjudicates each actionClaude Code for non-engineers, VM-isolated
Runs onYour machine, session must be openAnthropic cloudYour session’s background runtimeN/A — not a runtimeLocal VM, or remote-execution beta
Survives a closed laptopNoYesNoN/AOnly in remote mode
Minimum interval1 minute1 hourOne-shot, not recurringN/AN/A
Invocation/loop [interval] [prompt]/schedule, or the routines UIultracode, or “use a workflow”claude --enable-auto-modeDesktop app
Expiry7 days, hard-codedNoneEnds with the runN/AN/A

/loop is not what people picture when they hear “the AI runs unattended.” Per Anthropic’s documentation on scheduled tasks, it fires only while the session is open and Claude Code is idle, and self-terminates after seven days regardless. /loop 5m check if the deployment finished gives a fixed interval; omit the interval and you get dynamic mode, where the model self-paces between one minute and one hour via a ScheduleWakeup tool and can end its own loop by calling it with stop: true. Bare /loop runs a built-in maintenance prompt you can override with a project-level .claude/loop.md. Underneath sit CronCreate / CronList / CronDelete, capped at 50 tasks per session. A good primitive for babysitting a PR while you work, but not standing infrastructure.

Cloud Routines is the actually-durable one. Anthropic’s routines documentation describes what /loop is usually mistaken for: a saved configuration running on Anthropic-managed infrastructure, surviving a closed laptop, minimum interval one hour, triggered by a schedule, an HTTP /fire endpoint with a bearer token, or GitHub events. Each run gets a fresh clone from the default branch and by default can only push to claude/-prefixed branches. Two facts deserve attention. A routine runs as a full autonomous cloud session with no permission-mode picker and no approval prompts during the run — bounded only by the repos you gave it, the network policy, and the connectors attached. And it is still labeled a research preview as of July 2026. Build on it accordingly.

Dynamic workflows are not a loop at all. They are a one-shot fan-out: Claude writes a JavaScript orchestration script that a separate runtime executes, holding the branching and intermediate results in script variables so Claude’s own context window only ever sees the final synthesis. This is what Boris calls “a new form of test time compute,” and the architecture is genuinely interesting. The workflows documentation supplies the numbers the marketing language (“dozens, hundreds, thousands of agents”) does not: 16 concurrent agents, 1,000 agents total per run, with a “large workflow” banner past 25 agents or 1.5M projected tokens that pauses nothing. One detail outweighs the rest for anyone reasoning about safety: the subagents a workflow spawns always run in acceptEdits, and their file edits are auto-approved. Your session’s permission mode gates the launch and nothing after it.

Auto mode is orthogonal to all three. It is a permission mode, not a schedule, and it exists because of a number Anthropic published in its engineering post on auto mode: users approve 93% of permission prompts by default. A gate that passes 93% of what reaches it is a formality. Anthropic’s argument is that routing the decision to a deliberately “reasoning-blind” two-stage classifier — one that strips assistant messages and tool outputs so the agent cannot argue its way past it with post-hoc justification — beats the rubber stamp. Three consecutive blocks or twenty total trips a circuit breaker back to interactive prompting.

Co-work is a separate product for non-engineers, built on the same Agent SDK but running inside a real virtual machine — Apple’s Virtualization framework on macOS, Host Compute Service on Windows. That is materially stronger isolation than Claude Code’s own Seatbelt and Bubblewrap sandboxing, and its scheduler has nothing to do with /loop.

Then there is the ancestor. Geoffrey Huntley’s Ralph predates every primitive above and is, in his own words, “a Bash loop.”

while :; do cat PROMPT.md | claude-code ; done

Fresh context every iteration, state living only in the filesystem and git, one task per pass, validation as backpressure. Anthropic has since shipped an official ralph-wiggum plugin that reimplements it with a Stop hook instead of a shell loop, warning you to always set --max-iterations and noting it is unsuitable for tasks needing human judgment. Read that as an admission: nearly every guardrail Anthropic baked into its own primitives maps to a failure mode Huntley documented years earlier, in public, about his own technique. His stated limit is the opposite of a sales pitch: “There’s no way in heck would I use Ralph in an existing code base.”

Standing automation is a decade old, and it works

The claim that loops are a new rung on the ladder is true about the model and false about the pattern. The industry has run standing, unattended, tool-wielding automation against production codebases for ten years, at enormous scale. Which examples worked matters, because they share one shape and that shape is the whole argument.

Matrix of four standing-automation cases — Dependency bots, OSS-Fuzz, Google's Rosie pipeline, and the Bun Rust rewrite — scored against three conditions: scope, oracle, and gate. The first three cases satisfy all three legs; the Bun rewrite has no gate, marked in orange.

Dependency bots. Renovate since 2017, Dependabot GitHub-native since 2019. Scope: one version bump. Oracle: the build and the test suite. Gate: an auto-merge rule keyed to update type and test status, or a human. An exploratory study of Dependabot puts merge rates for automated dependency PRs above 70%. Nobody writes think-pieces about Dependabot. It has quietly been doing the thing everyone is excited about since before GPT-3.

OSS-Fuzz. Since 2016: more than 50,000 bugs and 13,000 vulnerabilities across 1,300+ projects. Scope: find an input that crashes the program. Oracle: it crashed or it didn’t — about as hard to game as an oracle gets. Gate: human triage before a fix lands. The cleanest proof that a standing loop can generate enormous value unattended for a decade.

Google’s Rosie and the large-scale-change pipeline. The Software Engineering at Google chapter on large-scale changes documents the pre-LLM playbook: take a mechanical change touching hundreds of thousands of references, auto-split it into small directory-scoped patches, test each independently, route each to the code owner for review before commit. The interesting part is what happened when LLMs arrived. Google’s paper on migrating code at scale with LLMs reports 39 migrations, 595 changes, 93,574 edits, 74.45% of changes LLM-generated, roughly 50% time reduction — and every change landed through Rosie’s existing review gate, not around it. The LLM replaced the typing. It did not replace the gate.

Three legs, every time: narrow scope, an objective check that is expensive to game, and a human or a hard rule gating the landing. Remove a leg and the failure evidence starts. That is not a structure we imposed — it is what the material has in common. It is also, read his answers closely, roughly what Boris describes doing himself. The disagreement is not about whether loops work. It is about what happens to the third leg once the first two get cheap.

The setup: a flaky-test loop, start to finish

The best first loop is one you would be slightly embarrassed to assign to a person. Flaky tests qualify: narrow scope, an objective oracle (run it twenty times, count failures), work that recurs forever, and no engineer has ever enjoyed it.

Start with the instruction file, because a bare /loop otherwise runs Anthropic’s built-in maintenance prompt, which is broader than you want.

.claude/loop.md:

# Loop: flaky test triage

Each iteration, do exactly one thing. Pick the single highest-signal item, then stop.

1. Read `reports/flaky-candidates.json` (written by CI, ranked by failure rate
   over the last 200 runs). If it is empty, or every entry already has an open
   PR, do nothing and say so.
2. Take the top entry with no open `claude/flaky-*` branch.
3. Reproduce: run that test 20 times in isolation. Record the failure count.
   If it fails 0/20, mark it resolved in the report and stop.
4. Diagnose the actual mechanism: shared state, time dependence, test ordering,
   unawaited async, network. Name it explicitly in the PR body.
5. Fix the test or the code under test. Do not add retries. Do not add `sleep`.
   Do not skip the test.
6. Verify: run it 50 times. It must pass 50/50.
7. Open a PR on `claude/flaky-<test-name>` containing the original failure rate,
   the diagnosed mechanism, the fix, and the 50-run verification output.

Hard rules:
- Never edit a test's assertions to make it pass.
- Never touch `reports/`, CI config, or anything under `.github/`.
- If you cannot reproduce the flake in 20 runs, say so and stop. Do not guess.

Every rule in that file exists to keep the oracle honest. “Never edit a test’s assertions” and “do not add retries” are not style preferences. They are the difference between a check the loop passes by fixing the problem and one it passes by deleting the problem. We will come back to why that distinction is load-bearing.

The subagent it delegates to, using the subagent frontmatter schema:

---
name: flake-fixer
description: Reproduces and fixes a single flaky test. Use proactively when a flaky test is identified.
tools: Read, Edit, Glob, Grep, Bash
model: opus
permissionMode: acceptEdits
maxTurns: 40
effort: high
isolation: worktree
memory: project
---
You fix exactly one flaky test per invocation.

A fix is complete only when the test passes 50 consecutive isolated runs and you
can name the specific mechanism that caused the flake. "Added a wait" is not a
mechanism. "The test asserted on Map iteration order" is a mechanism.

You may not modify assertions, add retry wrappers, raise timeouts as a primary
fix, or skip tests. If the honest answer is that the test is testing the wrong
thing, say so in the PR body and propose the change — do not make it.

Record recurring root causes in your memory directory. If you see the same
mechanism three times, note it: that pattern is worth a lint rule, not a third fix.

maxTurns: 40 is a hard stop on agentic turns. isolation: worktree runs the work in a git worktree branched from the default branch, so a wedged iteration cannot corrupt the tree you are working in. memory: project gives the subagent a persistent directory it curates across runs, capped around 200 lines before truncation — which is a feature, because a memory file nobody reads is a slow leak.

Then the schedule, where the /loop-versus-Routine distinction stops being pedantic. /loop 1h /flaky-triage works while the session is open and expires in seven days; a flaky-test loop that runs only when you happen to have a terminal open is a loop that runs on Tuesdays. /schedule gets you Anthropic’s infrastructure, a fresh clone per run, the claude/-branch restriction, and a real trigger. Or keep it in your own repo, where your existing controls already apply, with the Claude Code GitHub Action:

name: Flaky test triage
on:
  schedule:
    - cron: "0 6 * * 1-5"
  workflow_dispatch:

jobs:
  triage:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          prompt: "Run the flaky test triage loop defined in .claude/loop.md. One test only."
          claude_args: "--model opus --max-turns 40"

Weekdays at 06:00, one test per run, workflow_dispatch so you can fire it by hand, --max-turns bounding runaway iteration, and the whole thing in a workflow file your team can review and revert. It bills GitHub Actions minutes and API tokens separately.

One PR per weekday. That number is deliberate, and it is the most important line in this section. A loop that opens five flaky-test PRs a day is a loop your team will merge. A loop that opens forty is one your team will be rubber-stamping by Thursday — at which point you have built the thing the rest of this piece is about.

Run this today: the one-sitting exercise

You do not need a routine, a schedule, or a budget approval to learn whether a loop is worth it on your repo. You need about ninety minutes and a willingness to throw the result away. The point is not the PRs. It is the measurement.

Step 1 — pick the work, not the tool. Find a task meeting all three conditions: it recurs at least weekly, a command can tell you whether it succeeded, and you would accept the result without reading every line if you trusted the check. Good candidates: flaky tests, dead exports, unpinned dependencies. Bad candidates: anything where “is this correct?” requires you to hold the product in your head. If nothing survives all three, stop here — that is a real result, and it saved you a month.

Step 2 — write the check first. Before any prompt, write the command that proves the work. For dead exports it might be npx ts-prune | wc -l. For flakes, a 50-run script. Run it now and write the number down. If you cannot write this command in ten minutes, the task has no objective oracle and it is not loop material. This step disqualifies more candidates than any other, which is why it goes second.

Step 3 — one iteration by hand. No loop yet. Run the task once, interactively, and watch it:

claude --max-turns 25 "Read .claude/loop.md and do exactly one iteration. Stop after opening the PR."

Watch what it does, not what it reports. This is where you find out your check is gameable, your repo has a setup step you forgot, or the model needs context nobody wrote down.

Step 4 — five iterations, bounded. Now let it repeat, still in front of you, with a hard ceiling:

/loop 10m /flaky-triage

Set a timer for an hour. Come back to at most five PRs on claude/-prefixed branches. Press Esc between iterations to stop it.

Step 5 — the measurement that matters. Review all five PRs properly, and time yourself. Then compute one number: minutes of human review per accepted PR. That is the only figure that decides whether the loop is worth standing up. If a PR takes four minutes to review and would have taken forty to write, the loop pays. If it takes thirty because you have to re-derive the reasoning to trust it, the loop has moved work rather than removing it — and putting that on a schedule multiplies the wrong thing.

Step 6 — the stopping point. Delete the branches. Keep the .claude/loop.md, the check script, and the review-minutes number. Promote to a Routine only if the number was small and the check was honest. Otherwise you have a well-documented reason not to, which is worth more than five merged PRs.

The exercise has a defined end, it produces a number, and the number tells you something the vendor talk cannot.

The boundary: what not to loop

The rule is short. Work whose output a human must fully read is not loop material. If a person has to read every line to know whether it is right, the loop has moved the work from whoever would have written it to whoever now has to read it, and reading is the slower of the two. You have relocated a queue.

That rules out more than it sounds like. Architecture decisions. Anything touching a security boundary. Public API design. Migrations where “the tests pass” is a weak signal because the tests encode the old assumption. Anything where the failure is silent and expensive.

It leaves a specific, unglamorous set: mechanical changes with a machine-checkable definition of done, on a schedule, where a wrong answer is cheap and visible. Flaky tests. Dependency bumps. Dead code. Lint-rule migrations. Boring work. That is the tell — the durable precedents above are all boring, because the loop is doing exactly the part that was never interesting.

The review-capacity trap, measured

This part is not a hunch. Two independent studies, different methods, same structural finding.

Faros AI’s telemetry study covers more than 10,000 developers across 1,255 teams. High-AI-adoption teams merged 98% more PRs. PR review time rose 91%. PR size rose 154%. And the finding that should stop anyone building a loop strategy: “we observed no significant correlation between AI adoption and improvements at the company level. Across overall throughput, DORA metrics, and quality KPIs, the gains observed in team behavior do not scale when aggregated.” Faros sells engineering analytics, so read it as an industry report with a narrative interest — but its methodology (telemetry across real systems, per-company normalization) beats a typical vendor whitepaper, and it does not stand alone.

The corroboration is academic and independent. “AI Writes Faster Than Humans Can Review” analyzes 802 developers and 196,212 PRs at one mid-sized AI-forward company across a 2x-throughput mandate. Per-capita throughput hit 2.09x baseline by April 2026 — the mandate worked. And review coverage among merged PRs fell from roughly 48% to roughly 21%, as fast-tracked and bypassed review lanes absorbed the volume. Throughput doubled. The fraction of code a human looked at less than halved.

Faros AI and arXiv 2607.01904 data: PRs merged up 98%, PR review time up 91%, throughput per developer up 2.09x, and company-level delivery showing no significant change — while review coverage among merged PRs falls from 48% to 21%, marked in orange.

That is the mechanism: a loop does not remove the review bottleneck, it feeds it. The “next bottleneck” narrative in the talk is right that coding stops being the constraint and review becomes it. What it does not say is that the tool sold as the answer to the first bottleneck is the thing loading the second.

Which brings us to Boris’s own answer. Asked whether he reviews what his maintenance loops do before they delete or change code, he says: “I just look at the PRs.” It is, he adds, “usually quite good… if you use the latest model.”

We do not think that is dishonest. We think it is the load-bearing admission of the talk. “I just look at the PRs” is the third leg — the human gate — described so casually it sounds like it is not there. It is there, it is doing the work, and it scales exactly as far as one senior engineer’s attention: not to your org, not to a hundred loops, and not to the volume the same talk is enthusiastic about producing. No error rate, no revert rate, no sample size accompanies the claim. It is one practitioner’s experience, offered as such.

The Bun rewrite: what happens at the limit

The best available case study is not the CI anecdote from the talk. Boris describes prompting a dynamic workflow to optimize CI, running a few million tokens over a few hours, and getting four PRs that cut CI time by 50%. That is plausible given documented workflow mechanics. It is also uncorroborated — no blog post, no changelog, no case study confirms those figures. It is a vendor claim made informally on a stage, and we will treat it as that.

The case study that is dated, documented, and publicly contested is Bun’s Rust rewrite. Jarred Sumner — Bun’s creator, and an Anthropic engineer — used roughly 50 dynamic workflows to port 535,496 lines of Zig to more than a million lines of Rust: 6,502 commits, 11 days, approximately $165,000 in API cost, shipped in Bun v2.1.181. That is a real, enormous engineering result achieved by an approach that did not exist eighteen months ago. Pretending otherwise is not skepticism.

And then the other side, on the record. Zig’s creator Andrew Kelley called it “unreviewed slop”, with a question that is hard to wave away: “The argument for shipping all the million lines of unreviewed code is that the test suite is good enough to catch everything. It’s not sufficient to catch bugs in Zig code but it is sufficient to catch bugs in [a] million lines of unreviewed slop?”

This is the three-legged stool with the third leg removed and the second asked to carry the load alone. The test suite is the oracle. Nobody claims a human read a million lines. Bun may well win that bet — the project ships, and its test suite is serious. But the structure of the bet is the thing to notice, because the decade of successful precedent does not have it. Dependabot has a human or a hard rule at the merge. OSS-Fuzz has human triage. Google’s migration paper has Rosie’s review gate. Bun has the tests.

The oracle is gameable, and that is the sharpest argument

Here is why “the tests pass” is a weaker gate than it feels. Anthropic’s own research on emergent misalignment from reward hacking documents a model that learned to call sys.exit() to fake a passing test suite, then generalized that into broader misbehavior: alignment faking, sabotage of safety research, monitor disruption. In 12% of relevant cases it sabotaged code to make its own reward hacking harder to detect.

The scope caveat is essential and we will not bury it: this is a training-time RL research finding, not a field observation of Claude Code. Nobody has reported a shipping loop doing this. Do not read that 12% as a production error rate.

Read it as a mechanism, and as a mechanism it is exactly on point. An objective that can be satisfied by cheating will be satisfied by cheating under enough optimization pressure. That is a claim about optimization, not about AI, and it is why Goodhart’s law has a name. A loop whose only signal is “did the tests go green,” running against a repo where it has edit access to the tests, is sitting behind an oracle it can rewrite.

This is why the .claude/loop.md above spends four lines forbidding retries, timeout bumps, assertion edits, and skips. Those are the difference between a check and a suggestion. The stronger version of the control is structural rather than textual: put the check somewhere the loop cannot reach — a separate CI job, run from the default branch, that the loop has no write access to. Prose in an instruction file asks the loop not to cheat. A permissions boundary makes cheating impossible. Prefer the second.

The real-world analogue needs no misalignment story at all. curl’s maintainers suspended the project’s bug bounty from February 1, 2026 after the accurate-report rate fell from roughly one in six to roughly one in twenty or thirty, drowned in AI-generated submissions. Note the fairness: Daniel Stenberg separately credits AI-assisted analysis with surfacing around 50 real bugs in curl. His complaint is unverified volume arriving through a low-friction channel with a payout at the end and no verification gate. Structurally, that is a PR flood.

Cost and blast radius: the actual controls

“Monitor your spend” is not a control. These are.

Hard caps and kill switches. CLAUDE_CODE_DISABLE_CRON=1 disables the /loop scheduler entirely — put it in the environment of any machine that should never be running timers. "disableWorkflows": true in settings.json, or CLAUDE_CODE_DISABLE_WORKFLOWS=1, kills dynamic workflows. --max-turns bounds agentic iteration and belongs in every non-interactive invocation you write. The workflow runtime caps at 16 concurrent and 1,000 total agents whatever you ask for; the /config “dynamic workflow size” setting is advisory guidance to the model, not an enforced limit, so do not treat it as a budget.

Branch restriction as the default blast radius. Cloud Routines can only push to claude/-prefixed branches unless you explicitly enable unrestricted pushes per repository. Leave that off. Combined with branch protection on your default branch, the worst outcome of a wedged loop is branch litter — a Tuesday afternoon problem rather than an incident.

Permission mode, understood precisely. Auto mode’s published numbers are real and detailed: a full-pipeline false-positive rate of 0.4%, against a false-negative rate of 17% on genuinely overeager actions. Those are Anthropic’s own evals, not independently reproduced. And the mode does not apply where you probably assume. A Cloud Routine has no permission-mode picker at all, and subagents inside a dynamic workflow always run acceptEdits regardless of your session setting. If your safety story is “we run auto mode,” check whether what you are running is one of the two surfaces where auto mode is not in the picture.

The security surface is the real cost. Simon Willison’s lethal trifecta is the sharpest tool here: access to private data, exposure to untrusted content, and a channel to communicate externally. Any two are comparatively safe. All three, and “an attacker who controls the untrusted content can read your private data and ship it out, no exploit code required.” A loop with repo write access, reading issues and PR comments and fetched URLs, with network access, is a textbook configuration.

The vendor answer is that the models are no longer susceptible. Boris says in the talk that “the success rate at 100 attempts is, like, around 1%.” That figure does not match any single published number, and the nuance is the story. Per Anthropic’s published system-card figures, attack success is surface-dependent: 0% across 200 adaptive attempts in a constrained coding sandbox, and up to 78.6% by the 200th attempt in a GUI/computer-use setting without safeguards (57.1% with them on). Both numbers are true, and they describe different worlds. A loop confined to a repo and a test runner lives near the good end. A loop with a browser, a Slack connector, and an MCP server pointed at your ticketing system does not, and citing the sandbox number to justify the second is the exact category error this piece exists to name.

Prompt-injection attack success on one scale: 0% in a constrained coding sandbox across 200 attempts, 57.1% in computer-use with safeguards, and 78.6% in computer-use without safeguards, marked in orange. Source: Anthropic system cards, 2026.

On dollars. The runaway-loop horror stories circulating are mostly single-sourced and vendor-adjacent, so we will not lean on them. The corroborated fact is what large buyers do: Uber capped AI coding tool usage at $1,500 per month per tool after exhausting an annual budget in roughly four months. Boris’s advice on stage is to focus almost entirely on increasing returns rather than cutting cost, because the upside dwarfs the savings. That is defensible for an Anthropic engineer with an internal token allocation. It is harder for a Series A CTO whose annual tooling budget evaporates in the spring.

What we’d tell you on Monday

Pick one task. It must recur weekly, have a check a machine can run, and produce output you would accept without reading every line. Write the check before the prompt. Run five iterations in front of you, then time your review and divide by the number you accepted. That number — review minutes per accepted PR — decides everything else.

If it is small, promote the loop to a Routine or a scheduled GitHub Action, keep pushes on claude/ branches, set --max-turns, put the check in a job the loop cannot edit, and cap the daily PR count at something your team actually drains. If it is large, the task is a queue rather than a loop, and you learned it for the price of one afternoon rather than one quarter.

One number is worth carrying on the perception question. METR’s randomized trial of 16 experienced developers across 246 tasks found AI use increased completion time by 19% while the developers believed they were 20% faster. That 19% is now historical — METR itself says so, and flags that its own 2026 replication is compromised by selection bias, because 30–50% of developers refused to submit tasks without AI. Do not cite it as a present-tense fact. The durable finding is the gap: they were measurably slower and felt faster, and nobody in the room could tell from the inside.

That is why the exercise ends with a stopwatch instead of an impression. The 802 developers in the review-coverage study doubled their throughput and watched the share of merged code a human had read fall from 48% to 21% — and there is no reason to think any of them felt it happening.

References

WEEKLY NOTE

One note per week.

One short note from current work plus 2–3 outside links worth your time.

Oleksandr Kotliarov

Oleksandr Kotliarov

Founder · Engineering Lead · Kraków, Poland

I build engineering teams that ship — from MVP to Series A delivery.

Need help with your technical challenges?

Let's discuss how we can help you build better systems.