- Use this file as the default source of repo-wide agent guidance for
receipthog-ios. - Follow these rules before introducing new patterns.
- Use
docs/agents/for deeper architecture context when a task touches a documented architecture topic.
- This repo is a mixed UIKit and SwiftUI iOS app, not a greenfield SwiftUI-only codebase.
- Main app code lives under
receipthog/. ios-common/still exists, but its remaining use is limited and legacy.- Tests live primarily under
Receipt HogTests/. - Localization uses existing
.stringsfiles and key-based lookup patterns.
- Prefer Swift for implementation.
- Prefer SwiftUI for new UI where it matches the surrounding feature area.
- Use UIKit where the existing flow is UIKit-based, interop is required, or the task explicitly calls for it.
- Follow MVVM as implemented in the repo.
- Keep views lightweight; avoid business logic in views.
- Keep state and async work in view models.
- Make the smallest correct change that satisfies requirements.
- Do not refactor unrelated code.
- Match existing code style and patterns.
- If requirements are unclear, stop and ask for clarification.
- Do not introduce third-party frameworks without asking first.
- Treat an area as new isolated only when the work is being added to a part of the codebase without a strong pre-existing implementation pattern to follow.
- If the surrounding feature already has an established UIKit, SwiftUI, state-management, constants, or async pattern, follow that pattern unless explicitly instructed to update it.
- In new isolated SwiftUI-first areas, prefer modern SwiftUI, modern observable state patterns, and modern Swift concurrency where they fit cleanly.
- In existing areas, preserve the local architecture unless migration is explicitly part of the task.
- For new isolated SwiftUI-first areas, prefer modern observable state patterns.
- If introducing
@Observabletypes for UI-driven state, use appropriate main-actor isolation. - In existing areas that already use
ObservableObject,@Published,@ObservedObject,@StateObject,@EnvironmentObject, callbacks, or other established patterns, keep the local pattern unless migration is explicitly requested. - Prefer
async/awaitfor new asynchronous work when it fits the surrounding APIs and does not create unnecessary churn. - In legacy flows, preserve the current concurrency model unless the task explicitly includes modernization.
- Write new code with concurrency safety in mind and avoid introducing new actor or threading issues.
- Avoid force unwraps and force
tryunless failure is unrecoverable.
- In new UI work, match the surrounding feature's UI framework, navigation, and styling patterns before introducing a different approach.
- Prefer semantically correct controls such as
Buttonfor user actions when practical. - Keep SwiftUI views readable and composable; extract dedicated
Viewtypes when that improves clarity without causing unrelated refactors. - Avoid
AnyViewunless it is actually required. - Match existing typography patterns in the app and prefer shared
AppFontutilities for new UI work. - Do not introduce ad hoc font styling when an existing
AppFontpattern covers the use case. - Do not enable Dynamic Type or device text-size scaling unless the requirement or surrounding implementation explicitly calls for it.
- Add accessibility identifiers to UI elements where they materially help UI tests, automation, or stable screen assertions.
- When working in an existing feature, follow the local accessibility identifier naming and placement pattern if one already exists.
- Do not inline user-facing strings in code.
- Add new user-facing strings to the English localization file using the repo's existing key-based localization pattern, then reference the key from code.
- Preserve the existing localization workflow so downstream translation to other supported languages can continue through the team's translation service.
- For user-facing text search, prefer locale-aware matching behavior when appropriate for the feature.
- Match the existing search behavior in the touched area unless the task explicitly calls for changing it.
- Reuse existing shared constants before introducing new ad hoc literals.
- Prefer the existing
Kconstant-extension pattern for shared values, especially for event names, notification names, userInfo keys, and other repeated identifiers that benefit from central definition. - When a constants category already exists, extend that category instead of creating a parallel pattern.
- Follow the existing feature-oriented structure already used in the repo.
- Place app code under
receipthog/by default. - Touch
ios-common/only when working with the small set of genuinely shared legacy code that still lives there. - Prefer small, focused files when adding new types, but match the local file organization in the touched area unless restructuring is necessary.
- Write unit tests for core application logic.
- Prefer
XCTestfor new tests unlessQuick/Nimbleis already established in the touched test file or local test area. - Only add UI tests when unit tests are not practical.
- Add comments only where they clarify non-obvious behavior, business rules, or edge cases.
- Never commit secrets such as API keys.
- If the relevant linting, build, or validation tooling is available for the touched area, use it before finalizing changes and avoid introducing new warnings or errors.
- If Xcode MCP tools are available, prefer them when they improve accuracy or speed for reading project files, checking issues, rendering previews, or validating builds.
- Use
docs/agents/for architecture knowledge about key or complex app areas. - Read only the docs relevant to the architecture topic being touched; do not bulk-load all docs for every task.
- Each documented architecture topic should have a Markdown entrypoint under
docs/agents/architecture/<topic>/README.md. - Supporting files such as sequence diagrams, Mermaid files, or exports can live next to that README.
- Use this file for stable repo conventions, not one-off ticket decisions.
- If a developer corrects the agent on a convention, implementation pattern, naming rule, architectural expectation, or workflow preference, treat that as a candidate learned convention.
- When a correction appears durable rather than task-specific, summarize the proposed change and offer to update this file.
- Do not update this file automatically without explicit approval.
- Keep updates concise, repo-specific, and placed in the smallest relevant section.
- If a correction applies only to one subsystem or architecture topic, prefer updating a doc under
docs/agents/instead of expanding this file.