Autonomous coding agent with surgical file editing, four-worker multi-agent coordination (architect/coder/tester/reviewer), structured architecture planning, and aggressive context management. Built with LangGraph, GPT-5.4, and FastAPI.
Live API: https://shipyard-production-610b.up.railway.app API Docs: https://shipyard-production-610b.up.railway.app/docs LangSmith Traces: https://smith.langchain.com/public/8c7772fd-b6d6-449b-bf37-80bb78df7b12/r
- Three-phase plan/execute/review — architect analyzes the original codebase and produces a structured JSON plan; coder implements against a checklist; tester + reviewer run in parallel; fix loop iterates until issues are resolved
- Structured architecture plans — JSON schema with tech stack, database tables, API endpoints, components, file structure, security requirements, business rules, and accessibility notes
- Surgical file editing — anchor-based replacement (
old_string/new_string) that modifies only the targeted code block, never rewrites entire files - Persistent agent loop — FastAPI server maintains session state across instructions; SQLite persistence survives restarts
- Interactive CLI —
shipyard-clicommand with prompt_toolkit for proper keyboard handling (Home, End, PgUp, PgDn, arrow keys) - Aggressive context management — emergency truncation, hard token ceiling at 70%, content sanitization, 8K tool output cap; handles codebases with 20K-77K line files without crashing
- Full observability — every LLM call, tool execution, and agent decision traced via LangSmith
- Swappable LLM — GPT-5.4 is the default; switch to Claude by changing one environment variable
- File organization enforcement — reviewer auto-flags files exceeding 300 lines
- Python 3.11+
- An OpenAI API key (or Anthropic API key)
git clone https://github.com/lramosve/shipyard.git
cd shipyard
pip install -e .Create a .env file:
LLM_PROVIDER=openai
LLM_MODEL=gpt-5.4
OPENAI_API_KEY=sk-...
LANGSMITH_API_KEY=lsv2_... # optional, for tracing
LANGSMITH_TRACING=true # optional
LANGSMITH_PROJECT=shipyard # optional
shipyard-cliOr specify a working directory:
shipyard-cli --dir /path/to/projectpython -m shipyard.mainThe server starts on http://localhost:8000. API docs at http://localhost:8000/docs.
docker build -t shipyard .
docker run -p 8000:8000 --env-file .env shipyard$ shipyard-cli --dir ../my-project
Shipyard CLI — model: gpt-5.4 (openai)
Working directory: /home/user/my-project
Type /help for commands, or enter an instruction.
> Rebuild this application from scratch, preserving the original architecture
The supervisor will:
- Run the architect worker to analyze the codebase and produce a structured plan
- Run the coder worker to implement the plan section by section
- Run the tester and reviewer workers in parallel to validate output
- Loop back to the coder for fixes if CRITICAL or MAJOR issues are found
# Submit an instruction
curl -X POST http://localhost:8000/instruction \
-H "Content-Type: application/json" \
-d '{"instruction": "Read src/app.py and add error handling to the main function"}'
# Use multi-agent supervisor mode
curl -X POST http://localhost:8000/instruction \
-H "Content-Type: application/json" \
-d '{
"instruction": "Rebuild the application preserving the original architecture",
"use_supervisor": true
}'
# Inject context at instruction time
curl -X POST http://localhost:8000/instruction \
-H "Content-Type: application/json" \
-d '{
"instruction": "Update the code to follow the spec",
"context": [{
"type": "spec",
"source": "requirements.md",
"content": "Functions must validate inputs and return typed results"
}]
}'| Endpoint | Method | Description |
|---|---|---|
/health |
GET | Health check |
/history |
GET | Conversation history for current session |
/context |
POST | Inject context mid-session |
/context/file |
POST | Inject context from a file path |
/reset |
POST | Clear session state |
User Instruction
│
▼
┌──────────────────┐
│ Supervisor │ (deterministic routing, no LLM)
└──┬───┬───┬───┬───┘
│ │ │ │
▼ │ │ │
┌──────────┐ │ │
│ Architect │ │ │ Phase 1: PLAN
│(read-only)│ │ │ Produces structured JSON architecture plan
└──────────┘ │ │
│ │ │
▼ │ │
┌───────┐ │ │
│ Coder │ │ │ Phase 2: EXECUTE
│(all │ │ │ Implements plan as section-by-section checklist
│tools) │ │ │
└───────┘ │ │
│ │ │
▼ ▼ ▼
┌───────┐ ┌────────┐
│Tester │ │Reviewer│ Phase 3: REVIEW
│(all │ │(read- │ Run in parallel via LangGraph Send()
│tools) │ │ only) │ Tester writes+runs tests; Reviewer checks
└───┬───┘ └───┬────┘ fidelity, security, accessibility, file sizes
│ │
▼ ▼
┌──────────────┐
│ merge_results│ Dedup issues, filter by severity,
│ │ detect no-progress loops
└──────┬───────┘
│
┌─────┴─────┐
│ Issues? │ CRITICAL/MAJOR → fix cycle (max 3)
│ │ MINOR only → done
└───────────┘
The architect produces a JSON plan with:
tech_stack— packages, versions, rolesdatabase_tables— columns, relationships, indexesapi_endpoints— method, path, purpose, auth, middlewarecomponents— name, file path, purpose, childrenfile_structure— every file with purpose and 300-line maxsecurity_requirements— auth, hashing, CSRF, rate limitingbusiness_rules— state machines, workflows, validationaccessibility_notes— ARIA, semantic HTML, keyboard navcritical_rules— hard constraints the coder must never violate
The plan is converted to a markdown checklist and injected into the coder's context. It persists across instructions via SQLite.
| Tool | Description |
|---|---|
read_file |
Read file contents with optional line range (8K output cap) |
edit_file |
Surgical anchor-based replacement with uniqueness enforcement |
write_file |
Create new files or full overwrite (read-before-write guard) |
execute_cmd |
Run shell commands with timeout and output truncation |
check_background |
Check status and output of a background process |
stop_background |
Stop a background process (process tree kill) |
search_files |
Regex search across files with glob filtering |
list_files |
List directory contents with glob pattern support |
rollback_file |
Restore a file to a previous snapshot version |
web_search |
DuckDuckGo search for documentation and error solutions |
web_fetch |
Fetch a URL and extract text content |
Multiple safety layers prevent context overflow:
- Compaction at 50% — summarizes older messages, keeps last 10
- Emergency truncation — when LLM summarization fails, drops old messages with synthetic summary
- Hard token ceiling at 70% — truncates oversized messages (tool results at 8K, system at 50K), drops oldest if still over
- Content sanitization — strips null bytes, control characters, and broken UTF-8 before API calls
- Conservative estimation — 3 chars/token (not 4) to avoid underestimating code token count
Switch providers by setting LLM_PROVIDER in .env:
LLM_PROVIDER=openai # default (gpt-5.4)
LLM_PROVIDER=anthropic # Claude
Both AnthropicProvider and OpenAIProvider implement the same LLMProvider protocol.
shipyard/
├── shipyard/
│ ├── main.py # FastAPI server, endpoints, session management
│ ├── cli.py # Interactive CLI with prompt_toolkit
│ ├── config.py # Settings from environment variables
│ ├── persistence.py # SQLite session store (messages, plans, file tracker)
│ ├── llm/
│ │ ├── provider.py # LLMProvider Protocol + response models
│ │ ├── anthropic_provider.py
│ │ └── openai_provider.py
│ ├── tools/
│ │ ├── base.py # ToolResult model, FileReadTracker
│ │ ├── read_file.py
│ │ ├── edit_file.py # Anchor-based surgical replacement
│ │ ├── write_file.py
│ │ ├── execute_cmd.py
│ │ ├── search_files.py
│ │ ├── list_files.py
│ │ ├── rollback_file.py
│ │ ├── snapshots.py # FileSnapshotStore for rollback
│ │ ├── web_search.py
│ │ └── web_fetch.py
│ ├── agent/
│ │ ├── state.py # LangGraph AgentState TypedDict
│ │ ├── graph.py # Core agent loop (StateGraph)
│ │ ├── nodes.py # call_llm, execute_tools, should_continue
│ │ ├── supervisor.py # 4-worker supervisor (architect/coder/tester/reviewer)
│ │ ├── plan_schema.py # Pydantic models for structured architecture plans
│ │ └── compaction.py # Context management (compaction, truncation, sanitization)
│ ├── context/
│ │ └── injection.py # Format and load external context
│ ├── tracing/
│ │ └── setup.py # LangSmith configuration
│ └── utils/
│ └── retry.py # Exponential backoff retry logic
├── tests/
│ ├── test_edit_file.py # 11 tests for surgical editing
│ └── test_api.py # FastAPI integration tests
├── docs/
│ ├── CODEAGENT.md # Agent architecture documentation
│ ├── Comparative Analysis - V3.docx # UltraShip vs FleetGraph analysis
│ ├── Comparative Analysis - V2.docx # SuperShip vs FleetGraph analysis
│ └── DEMO_SCRIPT_FINAL.md # Demo walkthrough
├── scripts/
│ ├── generate_comparative_analysis_v3.py
│ └── generate_comparative_analysis_v2.py
├── Dockerfile
├── pyproject.toml
└── .env.example
~3,700 lines of Python across 34 source files, 53 commits.
Shipyard has rebuilt the Ship/FleetGraph application three times, each improving on the last:
| Version | Repo | LOC | Key Achievement |
|---|---|---|---|
| V1 (new_ship) | new_ship | ~5,500 | Working app, but swapped TypeScript→Python and used normalized tables |
| V2 (SuperShip) | supership | ~1,711 | Correct architecture (unified doc model) but in-memory, no auth |
| V3 (UltraShip) | ultraship | ~3,737 | Full fidelity: PostgreSQL, TipTap/Yjs, FleetGraph agent, auth, security |
Deployed URLs:
| App | Web | API |
|---|---|---|
| UltraShip (V3) | https://ultraship-six.vercel.app | https://ultraship-production.up.railway.app |
| SuperShip (V2) | https://supership-rho.vercel.app | https://supership-production.up.railway.app |
| new_ship (V1) | https://frontend-production-20c1.up.railway.app | https://backend-production-d97a.up.railway.app |
pip install -e ".[dev]"
python -m pytest tests/ -vDeployed on Railway as a persistent container:
railway upOr deploy via Docker to any platform that supports containers.
LangSmith traces every agent run automatically when LANGSMITH_TRACING=true and LANGSMITH_API_KEY are set. Each trace shows:
- Every LLM call with token counts
- Every tool call with inputs, outputs, and duration
- Error paths and recovery steps
- Aggregate cost and latency
MIT