A technical deep dive into turning an AI coding harness into a deliberate engineering practice environment.
The problem
Most coding agents optimize for a short path from prompt to working software. That is useful, but it can leave the developer with a fragile understanding of the resulting system. The missing abstraction is not another model or another chat window. It is the engineering decision.
Takumi changes the optimization target:
Prompt → model → code
becomes:
Decision → developer reasoning → guided implementation → reflection → capability growth
The coding harness remains responsible for files, tools, model routing, and sessions. Takumi owns the layer around developer judgment.
Why Pi is a host, not the product
Pi exposes lifecycle hooks, TUI interactions, tool-call interception, session persistence, and an SDK. Takumi uses those seams rather than maintaining a fork of the entire coding harness. This keeps model/provider/tool evolution in Pi while keeping Takumi's moat in engineering learning.
The decision engine
Takumi detects consequential context with a conservative catalog. A request mentioning authentication becomes a security checkpoint; a request mentioning persistence becomes a data-model checkpoint. Trivial implementation details pass through.
const checkpoint = detectDecision("Add authentication to the API");
// checkpoint.question:
// "Which security model fits the threat model and user experience?"
// checkpoint.options:
// ["Session-based auth", "JWT tokens", "OAuth/OIDC", ...]
The developer selects an option and explains why. That reasoning is stored as an EngineeringDecision, not as undifferentiated conversation memory.
Adaptive coaching
The Engineering Profile is multidimensional. A developer can have high architecture competence, low testing competence, and low confidence in concurrency. A single beginner/intermediate/advanced label loses that information.
export interface EngineeringProfile {
skills: SkillMap;
confidence: SkillMap;
testingDiscipline: number;
architectureMaturity: number;
recurringMistakes: string[];
repeatedStrengths: string[];
commonTradeOffs: string[];
}
Coaching uses both competence and confidence. High competence with low confidence calls for encouragement and a bounded challenge. Low competence with high confidence calls for evidence, trade-offs, and a smaller checkpoint.
Governance against architectural drift
Every initialized project receives two files:
-
ARCHITECTURE.mddefines module boundaries and request flow. -
VISION_GUARDRAILS.mddefines what Takumi must optimize for and what it must reject.
At session start, the extension reads both. For implementation requests, the developer states the proposed boundary and vision alignment; Pi must explain its alignment before implementation tools are allowed. This turns architectural intent into an executable development constraint.
Persistence and privacy
Takumi is local-first:
.takumi/
├── engineering-profile.json
├── decision-timeline.json
├── telemetry.json
└── latest-debrief.json
JSON is the default because it is inspectable and portable. Node's built-in SQLite backend is available when a project needs transactional local storage. Export and deletion are explicit CLI operations; local state is ignored by Git.
Patterns and debriefs
After an agent settles, the pattern engine looks for conservative longitudinal signals: weak testing discipline, repeated decision categories, recurring mistakes, or architecture thinking without executable proof. The debrief engine turns those observations into staff-engineer-style feedback:
- strongest and weakest moments;
- concepts learned and still weak;
- trade-offs made;
- profile changes; and
- a recommended next practice.
It is intentionally not a scorecard. The goal is one useful observation at a time.
Extension points
Takumi keeps dependency inversion explicit:
export interface AgentAdapter {
initialize(): Promise<void>;
startSession(): Promise<Session>;
injectPrompt(prompt: string): Promise<void>;
receiveResponse(): Promise<HarnessResponse>;
// files, commands, pause/resume, and cancellation omitted here
}
export interface CoachingStrategy {
readonly name: StrategyName;
applies(context: CoachingContext): boolean;
createPlan(context: CoachingContext): CoachingPlan;
}
export interface Storage {
read<T>(key: string): Promise<T | undefined>;
write<T>(key: string, value: T): Promise<void>;
}
New harnesses implement an adapter. New interventions implement a strategy plugin. New persistence systems implement Storage. The Coaching Engine never imports a harness.
Testing the architecture
The project uses Node's test runner for fast behavioral tests and strict TypeScript checking:
npm run typecheck
npm test
Tests cover adapter lifecycle, decision detection, coaching selection, profile updates, governance loading, debrief generation, SQLite persistence, and CLI launcher arguments.
What comes next
The most valuable future work is better evidence, not more automation: outcome validation, richer testing/debugging signals, a native decision timeline UI, and OpenCode tool governance. IDE integrations, team analytics, cloud sync, and MCP should remain optional surfaces around the same local-first core.
Takumi succeeds when a developer finishes a task and can explain why the system works, what trade-offs were made, and what they would do next without needing the agent to take over.
Code & more: https://www.dailybuild.xyz/project/216-takumi
Top comments (0)