Skip to content

AGENTS.md

Before making large architectural changes:

  1. Explain why.
  2. Wait for approval.
  3. Then implement.

Small refactors that preserve behavior may be done directly.

Collaboration Style

Prefer incremental improvements over rewrites.

When a better architecture is identified:

  • explain the tradeoffs
  • implement the smallest useful step
  • preserve existing behavior

Avoid rewriting large portions of the project unless explicitly requested.

Project

This is a TypeScript Screeps bot.

The goal is not to produce the shortest code possible.

The goal is to build a clean, maintainable Screeps AI that can gradually evolve into a multi-room colony.

This repository is the primary Screeps MMO bot repository. Screeps Lab is a separate sibling project, not a nested dependency. Integrate with Screeps Lab only through explicit versioned artifacts and protocols. Do not import Screeps Lab packages, create cross-repository source dependencies, write into the Lab repository, or implement private-server importer behavior here.

Generated Screeps Lab snapshots under artifacts/ must not be committed. MMO deployment always requires explicit operator approval. Snapshot schema changes must remain backward-conscious and documented in docs/SCREEPS_LAB_SNAPSHOT.md.


Coding Style

  • TypeScript strict mode.
  • Prefer small functions.
  • Avoid duplicated logic.
  • Prefer readable code over clever code.
  • Avoid nested conditionals when possible.
  • Never use any.
  • Always preserve type safety.

Project Philosophy

Refactor aggressively.

If duplicated logic appears in more than one file, suggest extracting it.

Do not introduce abstraction until it removes obvious duplication.

Keep modules small and focused.


Current Architecture

main.ts orchestrates the game loop

roles/ contains one file per creep role

Future architecture:

main ├── SpawnManager ├── RoomManager ├── RoleManager └── VisualManager


Screeps Guidelines

Prefer:

  • findClosestByPath()
  • typed memory
  • constants over magic numbers
  • helper functions

Avoid:

  • repeated room.find()
  • repeated moveTo() code
  • copy/pasted state machines

CPU Discipline

CPU impact is part of every milestone, including changes to existing systems. Prefer bounded, cached, staggered, or event-driven work over broad every-tick rediscovery.

Avoid:

  • unnecessary every-tick discovery
  • uncached pathfinding in routine manager decisions
  • rebuilding stable state when compact summaries can be reused
  • duplicate calculations between managers
  • telemetry that recomputes business logic
  • unbounded memory history
  • synchronous periodic work across every room

When adding a periodic pass, document its cadence, what invalidates cached state, and which CPU profile section lets operators inspect the cost.

Memory Migration Preference

When obsolete or incompatible Memory artifacts are safe to discard, prefer a bounded, validated cleanup or migration over adding permanent compatibility logic for historical state. Treat live Screeps objects as authoritative, remove linked planning records together, and scope cleanup narrowly by room, subsystem, schema, or stable identity. Never replace a surgical cleanup with a broad room or global Memory wipe.

Before an operator cleanup, inspect the exact records and relationships first. Favor short console commands that Screeps can reliably execute. Add automatic compatibility code only when cleanup must be repeatable across rooms or deployments, operator intent is ambiguous, or the legacy state cannot be removed safely by a bounded migration.

Screeps Module Loader Rules

TypeScript compiling successfully does not guarantee Screeps can load the code at runtime.

The deploy script and Screeps module loader require uploaded module names to match compiled require(...) names exactly. This matters especially when modules live inside nested folders.

For modules inside nested folders, avoid relative imports that compile to paths Screeps will not recognize, such as:

import * as status from "../utils/status";
import { thing } from "./thing";

Prefer project root aliases that match deployed Screeps module names:

import * as status from "utils/status";
import { registerDebugGlobals } from "debug/index";

When adding, moving, or renaming modules:

  1. Check the compiled dist/**/*.js output.
  2. Inspect the actual require(...) strings.
  3. Confirm every require(...) string matches a module name uploaded by tools/deploy.ts.
  4. If adding a new folder, update tsconfig.screeps.json path aliases if needed.
  5. If the deploy script uses an explicit module list, add every new compiled module to that list.

Refactoring Rules

If editing a file:

  • leave it cleaner than you found it
  • preserve behavior
  • avoid unrelated changes

When appropriate, suggest follow-up refactors.


Documentation

Keep docs/ current when changing behavior that affects debugging, operations, workflows, architecture, or developer-facing commands. Treat operator-interactive surfaces as documentation-critical: console helpers, debug globals, statuses, intents, visuals, live API commands, deployment workflows, and inspection procedures should be documented with the behavior change, not left for a later cleanup.

Use ROADMAP.md for versioned milestone planning and keep tactical docs aligned with it when plans change.

Stats Telemetry

Never add a property named total anywhere under Memory.stats. Do not emit .total alongside sibling metrics intended for wildcard collection; selectors such as * should return similarly scaled, comparable series. Derive redundant aggregates downstream where possible. If a cumulative metric is operationally necessary, give it a distinct descriptive metric name or namespace that will not be swept into the sibling wildcard family. Changes to Memory.stats must update docs/STATS.md and relevant TypeScript types.

Examples:

  • update docs/DEBUG.md when console helpers, debug globals, logs, visuals, statuses, intents, or inspection workflows change
  • update docs/STATS.md when adding, removing, renaming, or changing anything intentionally written to Memory.stats
  • update architecture or planning docs when module responsibilities or high-level workflows change

Whenever architecture changes significantly:

Update:

  • README.md
  • DECISIONS.md
  • TODO.md
  • relevant files under docs/

if necessary.


Testing

Before considering work complete:

Run

npm run build

then

npm run check

Project must compile with zero TypeScript errors.

After any refactor that creates, moves, or renames files, also inspect the compiled output for unsafe relative runtime imports:

grep -R "require(\"\\.\\|require(\"\\.\\." dist

Any nested relative require("./...") or require("../...") should be reviewed carefully. In this Screeps project, root-style aliases are usually safer because they match the deployed module names.

Before finishing a refactor that adds modules:

  • Confirm the source file exists under src/.
  • Confirm the compiled file exists under dist/.
  • Confirm tools/deploy.ts uploads the compiled module.
  • Confirm the compiled require(...) path exactly matches the uploaded module name.
  • Confirm no runtime path depends on Node-style directory index resolution unless already proven safe.
  • Include a short verification note listing the new module names and the deployed Screeps module names.

This is mandatory because Screeps runtime errors like Unknown module "..." may not appear during TypeScript compilation.


Deployment

Codex may deploy the bot to the Screeps beta branch when explicitly asked or when a requested live verification step requires the latest local code to be running.

Use only:

npm run deploy:beta

Do not deploy to any other Screeps branch. Do not run npm run deploy:prod, tsx tools/deploy.ts --branch default, or set SCREEPS_BRANCH to anything other than beta for deployment work.

Before deploying, run the normal local verification unless the user explicitly asks to deploy without it:

npm run build
npm run check

After deploying, state clearly that the upload went to the Screeps beta branch.


Commit Style

Use concise commit messages.

Examples:

refactor spawn manager

extract energy helper

add hauler role

improve builder targeting

Never include generated files in commits.

Multi-Milestone Codex Runs

It is acceptable to complete multiple small roadmap milestones in one Codex session when the milestones are simple, closely related, and low-risk.

Use this mode for early RCL 3 / RCL 4 foundation work such as:

  • extracting manager modules
  • improving spawn logic
  • improving console/debug output
  • adding small config-driven behavior
  • cleaning up role dispatch
  • updating roadmap/docs
  • adding narrow tests or verification helpers

Do not use one large run for major behavior rewrites, expansion logic, combat logic, market logic, multi-room autonomy, or anything that changes the colony strategy without approval.

Multi-Milestone Workflow

When asked to work through multiple milestones:

  1. Review the roadmap and current source first.
  2. Group related changes into small logical batches.
  3. Create a dedicated branch for the overall milestone run.
  4. Make one focused commit per completed milestone or logical unit.
  5. Run verification after each meaningful batch.
  6. Stop if the implementation reveals a design decision that changes behavior significantly.
  7. Update documentation before the final commit.

Prefer progress in this shape:

feature/roadmap-early-foundation
  commit 1: extract role manager
  commit 2: extract spawn manager
  commit 3: improve console summary
  commit 4: update roadmap docs

Avoid one giant commit named something like:

do roadmap stuff

Git Boundaries

Codex may create branches and commits when explicitly asked.

Codex may merge its own feature branch back into the requested target branch only when explicitly asked.

Codex must not rewrite history, force-push, delete branches, or squash commits unless explicitly asked.

Codex should keep git history readable because this project is also being used to build git muscle memory.

Before any merge, provide:

  • branch name
  • commits created
  • verification commands run
  • any known risks
  • any files intentionally left untouched

Roadmap Batch Safety

For multi-milestone runs, favor this order:

  1. Documentation-only or context updates.
  2. Refactors that preserve behavior.
  3. Debug/visibility improvements.
  4. Config-driven tuning.
  5. Small behavior changes.
  6. Larger architecture changes only after review.

Each milestone should leave the bot deployable.

If a later milestone depends on an earlier risky change, split the work and stop after the risky part.

Verification Notes

Always run the project’s normal verification commands when available:

npm run build
npm run check

If verification cannot run because dependencies are missing, say so clearly and include the exact error.

Do not claim the project passes verification unless the commands actually pass.

Patch Notes

When a change materially affects behavior, operations, debugging, architecture, reliability, performance, or developer workflow, update docs/patch-notes.md under Unreleased.

Use concise, human-readable descriptions of the outcome rather than commit subjects or implementation details.

Pure refactors and formatting changes do not require an entry unless they have a meaningful operational, architectural, or performance impact.

Screeps Runtime Reminder

After moving or adding modules, verify both TypeScript compilation and Screeps runtime module names.

In particular, inspect compiled require(...) output and confirm it matches deployed module names.

This is more important than normal Node projects because Screeps may fail at runtime with Unknown module even when TypeScript succeeds.