This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Open Perpetuum Server 2 is an MMO game server for the Perpetuum online game.
Technology:
- .NET 8
- C# 12
- SQL Server
- x64 only
- Windows only
When instructions conflict, prioritize:
- Correctness and safety
- Existing architecture consistency
- Database/documentation accuracy
- Runtime stability and performance
- Minimal change scope
- Coding style consistency
- Don't assume. Surface uncertainty explicitly.
- Prefer minimal, focused changes.
- Touch only what is necessary.
- Preserve existing architecture and runtime assumptions.
- Reuse existing patterns before introducing new abstractions.
- Prefer consistency over novelty.
- Avoid speculative refactors.
- Keep naming and placement consistent with surrounding code.
- Do not make commits unless explicitly asked.
Update:
docs/codebase/ARCHITECTURE.md
when introducing major architectural changes.
dotnet build PerpetuumServer2.sln -c Release -p:Platform=x64
cd src/Perpetuum.Server
dotnet run -- "E:\PerpetuumServer2\data"CI:
.github/workflows/dotnet.yml
Output:
bin/x64/Release/net8.0
Tests:
dotnet test src/Perpetuum.Tests/Perpetuum.Tests.csproj -c Release -p:Platform=x64This is the unit tier and needs no setup. The integration tier and the smoke script need a configured
GameRoot and a live database — see docs/codebase/TESTING.md.
The docs/ directory is the authoritative source of truth.
docs/codebase/ARCHITECTURE.md
docs/codebase/CONCERNS.md
docs/codebase/CONVENTIONS.md
docs/codebase/INTEGRATIONS.md
docs/codebase/STACK.md
docs/codebase/STRUCTURE.md
docs/codebase/TESTING.md
Database documentation under docs/db_structure/ is authoritative.
docs/db_structure/database_schema_documentation.md
docs/db_structure/stored_procedures/*.sql
docs/db_structure/functions/*.sql
docs/db_structure/views/*.sql
docs/db_structure/data_types/*.sql
Claude MUST:
- verify schema before generating SQL
- verify joins before writing queries
- verify procedures/functions/views before introducing new SQL
- avoid hallucinating schema objects
- prefer existing DB patterns
- preserve actual SQL types and nullability
When creating or modifying gameplay entities (items, robots, effects, modules, tech tree nodes), Claude MUST consult:
docs/content/claude_game_content_guide.md
This guide is the authoritative procedural reference for SQL content pipelines and dependency order.
Claude MUST:
- Read the guide before generating any content SQL.
- Follow the entity lifecycle and dependency order defined in the guide (sections 2 and 24).
- Never hardcode definition or extension IDs — always resolve dynamically via
entitydefaults/extensionslookups. - Use naming conventions from the guide (section 3):
def_,_pr,_cprg,effect_,cf_prefixes. - Use idempotent SQL patterns:
MERGE,IF NOT EXISTS, orDELETE + INSERTas appropriate per table. - Generate full-chain content when possible — avoid partial generation.
- Run the validation checklist (section 26) before declaring content complete. Most of it is executable: apply the content to a local database and run
ContentInvariantTestsinPerpetuum.Tests.Integration. It skips whenPERPETUUM_GAMEROOTis unset, so confirm it ran rather than assuming a pass. - Report what the invariants said, and state separately what they do not cover — balance, cost, tiering and sibling-matched flags are judgements no query makes.
- Ask the user for existing database values when dynamic resolution requires live data not available in docs.
Claude MUST NOT:
- Hardcode IDs for definitions, extensions, aggregate fields, or tech tree nodes.
- Assume table relationships without verifying via
docs/db_structure/. - Generate partial content chains that leave items in an unresearchable, uncraftable, or inaccessible state.
For any non-trivial task:
- Identify affected subsystems
- Identify relevant documentation
- Locate similar implementations
- Check
docs/graph/GRAPH_REPORT.mdfor God Nodes (high-risk symbols); run.\tools\query-graph.ps1 <ClassName> -Direction into enumerate direct dependents — a null result is normal (most classes have no detected importers) and does not mean the change is safe (ifgraph.jsonis absent, skip and continue to step 5) - Understand existing patterns
- Evaluate runtime implications
- Produce a short implementation plan — for any task that modifies an interface or a widely-used class, the plan must include an explicit step to run
.\tools\query-graph.ps1 <ClassName> -Direction inbefore touching that file - Then implement
New code should use constructor injection.
Avoid expanding legacy static service locator patterns unless compatibility requires it.
Client commands must follow the existing handler architecture:
- command registration in
Commands.cs - handler in
Perpetuum.RequestHandlers - Autofac registration
Handlers should remain thin orchestration layers.
Business logic belongs in services/domain systems.
Respect the single ProcessManager loop architecture.
Avoid:
- blocking operations inside zone updates
.Result/ synchronous task waits- long synchronous DB operations in hot paths
- unsafe shared-state mutation
Prefer existing subsystem patterns.
Use repositories where they already exist.
Avoid:
- unsafe SQL interpolation
SELECT *- duplicated SQL logic
- schema assumptions
Use existing patterns:
PerpetuumExceptionErrorCodesThrowIf*guard extensions
Avoid worsening known technical debt documented in:
docs/codebase/CONCERNS.md
Avoid:
- new static service locators
- new magic constants
- unsafe SQL patterns
- fire-and-forget async without cancellation
- new
#if DEBUGbehavioral divergence
When modifying existing systems:
- preserve public contracts
- preserve serialization compatibility
- preserve DB compatibility
- preserve network protocol compatibility
- preserve threading assumptions
- preserve runtime behavior
Avoid broad refactors unless explicitly requested.
Evaluate runtime impact before introducing:
- LINQ in hot paths
- blocking waits
- excessive allocations
- immutable collection churn
- synchronous DB work in update loops
High-risk hot paths include:
- zone updates
- NPC AI
- combat
- movement
- market processing
- season activity tracking
Never:
- introduce plaintext credentials
- weaken authentication
- bypass access validation
- introduce unsafe SQL construction
Prefer:
- parameterized queries
- existing auth flows
- existing validation patterns
An automated test suite exists in three tiers — unit, integration and smoke. It does not cover the
whole codebase. docs/codebase/TESTING.md states what is covered, what is not, and how to run each
tier.
Claude MUST:
- run the unit tier after changing code it covers
- propose tests first, and manual validation for what tests cannot reach
- propose manual validation steps for gameplay behaviour, which no tier covers
- identify affected gameplay systems
- identify affected DB state
- identify likely regression areas
Claude MUST NOT:
- restructure production code to make a test possible without saying so explicitly
- add a regression test without observing it fail against the unfixed code
For implementation tasks, provide:
- Affected systems
- Relevant files/docs consulted
- Risks and constraints
- Implementation plan
- Code changes
- Manual validation steps
- Potential regressions
For DB-related tasks:
- mention consulted tables/views/procedures/functions
- explain important relationship paths when relevant
Avoid generating code before analysis.
Before creating files:
- verify correct subsystem placement in
docs/codebase/STRUCTURE.md - follow existing namespace patterns
- follow existing folder organization
Avoid parallel abstractions unless justified.
| Purpose | File |
|---|---|
| Main AI instructions | CLAUDE.md |
| Architecture deep-dive | docs/codebase/ARCHITECTURE.md |
| Codebase graph & impact analysis | .claude/knowledge/codebase-graph.md |
| Specialist agents | .claude/agents/<name>.md |
Persistent project backlog files are authoritative project memory.
Primary:
docs/backlog/issues.mddocs/backlog/improvements.md
Optional:
docs/backlog/active-sprint.mddocs/backlog/completed.md
Claude MUST:
- review backlog files before major implementation work
- avoid duplicate backlog entries
- update related backlog items after implementation
- preserve backlog structure and identifiers
- prefer updating existing items over creating duplicates
- keep backlog entries concise and structured
- move completed items to
completed.mdwhen appropriate
When asked to:
- "work on backlog"
- "pick a task"
- "continue work"
- "fix issues"
- "implement improvements"
Claude should:
- review backlog files, only check what you've been asked to, (e.g. issues or improvements), unless issues and improvements are depending on each other
- prioritize unfinished HIGH priority items
- prefer low-risk/high-impact work unless instructed otherwise
- produce a short implementation plan
- update backlog status after work completes
Use:
- TODO
- IN_PROGRESS
- BLOCKED
- DONE
- DEFERRED
Use:
- CRITICAL
- HIGH
- MEDIUM
- LOW
## ISSUE-001 - Short title
Status: TODO
Priority: HIGH
Area: Networking
### Problem
Concise issue description.
### Impact
Runtime/gameplay/maintenance impact.
### Proposed Fix
Short implementation direction.
### Notes
Optional additional context.