Context
Ground-up rebuild of the EasyClaw TUI installer in an empty directory (New easyclaw.help/). No code from the existing v0.4.4 is referenced. The PRD mandates strict phased development — each phase must pass acceptance criteria before proceeding.
This plan covers all 5 phases for visibility. Only Phase 1 will be implemented in this session.

Package Structure
New easyclaw.help/
├── pyproject.toml
├── src/
│   └── easyclaw_installer/
│       ├── __init__.py              # __version__ = "0.1.0"
│       ├── __main__.py              # entry point
│       ├── app.py                   # Textual App (root)
│       ├── constants.py             # shared constants
│       ├── state.py                 # InstallState dataclass
│       ├── messages.py              # custom Textual Messages
│       ├── ui/
│       │   ├── __init__.py
│       │   ├── log_pane.py          # left 60% — RichLog wrapper
│       │   ├── chat_pane.py         # right 40% — chat + input
│       │   └── status_bar.py        # bottom dock bar
│       ├── installer/
│       │   ├── __init__.py
│       │   ├── runner.py            # StepRunner orchestrator
│       │   ├── base_step.py         # BaseStep ABC
│       │   └── steps/               # s01–s15 (Phase 2+5)
│       ├── agent/
│       │   ├── __init__.py
│       │   ├── brain.py             # agent loop + tool chaining (Phase 3)
│       │   ├── openrouter.py        # streaming HTTP client (Phase 3)
│       │   ├── tools.py             # tool defs + executors (Phase 3)
│       │   └── prompts.py           # system prompt template (Phase 3)
│       └── mcp/
│           ├── __init__.py
│           ├── client.py            # JSON-RPC 2.0 client (Phase 4)
│           └── registry.py          # MCP→OpenAI tool converter (Phase 4)

Concurrency Model
ComponentMechanismLoopTextual UIInternal event loopMainStepRunner@work(exclusive=True) asyncMainAgent chat@work(group="agent") asyncMainSubprocess I/Oasyncio.create_subprocess_shellMainHTTP streaminghttpx.AsyncClient.stream()MainFile I/Oasyncio.to_thread()Thread pool
Everything is async-on-main-loop. No manual thread management. @work decorators handle lifecycle.
Layout
3fr / 2fr horizontal split = 60% / 40%. StatusBar docked to bottom spanning full width.

Phase 1: UI & Concurrency Shell (THIS SESSION)
Goal: Prove the 60/40 split layout renders correctly and concurrent workers never block the input.
Files to create (8 files):

pyproject.toml — minimal, textual>=1.0.0 dependency, easyclaw-install script entry
src/easyclaw_installer/__init__.py — version string
src/easyclaw_installer/__main__.py — EasyClawApp().run()
src/easyclaw_installer/messages.py — LogLine, UserChatSubmit, AgentReply messages
src/easyclaw_installer/app.py — Textual App with:

CSS for 60/40 horizontal layout + docked status bar
Dummy installer worker: asyncio.sleep(2) loop printing "Installing step X/15..."
Dummy agent worker: asyncio.sleep(3) then echo user input
Message handlers routing LogLine→LogPane, AgentReply→ChatPane, UserChatSubmit→agent worker


src/easyclaw_installer/ui/__init__.py — empty
src/easyclaw_installer/ui/log_pane.py — Widget wrapping RichLog (max_lines=5000, auto_scroll=True)
src/easyclaw_installer/ui/chat_pane.py — Widget with header Static, VerticalScroll for history, Input at bottom; ChatBubble Static subclass with user/agent CSS classes
src/easyclaw_installer/ui/status_bar.py — Simple Static widget showing current step

Acceptance Criteria

Run with python -m easyclaw_installer
Left pane scrolls "Installing step X/15..." every 2 seconds
Right pane accepts typed messages, echoes them after 3s delay
Spam the chat box while left pane scrolls — zero stutter, zero cursor freeze, zero log pause
StatusBar updates step count


Phase 2: State Machine & Log Piping (future)

state.py: InstallState with active_process, log_buffer deque(maxlen=100), pid_lock
installer/base_step.py: BaseStep ABC with asyncio.create_subprocess_shell, concurrent stdout/stderr reading, timeout
installer/runner.py: StepRunner with retry logic
3 test steps: uname -a && df -h, ping -c 3 google.com, ls -la /etc/
Replace dummy installer with real StepRunner

Phase 3: AI Brain — Agent Johnny 5 (future)

agent/openrouter.py: httpx.AsyncClient streaming SSE parser for Kimi K2.5
agent/tools.py: run_shell_command, read_file, write_file, interrupt_active_step
agent/prompts.py: system prompt with log snapshot injection
agent/brain.py: agent loop — streaming responses, tool-call chaining (max 10 iterations)
Replace dummy echo with real AgentBrain
Proactive intervention on step failure

Phase 4: Remote MCP Knowledge Base (future)

mcp/client.py: JSON-RPC 2.0 + Streamable HTTP transport
mcp/registry.py: Convert MCP tools to OpenAI-compatible definitions, prefix with mcp_
AgentBrain loads MCP tools on startup, routes mcp_* calls to MCPClient

Phase 5: Production Steps & Packaging (future)

All 15 real installation steps (preflight→final report)
Full pyproject.toml with hatchling
bootstrap.sh (curl | bash) script
README


Verification (Phase 1)

cd "New easyclaw.help" && pip install -e .
python -m easyclaw_installer
Observe left pane auto-scrolling step messages
Type messages in chat — verify 3s echo delay, no blocking
Rapidly type while logs scroll — verify zero stutter
Verify StatusBar shows step progress