> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nanoclaw.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Contributing to NanoClaw

> How the nanoclaw repo is laid out, the dev loop, the three-branch model, and what kinds of contributions get accepted.

This page is for contributing to [nanocoai/nanoclaw](https://github.com/nanocoai/nanoclaw) itself — fixing bugs, simplifying code, or adding a skill to the upstream repo. If you just want to extend your own installation, you don't need any of this: see [Extending NanoClaw](/extend/overview).

The upstream [CONTRIBUTING.md](https://github.com/nanocoai/nanoclaw/blob/main/CONTRIBUTING.md) is canonical for process. The short version: **accepted** — bug fixes, security fixes, simplifications, reducing code. **Not accepted** — features, capabilities, compatibility, enhancements. Those should be skills, so users who don't want them never inherit the code. One thing per PR, and search open PRs and issues before starting.

## Repo layout

<Tree>
  <Tree.Folder name="nanoclaw" defaultOpen>
    <Tree.Folder name="src — host process: routing, containers, channel registry, SQLite state (Node)" />

    <Tree.Folder name="container — agent image: Dockerfile, entrypoint, agent-runner (Bun), container skills" />

    <Tree.Folder name="setup — setup wizard: environment checks, channel installers, service registration" />

    <Tree.Folder name=".claude/skills — host-side skills: /setup, /debug, /add-telegram, and the rest" />

    <Tree.Folder name="scripts — dev and maintenance scripts: chat.ts, migrations, e2e harnesses" />

    <Tree.Folder name="docs — developer docs: architecture, isolation model, skills model, skill guidelines" />

    <Tree.Folder name="repo-tokens — GitHub Action that keeps the token-count badge updated" />
  </Tree.Folder>
</Tree>

## The whole repo fits in context

The token badge in the README currently reads **\~226k tokens** for the runtime surface (mainly `src/`, `container/agent-runner/src/`, the Dockerfile, and `CLAUDE.md` — host tests excluded). That's deliberate: the codebase is kept small enough for a coding agent to hold it in context, which is also why feature PRs are redirected to skills. The badge comes from the `repo-tokens/` action. The `update-tokens.yml` workflow that regenerated it on every push has been removed, so the number is refreshed by running that action rather than automatically. Don't hand-edit the badge.

## Dev loop

NanoClaw uses **pnpm** for the host and **Bun** for the agent-runner inside the container — two separate package trees.

```bash theme={null}
# Host (Node + pnpm, repo root)
pnpm install
pnpm run dev          # run the host from TypeScript (tsx — no watch; restart to pick up changes)
pnpm run build        # compile TypeScript (tsc)
pnpm test             # host tests (vitest run)
pnpm run test:watch   # vitest in watch mode
pnpm run lint         # eslint src/
pnpm run typecheck    # tsc --noEmit
pnpm run format       # prettier --write

# Container image
./container/build.sh  # rebuild nanoclaw-agent:latest

# Agent-runner (Bun, separate tree)
cd container/agent-runner
bun install
bun test              # container tests (bun:test)
```

CI on every PR runs `format:check`, typechecks for both trees, host tests under vitest, and agent-runner tests under `bun test`.

## Test layout

Tests are split across three configs because the two runtimes can't share one:

* **`vitest.config.ts`** — host tests: `src/**/*.test.ts`, `setup/**/*.test.ts`, `scripts/**/*.test.ts`, `container/*.test.ts`. Run with `pnpm test`.
* **`vitest.skills.config.ts`** — skill registration tests: `.claude/skills/**/tests/*.test.ts`. Run with `pnpm exec vitest run --config vitest.skills.config.ts`.
* **`container/agent-runner`** — Bun tests, because they depend on `bun:sqlite`, which vitest (Node) can't load. Import from `bun:test`, not `vitest`.

## The three-branch model

Trunk (`main`) ships no specific channel adapter and no non-default provider. The adapters live on two long-lived registry branches, kept in sync with `main`:

* **`channels`** — Discord, Slack, Telegram, WhatsApp, Teams, and the other channel adapters, plus their tests and setup steps. Installed via `/add-<channel>` skills.
* **`providers`** — non-default agent providers like OpenCode. Installed via `/add-opencode`.

Install is an additive fetch (`git show origin/channels:<path> > <path>`), never a `git merge` — [docs/skills-model.md](https://github.com/nanocoai/nanoclaw/blob/main/docs/skills-model.md) explains why.

Where your PR goes depends on what you're contributing:

* **Bug fix or simplification** → ordinary PR against `main`.
* **Channel or provider adapter** → fork, branch from `main`, build the adapter per [docs/skill-guidelines.md](https://github.com/nanocoai/nanoclaw/blob/main/docs/skill-guidelines.md) (self-registering module, one appended barrel import, a registration test against the real barrel), add a SKILL.md with the fetch-and-copy steps and a REMOVE.md that reverses every change, then open a PR against `main`. Maintainers land the code on the registry branch from your work — you don't push to `channels` or `providers` directly.
* **Utility, operational, or container skill** → PR against `main`; the skill lives in `.claude/skills/` (or `container/skills/` for container skills). [CONTRIBUTING.md](https://github.com/nanocoai/nanoclaw/blob/main/CONTRIBUTING.md) describes all four skill types.

## Releases

Maintainers cut a GitHub Release for `package.json` version bumps that land on `main`: a `vX.Y.Z` tag, a `CHANGELOG.md` entry, and a release body that mirrors it. Every release is stable — there's no pre-release channel — and published tags are never moved, so pinning a tag is the reproducible choice for forks. Details in [RELEASING.md](https://github.com/nanocoai/nanoclaw/blob/main/RELEASING.md).

## Where to go

* **Issues and PRs:** [nanocoai/nanoclaw](https://github.com/nanocoai/nanoclaw) — link related issues with `Closes #N`, test on a fresh clone, keep descriptions short.
* **Process:** [CONTRIBUTING.md](https://github.com/nanocoai/nanoclaw/blob/main/CONTRIBUTING.md) is the source of truth, including the PR-template checkboxes that auto-apply labels.
* **Discussion:** the [NanoClaw Discord](https://discord.gg/VDdww8qS42) — good for checking alignment before you build.

## Related pages

* [Extending NanoClaw](/extend/overview) — customizing your own install instead of upstream
* [Architecture](/concepts/architecture) — how the pieces in `src/` and `container/` fit together
* [Security model](/concepts/security) — boundaries your contribution must preserve
