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:
src/hooks/runHooks.ts– sets up the agent session and permission checks.src/core/agenticLoop.ts– repeatedly calls the model, resolves tool calls viasrc/tools/Tool.ts, and manages state insrc/state/asyncAgentStore.ts.src/core/queryEngine.ts– handles multi‑turn context, memory attachment, and command dispatch (e.g.,src/core/queryEngine/commands/plugin.ts).src/sandbox/index.ts– optionally wraps shell execution in a sandbox, using profiles fromsrc/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 filessrc/core/queryEngine.ts,src/core/agenticLoop.ts,src/ui/components/PluginManager.tsx; deep nesting insrc/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-actionorosv-scannerstep would catch known‑vulnerable packages before build. - Checkout retains token –
release.ymlusescheckoutwithoutpersist-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.