Ctrl K
ComunidadGuías…

CONTRIBUTING.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Contributing to Todd

Thanks for your interest in Todd! Bug reports, fixes, new toolsets, docs and design feedback are all welcome.
This guide covers how to get a development environment running and what we look for in a pull request.

By participating you agree to follow the [Code of Conduct](CODE_OF_CONDUCT.md).

## Ways to contribute

- **Report a bug:** [open an issue](https://github.com/bobby-burns/todd/issues/new/choose) with steps to
  reproduce, the engine you used (Claude plan or API keys) and the relevant `docker compose logs api` output.
  Remove tokens, cookies and personal data first.
- **Suggest a feature:** open a feature request and describe the outcome you want, not only the
  implementation.
- **Report a security issue:** don't open a public issue. See [SECURITY.md](SECURITY.md).
- **Share a toolset:** a plugin file in `./plugins` is often the easiest way to add a capability. If it's
  broadly useful, open a PR.
- **Improve the docs:** typos, unclear steps and missing examples are all worth fixing.

For anything larger than a small fix, please open an issue first so we can agree on the approach before you
spend time on it.

## Development setup

Requirements: Docker with Compose v2.24+, Python 3.12, Node.js 22.

### Full stack (Docker)

```bash
cp .env.example .env
docker compose up -d --build
open http://localhost:3000
```

Rebuild a single service after changing it, e.g. `docker compose up -d --build api`.

### API (FastAPI + LangGraph)

```bash
cd services/api
python3.12 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt pytest
TODD_DATA_DIR=$(mktemp -d) TODD_PLUGINS_DIR=tests/plugins pytest -q tests
```

With no `DATABASE_URL` set, the API uses SQLite in `TODD_DATA_DIR`, so no Postgres is needed for tests.
Models are replaced by a scripted fake (`tests/helpers.py`), so no API keys are needed either.

Some tests run only when their dependency is available and are skipped otherwise:

| Tests                                          | Needs                                                   |
|------------------------------------------------|---------------------------------------------------------|
| `test_claude_code.py`                          | the `claude` CLI on `PATH` (`npm i -g @anthropic-ai/claude-code`) |
| sandbox cases in `test_flow.py`, `test_safety.py` | the sandbox server (`SANDBOX_URL`)                   |
| `test_browser_live.py`, `test_accounts_live.py` | a Chromium reachable over CDP (`BROWSER_CDP_HOST`)     |

To run everything, including the live tests, inside the stack:

```bash
docker compose exec api sh -c 'pip install pytest && TODD_DATA_DIR=$(mktemp -d) DATABASE_URL= TODD_API_TOKEN_FILE= TODD_PLUGINS_DIR=tests/plugins SANDBOX_WORKSPACE=/workspace pytest -q tests'
docker compose exec api python tests/browser_smoke.py
```

### Dashboard (Next.js)

```bash
cd services/web
npm install
API_URL=http://localhost:8000 npm run dev
npm run typecheck && npm run build     # what CI runs
```

## Project layout

```
services/
  api/        FastAPI + LangGraph orchestrator, tools, vault, spend policy (Python)
    todd/     application code (see ARCHITECTURE.md for a module map)
    tests/    pytest suite with scripted fake models
  web/        Next.js dashboard (TypeScript, Tailwind v4, Motion)
  sandbox/    container where code agents run commands
  browser/    headful Chromium + noVNC live view
plugins/      user toolsets, loaded at startup
prompts/      user prompt overrides
```

[ARCHITECTURE.md](ARCHITECTURE.md) explains how a run works end to end and the security model.

## Guidelines

### Code style

- Match the surrounding code: naming, comment density and idiom.
- **Python:** 3.12, type hints on public functions, `async` for anything that does I/O. Tools use
  Google-style docstrings, because they become the schema the model sees, so write them for the model.
- **TypeScript:** strict mode must stay clean (`npm run typecheck`). Reuse the primitives in
  `components/ui.tsx`, the tokens in `app/globals.css` and the spring presets in `lib/motion.ts` rather than
  adding one-off styles.
- Keep dependencies pinned in `services/api/requirements.txt` and `services/web/package-lock.json`.

### Safety-critical code

Todd can spend money and act from the user's accounts, so some areas get extra scrutiny. Changes to these
need tests and a clear explanation in the PR:

- `policy.py`: spend authorization and the ledger
- `vault.py` and output scrubbing: secrets must never reach a prompt, event or log
- `tools/sandbox_tools.py` (`git_push`) and `tools/web.py` (`api_request` host binding)
- card handling in `agents/browser.py` and `tools/browser_direct.py`
- API token checks and network isolation in `main.py` and `docker-compose.yml`

The rule of thumb is that **policy lives in code, not in prompts**. A model should never be able to talk its
way past a spend limit or an approval.

### Tests

- Add or update tests for behaviour changes. `tests/helpers.py` has `ScriptedModel` and `call()` for
  scripting an agent's tool calls without a real model.
- Make sure `pytest` passes and the dashboard type-checks and builds before you open a PR. CI runs both.

### Commits and pull requests

- Keep PRs focused: one logical change per PR is easier to review and to revert.
- Write commit messages in the imperative mood ("Add Cloudflare toolset", not "Added…").
- Fill in the PR template, including how you tested the change.
- Update `README.md`, `ARCHITECTURE.md` or `prompts/README.md` if you change behaviour they describe, and
  add a line to [CHANGELOG.md](CHANGELOG.md) under **Unreleased**.
- UI changes: include a screenshot or short clip, in light and dark mode.

## License

By contributing, you agree that your contributions will be licensed under the [MIT License](LICENSE).