The Problem

Developers who want a Claude Code‑style terminal agent often face opaque, monolithic codebases that are hard to audit, extend, or debug. This repo attempts to rebuild that functionality from scratch in a readable TypeScript/Node stack, but its size and architecture present practical barriers for newcomers.

What This Does

The codebase is organized around a stage‑driven roadmap (37 stages) that progressively adds capabilities: LLM communication, UI, tooling, permission control, query‑engine orchestration, sandboxing, MCP protocol, skills, sub‑agents, and more. Key files that embody the core logic are:

  • src/core/queryEngine.ts – the multi‑turn orchestration hub; 42 outgoing imports, 12 inbound dependents, instability 0.78.
  • src/core/agenticLoop.ts – the main loop that drives tool execution and model turns; 959 lines, flagged as oversized.
  • src/tools/Tool.ts – the single most‑imported module; 53 importers, 1 outgoing import, instability 0.02.
  • src/ui/App.tsx – the terminal UI with 39 outgoing imports and instability 1 (leaf node).
  • src/permissions/permissions.ts – auto‑classifier and permission flow; 25 inbound, 9 outbound, duplicated 6‑line blocks appear across 107 files.

The import graph contains 23 modules in circular dependencies (e.g., src/utils/settings.ts, src/config/sources.ts, src/agents/types.ts), and a hub‑spoke pattern around src/tools/Tool means any change ripples to many consumers.

How It Is Wired

Execution starts at the CLI entry point src/entrypoint/cli.ts, which parses arguments and invokes the hook executor (`src/hooks/executor.ts). From there the flow proceeds through:

  1. src/hooks/runHooks.ts – sets up the agent session and permission checks.
  2. src/core/agenticLoop.ts – repeatedly calls the model, resolves tool calls via src/tools/Tool.ts, and manages state in src/state/asyncAgentStore.ts.
  3. src/core/queryEngine.ts – handles multi‑turn context, memory attachment, and command dispatch (e.g., src/core/queryEngine/commands/plugin.ts).
  4. src/sandbox/index.ts – optionally wraps shell execution in a sandbox, using profiles from src/sandbox/macosProfile.ts.

The circular import set (src/utils/settings.ts, src/config/sources.ts, src/agents/types.ts) must be resolved at runtime; extracting a shared type file would break the cycle. The deep nesting in src/entrypoint/cli.ts (max indent 8) makes the control flow hard to follow; guard‑clause refactoring would improve readability.

How To Use It

# 1️⃣ Clone the repo
git clone https://github.com/moses-y/easy-agent

# 2️⃣ Install dependencies
cd easy-agent
npm install

# 3️⃣ Run the installer (creates any needed dirs & default config)
./install.sh   # or: npm run install   (if defined)

# 4️⃣ Launch the CLI
npx ts-node src/entrypoint/cli.ts --help

Configuration lives under src/config/ (globalState.ts, schema.ts, sources.ts). No .env file is provided; any required API keys must be supplied through the environment or the interactive prompt.

Real‑World Use

A developer wants to iteratively refactor a legacy codebase. They run easy-agent with --mode auto, the agent queries the model, uses the bashTool to list files, and the permission system asks for approval before destructive commands. The agent writes a plan, executes edits, and commits changes via the MCP client (src/services/mcp/client.ts). Because the codebase is stage‑36 complete, the workflow is functional but lacks test coverage, so each run should be inspected.

Code Health & Issues

Measured static‑analysis results (89 findings)

  • 28 high: hub module src/tools/Tool (53 dependents), import‑cycle members (src/utils/settings.ts, src/config/sources.ts, src/agents/types.ts), duplicated 6‑line blocks (242 occurrences across 107 files).
  • 60 medium: high branching density in src/utils/settings.ts, src/services/api/streaming.ts, src/ui/components/ConversationView.tsx; oversized files src/core/queryEngine.ts, src/core/agenticLoop.ts, src/ui/components/PluginManager.tsx; deep nesting in src/entrypoint/cli.ts.
  • 1 low: deep nesting elsewhere.

All counts and file paths come from the pipeline’s import‑graph and metric analysis; they are not opinionated.

SDLC observations (beyond the measured block)

  • No test suite – 341 source files with zero test files; any change ships without regression signal.
  • Dependabot/Renovate absent – only a single package.json; no automated dependency updates.
  • Dependency‑vulnerability scan missing from CI; a dependency-review-action or osv-scanner step would catch known‑vulnerable packages before build.
  • Checkout retains tokenrelease.yml uses checkout without persist-credentials: false, risking credential leakage.
  • No timeout on workflow jobs – a wedged step can run the platform’s six‑hour default, overlapping scheduled runs.
  • Missing convention files.editorconfig, .gitattributes, and formatter config are absent, risking inconsistent formatting across contributors.

The Bottom Line

The repository delivers a fully‑featured, stage‑progressed terminal agent that mirrors Claude Code’s capabilities and provides a valuable learning artifact. Its strength lies in the granular, stage‑wise implementation and a clear import‑graph that reveals hot spots (src/tools/Tool, circular‑import set). The main drawbacks are the lack of tests, absent dependency‑automation, and several high‑impact code‑health findings (oversized files, duplicated blocks, unguarded credential handling). Teams comfortable auditing and refactoring a large, circular‑dependency codebase will find it educational; others may need to invest in test coverage and CI hygiene before production use.