Hierarchical multi-agent orchestration for AI coding tools. Giraffe can now operate in three modes:
- orchestrate — plan and delegate across agents
- chat — reply directly as Giraffe
- delegate — manually send a task to one agent without using the planner
Everything is tracked in a project-local .giraffe/ runtime folder.
┌──────────────────────────────────────────────────────────────┐
│ 🦒 GIRAFFE CODE [Tab] [Q: Quit] │
├─────────────────────┬────────────────────────────────────────┤
│ TASK PLAN │ AGENT OUTPUT (Live) │
│ │ │
│ ✅ 1. claude │ > Writing auth/index.ts... │
│ Write auth code │ > Created: src/auth/index.ts │
│ │ > Created: src/auth/middleware.ts │
│ ⏳ 2. codex │ > Running tests... │
│ Write tests │ ✓ All 12 tests passed │
│ │ │
│ ⏸ 3. gemini │ [WAITING FOR HANDOFF...] │
│ Write docs │ │
├─────────────────────┴────────────────────────────────────────┤
│ STATUS: codex running... (Step 2 of 3) [Q: Quit] │
└──────────────────────────────────────────────────────────────┘
xcode-select --install # Required for node-pty native compilationInstall whichever agents you plan to use:
npm install -g @anthropic-ai/claude-code # Claude Code
npm install -g @openai/codex # Codex CLI
npm install -g opencode # OpenCode (if installed under this name)# pi: see https://pi.ai/cli# gemini: see https://ai.google.dev/gemini-api/docs/cliUse the built-in login flow (recommended):
giraffe loginYou can still use environment variables if you prefer (e.g. ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY).
git clone <repo>cd giraffe-code
npm installnpm install triggers node-pty native compilation automatically.
npm run dev -- "Add an auth system, write tests, document it"npm run devgiraffe chat "what should we refactor next?"giraffe delegate codex "build a todo app"
giraffe delegate claude "review the latest handoff and continue"giraffe resumeThis resumes from .giraffe/handoffs/latest and asks Giraffe to continue instead of starting blind.
giraffe improve
giraffe improve "focus on onboarding UX and docs"giraffe --headless "Refactor the database layer"
giraffe improve --headless "focus on planner reliability"npm run dev -- --config ./my-agents.yaml "Refactor the database layer"npm run build
node dist/index.js "Your task here"npm run build
npm link
giraffe "Your task here"giraffe native
giraffe native claude "build a todo app"# Agent execution timeout (default: 300000 ms)export GIRAFFE_AGENT_TIMEOUT_MS=600000
# Transport mode: auto | child | pty (default claude=child, others=auto)export GIRAFFE_AGENT_TRANSPORT=auto
export GIRAFFE_CLAUDE_TRANSPORT=pty| Key | Action |
|---|---|
q | Quit a running orchestration |
Enter | After a run finishes, return to input mode |
Ctrl+C | Force quit |
/login/logout/model/status/doctor/resume/handoff/sessions/agents/mode/mode orchestrate/mode chat/mode delegate <agent>/delegate <agent> <task>/native(or/native <agent> <task>)/improve(or/improve <focus>)
Giraffe now creates a project-local .giraffe/ folder similar in spirit to .claude/.
.giraffe/
├── README.md
├── config.json # local mode + delegate defaults
├── sessions/*.jsonl # append-only session/event logs
└── handoffs/
├── latest.md
├── latest.json
└── <session-id>.md|json
This makes handoffs and agent-session continuity codebase-local instead of only user-local.
This file is the single source of truth for all agent definitions. Edit it to add, remove, or reconfigure agents — no code changes needed. Giraffe now builds worker nodes dynamically from this file.
agents:
claude:
name: "Claude Code"command: "claude"args: []handoff_system_prompt: | When you complete your task, you MUST output EXACTLY this block...strengths:
- backend_code
- architecturefallback: codex # Agent to use if this one failsJust add an entry to config/agents.yaml with:
- CLI command
- args
- handoff prompt
- strengths
- optional fallback
That is enough. No graph wiring is needed for normal worker agents.
When an agent finishes its task, it must output:
[GIRAFFE_HANDOFF]
COMPLETED: Auth system implemented, 3 files created
FILES: src/auth/index.ts, src/auth/middleware.ts, src/auth/types.ts
CONTEXT: JWT-based auth, bcrypt hashing, Express-compatible middleware
NEXT_HINT: Write tests for middleware edge cases, especially token expiry
[/GIRAFFE_HANDOFF]
Giraffe parses this block and forwards the context to the next agent automatically. The latest normalized handoff is also written to .giraffe/handoffs/latest.{md,json}, so manual delegate runs can continue from the latest workspace context.
src/
├── agents/ # Worker CLI adapters / transport wrappers
├── auth/ # OAuth, token refresh, auth storage
├── config/ # Static + user config loading
├── core/
│ ├── handoff/ # Handoff parsing / normalization helpers
│ ├── orchestration/ # Graph, state, planner/router/handoff nodes
│ └── runtime/ # Sessions, native/headless execution, event bus
├── doctor/ # Health checks and diagnostics
├── providers/ # Planner/reply model provider adapters
├── tui/
│ ├── components/ # Reusable Ink UI building blocks
│ ├── controllers/ # TUI state, run actions, commands, hooks
│ └── screens/ # Screen-level Ink views
├── types/ # Shared zod schemas and TS types
└── index.ts # CLI entry point
For a more detailed architectural rationale and evolution plan, see docs/architecture.md.
- Phase 1 — Basic Skeleton: PTY wrapper, Ink TUI, handoff protocol, config loading
- Phase 2 — Full Orchestration: LangGraph StateGraph, all agents, task tree TUI
- Phase 3 — Smart Planner: LLM-based planner, strength-based routing, fallback agent selection
- Phase 4 — Baby Giraffe: Sub-orchestrator subgraph, parallel execution, split-panel TUI
- Phase 5 — Polish: LangSmith tracing, SQLite session history, npm publish
- Lightweight first. Giraffe is a thin orchestrator for other coding CLIs, not a heavy all-in-one IDE.
- Workers stay external. Agent TUIs remain their own CLIs; Giraffe watches, delegates, resumes, and hands off.
- Handoff is the standard. All agents speak the same protocol. Adding a new agent takes 5 minutes.
- Config over code. Agent definitions live in
agents.yaml, not hardcoded. - Human always in the loop. Switch modes with slash commands, delegate manually when you want, and drop to native UI when needed.