ApexLibrarian
A librarian for your Apex classes.It restores the directory layout the org stripped — from a declaration inside each class.
Salesforce orgs have no concept of folders for Apex classes. Every retrieve flattens your repository layout into classes/. ApexLibrarian lets each class declare its shelf in a doc comment, and one command puts every file back where it belongs.
/** * Recalculates opportunity discounts from line items. * @directory Usecases/opportunity */public with sharing class ReconcileDiscount {Doc comments are part of the class body, so the@directorytag survives every round trip through the org.
The hierarchy a retrieve destroys, one command restores
A real example: the four Apex Stem frameworks installed as Unlocked Packages, right aftersf project retrieve. All 95 classes return to the exact layout a submodule install would give you.
classes/ ├── AbstractEntry.cls ├── ApexBlueprintException.cls ├── CountClause.cls ├── Eloquent.cls ├── MockEntry.cls ├── SBlueprint.cls ├── Scribe.cls ├── Trace.cls ├── TraceFlow.cls ├── TriggerHandler.cls └── … all 95 classes, flat
npx apex-librarian arrange→classes/ ├── ApexBlueprint/ │ ├── SBlueprint.cls │ └── tests/ ├── ApexEloquent/ │ ├── Scribe.cls │ ├── AggregateClauses/ │ │ └── CountClause.cls │ ├── Eloquents/ │ │ └── Eloquent.cls │ └── Entries/ │ └── MockEntry.cls ├── ApexTrace/ │ ├── Trace.cls │ └── TraceFlow.cls └── ApexTools/ └── TriggerHandler/ └── TriggerHandler.cls
Every .cls-meta.xml moves together with its class. Each move is a plain rename — git status shows exactly what happened, and git checkout . undoes it.
The tag is the declaration, the filesystem is the reality
Three commands, each resolving divergence in one direction.
checkcompare only
Detects divergence between declaration and reality, exiting 1 if any exists. Put it in CI or a pre-commit hook to stop layout drift mechanically.
arrangetag → location
After a retrieve: moves files to the directory their tag declares. It never overwrites — an occupied target is reported and skipped.
stamplocation → tag
When adopting an existing project: writes the current layout into every class's doc comment, once. Also after a deliberate git mv.
Every Apex Stem class ships pre-stamped
All four Apex Stem frameworks (ApexEloquent v3.7.0 / ApexBlueprint v2.1.0 / ApexTrace v1.5.0 / ApexTools v1.1.0 and later) are distributed with @directory tags on every class. Install them as Unlocked Packages, retrieve, run arrange once — and you get the exact same hierarchy as a submodule install.