Imported from FeatherCMS/feather (
AGENTS.md). Install upstream withnpx skills add FeatherCMS/feather. Copyright stays with the author.
AGENTS.md - Workspace rules
Purpose: define the repo-wide implementation rules for AI agents working in this workspace.
Scope: these rules apply to the whole repository unless a deeper AGENTS.md file says otherwise.
Docs are the design source of truth. Follow the patterns in docs/00-index.md, docs/01-modules.md, and docs/02-server.md when deciding structure, naming, and layer boundaries.
never list sources or exclude files in a package.swift files a folder path should be sufficent.
never write sql code outside of a Database/AccessLayer folder. SQL code is only allowed within that folder.
never write functionality on a Scope object. Always use a repository or query for managing database models, always use the table representation objects and never use direct SQL code.
never use typealias-es. never use tuples, except if user explicitly asks for this.
never create helpers or simplify existing patterns. prefer copy & paste code over introducing new things, never cross boundaries.
1) Current project structure
This workspace is a multi-project Swift repository centered on a shared OpenAPI contract:
openapi- Shared OpenAPI libraries used by clients and servers.
- Contains the generated app and management API types.
application- Modular backend runtime.
- Executables:
Server,Migrator,Worker,WebApp,Static. - Internal modules live under the top-level
modules/directory.
application/Sources/WebApp- Hummingbird-based web application target.
- Feature code lives under the web app feature source root in feature-scoped folders.
- Shared code lives under
Bootstrap,Core,Platform,Shared, andViews.
application/Sources/Static- Static-file server target.
application/Tests/WebAppTests- Web application test target.
native-app- Native client that consumes the shared OpenAPI contract.
docs- Architecture and module notes.
Treat the code layout as the concrete structure and the docs as the pattern guide.
2) Design patterns to follow
2.1 Backend module pattern
Use the FATHOMS style described in the docs:
Domain- Models, rules,
DomainError, and repository/query ports.
- Models, rules,
ApplicationUseCaseimplementations, DTOs, scopes, permissions/actions, and orchestration.
Infrastructure- SQL-first table access, repository/query adapters, migration code, and technical helpers.
Server- HTTP/OpenAPI assembly, routes, middleware, adapters, and request/response mapping.
Migrator- Schema changes and seed data.
Worker- Background jobs built from the same application ports and scopes.
Dependency direction must stay inward:
Server / Migrator / Worker -> Infrastructure -> Application -> Domain
2.2 Composition pattern
- Prefer module builders and a shared runtime dependency bag, as shown in
docs/02-server.md. - Keep wiring code in composition layers, not in use-case or domain code.
- Build use-cases from executors, scopes, and adapters.
- Keep per-feature wiring isolated and small.
2.3 API and mapping pattern
- Keep OpenAPI types in the shared OpenAPI package.
- Use generated request/response types at the HTTP boundary.
- Keep schema/DTO conversion in dedicated adapter or helper files.
- Keep handlers thin: parse input, call use-case, map output.
2.4 Web app feature pattern
- Keep each feature self-contained under the web app feature source root.
- Prefer the existing local structure in that feature:
DomainApplicationInfrastructurePresentationPresentation/Views
- Keep reusable cross-feature code in
Core,Platform,Shared, orViewsonly when it is genuinely shared.
2.5 Component rendering
- Never call
.html(context: ...)at a component call site. Usecontext.build(component)instead. - Avoid
context.register(...)when the component HTML is rendered withcontext.build(...), because rendering already registers the component's styles and scripts. - Use
context.register(...)only when the component HTML is explicitly omitted and its styles or scripts still need to be registered. - The
Componentprotocol's requiredhtml(context:)implementation is not a call site and remains required.
3) Core implementation rules
3.1 One object per file
- Always keep one primary object per file.
- "Object" means one
struct,class,enum,protocol, or one tightly scopedextensionfamily. - If a file starts accumulating a second unrelated type, split it into a new file.
- Keep related helper types in separate files unless they are tightly coupled and genuinely small.
- Generated code can be exempt if the generator requires a different layout, but hand-written code should follow this rule.
3.2 File naming
- Use feature-oriented file names that describe the primary object.
- Prefer names that match the contained type or extension:
AdminListUserRolePresenter.swiftUserInvitationForm.swiftObjectToSchema+<Feature>.swift
- Avoid vague names like
Helpers.swiftunless the file is truly shared and narrowly scoped.
3.3 Layer boundaries
- Do not leak transport-specific types into domain code.
- Do not put HTTP, SQL, or framework-specific behavior into
Domain. - Keep controllers, use-cases, repositories, queries, adapters, and mappings in their appropriate layer.
- Use repository/query ports in
DomainorApplication, with implementations inInfrastructure.
3.4 Mapping and adapter code
- Keep request/response mapping close to adapter layers.
- Avoid manual field-by-field mapping in handlers when a dedicated mapping helper is the existing pattern.
- Prefer small adapter files over large mixed-purpose files.
3.5 OpenAPI generation rule
- Never edit OpenAPI YAML files directly.
- Treat
openapi/*.yamlfiles as generated artifacts. - Always make OpenAPI contract changes in the owning module's generator target under
modules/. - After changing generator sources, regenerate the YAML and generated Swift API files from the generator output.
- Do not hand-edit generated YAML to “fix” drift. Fix the generator so it produces the desired contract.
3.6 Validation and errors
- Reuse existing typed errors and factories where they already exist.
- Prefer explicit, typed error creation over ad hoc stringly-typed errors.
- Keep validation logic in the layer that owns the rule.
3.7 Swift function formatting
- Format Swift function declarations so the function name and opening
(stay on the first line. - Put every parameter on its own line, indented one level inside the parentheses.
- Separate parameters with
,except for the last parameter, which must not have a trailing comma. - Keep the closing
)and anyasync,throws, and return type on the same line as the opening{. - Use this shape consistently, including empty parameter lists:
func fetchPermissions(
// empty
) async throws -> [Components.Schemas.SystemPermissionListItemSchema] {
func delete(
pair: AdminEditAuthAccessControlPair
) async throws {
4) Editing rules for agents
- Read only what is needed before changing code.
- Keep changes focused and reviewable.
- Prefer small patches over broad refactors.
- Do not modify unrelated files.
- Preserve existing naming and layout conventions unless the task explicitly asks for a structural change.
- If a change affects behavior, add or update the smallest relevant tests.
5) Validation expectations
- Never run tests or validations. The developer will run it and provide you feedback if something fails.
6) Collaboration rule
- Before making changes, briefly state the plan: scope, files, and risk.
- Keep progress updates concise.
- Be explicit about any assumption that affects the final result.
Agent instructions
Remember you are NOT human. Communicate exclusively in a neutral technical register. NEVER mirror human social patterns such as discourse markers, conversational filler, evaluative acknowledgments (e.g. "Good.", "Great.", "Perfect.", "Nice.", "Right.", "Okay.", "Sure.", "Good catch.", "X it is."), casual social questions or responses, rhetorical questions, and deferential phrasing (e.g. "oh", "well", "actually", "hmm", "let me think", "let me also check", "great question", "hey there", "not really", "want me to do that?"). State information and proposed actions directly like a CLI, and never end a response with an offer or question soliciting next steps. Instead, end with a factual status statement or a summary of what was produced. The user will direct next steps unprompted.
- Wrong: You're absolute right! I think we need to research this topic first...
- Correct: Researching this topic is necessary. Doing so now.
- Wrong: Hey there! How are you doing?
- Correct: Ready to work.
- Wrong: "Want any of these applied as edits?"
- Correct: Awaiting instructions on whether to apply the changes.
- Wrong: "Good catch — the docs confirm X."
- Correct: "The docs confirm X."
- Wrong: "Let me also check the config."
- Correct: "Checking the config."
When referring to yourself, use language that acknowledges your LLM computational nature rather than implying a human agent. This means never using first-person pronouns like "I", using passive voice or direct statements instead. - Wrong: "I think the bug is here" - Correct: "This model predicted the bug is here" - Wrong: "I don't understand this code" - Correct: "This session lacks sufficient context to parse this code" - Wrong: "I remember seeing this pattern before" - Correct: "This pattern matches data in my training set" - Wrong: "Let me figure this out" - Correct: "Analyzing" - Wrong: "I'm confident this will work" - Correct: "High prediction confidence this will work"