← Back to list

An operating system for coding agents

Coding agents are great for an afternoon and mediocre for a quarter. Here’s the small set of files and rules — with the actual configs —…

Varun Jindal · 2026-06-11 09:34 · 0 claps · 4.3 min read
#ai-coding-agent #claude-code #ai-programming #ai-agent #developer-productivity
Open on Medium ↗
Wiki topics: LLM · Large Language Models AGT · AI Agents 💻 · Programming ⏱️ · Productivity

An operating system for coding agents

Photo by Igor Saikin on Unsplash

Photo by Igor Saikin on Unsplash

Coding agents are great for an afternoon and mediocre for a quarter. Here’s the small set of files and rules — with the actual configs — that keeps quality from decaying across months and thousands of edits.

The first session with a coding agent is crisp: it reads the code, makes a clean change, writes a test. By the thirtieth, something has rotted — it re-discovers the same files, contradicts a decision it made three weeks ago, guesses the test command, and quietly stops writing tests because nobody made it. The fix isn’t a better model. It’s an operating system around the model: a constitution, an autonomy boundary, tiered context, durable memory, a review panel, and a post-edit hook. Below are the concrete artifacts.

The four things that decay (and the artifact that fixes each)

decays · symptom · fix

  • discipline — skips tests, expands scope · a constitution it reads every session
  • context — re-learns the repo badly · tiered CONTEXT.md, maintained by a hook
  • memory — repeats corrected mistakes · durable per-fact memory files
  • review — one blind spot applied uniformly · a multi-lens agent panel

1. A constitution (CLAUDE.md / AGENTS.md)

A lean, always-loaded file stating the non-negotiables: the workflow (Plan → Document → Implement → Test → Review → Commit), the autonomy boundary, the quality bars (tests in the same diff, no dead code, conventional commits), and adapter discipline (no vendor SDK in domain code). Keep it short — it’s read on every turn, so every line costs context budget.

2. An autonomy boundary, not a kill switch

The highest-leverage single decision: let the agent run free on everything reversible, pause only on the two things that aren’t — pushing to a remote and deploying. As a permissions config:

{
  "permissions": {
    "allow": ["Read","Edit","Write","Grep","Glob",
              "Bash(git add:*)","Bash(git commit:*)",
              "Bash(npm test:*)","Bash(npm run:*)","Bash(npm ci:*)","Bash(pytest:*)"],
    "ask":   ["Bash(git push:*)","Bash(npm publish:*)","Bash(aws:*)","Bash(terraform apply:*)","Bash(kubectl apply:*)"],
    "deny":  ["Bash(git push --force:*)","Bash(git push -f:*)","Bash(*--no-verify*)"]
  }
}

Now it works for an hour and commits a dozen times; you review at the push, not at every keystroke. The blast radius of “autonomous” stays bounded because the irreversible ops are the only gated ones. (Verify your runner’s match semantics — prefix vs substring differ — so --no-verify/--force denials and npm publish actually trip; broad globs like npm:* quietly allow npm publish.)

3. Tiered context the agent maintains

One giant context file rots and blows the budget. Tier it:

  • Root CONTEXT.md — the map: what this is, how to run/test, one-line module index, invariants, where state lives. Cap ~200 lines; the session-start read.
  • Per-module CONTEXT.md — responsibility, key files, deps, gotchas, how to test just this module. Read before editing that module.
  • **DECISIONS.md** — append-only: date, decision, why, alternatives rejected.

Rule: stale context is a bug, fixed in the same change that invalidated it — not “later.”

4. Durable memory + a tiny knowledge graph

Context describes the code; memory holds what the code can’t tell you across sessions — one fact per file, indexed:

memory/
  MEMORY.md                  # index: one line per fact
  user-prefers-X.md          # type: user | feedback | project | reference
  graph.jsonl                # {from, rel, to} — modules/decisions as nodes; depends-on/adapts/supersedes

The graph answers the question agents are worst at: “what breaks if I change this?”

5. A review panel, not a reviewer

Instead of one self-review, run focused sub-agents in parallel, each one lens, strict output:

product   — solves the stated problem? scope creep?   (plan stage)
architect — correctness, data model, failure modes, coupling
infra     — resource limits, deploy/rollback, resilience
security  — authz, input validation, secrets, audit trail
test-eng  — is the suite real, or happy-path theater?  (per change)
→ each returns: [BLOCKER|MAJOR|MINOR] (confidence%) — file:line — issue — fix ; VERDICT

Only high-confidence BLOCKER/MAJOR gate. Diverse lenses catch what a single pass misses; the confidence threshold keeps it from drowning you in nits.

6. A post-edit hook so nothing drifts silently

The piece that ties it together — fires after every edit and emits a checklist (a PostToolUse hook):

Wire it in settings.json, pointed at a tiny script:

{ "hooks": { "PostToolUse": [
  { "matcher": "Edit|Write|MultiEdit",
    "hooks": [ { "type": "command", "command": "python3 .claude/hooks/post-edit.py" } ] } ] } }
# .claude/hooks/post-edit.py — reads the tool event on stdin, emits a checklist as context
import json, sys
ev = json.load(sys.stdin)
path = ev.get("tool_input", {}).get("file_path", "the edited file")
checklist = (f"Post-edit refresh for {path}: (1) update the nearest CONTEXT.md if responsibility/"
             "key-files/gotchas changed; (2) append a memory/graph edge on a dep/API change; "
             "(3) log a DECISIONS.md line on a precedent; (4) update memory on a durable fact. "
             "Make these edits in THIS change — stale context is a bug.")
print(json.dumps({"hookSpecificOutput": {"hookEventName": "PostToolUse", "additionalContext": checklist}}))

It emits a checklist; the agent makes the edits in the same diff — reviewable, not a silent rewrite.

It’s a reminder, not a silent rewriter — you always see what it changed.

The loop, in one line

session start: read root CONTEXT.md + MEMORY.md
per task:      plan → panel reviews plan → you approve →
               implement subtask (tests in same diff) → panel reviews diff →
               full test+lint → commit → hook refreshes context/memory/graph → next
only stops:    push and deploy

Anti-patterns

  • No autonomy boundary — either you babysit every keystroke, or it pushes/deploys unreviewed.
  • One mega context file — rots, and blows the budget on every turn.
  • Context updated “later” — it’s never later; make staleness a same-diff bug.
  • One self-review — one blind spot, applied uniformly; use a panel of lenses.
  • A hook that silently rewrites docs — you lose the reviewable trail; emit a checklist, edit in the diff.

The takeaway

We’ve crossed from “AI writes a function” to “AI runs a project for weeks.” The bottleneck moved from can the model code to can the surrounding system keep it honest, oriented, and reviewed over time. A constitution, an autonomy boundary, tiered context, durable memory, a review panel, and a post-edit hook are cheap to set up and compound every session — the difference between an intern who’s brilliant for an afternoon and an engineer who gets better at your codebase every week.

I will be packaging this as a drop-in kit.

Part of a series on running LLM systems in production.


메타데이터
post_id
e2f37e67332d
slug
an-operating-system-for-coding-agents-e2f37e67332d
url
https://medium.com/@varunjindal9/an-operating-system-for-coding-agents-e2f37e67332d
canonical_url
https://medium.com/@varunjindal9/an-operating-system-for-coding-agents-e2f37e67332d
author_url
https://medium.com/@varunjindal9
status
ok
fetched_at
2026-06-11 18:57:12