惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
Cisco Blogs
Scott Helme
Scott Helme
Know Your Adversary
Know Your Adversary
NISL@THU
NISL@THU
C
Cyber Attacks, Cyber Crime and Cyber Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
Schneier on Security
I
Intezer
Spread Privacy
Spread Privacy
AWS News Blog
AWS News Blog
V
Vulnerabilities – Threatpost
Cloudbric
Cloudbric
V2EX - 技术
V2EX - 技术
Google Online Security Blog
Google Online Security Blog
L
Lohrmann on Cybersecurity
Recent Commits to openclaw:main
Recent Commits to openclaw:main
L
LINUX DO - 热门话题
S
Secure Thoughts
T
The Exploit Database - CXSecurity.com
博客园 - 【当耐特】
Recent Announcements
Recent Announcements
Security Archives - TechRepublic
Security Archives - TechRepublic
Stack Overflow Blog
Stack Overflow Blog
罗磊的独立博客
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
K
Kaspersky official blog
阮一峰的网络日志
阮一峰的网络日志
博客园_首页
Latest news
Latest news
B
Blog
F
Full Disclosure
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗
L
LangChain Blog
GbyAI
GbyAI
Last Week in AI
Last Week in AI
S
Security Affairs
Apple Machine Learning Research
Apple Machine Learning Research
N
Netflix TechBlog - Medium
Security Latest
Security Latest
Vercel News
Vercel News
Y
Y Combinator Blog
G
GRAHAM CLULEY
S
Securelist
T
Troy Hunt's Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
雷峰网
雷峰网

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
How I built my own Claude code in Typescript
Subhraneel · 2026-06-04 · via DEV Community

I Built a Mini Claude Code from Scratch. Here's What I Learned

A few months ago I went down a rabbit hole: reading OpenCode's GitHub repo, studying screenshots of Claude Code's behavior, reverse engineering the flows. I wanted to understand how these terminal coding agents actually work under the hood, not just use them, but build one. This post is about what I built, the real technical challenges I hit, and what I'm planning next.


What I Built

A CLI-based AI coding agent. You open your terminal, run it inside a project, describe a task, and the agent autonomously reads files, edits them, runs commands, searches the web, and commits to Git. This happens all while asking for your approval before changing any of your code.

I started it as a simple sidequest, to read and implement things side by side. It's built in TypeScript, runs on Bun, uses Vercel's AI SDK (Agents, Tools and Loop Control), and uses Google Gemini 2.5 Flash as the model (because it has a free tier, lol), and the terminal UI is built with Ink, I used it because it is very similar to writing frontends in React.

Here's a rough breakdown of what the coding agent can do:

  • filesystem tools: read, write, search, and edit files
  • bash tools: ls, pwd, grep
  • git tools: commit, push, pull, create/manage PRs and issues via github cli
  • command execution: run npm, pnpm, python, pip, cargo, etc.
  • web tools: search the web with any query, fetch URLs
  • a planner sub-agent: breaks big tasks into smaller todos
  • a memory system: persists context across sessions in .agent/ markdown files

Everything is strictly typed end-to-end with Zod schemas, tools have typed inputs and outputs, which I'll get into below.


The Architecture

The core is a tool-calling agent loop. The model receives your prompt, a list of available tools, and the conversation history. It decides which tool to call, the agent executes it, the result is fed back, and the loop continues until the task is done or the model stops requesting tools.

I used Vercel's AI SDK to handle the streaming and loop control, and registered all my tools in a central tools-registry.ts:

export const tools = {
  write_file: writeFileTool,
  read_file: readFileTool,
  search_files: searchFilesTool,
  edit_file: editFileTool,
  ls: lsTool,
  pwd: pwdTool,
  grep: grepTool,
  git_tool: gitTool,
  // planner sub-agent tools
  createTodoTool,
  createAllTodosTool,
  updateTodoStatusTool,
  getNextPendingTodoTool,
  checkIfAllTodosAreCompletedTool,
  // memory + web
  write_memory: writeMemoryTool,
  run_command: runCommandTool,
  web_search: webSearchTool,
  web_fetch: webfetchTool,
} satisfies ToolSet;

Enter fullscreen mode Exit fullscreen mode

Every tool is defined with a Zod schema for its input and output. This gives the model a clear, typed contract for what each tool expects and returns, and it gives me safe failure handling throughout , if a tool call has malformed input, Zod can catch it before it touches the filesystem.


Challenge 1: The Edit File Tool and Human-in-the-Loop

This was the an interesting problem to solve.

All other tools: reading files, running commands, searching can execute automatically without any user intervention. But file editing is destructive. If the agent makes a wrong edit, you want a chance to catch it before it's directly written to disk.

The pattern I took inspiration (from studying Claude Code and OpenCode) is:

  1. agent calls read_file first to read the current file content
  2. agent calls edit_file with the old string and the new string it wants to substitute (diff)
  3. before writing, show the user a colored diff (red for removed lines, green for added lines)
  4. wait for the user to approve or reject

The tricky part is step 4. The agent loop is running. I can't just await a user keypress inside a tool execution without some way to pause the loop itself.

The way I solved this: Vercel's AI SDK's streamText (and generateText) exposes a stopWhen parameter on the loop control. I use this to pause the agent loop when the edit tool is waiting for approval. The TUI sets an isApproved flag asynchronously, the user sees the diff rendered in the terminal via Ink components, presses a key to approve or reject, the flag flips, and the loop resumes or the edit is discarded.

The isApproved field is actually part of the edit tool's input schema:

export const EditFileInputSchema = z.object({
  filename: z.string(),
  folder: z.string().optional(),
  oldStr: z.string(),
  newStr: z.string(),
  isApproved: z.boolean().optional().describe("Needs approval before writing new changes"),
});

Enter fullscreen mode Exit fullscreen mode

And the output schema carries a needsApproval flag back:

needsApproval: z.boolean().optional().describe(
  "Needs human approval to be true for the agent to write the changes in the file"
)

Enter fullscreen mode Exit fullscreen mode

This creates a clear handshake: the tool signals it needs approval, the loop pauses, the human decides, the loop resumes. Everything else runs autonomously.

I also added path traversal protection, the agent cannot operate outside the project root directory. Every file path is validated against the root before any read or write happens.


Challenge 2: The Planner Sub-Agent

For small, focused tasks, the main agent handles everything directly. But when a user gives a bigger, more open-ended task like "refactor this module", "add authentication to my nodejs backend", a single flat loop gets difficult to handle.

My solution was a planner sub-agent. The main agent calls it as a tool when it detects a bigger task. The planner sub-agent has its own system prompt focused entirely on task decomposition. It breaks the task down into a list of structured todos, each with:

  • A unique ID
  • The task description
  • A status (not completed, ongoing, completed)
  • A priority (1–5)

These are typed with Zod too:

export const SingleTodoSchema = z.object({
  id: z.string(),
  todo: z.string(),
  status: z.enum(["completed", "not completed", "ongoing"]).default("not completed"),
  priority: z.number().min(1).max(5).default(3),
});

Enter fullscreen mode Exit fullscreen mode

Once the planner creates the todos, the main agent picks them up one by one using getNextPendingTodoTool, executes them using the available filesystem/git/web tools, and marks each one complete before moving to the next. The TUI renders a live todo list so you can watch the agent work through the task.

Right now this is synchronous, so one task at a time. That's the current limitation that I'm planning to address next.


What's Next: Parallel Sub-Agents

The natural evolution of the planner is running multiple smaller agents in parallel, each picking up one todo from the breakdown independently. But this introduces an obvious conflict problem: what if two agents try to edit the same file at the same time?

My planned approach is to solve this at the task metadata level, not at the execution level. When the planner sub-agent breaks down a task, each todo will also carry metadata about which files it needs to touch:

// rough idea, not yet implemented
{
  id: "task-3",
  todo: "Add input validation to auth.ts",
  files: ["src/auth.ts", "src/validators.ts"], (not guessed, these will be grepped/searched using the tools)
  status: "not completed",
  priority: 2
}

Enter fullscreen mode Exit fullscreen mode

When a smaller agent picks up a task, it only has access to the files assigned to it. The planner ensures no two tasks share the same file. This way, parallel agents work completely independently with well-defined boundaries, no conflict resolution at runtime, because the conflict is prevented structurally at planning time. And to maintain the bigger context the smaller agents will update the main agent about their current status (when it gets updated), e.g: "task1 failed", "task2 succeded", "task 3 in-progress".


Why Gemini 2.5 Flash?

Cause it has a generous free tier. When you're building something from scratch and running dozens of test runs a day, it matters.

The plan is to make the model configurable, so the user will be able to select their provider and model and bring their own API key. The agent's tool-calling logic doesn't care which model is underneath as long as it supports function/tool calling.


The TUI: Ink (React for Terminals)

The terminal UI is built with [Ink], which lets you write React components that render in the terminal. If you know React, there's almost no learning curve.

I used it for:

  • rendering the diff display during file edits (the red/green approval screen) + used the "diff" npm package as well.
  • showing the live todo list as the planner sub-agent creates and the main agent completes tasks
  • the thinking/loading indicators while the model is streaming
  • the GitHub activity log component
  • the text input field for user prompts

Basically it gets the job done with a simple, clean UI.


Memory System

One thing I wanted from the start was for the agent to remember things across sessions. And get more personalised based on the user. The memory system stores three types of information in a .agent/ folder in your project root:

File What it stores
USER.md Your preferences and habits (e.g. "prefers pnpm")
PROJECT.md Facts about the repo (e.g. "uses Next.js, tests in /tests")
AGENT.md Lessons the agent learned (e.g. "avoid editing generated files")

The agent can call write_memory tool at any point of time to store something. On the next session, these files are loaded into the system prompt so the agent already knows the context without you having to re-explain it.


What I'd Do Differently

A few things I'd approach differently if I started over:

  • start with the edit tool's approval flow first. It touches the most parts of the system (tool schema, loop control, TUI state, async coordination) and sets the pattern for everything else.
  • design the todo schema with file metadata from the beginning. Adding it later to support parallel agents means touching the planner sub-agent's prompt, the schema, and the main agent's task-picking logic all at once.
  • Add a proper token tracking display earlier. right now it's in the upcoming features list.

Where to Find It

Here's the github repo: https://github.com/subhraneel2005/sidequests
I have started to polish this project again and will work on some improvements. You can check them in the issues section of the repo, everything I do will be completely transparent.

If you're thinking about building something similar, the best way to start is reading how tool-calling, loops, sub-agents and orchestration actually work in whatever AI SDK you're using. The rest is just building on top of that foundation.


Thanks for Reading

If you made it this far, I genuinely appreciate. This was a fun project to build and an even more fun one to write about.
I keep posting about my projects, experiments, and side quests on X. If you want to follow along, here's my X(twitter) account: @subhraneeltwt

And if you have thoughts, feedback, criticism, questions, or just want to tell me something is wrong or could be done better, DM me, drop a comment, quote the post, whatever you want. I'm always looking to learn. Nothing is too small to share. See ya' :)