Metadata-Version: 2.5
Name: monkeyscode
Version: 1.0.2
Summary: MonkeysCode SDK — programmatic agent control for Python
Project-URL: Homepage, https://monkeyscode.com
Project-URL: Documentation, https://monkeyscode.com/docs/sdk/python
Project-URL: Repository, https://github.com/MonkeysCloud/monkeyscode
Project-URL: Issues, https://github.com/MonkeysCloud/monkeyscode/issues
License: MIT
License-File: LICENSE
Keywords: ai,automation,coding-agent,monkeyscode,sdk
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2.0
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Description-Content-Type: text/markdown

# MonkeysCode Python SDK

Run the MonkeysCode coding agent from Python. `monkeyscode.cli_process` starts
an installed `mc` and yields its events: the same tools, permission rules,
hooks and MCP servers as `mc -p`. The module uses only the standard library.

```bash
pip install monkeyscode            # Python 3.10+
npm install -g monkeyscode-cli     # the mc it drives, 1.0.0 or newer
```

```python
import asyncio
from monkeyscode.cli_process import (
    CliOptions, MonkeysCodeClient, PermissionAllow, PermissionDeny, ResultMessage, query,
)

async def can_use_tool(tool, tool_input, ctx):
    if str(tool_input.get("path", "")).startswith("docs/"):
        return PermissionAllow()
    return PermissionDeny(message="only docs/ may be written")

async def main() -> None:
    # One turn
    async for event in query("What does src/main.ts do?", CliOptions(cwd="/path/to/repo")):
        if isinstance(event, ResultMessage):
            print(event.subtype, event.result, event.cost_usd)

    # Several turns in one session
    options = CliOptions(cwd="/path/to/repo", can_use_tool=can_use_tool, max_cost_usd=1)
    async with MonkeysCodeClient(options) as client:
        await client.send("Write docs/intro.md")
        print((await client.receive_result()).result)
        await client.send("Now summarise what you changed")
        print((await client.receive_result()).result)

asyncio.run(main())
```

Auth: `MONKEYSCODE_API_KEY`, or the login saved by `mc auth login`.

Deny rules, plan mode and destructive-command guards are decided before
`can_use_tool`, and it can't override them.

## Using Auto mode

Auto mode lets MonkeysCode pick the model for each step: Capuchin by default,
a frontier model only when the task needs it. Pass `model="auto-mode"` (or
`"monkeyscode-auto"`), or `"auto-max"` for Max quality. The plain `"auto"`
still means your default model, not Auto mode. Auto needs a Pro plan or
above (Max: Pro+); on other plans the result has `exit_code` 4 and a
`plan_required` card.

```python
from monkeyscode import PlanRequiredError, ResultMessage, RouteMessage, require_success
from monkeyscode.cli_process import CliOptions, query

async def run(model: str) -> ResultMessage:
    result = None
    async for event in query("Fix the failing test", CliOptions(cwd="/path/to/repo", model=model)):
        if isinstance(event, RouteMessage):
            print(f"step ran on {event.routed} ({event.reason})")
        elif isinstance(event, ResultMessage):
            result = event
    assert result is not None
    return require_success(result)

try:
    await run("auto-mode")
except PlanRequiredError as e:
    print(e, e.upgrade_url)
    if e.fallback_model:  # e.g. capuchin-reason
        await run(e.fallback_model)
```

`PlanRequiredError` subclasses `McProcessError`, so existing `except` code
still catches it. Route events are informational: the routed model can change
from step to step.

## Docs

- [Python guide](https://monkeyscode.com/docs/sdk/python): permissions,
  multi-turn, structured answers, every option
- [Events and results](https://monkeyscode.com/docs/sdk/events)
- [SDK overview](https://monkeyscode.com/docs/sdk/overview)

The `monkeyscode.MonkeysCode` class, `monkeyscode.ci.ci_run` and `Session`
call a hosted endpoint that isn't live yet, so they fail with an HTTP error.
Use `cli_process`.

## License

MIT
