.claude/skills/crane-architecture/SKILL.md
This skill should be used when the user asks about "facet", "target", "repo", "diamond pattern", "storage slot", "guard function", "DFPkg", "AwareRepo", "Service pattern", "Modifiers", "ERC2535", or needs guidance on Crane's core architectural patterns for building modular, upgradeable smart contracts.
npx skillsauth add cyotee/crane crane-architectureInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Crane is a Diamond-first (ERC2535) Solidity development framework for building modular, upgradeable smart contracts. This skill provides guidance on the core architectural patterns.
Every feature in Crane follows a three-tier architecture:
| Layer | File Pattern | Purpose |
|-------|--------------|---------|
| Repo | *Repo.sol | Storage library with assembly-based slot binding. Defines Storage struct and dual _layout() functions. No state variables. |
| Target | *Target.sol | Implementation contract with business logic. Uses Repo for storage access. Inherits interfaces. |
| Facet | *Facet.sol | Diamond facet. Extends Target and implements IFacet for metadata (name, interfaces, selectors). |
All Repos use the Diamond storage pattern with dual function overloads:
library ExampleRepo {
bytes32 internal constant STORAGE_SLOT = keccak256(abi.encode("crane.feature.name"));
struct Storage {
mapping(address => bool) isOperator;
}
// Parameterized version - allows custom slot
function _layout(bytes32 slot) internal pure returns (Storage storage layout) {
assembly { layout.slot := slot }
}
// Default version - uses STORAGE_SLOT
function _layout() internal pure returns (Storage storage) {
return _layout(STORAGE_SLOT);
}
}
Every Repo function has TWO overloads:
// 1. Parameterized: takes Storage as first param
function _isOperator(Storage storage layout, address query) internal view returns (bool) {
return layout.isOperator[query];
}
// 2. Default: calls parameterized with _layout()
function _isOperator(address query) internal view returns (bool) {
return _isOperator(_layout(), query);
}
This enables:
Repos contain _onlyXxx() guard functions with access control logic. Modifiers are thin wrappers:
// In Repo - contains the actual check logic
function _onlyOperator(Storage storage layout) internal view {
if (!_isOperator(layout, msg.sender) && !_isFunctionOperator(layout, msg.sig, msg.sender)) {
revert IOperable.NotOperator(msg.sender);
}
}
function _onlyOperator() internal view {
_onlyOperator(_layout());
}
// In Modifiers contract - thin delegation wrapper
modifier onlyOperator() {
OperableRepo._onlyOperator();
_;
}
*Modifiers.sol)Abstract contracts with reusable modifiers delegating to Repo guards:
abstract contract OperableModifiers {
modifier onlyOperator() {
OperableRepo._onlyOperator();
_;
}
}
*Service.sol)Stateless libraries for complex business logic. Use structs to avoid stack-too-deep:
library CamelotV2Service {
struct SwapParams {
ICamelotV2Router router;
uint256 amountIn;
IERC20 tokenIn;
}
function _swap(SwapParams memory params) internal { ... }
}
*AwareRepo.sol)Dependency injection for external contract references:
library BalancerV3VaultAwareRepo {
bytes32 internal constant STORAGE_SLOT = keccak256("protocols.dexes.balancer.v3.vault.aware");
struct Storage {
IVault balancerV3Vault;
}
function _initialize(IVault vault) internal { _layout().balancerV3Vault = vault; }
function _balancerV3Vault() internal view returns (IVault) { return _layout().balancerV3Vault; }
}
*DFPkg.sol)Bundles facets into deployable packages. See references/dfpkg-pattern.md for complete details.
All facets implement IFacet:
function facetName() external view returns (string memory name);
function facetInterfaces() external view returns (bytes4[] memory interfaces);
function facetFuncs() external view returns (bytes4[] memory funcs);
function facetMetadata() external view returns (string memory name, bytes4[] memory interfaces, bytes4[] memory functions);
Use hierarchical dot-notation:
| Pattern | Example |
|---------|---------|
| Crane core | "crane.access.operable" |
| Protocol integrations | "protocols.dexes.balancer.v3.vault.aware" |
| EIP implementations | "eip.erc.8023" |
For complete implementations, examine these files in the Crane codebase:
contracts/access/operable/ - Complete Facet-Target-Repo examplecontracts/introspection/ERC2535/ERC2535Repo.sol - Diamond storage managementcontracts/access/ERC8023/ - Two-step ownership (EIP-8023)contracts/protocols/dexes/camelot/v2/services/CamelotV2Service.sol - Service patternFor detailed patterns and complete examples:
references/dfpkg-pattern.md - Diamond Factory Package pattern in depthreferences/factory-service.md - FactoryService pattern for deployment| Need | Pattern |
|------|---------|
| Storage for a feature | Create *Repo.sol |
| Business logic | Create *Target.sol or *Service.sol |
| Diamond-exposed functions | Create *Facet.sol |
| External contract reference | Create *AwareRepo.sol |
| Reusable access control | Create *Modifiers.sol |
| Deployable package | Create *DFPkg.sol |
development
Review UI code for Web Interface Guidelines compliance. Use when asked to "review my UI", "check accessibility", "audit design", "review UX", or "check my site against best practices".
documentation
Write to contracts and send transactions. Use when executing state-changing contract functions.
development
HTTP and WebSocket transports for blockchain connectivity. Use when configuring network connections.
data-ai
Read contract data with type-safe ABI. Use when querying smart contract view/pure functions.