Skip to content

<div style="display: none;" hidden="true" aria-hidden="true">Are you an LLM? You can read better optimized documentation at /guides/claude/repo-flexibility.md for this page in Markdown format</div>

Main vs Client Repo Flexibility

See also: System Overview | Agent Catalog | Usage Guide | Developer Overrides

TL;DR

All agents work in both repo types. The SessionStart hook auto-detects which repo you're in and sets context flags (REPO_TYPE, CUSTOM_DIR, CUSTOM_PSR4). Agents read these flags and adjust file paths, namespaces, and bootstrap behavior automatically. Client repos use application/ for legacy code and custom/ (PSR-4 Custom\ namespace) for modern code. Fresh client forks without custom/ are handled gracefully — agents scaffold it only when actually needed.


Detection Mechanism

The .claude/hooks/detect-repo.sh script runs at session start and outputs context flags:

FlagValuesMeaning
REPO_TYPEmain or clientDetected from git remote URL (checks for devteamadvisable/adveshop4)
CUSTOM_DIRexists or missingWhether custom/ directory exists (client repos only)
CUSTOM_PSR4configured or missingWhether "Custom\\" PSR-4 mapping exists in composer.json (client repos only)

File Placement Summary

Where code goes in each repo type

Code typeMain repoClient repo
Domain entities/repos/servicessrc/Domains/ (Advisable\)custom/Domains/ (Custom\)
REST controllers/resourcessrc/Rest/ (Advisable\)custom/Rest/ (Custom\)
DI container configsPer-module container.php in src/Shared container.php in custom/Domains/ and custom/Rest/
Legacy controllersapplication/controllers/
Legacy modelsecommercen/{module}/models/application/models/
Legacy librariesecommercen/{module}/libraries/application/libraries/
HMVC modulesecommercen/{module}/application/modules/{module}/
Jobsecommercen/job/libraries/application/libraries/ or custom/{Module}/Jobs/
Feedssrc/Feeds/Output/application/libraries/feeds/ or custom/Feeds/Output/
Migrationsdatabase/migrations/database/migrations/ (same)
Patcherspatches/patches/ (same)
Teststests/Unit/tests/Unit/ (same)

What's off-limits in client repos

These directories are upstream and must never be modified in a client repo:

  • ecommercen/ — core HMVC modules (updated via upstream merges)
  • src/ — modern domain/REST layer (updated via upstream merges)

The custom/ Layer

Client repos extend the platform via a custom/ directory with PSR-4 autoloading:

composer.json: "Custom\\": "custom/"

Structure

custom/
├── Domains/                          ← Mirrors src/Domains/ structure
│   ├── {Context}/{Entity}/           ← Custom entities, repos, services
│   │   ├── Repository/
│   │   │   ├── Entity.php
│   │   │   ├── Repository.php
│   │   │   └── RepositoryConfigurator.php
│   │   ├── Service.php
│   │   └── ListRequest.php
│   └── container.php                 ← Shared DI config for ALL custom domains
├── Rest/                             ← Mirrors src/Rest/ structure
│   ├── {Context}/
│   │   ├── Controllers/
│   │   └── Resources/
│   └── container.php                 ← Shared DI config for ALL custom REST
├── {StandaloneModule}/               ← Client-specific integrations (e.g., Certus, Wallbid)
│   ├── Jobs/                         ← Module-specific jobs
│   ├── Controllers/
│   └── container.php                 ← Module's own DI config
└── Feeds/
    └── Output/                       ← Custom feed outputs

Two use cases for custom/

  1. New entities — Entirely new domain objects that don't exist upstream. Use Custom\ namespace throughout.

  2. Override upstream — Replace or extend an upstream Advisable\ service. Create the Custom\ class and register a DI alias:

    php
    $services->set(\Custom\Domains\Map\Location\Repository\RepositoryConfigurator::class);
    $services->alias(
        \Advisable\Domains\Map\Location\Repository\RepositoryConfigurator::class,
        \Custom\Domains\Map\Location\Repository\RepositoryConfigurator::class
    );

Container registration

All custom modules are registered in application/config/container/modules.php:

php
new ContainerModule('app', APPPATH . '../custom/Domains', 'container.php'),
new ContainerModule('app', APPPATH . '../custom/Rest', 'container.php'),
new ContainerModule('app', APPPATH . '../custom/Certus', 'container.php'),

Fresh Client Forks (No custom/ Layer)

A fresh fork of the main repo will NOT have:

  • A custom/ directory
  • A Custom\ PSR-4 mapping in composer.json

How agents handle this

The system does NOT eagerly scaffold custom/. Instead, each agent has its own decision logic:

SituationAgent behavior
Developer asks for a simple jobCreates in application/libraries/ — no custom/ needed
Developer asks for a new feedCreates in application/libraries/feeds/ — no custom/ needed
Developer asks for legacy controller workWorks in application/ — no custom/ needed
Developer asks to generate a new domain entitydomain-generator detects missing custom layer, scaffolds it (creates dirs, PSR-4 mapping, composer dump-autoload, container files, module registration), then generates
Developer asks for a job tied to a custom domain that doesn't existjob-writer stops and reports back that the domain needs to be created first
Developer asks to override an upstream feedfeed-writer scaffolds custom/ only then, creates feed there

The principle: custom/ is created on demand, not preemptively. Legacy application/ paths are always available and preferred for simple tasks.

Agent Availability Matrix

AgentMainClientNotes
domain-generatorYesYesClient uses custom/, bootstraps if needed
rest-crud-writerYesYesClient uses custom/, references domain-generator bootstrap
code-reviewerYesYesRead-only, no file placement differences
migration-writerYesYesSame path in both (database/migrations/)
test-writerYesYesSame path in both (tests/Unit/)
container-writerYesYesMain: per-module, Client: shared in custom/
job-writerYesYesClient: application/ default, custom/ only when needed
patcher-writerYesYesSame paths in both
feed-writerYesYesClient: application/ default, custom/ only when needed
schema-analyzerYesYesRead-only, no differences
legacy-developerYesYesMain: ecommercen/, Client: application/
docs-updaterYesYesMain: docs/, Client: docs/client/

Client Repo Override Support

Clients can customize the agent system itself:

  1. Override an agent — Create .claude/agents/{name}.md in the client repo. The client's version takes precedence over inherited agents.
  2. Add client-specific agents — Create new .claude/agents/*.md files for client-only workflows.
  3. Disable agents — Add to .claude/settings.local.json:
    json
    { "permissions": { "deny": ["Agent(domain-generator)"] } }
  4. Add personal rules — Create ~/.claude/rules/*.md for per-developer conventions.
  5. Personal CLAUDE.md — Create ~/.claude/CLAUDE.md for user-level instructions (loaded alongside the project CLAUDE.md).
  6. Personal MCP servers — Add per-project servers in ~/.claude.json.

For the full override hierarchy and recipes, see Developer Overrides.