Adventures in Claude Code land
A Deep Dive into the Architecture & Components needed to Master Anthropic’s Coding Agent
Adventures in Claude Code land
A Deep Dive into the Architecture & Components needed to Master Anthropic’s Coding Agent
To extract the most out of Anthropic’s Claude Code, one needs to understand its core design, philosophy and the wide landscape of tools it provides. This article is an easy flowing, plain English introduction to key foundational concepts. We deep dive into Claude components like Skills, Commands, Agents, Hooks & the SDK. There is no prerequisite to understand this article. Like my other articles, this too is 100% human written, embellished with best practices from the field.
What is Claude Code
Claude Code is a tool that was initially developed as a “side project” to help Anthropic coders use AI more effectively. It turned out to be so popular that they decided to release it to the public. Claude Code is:
- A Coding tool: yea, helps generate code, but there is much more…
- AI-powered: connects to Claude AI models for the intelligence
- Terminal-based: It first started life as a simple Command Line Interface (CLI) but now supports various IDEs. Maybe the CLI simplicity is what made it popular. CLI continues to remain the most popular interface
- Agentic: How can it not be in today’s world :) Claude Code comes packaged with a neat set of tools which helps it autonomously perform tasks requested. But it also has “deterministic triggers” that ensure an element of predictability & more safety. We will study these later.
Inspired by the way “cool programmers” work
You may have noticed that good programmers use Terminal commands a lot. These are instructions typed into a CLI (such as Terminal on mac or CMD on Windows) which allow us to directly interact with the OS. One can achieve a lot by chaining simple Terminal commands. Boris Cherny & team likely pondered over how to combine the power of Terminal commands with the intelligence of an LLM. They wrote wrappers that enabled Claude LLMs use the very same tools that great programmers use every day!
Instead of abstract API wrappers, they enabled direct & easy usage of tools like the Terminal, the file system, GIT commands, bash commands (grep, tail etc) in the same raw way like how a programmer would use them. This simple design decision made a lot of difference. Why? You see, instead of using AI big-time, Claude code mainly relies on the above tools (like a programmer would) to gather a lot of context about the task and then use AI as needed. Since these tools are **deterministic (**i.e. they perform the action requested & return the outputs expected), this means lesser AI tokens, lesser hallucination etc. Of course, Boris & co had to put in a lot of work to build security & controls to ensure these powerful tools are not misused.
Consider the task of analyzing a huge codebase. Tools depending on AI & semantic searches may struggle with complex queries as compared to conventional tools & regular text searches. This is where Claude Code shines. It is exceptionally good at understanding code bases. An excellent way to dip your feet into Claude Code land, is to simply point it to a codebase & ask some tough questions. You would be surprised the level of sophistication in the answers. Because it has tools to access the GIT history & commit logs, it can literally see an instant how the codebase evolved over time & can answer rather philosophical queries (sigh, how did this function turn out this way?).
Tip: While it is famous for coding, Claude Code is surprisingly good at other tasks, particularly creative ones. So it is actually a general-purpose agent! I have found it to be surprisingly effective at generating innovative presentations.
The AI behind Claude Code
Claude Code itself is just a program running on your desktop with the CLI as the user interface. The intelligence comes from the Anthropic’s LLMs that it connects to. We can choose between Opus (the intelligent one), Sonnet (the balanced one), and Haiku (the nimble one). Use Haiku for the initial learning and switch to Sonnet for professional work. Leave Opus for the planning part alone. Sonnet gives about 98% of the performance of Opus at a fifth of the cost. My son burnt up a month’s worth of our tokens for his “Hello World” programs by using Opus as the model & got an earful from me.
These LLMs support a 200K context window, though the latest Opus goes up to a million. A context window is the task specific information fed to the LLM in addition to the actual task. It should contain information that helps the LLM do the task requested. Contexts could contain custom code or libraries we want the LLM to analyze before generating new code, it could contain custom instructions, company specific coding standards we want it to follow, domain specific data which is unavailable in public or a user-guide to your application or details of the ongoing chat (since LLMs are stateless, the next call to it has to contain all the past chat history) and whatever else is necessary for an LLM to perform your task better. 200K means about 500 pages of text.
That is a LOT of context! LLMs use their general reasoning power to interpret the context (which has domain-specific information) to do the task requested. So you have the full picture now. Claude Code gets the task from the user, gathers all the necessary information needed to execute the task and passes it on to the Claude LLM. It uses the LLM intelligence to get the job done and responds back to the user. We will study the famous “agent loop” later.
When the context gets bloated, Claude has a feature to automatically zip it. It stops, summarizes & uses the “compact” **command to compact all information available & save it. It then clears its context window & **a fresh version of Claude Code reads the saved info & continues seamlessly.
The LLMs that Claude uses are based on the usual transformer architecture. They are trained the regular way for most part. Apart from RLHF, Anthropic use something called Constitutional AI (a set of rules like a constitution) which aligns the model with human values. The way they do it is to have the model generate responses to various prompts, including toxic ones. Claude then self-critiques its own answers based on a principle from its constitution & rewrites them. The model is then fine-tuned on these improved responses.
Claude Code has a non-CLI interface too!
Apart from the CLI interface, Claude comes in the form of a Desktop App with a neat GUI for Terminal-phobic users. There is also a web interface claude.ai wherein we can use Claude Code through a regular browser. Then we have the IDE extensions — VS Code & JetBrains. There is even the Claude Cowork which is an agentic tool suited for everyday (non-software related) tasks. Lastly, there is the Claude app for mobiles. That is a lot of choice!
As of date, Claude code is neither open source nor free. It is available for a $17 monthly subscription (if billed annually). One can use Claude Code CLI with locally hosted, open-source LLMs using Ollama (via the environment variable ANTHROPIC_BASE_URL ). This way, there are zero costs. However, there may not be official support for this arrangement.
A strange incident that happened on the night of 31 Mar 2026
Claude Code is in Typescript & its compiled version is usually released for user-installations. An interesting development happened on 31 March 2026. A Source-map file was apparently “published” along with the Claude Code installation package due to a human oversight. Source-maps contain information about the source code & are used for (internal) debugging purposes & should not ideally have been released.
This source-map apparently referenced a publicly accessible ZIP archive, allowing anyone to download the entire TypeScript source code of Claude code. Someone used that code to do a clean-room rewrite: basically cleanly re-write a new version from scratch “inspired” by the leaked architecture and functionality. Of course, AI was used for the re-write that happened in a span of a few hours. Named Claw-Code, this repo was then hosted on Github & went on to accumulate 50K stars in 2 hours. This is a record nobody has managed to achieve ever since Github was born.
Unfortunately (for Anthropic), this source code contained a number of extremely interesting patterns & techniques on how to harness AI like Claude Code. Surprisingly enough, Anthropic seemed to be unaffected by all this and a couple of weeks later, didn’t release Mythos. You read it right, they didn’t release Mythos (their next AI model) because it was so powerful that it could find vulnerabilities in some of the strongest software on this planet. The only reasonable thing they felt they could do, was to release it to a few Tech companies & organizations so that the world could study the impact this intelligence would bring in and jointly prepare for it.
Another important point. In all the hysteria that followed the Source-map leakage, an important aspect seems to have been under-reported. To me, the single takeaway from this episode is the fact that AI was used to succesfully migrate a huge code base overnight with minimal human oversight.
An overview of the Claude code design
Claude Code is an “Agentic harness” around an LLM. It provides the tools, context management, execution environment & safety needed to convert a plain LLM into an Agent. We discussed its core — the Agentic loop which is a while(true) loop which is the main thread and goes something like: (1) gather context & reason (2) take action (3) verify results. Repeat! Claude Code starts this Agentic loop to execute your tasks.

Claude Code Agentic loop: https://code.claude.com/docs/en/how-claude-code-works
The Agentic loop adapts itself to the task at hand. Some tasks may just need context gathering (e.g., a simple query on code base), others may need to run in the above loop several times till an appropriate response is generated.
The Agentic loop in Claude Code is a single-threaded one, though it can execute some read-only tools concurrently. Claude Code prioritizes simplicity & hence avoid complex multi-agent swarms. But there are ways to spawn sub-agents in Claude which we study later. The Agentic loop continues (in an async loop which allows the system to remain responsive while waiting for long-running operations) until the task is complete, a limit is hit, or Claude determines it cannot proceed. Basically, it moves through one “turn” at a time of the loop of: Gather Context & Reason — Act — Observe. It does not start a new cycle until the results of the current tool calls are returned.
As discussed, Claude code has several in-built tools to read file systems, edit files, regex stuff, use GIT, run bash commands etc. All these tools are exposed & can be directly used in your own applications if you so desire. There is also the optional Code intelligence plugin which use Language Server Protocol (LSP) connections to enable Claude to jump around in code to identify code definitions, find references & see type errors immediately after code edits. It is also very useful to catch missing imports/syntax issues WITHOUT needing to run a compiler (saving on AI tokens in the process).
Moreover, a single “go to definition” call replaces what might otherwise be a grep followed by reading multiple candidate files. These are the small things that make Claude Code frugal & effective! These plugins also bundle MCP servers so you can connect to external services like Jira/Slack etc.
A View from the co-pilot’s seat
Given a task like: “fix the latest bug in XYZ codebase,” Claude code might:
- Connect to the defect database (via MCP configured) and search for the latest defect & get the error details
- “grep” the source code on the keywords found in the error. Read all the relevant files. Do more searches and navigate from code to code searching for the right set of context just like how a programmer would. Use (minimal) AI to oversee this whole process.
- Use git log to see changes that might have caused this bug
- Fix the bug (using AI calls with context)
- Run impacted tests (before & after) to verify that the defect is fixed
- The fix may not work at first shot. If so, it repeats few of the above steps
![Fixing a Defect. Fig architected by Claude Design [https://www.anthropic.com/news/claude-design-anthropic-labs] & rendered via Google Nano Banana [https://gemini.google/overview/image-generation/] engine.](https://miro.medium.com/v2/resize:fit:1400/1*8NxNJRaZNGPgjeTQr1I05A.png)
Fixing a Defect. Fig architected by Claude Design [https://www.anthropic.com/news/claude-design-anthropic-labs] & rendered via Google Nano Banana [https://gemini.google/overview/image-generation/] engine.
<Fun fact: While reviewing the article, Google search AI asked whether it could generate this image to enhance my article. I generally prefer to keep AI out of the loop in my writings & strictly limit its use to reviews. But I felt particularly touched with the proactive help & decided to include it. However, we did have a lengthy back & forth conversation on how I could correctly attribute the same>
So, how is Claude different from the AI tools we have been using so far:
- It doesn’t need lengthy prompt templates & libraries! Claude makes reasonable assumptions (like any programmer) & silently goes about its job. Your job is to only provide it with crisp English instructions & provide it additional tools that are very specific to your setup.
- Because Claude sees your whole project, IT CAN WORK ACROSS IT. Just show it the path to your codebase. It does NOT depend on RAG. It however CAN be combined with RAG to help with token savings, efficiency, response times, explainability etc.
- In fact, it relies more on regular search using bash tools like grep instead of semantic search for most use cases. Those familiar with building RAG pipelines may recall that Semantic search (which match the meaning & not the exact text) are usually preferred because they are more powerful. Claude Code seems to turn this theory around its head*.
* In reality, it adopts a hybrid approach, using Grep to find the location & then uses the LLM’s reasoning power to grasp the meaning of what it found & iterates.
Using Claude Code
Claude code works at a folder level. Just navigate to the root folder of your code in Terminal & type Claude to open a Claude session. Start giving it tasks in plain English. No other setup needed. You will find the interface to be remarkably intuitive & understandable even if Terminal is new to you.
For a more structured approach to interact with Claude, you can create a CLAUDE.md file. What should it contain? Simple plain English instructions and information about the folder in question. For e.g., you could give a high-level description of what the project is, who it is for, and its primary goals. You could highlight the Tech-stack, Architecture, Coding conventions, commands to build and test the project etc. Claude can likely discover all this for itself but there are 2 advantages to creating this file:
- It is persistent. Next time, you open a Claude session, Claude can refer to this file instead of having to re-discover everything on its own again
- You can add useful information along the course of your interaction with Claude over sessions. For e.g., maybe Claude missed a code review comment which one of your architects manually caught or maybe you typed the same clarification into chat that you typed last session. All these are prime candidates to get into the CLAUDE.md file.
Why not simply let Claude create the initial CLAUDE.md file for you? Just run /init command. Claude analyzes your codebase and creates a nice CLAUDE.md file at the root. You can then choose to augment it if needed.
CLAUDE.md needs to be crisp & concise for 2 reasons. One, it is loaded by default into the context window with every prompt & hence consumes tokens. Secondly, too many instructions can confuse the model. The recommended target is under 200 lines. How do we keep CLAUDE.md crisp & relevant? The general principle is that of progressive disclosure i.e. loading additional information only when it is needed & leaving only the core information in CLAUDE.md. One way to do this is to keep detailed instructions in separate files & only have their references in the main file.
So we group instructions into logical, well named categories (e.g., code-checklist.md, security-checklist.md etc) & create separate files. Claude can understand the content from the file name alone & refer to it autonomously when needed. Or to be safer, we could reference the external files in the CLAUDE.md using markdown links & provide a 1-line description of each file like a “Table of contents” and generically instruct Claude to use relevant files as needed. Note that, we need not explicitly instruct Claude to read a file in a rigid “if X, read Y” format. Instead, we simply provide the details and trust Claude’s reasoning ability to determine when it needs to access what.
Later on we will read about building Skills which extend this concept further. Skills too are based on progressive disclosure. We discuss Skills in a separate section but maybe it is important to call out the difference at this stage itself. Skills are used for complex, automated workflows performing specific tasks (e.g. a skill to security test the code once generated). On the other hand, the .md file references in Claude.md are used for providing general instructions & guidelines. Confused?
Use Skills if you want to tell Claude “Every time I ask you to do X task, perform these 3 specific steps”. Use a .md file Reference in Claude.md if you want to tell Claude “If you ever need to know details about X task, then look at this file”.
Then, we have the @path/to/import syntax in CLAUDE.md which acts as a “mandatory directive” to read the said file’s content & treat that content as being pasted in the CLAUDE.md file itself. So this syntax retains the advantage of maintaining crisp, decluttered & easily readable instructions BUT there is no concept of progressive disclosure. Since these files are loaded every time a session starts along with Claude.md, they consume tokens immediately. This is different from the .md file reference where Claude “chooses” to read the file if and when it wants to.
Summary: We discussed the Claude.md file which is like a persistent memory for Claude and provides it with guidelines and information. We talked of 2 options to declutter this file. 1) Move out logical pieces of information into separate files & provide a TOC like file-reference here. This allows Claude to read the additional files as and when needed. 2) Move out logical pieces of information into separate files and provide @import directive here. This mandatorily forces Claude to read those files and merge the information with the main Claude.md content when interacting with the LLM. Lastly, we didn’t discuss Skills but just mentioned these are used to perform repetitive, complex tasks needing a specific sequence of steps.
A good practice is to end every session with a “Surgically update CLAUDE.md with key new findings”. Of course, you may want to review the suggested changes as you don’t want CLAUDE.md to bloat unnecessarily.
Under the Hood: Key Claude Components
Strictly speaking, using Claude code does not need anything beyond the ability to naturally converse with someone. However, understanding the key components of Claude will determine how much more you can extract out of it. There are Commands, sub-Agents, Tools, Skills, Hooks & some Misc stuff. The semantics keep rapidly evolving & this is the part that can be confusing.
1. Commands (/command)
These do a quick action or execute a simple workflow. We talked about the *compact* Command earlier. There are many such commands already in-built into Claude. Just type “/” and you will see them. When a user invokes Claude Commands, they have to do so with the “/**” prefix.
We can also create custom Commands. How? We just define what the Command should do in a Markdown file. The name of the file becomes the Command. Thats it. So do_epic_stuff.md can be invoked with /do_epic_stuff. What goes inside this file? No code or Python stuff. It needs to just contain natural language instructions telling exactly what steps to take when that command is run. For e.g.: “Review the current changes for code quality. Focus on potential security vulnerabilities and performance issues”.
You can have your own bunch of personal Commands stored in ~/.claude/commands/ which are available across all your projects or you can enforce project Commands (stored in .claude/commands/) across a team.
Note the minor differences between commands (that come pre-bundled with Claude code e.g. compact which Claude code autonomously invokes when necessary), slash-commands (same commands but now a user is explicitly invoking them with a slash e.g., /compact) and custom-commands (yea, the do epic-shit stuff). To add to the confusion, simple actions like grep or ls are technically called Tools & are not in the .claude/commands/ folder.
2. Agents (actually, sub-Agents)
Sub-agent is the term used in Anthropic’s documentation. An Agent (oops, sub-agent) is defined in exactly the same way as a command above i.e. Natural language instructions in a .md file defining the agent’s role, capabilities & approach. So how is it different from a command?
A Command (like /compact) is usually manually triggered by the user. A Sub-agent is integrated into Claude's toolbelt as an autonomous capability. You see, when Claude processes a task, it evaluates all the available sub-agent descriptions. If any of these descriptions match the current need, Claude can proactively delegate work to that sub-agent. Alternatively, we can also explicitly ask Claude to use a specific sub-agent.
Note: Claude can autonomously trigger Commands too. For e.g. if the context size becomes large, it can itself trigger a /compact). In fact, we discussed that Claude can autonomously trigger any custom command created by the user as well. Yea, the above para does not reflect the true difference between a Command & a sub-agent though it seems to be a popular one in the Internet.
So what is the key difference? Sub-agents are spawned separately and work in an isolated context window & only bring a concise result back to the main chat, keeping the main workspace clean & main context window lean. Sub-agents can also run in parallel (Claude decides). This is a huge advantage!
There are other minor differences, e.g. all sub-agents are stored in the claude/agents/ folder. wheras Commands are stored in claude/commands/, but we are being nit-picky here. Oh, also note that we can empower each sub-agent we create to use a set of commands as & when needed. Lastly, sub-agents don’t automatically coordinate with each other by default; they report back to the ‘parent’. If you need them to hand off work to one another, you must explicitly give them the permission and instruction to do so.
Let us look at the classic Orchestrator-Worker pattern. Here, Opus (the intelligent one) can create a plan & initiate execution of that plan. It can hand off easier tasks to sub-agents which run in their own context & use Sonnet/Haiku to do some specific things & share the results back with Opus.
The sub-agent’s .md file could also specify information, like the model to be used, efforts, MCP servers (which need not be accessible to main code) etc. We could even launch a sub-agent directly instead of launching Claude. For e.g. Claude — agent=reviewer which launches the reviewer.md sub-agent directly.
Trivia: Claude Code includes several built-in subagents like Explore, Plan etc. Between sessions, Claude Code spawns an interesting sub-agent whose sole job is memory consolidation. The subagent reads the project’s memory directory, reviews recent logs, identifies intormation worth persisting & rewrites the memory files to be cleaner & more accurate. The system prompt for this sub-agent goes something like: “You are performing a dream, a reflective pass over your memory files. Synthesize what you have learned recently into durable, well-organized memories so that future sessions can orient quickly.”
Tip: Sub-agents have a context of their own & can work in parallel. These are useful properties. We can make use of them even if we haven’t defined any sub-agent .md files. How? Say, we are conversing with Claude asking it to prepare a presentation. Say, information from 3 different sources feed into this. We could (in plain English) request the main Claude thread to use sub-agents to gather this data, while we continue to converse with it on how to structure the presentation.
Very recently, Claude introduced Agent-Teams on an experimental basis. Here, there are a group of sub-agents which can communicate with each other to achieve more (was not possible in above set-up where sub-agents could only communicate with the mother Agent). In fact, it is not just communication, they can do Task Management & Control. Agent-teams are most effective for tasks where parallel exploration & collaboration is important… like in research, reviews etc. BUT, they add coordination overhead & use much more tokens, since each teammate is a separate Claude instance!
How to create Agent-teams? Just enable the setting in the config & describe the task & team structure you want in natural language! Claude creates the team, spawns teammates & coordinates work based on the prompt.
E.g. prompt: Create an agent team to explore this code base from different angles: one teammate on UX, one on technical architecture, one playing devil’s advocate.
The Team-lead’s console lists all teammates & what they’re working on. Use Shift+Down to cycle through teammates and message them directly. After the last teammate, Shift+Down wraps back to the lead. Lots of other interesting tips at: https://code.claude.com/docs/en/agent-teams
3. Claude Tools
Next, there are Tools. This is straightforward & matches the general Tools definition that is used when we talk of Agents. Essentially, they are executable functions that allow Claude to interact with external systems. We already discussed how Claude has many internal tools built-in, like Bash, Read (files), Edit and Grep etc. These Tools run directly inside our current conversation & context. They are largely deterministic in nature.
Claude or its sub-agents use these tools autonomously to achieve the tasks at hand. One can also write a custom tool. Guess what that would be? Yes, an MCP tool. MCP is a protocol that allows AI to connect to external systems to read/write data. Writing a custom MCP tool is not as easy as writing out a set of natural instructions. One needs to define a JSON Schema object that defines the parameters Claude must provide to use the tool. The code implementation needs to be written etc.
Hope you are understanding the distinction & the specific uses of each of these components. We still have 2 more to go.
4. Claude Skills
It is basically a packaged prompt containing instructions, scripts, and resources that teach Claude a new procedure. Think of it as a training manual with all the instructions that can be loaded into Claude’s memory in an instant which will enable it to perform a certain procedure that helps in taking Claude one step closer towards achieving the task given by the user.
Trinity: I need a download to hotwire a motorcycle. Link: Not a problem, one crash course in motorcycle…
The Matrix Reloaded — Scene just before Trinity rides the Ducati 996…
At the start of a session, Claude gets the name & description of all available Skills. When given a task, Claude autonomously decides to invoke a particular skill, if it is needed to solve the task at hand. Alternatively, the user can explicitly ask Claude to use a particular skill. Sub-agents too (like the main Claude thread) can discover and use skills. In its simplest form, a skill can be just a SKILL.md file with some meta data at the top & Natural language instructions about that skill along with the relevant references (e.g. the Official Ducati Owner’s Manual, Ducati Service Manual, Parts Catalog etc).
Skills can bundle additional .md files within the skill directory & reference them by name in the original SKILL_Name.md file. These sub-skills are the third level of detail (progressive disclosure again). E.g., Yoga.md could be the main skill, containing references to Asana.md, Bandhas.md, Mudras.md, etc.
Skills can contain calls to code for deterministic activities. They can also use MCPs to connect to external data sources. Setting disable-model-invocation parameter to True, prevents Claude from using Skills autonomously which is a good idea for sensitive skills dealing with security etc.
Now here is the key thing. In recent times, both Skills and Commands work in the same way under the hood. Both are written in natural language instructions & can be invoked by the user or Claude. But there are key differences. Commands are used for quick & immediate actions (Do this & get it over with). Skills are best for complex multi-step workflows needing domain knowledge & skills (as we saw, riding a Ducati or Mastering Yoga). A Command is typically a single .md file. A skill is usually a directory that includes supporting files, reference material, executable scripts etc. Skills can refer to additional skills (progressive disclosure) unlike commands.
There are other minor differences. E.g., Skills are more efficient because only their description is loaded at session start & full instructions are “lazy-loaded” into the context when actually needed. Command contents are fully loaded into the context on invocation. Note: Unlike a Sub-agent (which runs in a new context), both Skills & Commands are loaded into the main Claude context.
In case the distinction between a skill and a command, is still not clear, this code-security detection scenario generated by AI seems to be a good e.g..
Scenario A: Using a Custom Command (say /scan)
- Behavior: You type /scan, Claude runs the instructions associated with that Command. (say) “Look at this file and find SQL injection security bugs.”
- Limitation: Once the scan is done, Claude goes back to “normal” mode. If you then ask, “How do I fix line 10?”, Claude might give you a generic fix that ignores the high-security context just established.
Scenario B: Define a Security Skill (Create Security-Audit with instructions)
- Behavior: Typing /Security-Audit loads a specialized environment.
- Difference: (1) **Continuous Context: Claude stays in “Security Auditor” mode. Every follow-up question you ask is filtered through that security lens without you repeating yourself. (2) Tool Access: The skill can give Claude specific tools (like a static analysis script or a regex scanner) that aren’t available in the standard chat. (3) Autonomy: If you don’t type the slash but suddenly paste a block of sensitive API keys, tne Skill’s metadata (“I am an expert in security”) triggers autonomousty to warn you, whereas a Command would just sit there waiting for you to type /scan**.
How is a Skill different from a sub-agent? Thankfully this is easier to understand. Skills are like the Manual/Guide, while a Sub-agent is the Worker. We also discussed how Sub-agents run in the background in their own isolated context window. In fact, Sub-agents can actually use a Skill autonomously (based on the skill description) to do its job. Yes, they do have some things in common — both are defined using Markdown files & both contain natural language instructions that guide how Claude should behave for a specific task. That is where the commonality ends.
How are Skills different from the .md file references in the Claude.md file? We already discussed this in detail earlier.
5. Claude Hooks: Bringing in determinism and predictability to AI
Hooks are “event listeners”. They are basically user-defined shell commands that execute at specific points in Claude Code’s lifecycle. They provide deterministic control over Claude Code’s behavior, ensuring certain actions always happen at certain times. You can put “Verifiers” and other “Checks & balances” in these Hooks to ensure the actions taken by AI are OK.
There are also prompt-based hooks or agent-based hooks that use a Claude model to evaluate conditions. These are decisions that require judgment rather than deterministic rules.
Custom hooks can preprocess data before Claude sees it. E.g., instead of Claude reading a 10,000-line log file to find errors, a hook can grep for ERROR and return only matching lines, reducing context significantly.
Hooks are also good for automating “side effects,” like running a linter automatically after every edit.
6. Misc Claude Components
First is the .claude/rules/ directory which contains Markdown files containing team-wide coding rules, review checklists etc. All Markdown files within this directory are automatically loaded into Claude Code’s context at the beginning of every session (unlike @imports which need to be specifically mentioned in the Claude.md file). Moreover, by adding a YAML block at the top, we can make rules that load only when Claude is working on relevant stuff (needing that rule). This makes loading dynamic & saves “tokens” in the process apart from preventing Claude from getting confused by irrelevant rules. So it has certain advantages over the @import.
We also have a docs/Directory where we can dump the project’s actual documentation. It is not a “special” internal Claude folder like .claude/ & is not mandatory but it is recommended as a source of Rich Context for Claude to dip into. Claude looks it up when it feels the need. It differs from .md file references because there is no written list/description of file locations in this case. This is a physical location Claude can explore using its ls or grep tools. If you don’t mention a file from docs/ in your CLAUDE.md, Claude might only find it if it explicitly decides to search for documentation. As a hybrid approach, we can move all our documentation here & have important files mentioned as file references in Claude.md file.
Lastly, Plugins are shareable bundles of all the components we have studied so far. While we can configure a Skill or a Command standalone in our .claude/ directory, a plugin allows us to package all those features into a single, version-controlled unit that can be shared across different projects.
That is a ton of components we covered! Each works in a different way. Just because Claude offers all these features; we need not necessarily have to use all of them in a project. We can pick and choose the ones we need.
Claude Agent SDK
While Claude Code is designed for interacting with a human, there is an option for a human-less interface as well. For e.g., we may want Claude Code to react to an event & execute a series of actions (without involving human interventions). Claude Agent SDK, released in September 2025 allows us to do that. It is the entire infrastructure behind Claude Code, exposed as a library. We get the complete agent loop ready-made along with all the built-in tools, the context management & everything else. Claude Agent SDK is the new name of Claude Code SDK that was released in Jun 2025.
The SDK is an open-source Python library. However, it offers native support to Claude LLMs only. All the components discussed earlier, like skills, sub-agents, tools, commands etc are available in the SDK as well. Sub-agents can be defined programmatically. Skills & Commands must be created as filesystem artifacts & there is no programmatic API for them. Custom Tools are defined as standard Python functions using the @tool decorator.
Interestingly, Claude CLI itself can be run in a headless mode for non-interactive tasks. Just use the -p option. E.g: claude -p “Summarize changes in this directory” > summary.txt. For complex tasks needing finer control, Agent SDK is better. It allows us direct access to the Messages array. Messages are the core data structure used by Claude Code to communicate with the LLM. With Agent SDK, we can inspect, edit, truncate messages etc.
Tip: In headless mode, add --bare to reduce startup time by skipping auto-discovery of hooks, skills, plugins, MCP servers, auto memory, and CLAUDE.md.
There’s a separate Anthropic SDK Python one can use, if one wants to interact directly with the Anthropic API. This provides direct API access to all the APIs internally used by Claude Code but it does not provide the default Agentic loop, context handling etc & one must manually orchestrate all this (sort of like building a Claude Code from scratch).
Unlike standard stateless API calls, the Agent SDK operates as a long-running process. This means, we need not send the history to the model every time. We can also stop & restart agents later by providing a session_id reference. We also have lifecycle Hooks for deterministic control.
Claude Code Best Practices
- Before any major endeavour, start in Plan Mode. Press Shift+Tab to switch to this mode. Create/review the plan & then move to Execute Mode. Use Opus for planning & Sonnet/Haiku for execution.
- Claude outshines when it can verify its own output. So Tests (or any way for Claude to verify the accuracy of its output) are important. In particular, Anthropic’s Chrome integration is explicitly designed for this kind of feedback loop. It can read console errors, inspect DOM state, test user flows & iterate until the behavior matches what you asked for.
- Claude can be forced to think deeply with the Ultrathink mention in the prompt. It will max out the scratch pad & consume lots of reasoning tokens but may be worth it for a particularly knotty scenario.
- Sub-agents may conflict if they modify the same file in parallel. A good option here is Git worktrees. This lets you have multiple working directories linked to the same repo.
- For code generation, choose the language wisely. For e.g., generate TypeScript instead of JavaScript. Why? TypeScript adds structural rules the agent can verify against. The type checker provides instant feedback about interface mismatches, missing properties, and type errors. These mistakes are caught early saving tokens.
- If Claude goes off track when using a skill to complete a task, ask it to self-reflect on what went wrong. This process will help discover what context Claude actually needs, instead of trying to anticipate it upfront. In fact, a good practice is to identify gaps in your agents’ capabilities by running them on representative tasks and observing where they struggle or require additional context. Then build skills incrementally to address these shortcomings. There is an Open source library of skills. But be aware that one could easily hijack a skill with an embedded, hidden prompt inject, so be sure to only use 100% trusted skills.
- There is a tradeoff between generating machine readable documents (JSON format) versus generating human readable documents (Markdown files). The latter is easy to read/debug/explain & helps when there is a human in the loop. But LLMs parse Markdown probabilistically whereas they parse JSONs deterministically. Balance the two. Else, go for a “Reason in Markdown, Extract to JSON” pattern, ensuring best of both worlds.
- Some (Reddit posts) argue that instead of trusting auto-compaction, one can better control what’s preserved during compaction by adding a “Compact Instructions” section to CLAUDE.md. Since auto-compact invokes an API outside the current context window to do the compacting, it need not do a good job. A better option is to have Claude itself (within its current context) “generate a machine-readable handoff document to ensure a new instance to seamlessly resume this work”.
- By nature, Claude uses MCP to autonomously connect to external systems whenever needed. Hence, the MCP definitions are provided with every request. Even a few MCP servers can consume significant context before you start. Hence use them judiciously. If you want to simply read a file or a DB use direct API calls instead. One can also configure “Lazy Tool Loading” and “Tool Search/Filtering” to solve context bloat issue with MCP. In Lazy loading, only the definitions are loaded initially & the rest when needed. Tool Search is the mechanism that enables lazy loading.
- Prefixing a command with “!” triggers Bash Mode. One can run shell commands directly without going to the AI model & wasting tokens. The output of the command is automatically added to the context & history.
Some misc tips:
- Run /context to see what’s using space. Use /clear to start fresh when switching to unrelated work.
- Set max-Turns to a reasonable number. A turn is a single round-trip in the agent loop for a tool call. Too few may just not work. Too many may simply end up wasting tokens. This needs to be tuned.
- Use Accessibility interface to talk to Claude if you are bored of typing.
- Claude saves things worth preserving automatically (as you work) to a file called MEMORY.md. The first 200 lines of MEMORY.md are loaded at the start of each new session. You can edit this to keep important notes here that you want Claude to refer to. Don’t clutter it too much & don’t repeat what is already there in Claude.md.
- Run /insights occasionally to identify patterns from sessions & add rules
- (hearsay) Use IMPORTANT or YOU MUST prefixes for critical rules to improve adherence. Use all CAPS to stress important things.
- Explore these interesting pre-loaded skills/commands. They are incredibly useful. /batch, /cost, /simplify, /security-review, /voice etc.
- Extended thinking is enabled by default because it significantly improves performance on complex tasks. Thinking tokens are billed as output tokens & can accumalate steeply. For simple tasks, reduce costs by lowering the effort level with /effort, disabling thinking in /config, or lowering the MAX_THINKING_TOKENS setting.
- Effort levels control adaptive reasoning, which lets the model decide whether and how much to think on each step based on task complexity. Lower effort is faster & cheaper, while higher effort provides deeper reasoning. In Opus 4.7,
xhighis the default effort setting. It is positioned between ‘high’ and ‘max’. Change as needed.
Deploying Claude Agents in Production
A typical approach when agents take more than ~10 seconds to finish a task is a Queue + Worker Pattern which decouples request intake from execution. The Workers can be Docker containers or micro VMs. The user either polls or gets notified via webhooks once the task is done.
The Worker is just a program that sits in a loop, waiting for jobs to do. Since they are autonomous, it makes sense to put tight blinkers on them & isolate them to the max extent possible. Docker is the standard way to package agents into a container. We could then leverage K8s directly or via a wrapper like AWS Fargate to scale up deployment of these containers as per the situation/size of the queue. We can limit the Docker to restrict networking ( — network none) and enable read-only mounts etc.
A stricter option is a MicroVM like Firecracker/gVisor which can be used in situations where the agent can run arbitrary code (say user entered). It is the same idea as above but instead of a container, each job gets a tiny but full virtual machine that boots in milliseconds, runs your agent, then disappears. This provides much stronger isolation. With adoption of the Modal library, you just write a normal Python function & decorate it. Modal handles everything else. Just define a function, Modal handles the VM lifecycle.
Other safety measures include routing agent traffic through a proxy like LiteLLM Proxy. This sits in front of your Claude API calls & enables routing, observability, rate limiting, caching etc. The proxy also holds the keys and injects them into outgoing requests.
Hosting the Agent SDK has additional details.
Bottomline
At the risk of repeating myself, let me state that using Claude code does not need anything beyond the ability to naturally converse with someone. That is the reason this article does not have cheat-sheets, magical prompts or other Claude.md templates etc which suddenly make you 10X more productive. On the other hand, understanding the core design of Claude Code and knowing the role of each key component helped me organize my thoughts & give instructions in a structured way to Claude. That helped it perform better. This article reflects some of that understanding.
I would, however, like to give a reference to one particular template that is precious. Earlier this year, one of the most followed programmers, Andrej Karpathy posted his experiences working with Claude. Jiayuan Zhang distilled knowledge from Karpathy’s post & created a 4-pointer Claude.MD file that went onto get 60K stars on Github. Readers may benefit by looking at that file & picking up something from there. Though several months have passed & Opus 4.7 is out, the information shared by Karpathy still holds.
Other articles of mine explaining AI in a simple, intuitive & fun way.
- PPO & Reinforcement Learning for absolute beginners — Fun in RL land
- Advanced RAG: Techniques & Concepts — Summary of a 1000 papers
- Rise of the EBMs: Why Energy Based Models may replace the current LLMs
- MCMC & the magical art of Sampling without Sampling — Story, Intuition & the gentle Math behind the greatest algorithm of the 20th century
- Secrets of the VAE — Appreciation without the apprehension
- The Enchanting world of GNNs — MPNNs, GCN, GAT, GTN, GraphSAGE
- Understanding LLM Agents: Concepts, Patterns & Frameworks
- Anatomy of a GPU — A peek into the hardware fuelling LLM operations
- My fav: Cosine Distance vs Dot Product vs Euclidean in vector similarity search — Why my webpages will never be ranked at the top of a search engine result (well, looks like the folks at Google are having the last laugh. This is the only article of mine that has a decent search rank!)
메타데이터
- post_id
- f9dd85f2e072
- slug
- claude-code-the-complete-architectural-deep-dive-best-practices-f9dd85f2e072
- url
- https://medium.com/@allohvk/claude-code-the-complete-architectural-deep-dive-best-practices-f9dd85f2e072
- canonical_url
- https://medium.com/@allohvk/claude-code-the-complete-architectural-deep-dive-best-practices-f9dd85f2e072
- author_url
- https://medium.com/@allohvk
- status
- ok
- fetched_at
- 2026-06-09 14:34:10