# AGENTS / CLAUDE.md Concise guidance for agents working in this repository. ## Project ComputerCraft / CC:Tweaked Lua APIs, servers, and programs for Minecraft 1.21. Code runs in the ComputerCraft runtime, not standard Lua. Use [`docs/README.md`](docs/README.md) as the entrypoint for CC:Tweaked, CraftOS-PC, Advanced Peripherals, and Create integration documentation links. Use [`docs/adrs/README.md`](docs/adrs/README.md) for repository architecture decisions. ## Constraints - Do not add a standalone Lua test harness unless asked. Local execution happens through the CraftOS-PC harness (see [`docs/install-craftos-pc.md`](docs/install-craftos-pc.md), [`docs/craftos_pc_glossary.md`](docs/craftos_pc_glossary.md), and [ADR-0005](docs/adrs/adr-0005-craftos-pc-harness-and-probes.md)); code otherwise executes in-game. - Do not run `just repl` as an LLM agent; it is a human-only interactive CraftOS-PC wrapper. Use `just trapos-exec ''` for automated probes against the TrapOS dev environment, or `just craftos-exec ''` for probes against vanilla CraftOS (no TrapOS mounts). These wrappers shut down the machine and include a host watchdog. Headless probes are the recommended way to verify hypotheses about CC:Tweaked behavior; see [ADR-0005](docs/adrs/adr-0005-craftos-pc-harness-and-probes.md). - When changing behavior, add as many useful CraftOS-PC tests as practical. It is acceptable to skip tests that require human-only validation, such as complex turtle motion, in-game UX feel, or visual approval, but still add unit-style non-regression tests for deterministic parts when possible. - Use `/apis/libtest.lua` for test scripts under `tests/`; `/programs/runtest.lua` prints `__TRAPOS_TEST_OK__` only after the suite passes. - `libtest` cancels each case after `3`s (`--timeout ` / `--no-timeout` to override); never commit a hanging test to `tests/`. Slow harness fixtures go in `tests/harness/` behind dedicated recipes. See [ADR-0007](docs/adrs/adr-0007-test-framework.md). - Git hooks own commit/push verification: pre-commit runs `just check test`, and pre-push runs `just ci`. When explicitly asked to commit and/or push, do not run `just test` manually first; rely on the hooks. See [ADR-0011](docs/adrs/adr-0011-repo-conventions.md). - After editing Lua or Markdown, run `just check` and fix all `luacheck` warnings and `lychee` broken-link reports (markdown link validation is offline-only via `just lint-markdown`). - Use 2-space indent, semicolons, and `local function`. - `require` paths are absolute ComputerCraft paths, for example `require('/apis/eventloop')()`. - Most API modules return factories; call the required module once before use. ## Running CraftOS-PC Always go through the `just` recipes — they set repo-local state and the macOS `--rom` path; never call `craftos` directly. - `just craftos [args]` — interactive vanilla CraftOS-PC, no TrapOS mounts, state in `.craftos-vanilla/`. `just trapos [args]` is the same but with the repo mounted and TrapOS state in `.craftos/`. - `just craftos --headless` — pass-through flags to CraftOS-PC; `--headless` boots without a GUI and `--exec ''` runs Lua before the shell. Handy for quick non-interactive boots; combine with `just trapos --headless` for a booted TrapOS env. - For one-shot automated probes prefer `just trapos-exec ''` / `just craftos-exec ''`: they always shut down and have a host watchdog, so they cannot hang the terminal. - `just test [--pretty]` runs the full CraftOS-PC test suite (`__TRAPOS_TEST_OK__` on success). ## Running Connected Computers - For connected TrapOS computers, prefer the MCP `run-file` tool for existing ComputerCraft programs such as `/programs/ccpm.lua`; pass CLI-style arguments with its `args` array, for example `path = "/programs/ccpm.lua", args = { "install", "pkg" }`. Do not use raw MCP Lua execution as a substitute for launching a program, because raw snippets may not provide globals such as `shell` or `require`. - The MCP `run-file` tool path is a file path, not a shell command. Do not append CLI arguments to `path`; `/programs/ccpm.lua install pkg` is treated as a single missing file path. ## Architecture - `apis/eventloop.lua` is the single-threaded event loop around `os.pullEventRaw`; consider using it everywhere async behavior is needed. A handler that returns `api.STOP` auto-unregisters. - `startup/boot.lua` creates a single boot eventloop at `_G.bootEventLoop` and runs it alongside the shell via `parallel.waitForAny`. Servers register handlers on it and return; programs call services via `os.pullEvent` without touching the loop. See [ADR-0002](docs/adrs/adr-0002-eventloop-and-service-bus.md). - `apis/libtest.lua` is the lightweight test helper used by scripts under `tests/`; `/programs/runtest.lua` discovers tests, renders suite output, and owns the `__TRAPOS_TEST_OK__` success marker. - `servers/` register handlers on the boot eventloop and return; `programs/` are clients that exit. ## Boot And Install - `startup/boot.lua` creates the boot eventloop, runs autostart server files (which register handlers and return), then runs the shell and the eventloop in parallel via `parallel.waitForAny`. - Preserve `periphemu` guards used for CraftOS-PC emulation; see [`docs/craftos_pc_glossary.md`](docs/craftos_pc_glossary.md) for upstream emulator references. - Global CraftOS-PC save data lives in `~/Library/Application Support/CraftOS-PC` on macOS and `~/.local/share/craftos-pc` on Linux. Repo launchers use local state instead: `.craftos/` for TrapOS and `.craftos-vanilla/` for vanilla CraftOS-PC. See [`docs/install-craftos-pc.md`](docs/install-craftos-pc.md). - TrapOS ships as packages, each described by `packages//ccpm.json` (`name`, `version`, `dependencies`, `files`, `autostart`); `packages/index.json` lists them. Source files stay in place — descriptors only reference them. To ship a new file, add it to the right package's `files` (and `autostart` if it is a server). `packages/trapos/ccpm.json` is the full OS meta-package. See [ADR-0010](docs/adrs/adr-0010-ccpm-package-manager.md). - `install-trapos.lua` is the one-time wget bootstrap (public entry point `https://os.trapcloud.fr/install`). It installs `trapos-core`/`ccpm`, seeds the default `guillaumearm/cc-libs` registry as a `gitea` registry on `git.trapcloud.fr` tracking `master` (the only channel), then runs `ccpm update` + `ccpm install trapos` and `trapos-postinstall`. Pass `--cpm-only` to stop after the ccpm bootstrap. - `ccpm` (in `trapos-core`) is the package manager: `apis/libccpm.lua` is the testable core (factory with injectable `http`/`stateDir`/`installRoot`), `programs/ccpm.lua` the CLI. State: `/trapos/ccpm.json` (registries), `/trapos/ccpm.lock.json` (installed packages), and `/trapos/ccpm.cache.json` (available packages from `ccpm update`). Never use the word "manifest" in ccpm — it is reserved for the OS manifest. - Add new servers to the relevant package `autostart` list as needed. ## Conventions - Bump the owning `packages//ccpm.json` version (and mirror it in `packages/index.json`) when changing module behavior; programs report it at runtime via `require('/apis/libversion')().forSelf()`. `install-trapos.lua` is the only file that still carries its own `_VERSION` because it is the wget bootstrap and lives outside the package system. - Programs support `-version`/`--version` and `-help`/`--help`; router also supports `-silent`/`--silent`. - French or English comments are fine; match surrounding code. - Commit messages use lightweight conventional style: `topic(scope): description` or `topic: description`. - Reference other `.md` files (and `ADR-####`) with `[text](path)` link syntax so `just lint-markdown` (lychee) can validate them. See [ADR-0011](docs/adrs/adr-0011-repo-conventions.md). See [`DEVELOPMENT.md`](DEVELOPMENT.md) for local setup.