Wcode is a personal AI coding agent that runs in your terminal. It's model-agnostic (powered by LiteLLM), extensible via skills and MCP servers, and built for long-running autonomous sessions with fire-and-forget subagents, task management, cron scheduling, and persistent memory.
agent.py — Main orchestrator loop (LLM calls, tool execution, error handling)
├── config.py — Paths, model selection, MCP server definitions, logging setup
├── tools.py — Central TOOLS / TOOL_HANDLER registry (21+ tools)
├── utils.py — Shared helpers (frontmatter parsing, tool_def, safe_path)
│
├── mcp_manager.py — MCP server lifecycle: async event-loop thread, tool discovery & execution
├── memory.py — File-based persistent memory (YAML frontmatter + markdown)
├── messaging.py — Subagent spawning (sync teaching subagent & fire-and-forget async)
│
├── skills.py — Skill discovery & loading from SKILL.md manifests
├── hooks.py — Lifecycle hooks (PreToolUse, PostToolUse, Stop) & permission/safety checks
├── background.py — Background task execution for slow commands (install, build, test)
├── context.py — Context compaction, summarisation & large-output persistence
│
├── cron_system.py — Cron-style recurring / one-shot task scheduler with persistence
└── task_system.py — Task CRUD with dependency tracking & claim/complete workflow
- Model-agnostic — Uses LiteLLM; swap between OpenAI, Anthropic, DeepSeek, Ollama, and others via the
MODELenv var. - Persistent memory — File-based memories in
.memory/with YAML frontmatter, relevance-based retrieval via LLM selection, automatic extraction from conversations, and periodic consolidation. - Skill system — Drop
SKILL.mdmanifests intoskills/<name>/and they're auto-discovered. Built-in skills include code-review and pdf. - MCP support — Launch MCP servers as child processes; tools are auto-discovered and namespaced as
mcp__<server>__<tool>. Runs its own asyncio event loop in a daemon thread for seamless sync/async bridging. - Subagent spawning — Fire-and-forget async subagents run in background threads and notify the main agent when done (via
collect_subagent_results). A synchronous subagent is also available for teaching and quick blocking tasks. - Cron scheduler — Recurring or one-shot scheduled tasks via standard 5-field cron expressions. Jobs can be persisted to disk (
durable) for survival across restarts. - Task system — Create, list, claim, and complete tasks with dependency tracking.
- Hook system —
PreToolUse,PostToolUse,Stoplifecycle hooks for extensibility. - Safety layer — Deny-list for dangerous commands (
rm -rf /,sudo,shutdown, etc.) + workspace-bound path permission rules with user prompt on risky operations. - Background execution — Slow shell commands (installs, builds, tests) are auto-detected and dispatched to background threads; results are injected as XML notifications when complete.
- Context management — Auto-compaction via LiteLLM's
trim_messages, large-output persistence to disk, transcript saving, and LLM-based summarisation for context window recovery. - Rich logging — Console output via
richwith rotating file handler (10 MB, 5 backups) inlogs/wcode.log.
- Python 3.12+
- An API key for your chosen model provider
# Clone the repo
git clone <repo-url> && cd Wcode
# Create and activate a virtual environment
python -m venv .venv && source .venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Configure your environment
cp .env.example .env # or create .env manually (see below)MODEL=deepseek/deepseek-v4-flash # LiteLLM model string
DEEPSEEK_API_KEY=sk-... # or OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.Other supported providers (examples):
# Ollama (local)
# MODEL=ollama_chat/qwen3.5:4b
# OLLAMA_BASE_URL=http://localhost:11434
# Custom OpenAI-compatible endpoint
# MODEL=gpt-5.4-nano
# BASE_URL=https://api.example.com/v1
# API_KEY=sk-...python agent.pyType a question or command at the >> prompt. Type q or exit to quit.
.
├── agent.py # Main entry point & orchestration loop
├── config.py # Global configuration, paths, environment, logging
├── tools.py # Tool registry (21+ tools: bash, file ops, cron, task, messaging, etc.)
├── utils.py # Shared utilities (frontmatter parser, tool_def, safe_path)
├── mcp_manager.py # MCP client lifecycle & tool execution (async event-loop thread)
├── memory.py # Memory CRUD, relevance selection, extraction & consolidation
├── messaging.py # Subagent spawning (sync & fire-and-forget async)
├── skills.py # Skill discovery & loading from SKILL.md manifests
├── hooks.py # Hook system, deny-list & permission checks
├── background.py # Background task dispatch for slow commands
├── context.py # Context compaction, summarisation & large-output persistence
├── cron_system.py # Cron-style scheduler with validation & disk persistence
├── task_system.py # File-backed task management with dependency tracking
├── requirements.txt # Python dependencies
│
├── skills/ # Skill definitions (SKILL.md manifests)
│ ├── code-review/ # Code review skill
│ └── pdf/ # PDF processing skill
│
├── tests/ # Test suite
│ └── test_task_system.py # Comprehensive tests for task system
│
├── .memory/ # Persistent memory storage (auto-managed)
├── .tasks/ # Task persistence store
├── logs/ # Log files (rotating, 10 MB / 5 backups)
│ └── wcode.log
├── .transcripts/ # Conversation transcripts (saved on compaction)
└── .task_outputs/ # Large tool-output persistence
The agent exposes 17+ tools grouped by domain:
| Category | Tools |
|---|---|
| Shell & FS | run_bash, run_read_file, run_write_file, run_edit_file, run_glob |
| Skills | run_load_skill |
| Tasks | run_create_task, run_get_task, run_list_tasks, run_claim_task, run_complete_task |
| Cron | run_schedule_cron, run_list_crons, run_cancel_cron |
| Subagents | run_spawn_subagent (sync), run_spawn_teammate (fire-and-forget) |
| MCP | Auto-discovered as mcp__<server>__<tool> (e.g. mcp__fetch__fetch) |
Skills are auto-discovered from subdirectories of skills/. Each skill is a directory containing a SKILL.md file with YAML frontmatter:
skills/
└── my-skill/
└── SKILL.md # name, description in frontmatter; body = skill content
The agent lists available skills in its system prompt. Use run_load_skill(name) to load a skill's full content when relevant.
Built-in skills:
- code-review — Structured code reviews covering security, correctness, performance, maintainability, and testing. Includes common anti-patterns and review workflow guidance.
- pdf — Comprehensive PDF manipulation guide: merge, split, rotate, watermark, create, extract text/tables, OCR, fill forms, encrypt/decrypt, and extract images using Python libraries (
pypdf,pdfplumber,reportlab,pytesseract) and CLI tools (qpdf,pdftotext,pdftk).
Define MCP servers in config.py under MCP_SERVERS. Each entry specifies a command, arguments, and optional environment variables:
MCP_SERVERS: dict[str, dict] = {
"fetch": {
"command": "python",
"args": ["-m", "mcp_server_fetch"],
},
"my_tool": {
"command": "my-mcp-server",
"args": [],
"env": {"API_KEY": "..."}, # optional
},
}Tools from each server are exposed as mcp__<server_name>__<tool_name> and auto-discovered at startup via the MCPManager (runs an asyncio event loop in a daemon thread).
Memories are stored as individual markdown files in .memory/ with YAML frontmatter:
---
name: my-memory-slug
description: One-line summary
type: user | feedback | project | reference
---
Memory body content here.An MEMORY.md index file is auto-maintained. The system supports:
- Relevance-based retrieval — LLM selects relevant memories each turn
- Extraction — New preferences/constraints are extracted from conversations
- Consolidation — Periodic merging of duplicates and removal of outdated entries
Wcode supports two subagent modes:
- Spawn via
run_spawn_teammate(name, role, prompt)— returns immediately - Runs in a background daemon thread with its own LLM tool loop (max 15 turns)
- Tool set: bash, read/write/edit files, glob
- On completion, stores result in a thread-safe dict
- Main agent collects results via
collect_subagent_results()after each turn - Results are injected as
<subagent_notification>messages
- Spawn via
run_spawn_subagent(description)— blocks until done - Same tool set and 15-turn limit as async
- Best for teaching, quick code search, or small self-contained work
Standard 5-field cron expressions with two job types:
- Recurring — Fire repeatedly (e.g.
0 9 * * *for daily at 9 AM) - One-shot — Fire once, then auto-remove
- Durable — Persisted to
.scheduled_tasks.json, survive agent restarts - Session — Lost on agent shutdown
File-backed task management with dependency tracking:
- Tasks have
pending→in_progress→completedlifecycle - Dependencies block task start until all deps are completed
- Persisted as JSON files in
.tasks/
Three lifecycle hooks with built-in implementations:
- PreToolUse — Permission checks (deny-list + rule-based + user prompt)
- PostToolUse — Tool call logging
- Stop — Session summary logging
Custom hooks can be registered via register_hook(HookType, callback).
pytest tests/ -vCurrent test coverage: comprehensive task system tests covering creation, persistence, dependency resolution, claiming, completion, and edge cases.
- Console — Rich-formatted output with timestamps and level indicators
- File — Rotating file handler (10 MB, 5 backups) at
logs/wcode.log - Third-party libraries (LiteLLM, httpx, openai, etc.) are suppressed to WARNING level by default
MIT