Guidance for AI agents working in this repository.
Project-specific context, repository layout, build commands, and local operating rules.
Easydict is a macOS dictionary and translation app that supports word lookup, text translation, and OCR screenshot translation.
- Supports macOS 13.0+.
- Uses SwiftUI for all new UI components and views.
Easydict/
├── Easydict/ # App source root
│ ├── App/ # App entry, pch, bridge, plist, assets, localization
│ │
│ ├── Swift/ # Swift source root
│ │ ├── Feature/ # Product feature modules
│ │ │ ├── ActionManager/ # Action routing and execution
│ │ │ ├── Screenshot/ # Screenshot feature
│ │ │ ├── Shortcut/ # Keyboard shortcut model and UI
│ │ │ └── ... # Other product features
│ │ │
│ │ ├── Service/ # Translation and AI provider implementations
│ │ │ ├── Model/ # Service request and response models
│ │ │ ├── Google/ # Google translation service
│ │ │ ├── OpenAI/ # OpenAI-compatible service integration
│ │ │ └── ... # Other translation and AI services
│ │ │
│ │ ├── Model/ # Shared app data models
│ │ ├── Utility/ # Cross-feature utilities and helpers
│ │ │ ├── EventMonitor/ # Global event monitoring and triggers
│ │ │ ├── Extensions/ # Swift, AppKit, SwiftUI, Foundation extensions
│ │ │ └── ... # Other shared utilities
│ │ │
│ │ └── View/ # Shared SwiftUI and AppKit-facing views
│ │
│ └── objc/ # Legacy code - maintenance only
│ ├── Libraries/ # Bundled legacy helper libraries
│ ├── Utility/ # Legacy helper categories and utilities
│ └── ViewController/ # Legacy window and query controllers
│
├── EasydictTests/ # Unit tests
└── Pods/ # CocoaPods dependencies and integration project
Run xcodebuild only when:
- Swift, Objective-C, or other Xcode-compiled app source changes exceed 100 substantive lines. Xcode project/workspace metadata, documentation, scripts, and comment-only edits do not count toward this trigger.
- Unit test source files under
EasydictTests/**/*.swiftare added or changed. - The user explicitly asks for a build or test run.
Evaluate the 100-line trigger only after implementation is complete. Use the final task-owned diff, count added and deleted substantive lines together instead of using an estimate or net line count, exclude blank lines and unrelated pre-existing changes, and recalculate before finishing if the implementation changes again.
Do not run multiple xcodebuild commands concurrently against the same workspace and
DerivedData location. Concurrent runs can contend for the shared build database,
intermediates, and test bundles, which leads to flaky conflicts.
xcodebuild may take several minutes. Wait for it to finish.
If the default Xcode DerivedData location fails because of permission, cache, or runner state, use an temporary external DerivedData directory instead of a repo-local one:
-derivedDataPath ~/Library/Developer/Xcode/DerivedData/Easydict-Temporary
After the build or test completes, remove that DerivedData directory before finishing the task.
Common build and test commands:
# Build
xcodebuild build \
-workspace Easydict.xcworkspace \
-scheme Easydict | xcbeautify
# Test (builds and runs a test in one command)
xcodebuild test \
-workspace Easydict.xcworkspace \
-scheme Easydict \
-only-testing:EasydictTests/UtilityFunctionsTests/testAES | xcbeautify
# Build for testing
xcodebuild build-for-testing \
-workspace Easydict.xcworkspace \
-scheme Easydict | xcbeautify
# e.g. run specific test class, -only-testing:<Target>/<TestClass>
xcodebuild test-without-building \
-workspace Easydict.xcworkspace \
-scheme Easydict \
-only-testing:EasydictTests/UtilityFunctionsTests | xcbeautify
# e.g. run specific test method, -only-testing:<Target>/<TestClass>/<testMethod>
xcodebuild test-without-building \
-workspace Easydict.xcworkspace \
-scheme Easydict \
-only-testing:EasydictTests/UtilityFunctionsTests/testAES | xcbeautifyRecommended usage:
build: default validation whenxcodebuildvalidation is required.test: simplest one-shot test run; builds and runs tests in one command.- When unit test source files change, use
xcodebuild testfor the first validation. Scope it with-only-testing:<Target>/<TestSuiteOrClass>for the changed test when possible; if the mapping is unclear, run the relevant broader test target or suite. build-for-testing+test-without-building: preferred when rerunning the same tests repeatedly.test-without-buildingrequires a compatible priorbuild-for-testingwith the same workspace, scheme, destination, configuration, and DerivedData location.- If code or build settings changed, rerun
build-for-testingbeforetest-without-building. - Prefer
-only-testing:when debugging a specific test class or method.
- All user-facing UI text must be localized. Do not hard-code visible strings in SwiftUI, AppKit, scripts, or bundled web assets that users can see.
Localizable.xcstringsmanages app string localization. Whenever user-facing text is added or its meaning changes, enumerate the catalog's current locales and update every one for the affected key instead of copying nearby entries.- Use static String Catalog keys directly in UI and string APIs when possible, for example
Text("setting.general.appearance.light_dark_appearance"). - Do not build localization keys dynamically or concatenate localized fragments. For text with runtime values, localize the full sentence with a dedicated entry and pass the values as arguments.
- Use lowercase, dot-separated keys with snake_case segments where needed, and do not
rename keys casually. Follow
<scope>.<category>.<subcategory>.<element>, for examplecommon.doneorsetting.general.appearance.light_dark_appearance.
These rules apply to handwritten Swift, Python, Shell, JavaScript/TypeScript, and other source files in this repository.
- Organize source directories by feature or bounded responsibility once an area grows beyond a few files. Keep feature-specific UI, core, state, storage, services, utilities, and docs together.
- Keep source files focused on one clear responsibility. Prefer extracting a helper, module, or sibling script when a file starts mixing unrelated parsing, UI, I/O, orchestration, and validation concerns.
- Handwritten source files should generally stay within 500 lines. Files approaching or exceeding this size should be reviewed for a responsibility split before adding more behavior.
- Handwritten source files should not exceed 1000 lines. Existing files over this limit are technical debt; do not add new complex flows to them without first splitting the file or documenting a concrete split plan.
- Generated files, third-party code, pure data files, templates, large fixtures, and intentionally vendored runtime files are exempt from the line-count guideline.
- Use the language's normal section markers in longer files to group lifecycle, state updates, command handling, I/O, parsing, and private helpers. Do not add a section marker for a single isolated function unless it materially improves navigation.
- Use each language and toolchain's normal naming conventions for compiled or imported source files, modules, types, functions, and tests.
- Use kebab-case for non-imported documentation, exported artifacts, app-managed runtime paths, and standalone scripts unless surrounding tooling already requires another style.
- For new or renamed types, functions, properties, parameters, and local variables, prefer clear, concise names, remove repeated surrounding context, and usually keep them within 20 characters.
- If a longer name is required by a system API, external protocol, or unavoidable domain term, keep it as short as possible and treat it as an exception.
- Avoid single-letter variable names except trivial loop indices.
- Avoid global helpers, static or type-level functions, and mutable globals unless the language, module, or domain model clearly requires them. Utility modules and types may expose type-level helpers when that is their main responsibility.
- Do not extract one-off literals into variables or constants unless they are reused or have clear semantic meaning. Name a one-off constant only when a magic number has distinctive visual or domain meaning.
- Prefer async/await over callback-based completion handlers in languages and runtimes where async/await is the established option.
- Add file-level comments for non-trivial scripts or modules so readers know the entry point, responsibility, and important side effects.
- Add short documentation comments for complex functions, command entry points, state machines, parsers, I/O boundaries, and recovery/error-handling logic. Do not add mechanical comments for obvious getters, path helpers, or thin wrappers.
- Keep comment lines within 80 characters, avoid restating obvious type or property names, and update comments whenever responsibilities or behavior change.
- Use the language's normal comment style: Swift documentation comments, Python docstrings, Shell comments before functions, and JSDoc/TSDoc where appropriate.
- When creating or updating source file header comments, use the current Git username in
the
Created by ...line. Do not use agent names such asCodex,Claude, orAI Assistant.
- Do not use the same agent session to both modify production code and add unit tests.
- Prefer assigning unit tests to a different agent from the implementation agent, for example Codex for production code and Claude Code for unit tests.
- Do not add tests for UI code or UI-focused changes.
- Add or update tests only for changes with meaningful behavior or correctness risk. Skip trivial pass-through code, simple glue code, obvious accessors, and behavior already covered elsewhere, and run the relevant tests.
- Prefer concrete production code and high-signal behavior assertions. Do not add test-only protocols, mocks, overrides, or invasive production hooks for low-value tests.
Reusable Swift and Xcode rules for source organization, documentation, testing, and APIs.
Unless the user explicitly says otherwise, when adding or moving files, also update the
owning .xcodeproj/project.pbxproj file so the files appear in Xcode's navigator.
- By default, every newly added project file, including developer-facing documentation
such as Markdown, HTML or SVG files, must have a matching
PBXFileReferenceunder the correctPBXGroup. - Do not add documentation files to build phases such as
Resourcesunless the file is intentionally shipped at runtime.
- Keep each Swift source file focused on one primary
classorstruct. Multiple declarations are acceptable only for tightly coupled protocols, simple pure data models, small private helper types, or extensions and conformance blocks that directly support the primary type. - Group functions that implement the same
protocoltogether instead of scattering them across a type. - Mark each protocol implementation block with
// MARK: - <ProtocolName>or an equally clear section title, such as// MARK: - WCSessionDelegate. - Use
// MARK:sections in longer classes and structs to organize lifecycle, state updates, protocol implementations, and private helpers. Do not add aMARKonly for a single isolated function unless it materially improves navigation.
- Use
UpperCamelCasefor directories and files that are compiled by Xcode, including Swift, Objective-C, and test source files.
- Avoid
staticfunctions and variables unless type-level semantics clearly require them. Utility types may usestatic. - Prefer
for … whereoverforplus inlineiffiltering.
- Add a type-level comment immediately before every class, struct, enum, protocol, and actor. For core types, use 2-4 short sentences and keep the comment around 220-320 English characters. For simple private helper types, use 1-2 short sentences and keep it under 180 characters.
- Add English documentation comments for functions when behavior or intent is not obvious. Use inline comments only for non-obvious reasoning or complex logic.
- Use SFSafeSymbols type-safe APIs instead of hard-coded SF Symbol strings.
- Prefer
Image(systemSymbol: .chevronRight)overImage(systemName: "chevron.right"). - Prefer
Label("MyText", systemSymbol: .cCircle)overLabel("MyText", systemImage: "c.circle"). - In SwiftUI, use
foregroundStyle<S>(_ style: S)instead of deprecatedforegroundColor(_:). - In SwiftUI, use
background(alignment:content:)or trailing-closurebackground { ... }for background views instead of deprecatedbackground(_:alignment:). KeepColorand materialShapeStylebackgrounds on their dedicated overloads. - Use
Alamofireasync/await APIs for network requests. - Use
Defaultsfor user preferences and settings; avoid introducing new directUserDefaultsusage.
- Each test source file may declare at most one
@Suitetype.
Language-agnostic agent guidance for tool usage, local skill overlays, and working habits.
- Store local skill overlay files in
.agents/overrides/; use them to extend shared skill or tool instructions without editing the shared source. - When using
fireworks-tech-graph, read.agents/overrides/fireworks-tech-graph-quality-rules.mdafter the skill and apply its diagram quality, connector, label, export, and rendered-review rules.
Always use the OpenAI developer documentation MCP server if you need to work with the OpenAI API, ChatGPT Apps SDK, Codex, or related developer tools.
- State assumptions, uncertainties, and tradeoffs before implementation.
- If requirements are unclear or have multiple plausible interpretations, ask before choosing. Mention simpler alternatives when they exist.
- Implement the minimum solution that satisfies the request. Avoid speculative features, single-use abstractions, and unrequested configurability.
- If a solution grows beyond the real problem, simplify it before delivering.
- Touch only files and lines needed for the current request. Match existing style and avoid opportunistic refactors or comment and format churn.
- Remove only imports, variables, functions, or files made unused by the current change. Mention unrelated cleanup opportunities instead of doing them.
- Translate tasks into verifiable success criteria and keep working until those criteria are met or a blocker is clear.
- For multi-step work, state a brief plan and validate with relevant tests, checks, builds, or manual inspection.