AI Commentary · Part 11 of 14

Claude Code Analysis Paper (Part 2)

This is the second part of the excellent paper that does a deep dive of Claude Code. It is titled “Dive into Claude Code: The Design Space of Today’s and Future AI Agent Systems” by Jiacheng Liu, Xiaohan Zhao, Xinyi Shang, Zhiqiang Shen.

In the previous post, we explained the overall architecture of Claude which is very straightforward. The agent loop calls the LLM model iteratively. In this post, we take a deeper look at the extensibility.

There are actually different types of extensibilities available to Claude:

  1. MCP Server. This is the primary external tool. Each server provides tool definitions, and is available for the agent to use. Here’s an example of .mcp.json which lists 3 MCP servers:
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"]
    },
    "github": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp",
      "headers": {
        "Authorization": "Bearer ${GITHUB_TOKEN}"
      }
    },
    "perplexity": {
      "command": "node",
      "args": ["/path/to/perplexity-mcp/build/index.js"],
      "env": {
        "PERPLEXITY_API_KEY": "pplx_xxxxxxxxxxxx",
        "PERPLEXITY_MODEL": "sonar"
      }
    }
  }
}
  1. Skills. Each skill is defined by a SKILL.md file with YAML frontmatter. It contains fields like display name, description, allowed tools, argument hints, model overrides, execution context, associated agent definition, etc. Here’s an example SKILL.md stored in ~/.claude/skills/summarize-changes/SKILL.md:
---
name: summarize-changes
description: Summarizes uncommitted git changes and flags anything risky like secrets, large binary files, or accidental deletions. Use when the user asks "what did I change", "summarize my work", or before they commit or push.
---

# Summarize uncommitted changes

When this skill activates, do the following:

1. Run `git status --short` to list modified files.
2. Run `git diff --stat` for a size overview.
3. Run `git diff` and read the actual changes.
4. Produce a summary with these sections:
   - **What changed** — one bullet per file, grouped by area
   - **Why it likely changed** — your inference of the intent
   - **Flags** — anything risky:
     - Hardcoded credentials or API keys
     - Large binary files (>1MB) committed without LFS
     - Files in `.gitignore` patterns that escaped through `-f`
     - Deleted files that look load-bearing (config, schemas, migrations)

Keep the summary under 200 words unless the diff is genuinely large.
If there are no uncommitted changes, say so and stop — don't invent a summary.
  1. Hooks: Hooks are user-defined shell commands that execute at various points in Claude Code’s lifecycle. They provide deterministic control over Claude Code’s behavior, ensuring certain actions always happen rather than relying on the LLM to choose to run them. Here’s an example of a hook (.claude/settings.json) that blocks rm -rf on Bash calls, project-scoped:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "if": "Bash(rm *)",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.sh",
            "args": []
          }
        ]
      }
    ]
  }
}

.claude/hooks/block-rm.sh:

#!/bin/bash
COMMAND=$(jq -r '.tool_input.command')

if echo "$COMMAND" | grep -q 'rm -rf'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "Destructive rm -rf blocked by hook"
    }
  }'
else
  exit 0
fi
  1. Plugin: A plugin is a package of hooks, skills and MCP servers so it can be shared across projects and teams. Here’s a standard plugin structure and it can be installed using the /plugin command.
plugin-name/
├── .claude-plugin/plugin.json   # metadata
├── commands/                    # slash commands
├── agents/                      # specialized agents
├── skills/                      # agent skills
├── hooks/                       # event handlers
├── .mcp.json                    # MCP server config
└── README.md

The reason for having four types of tools is that they have very different context costs. MCP servers have high context cost because the tool schemas are needed. Skills have low context cost, and hooks have no context cost.

As you can see, although the LLM is central to Claude, it’s the extensibilities that give its power. As pointed out in this post, the harness is the real hero to Claude and agents in general.