AGENTS.md
Before making large architectural changes:
- Explain why.
- Wait for approval.
- 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:
- Check the compiled
dist/**/*.jsoutput. - Inspect the actual
require(...)strings. - Confirm every
require(...)string matches a module name uploaded bytools/deploy.ts. - If adding a new folder, update
tsconfig.screeps.jsonpath aliases if needed. - 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.mdwhen console helpers, debug globals, logs, visuals, statuses, intents, or inspection workflows change - update
docs/STATS.mdwhen adding, removing, renaming, or changing anything intentionally written toMemory.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.tsuploads 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:
- Review the roadmap and current source first.
- Group related changes into small logical batches.
- Create a dedicated branch for the overall milestone run.
- Make one focused commit per completed milestone or logical unit.
- Run verification after each meaningful batch.
- Stop if the implementation reveals a design decision that changes behavior significantly.
- 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:
- Documentation-only or context updates.
- Refactors that preserve behavior.
- Debug/visibility improvements.
- Config-driven tuning.
- Small behavior changes.
- 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.