Clawd Code Python Port

作者 reason-machines2384a003145a无许可证83 个星标收录于 2026年10月8日更新于 2026年10月8日仓库3个月前更新

Python port of Claude Code agent harness — tools, commands, task orchestration, and CLI entrypoint via oh-my-codex

AI 生成的概览

介绍 Claude Code 智能体框架的 Python 重写项目 clawd-code,涵盖其命令行、工具、命令与任务编排。

功能
该技能是 clawd-code 的参考文档,clawd-code 是一个用于教学、以 Python 重写 Claude Code 智能体框架的项目。它说明仓库结构、命令行子命令、数据模型、工具与命令注册表、任务编排原语、查询引擎、移植清单与一致性审计。它还演示如何新增工具和命令,以及如何运行 unittest 测试套件。
适用场景
当你需要了解、运行或扩展 clawd-code Python 移植项目时使用,例如查看其命令行、添加工具或命令,或运行一致性审计与测试。
运行要求
需要 Python 3,并克隆仓库、安装依赖;清单、摘要和命令行命令无需 API 密钥,但若要调用真实模型则需设置 ANTHROPIC_API_KEY 或 OPENAI_API_KEY。该技能不附带脚本,仅为说明文档。

clawd-code Python Port

Skill by ara.so — Daily 2026 Skills collection.

What This Project Does

clawd-code is an independent Python rewrite of the Claude Code agent harness, built from scratch for educational purposes. It captures the architectural patterns of Claude Code — tool wiring, command dispatch, task orchestration, and agent runtime context — in clean Python, without copying any proprietary TypeScript source.

The project is orchestrated end-to-end using oh-my-codex (OmX), a workflow layer on top of OpenAI Codex. It is not affiliated with or endorsed by Anthropic.


Installation

bash
# Clone the repositorygit clone https://github.com/instructkr/clawd-code.gitcd clawd-code
# (Optional but recommended) Create a virtual environmentpython3 -m venv .venvsource .venv/bin/activate
# Install dependencies (if a requirements.txt or pyproject.toml is present)pip install -r requirements.txt# orpip install -e .

No API keys are needed for the manifest/summary/CLI commands. If you extend the query engine to call a live model, set your key via environment variable:

bash
export ANTHROPIC_API_KEY="your-key-here"export OPENAI_API_KEY="your-key-here"

Repository Layout

.├── src/│   ├── __init__.py│   ├── commands.py       # Command port metadata│   ├── main.py           # CLI entrypoint│   ├── models.py         # Dataclasses: subsystems, modules, backlog│   ├── port_manifest.py  # Python workspace structure summary│   ├── query_engine.py   # Renders porting summary from active workspace│   ├── task.py           # Task orchestration primitives│   └── tools.py          # Tool port metadata├── tests/                # unittest-based verification└── assets/

Key CLI Commands

All commands run via python3 -m src.main <subcommand>.

bash
# Print a human-readable porting summarypython3 -m src.main summary
# Print the current Python workspace manifestpython3 -m src.main manifest
# List current Python modules/subsystems (paginated)python3 -m src.main subsystems --limit 16
# Inspect mirrored command inventorypython3 -m src.main commands --limit 10
# Inspect mirrored tool inventorypython3 -m src.main tools --limit 10
# Run parity audit against local ignored archive (when present)python3 -m src.main parity-audit
# Run the full test suitepython3 -m unittest discover -s tests -v

Core Data Models (src/models.py)

The dataclasses define the shape of the porting workspace:

python
from dataclasses import dataclass, fieldfrom typing import List, Optional
@dataclassclass Module:    name: str    status: str          # e.g. "ported", "stub", "backlog"    source_path: str    notes: Optional[str] = None
@dataclassclass Subsystem:    name: str    modules: List[Module] = field(default_factory=list)    description: Optional[str] = None
@dataclassclass PortManifest:    subsystems: List[Subsystem] = field(default_factory=list)    backlog: List[str] = field(default_factory=list)    version: str = "0.1.0"

Tools System (src/tools.py)

Tools are the callable units in the agent harness. Each tool entry carries metadata for dispatch:

python
from dataclasses import dataclassfrom typing import Callable, Optional, Any, Dict
@dataclassclass Tool:    name: str    description: str    parameters: Dict[str, Any]          # JSON-schema style param spec    handler: Optional[Callable] = None  # Python callable for this tool
# Example: registering a tooldef read_file_handler(path: str) -> str:    with open(path, "r") as f:        return f.read()
READ_FILE_TOOL = Tool(    name="read_file",    description="Read the contents of a file at the given path.",    parameters={        "path": {"type": "string", "description": "Absolute or relative file path"}    },    handler=read_file_handler,)
# Tool registry patternTOOL_REGISTRY: Dict[str, Tool] = {    READ_FILE_TOOL.name: READ_FILE_TOOL,}
def dispatch_tool(name: str, **kwargs) -> Any:    tool = TOOL_REGISTRY.get(name)    if tool is None:        raise ValueError(f"Unknown tool: {name}")    if tool.handler is None:        raise NotImplementedError(f"Tool '{name}' has no handler yet.")    return tool.handler(**kwargs)

Commands System (src/commands.py)

Commands are higher-level agent actions, distinct from raw tools:

python
from dataclasses import dataclassfrom typing import Optional, Callable, Any
@dataclassclass Command:    name: str    description: str    aliases: list    handler: Optional[Callable] = None
# Example commanddef summarize_handler(context: dict) -> str:    return f"Summarizing {len(context.get('files', []))} files."
SUMMARIZE_COMMAND = Command(    name="summarize",    description="Summarize the current workspace context.",    aliases=["sum", "overview"],    handler=summarize_handler,)
COMMAND_REGISTRY = {    SUMMARIZE_COMMAND.name: SUMMARIZE_COMMAND,}
def run_command(name: str, context: dict) -> Any:    cmd = COMMAND_REGISTRY.get(name)    if not cmd:        raise ValueError(f"Unknown command: {name}")    if not cmd.handler:        raise NotImplementedError(f"Command '{name}' not yet implemented.")    return cmd.handler(context)

Task Orchestration (src/task.py)

Tasks wrap a unit of agent work — a goal, a set of tools, and a result:

python
from dataclasses import dataclass, fieldfrom typing import List, Optional, Any
@dataclassclass TaskResult:    success: bool    output: Any    error: Optional[str] = None
@dataclassclass Task:    goal: str    tools: List[str] = field(default_factory=list)   # tool names available    context: dict = field(default_factory=dict)    result: Optional[TaskResult] = None
    def run(self, dispatcher) -> TaskResult:        """        dispatcher: callable(tool_name, **kwargs) -> Any        Implement your agent loop here.        """        try:            # Minimal stub: just report goal received            output = f"Task received: {self.goal}"            self.result = TaskResult(success=True, output=output)        except Exception as e:            self.result = TaskResult(success=False, output=None, error=str(e))        return self.result
# Usagefrom src.tools import dispatch_tool
task = Task(    goal="Read README.md and summarize it",    tools=["read_file"],    context={"working_dir": "."},)result = task.run(dispatcher=dispatch_tool)print(result.output)

Query Engine (src/query_engine.py)

The query engine renders a porting summary from the active manifest:

python
from src.port_manifest import build_manifestfrom src.query_engine import render_summary
manifest = build_manifest()summary = render_summary(manifest)print(summary)

You can also invoke it from the CLI:

bash
python3 -m src.main summary

Port Manifest (src/port_manifest.py)

Build and inspect the current workspace manifest programmatically:

python
from src.port_manifest import build_manifest
manifest = build_manifest()
for subsystem in manifest.subsystems:    print(f"[{subsystem.name}]")    for module in subsystem.modules:        print(f"  {module.name}: {module.status}")
print("Backlog:", manifest.backlog)

Adding a New Tool

  1. Define a handler function in src/tools.py.
  2. Create a Tool dataclass instance.
  3. Register it in TOOL_REGISTRY.
  4. Write a test in tests/.
python
# src/tools.py
def list_dir_handler(path: str):    import os    return os.listdir(path)
LIST_DIR_TOOL = Tool(    name="list_dir",    description="List files in a directory.",    parameters={"path": {"type": "string"}},    handler=list_dir_handler,)
TOOL_REGISTRY["list_dir"] = LIST_DIR_TOOL

Adding a New Command

python
# src/commands.py
def lint_handler(context: dict) -> str:    files = context.get("files", [])    return f"Linting {len(files)} files (stub)."
LINT_COMMAND = Command(    name="lint",    description="Lint the current workspace files.",    aliases=["check"],    handler=lint_handler,)
COMMAND_REGISTRY["lint"] = LINT_COMMAND

Running Tests

bash
# Run all tests with verbose outputpython3 -m unittest discover -s tests -v
# Run a specific test filepython3 -m unittest tests.test_tools -v

Example test pattern:

python
# tests/test_tools.pyimport unittestfrom src.tools import dispatch_toolimport tempfile, os
class TestReadFileTool(unittest.TestCase):    def test_read_file(self):        with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as f:            f.write("hello clawd")            path = f.name        try:            result = dispatch_tool("read_file", path=path)            self.assertEqual(result, "hello clawd")        finally:            os.unlink(path)
if __name__ == "__main__":    unittest.main()

Parity Audit

When a local ignored archive of the original snapshot is present, run:

bash
python3 -m src.main parity-audit

This compares the current Python workspace surface against the archived root-entry file surface, subsystem names, and command/tool inventories, reporting gaps.


Common Patterns

Chaining tools in a task loop

python
from src.tools import dispatch_toolfrom src.task import Task
task = Task(    goal="Read and list files",    tools=["read_file", "list_dir"],    context={"working_dir": "."},)
# Manual tool chain (before full agent loop is implemented)files = dispatch_tool("list_dir", path=".")for fname in files[:3]:    content = dispatch_tool("read_file", path=fname)    print(f"--- {fname} ---\n{content[:200]}")

Using the manifest in automation

python
from src.port_manifest import build_manifest
def unported_modules():    manifest = build_manifest()    stubs = []    for sub in manifest.subsystems:        for mod in sub.modules:            if mod.status != "ported":                stubs.append((sub.name, mod.name, mod.status))    return stubs
for subsystem, module, status in unported_modules():    print(f"{subsystem}/{module} → {status}")

Troubleshooting

SymptomFix
ModuleNotFoundError: srcRun commands from the repo root, not inside src/
NotImplementedError: Tool 'x' has no handlerThe tool is registered but the Python handler hasn't been written yet — implement handler in tools.py
parity-audit does nothingThe local ignored archive must be present at the expected path; see port_manifest.py for the expected location
Tests not discoveredEnsure test files are named test_*.py and located in tests/
Import errors after adding a moduleAdd __init__.py to any new package subdirectory

Key Links

来源与署名

来源:reason-machines/trending-skills位于skills/clawd-code-python-port提交2384a00

许可证: 无许可证

内容归原作者所有。SourceWeft 从公开仓库中收录这些内容。

举报或申请下架