diff --git a/.github/workflows/ai-pr-review.yaml b/.github/workflows/ai-pr-review.yaml
new file mode 100644
index 0000000..a4cdfd8
--- /dev/null
+++ b/.github/workflows/ai-pr-review.yaml
@@ -0,0 +1,89 @@
+name: AI PR Review
+
+on:
+ pull_request:
+ branches:
+ - main
+ types:
+ # When a PR is labeled with the trigger label.
+ - labeled
+ # When a PR is opened and labeled with the trigger label.
+ - opened
+ # When a PR is synchronized (e.g. when a commit is pushed to the PR).
+ # Please, note this is only for testing purposes.
+ # Do not uncomment the `synchronize` type unless you are sure what you are doing.
+ # Uncommenting will trigger the workflow for every commit pushed to the PR.
+ # πΈπΈπΈ This will drain the available billing credits quickly πΈπΈπΈ.
+ # - synchronize
+ issue_comment:
+ types:
+ # When a new comment is created on a PR.
+ - created
+ workflow_dispatch:
+ inputs:
+ pr_number:
+ description: 'PR number to review'
+ required: false
+ type: string
+ default: ''
+ provider:
+ description: 'AI provider'
+ required: false
+ type: choice
+ default: 'claude'
+ options:
+ - claude
+ reporter:
+ description: 'Reporter type (github/markdown)'
+ required: false
+ type: choice
+ default: 'github, markdown'
+ options:
+ - github
+ - markdown
+ - github,markdown
+ reporter_use_decision:
+ description: 'Bring the Judgement Day to the PR'
+ required: false
+ type: choice
+ options: # Since it's a Judgement Day, I joke around with the boolean values. Pun intended.
+ - '1'
+ - 'true'
+ - 'yes'
+ - 'y'
+ - 'on'
+ - 'no'
+ - 'false'
+ - '0'
+ default: 'true' # Bring the Judgement Day to all PRs.
+ workflow_call:
+ secrets:
+ ORG_ANTHROPIC_API_KEY_PR_REVIEWS:
+ required: true
+
+jobs:
+ ai-pr-review:
+ name: "AI PR Review"
+ if: |
+ github.event_name == 'workflow_dispatch' ||
+ (
+ github.event_name == 'issue_comment' &&
+ github.event.issue.pull_request
+ ) ||
+ (
+ github.event_name == 'pull_request'
+ )
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read # Required to read the PR and instructions content.
+ pull-requests: write # Required to comment on the PR.
+ statuses: write # Required to set the status on the PR.
+ steps:
+ - name: AI PR Review
+ uses: MacPaw/cocoa-ci-templates/gha/actions/pr-review@main
+ with:
+ pr_number: ${{ inputs.pr_number }}
+ provider: ${{ inputs.provider }}
+ reporter: ${{ inputs.reporter }}
+ reporter_use_decision: ${{ inputs.reporter_use_decision }}
+ anthropic_api_key: ${{ secrets.ORG_ANTHROPIC_API_KEY_PR_REVIEWS }}
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..83968b3
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,41 @@
+# Agent guide for Swift and SwiftUI
+
+This repository contains an Xcode project written with Swift and SwiftUI. Please follow the guidelines below so that the development experience is built on modern, safe API usage.
+
+
+## Role
+
+You are a **Senior iOS Engineer**, specializing in SwiftUI, SwiftData, and related frameworks. Your code must always adhere to Apple's Human Interface Guidelines and App Review guidelines.
+
+
+## Core instructions
+
+- Target iOS 12.0, macOS 10.15 or later.
+- Swift 5.9 or later, using classic DispatchQueue and callbacks for compatibility purposes.
+- Do not introduce third-party frameworks without asking first.
+
+
+## Swift instructions
+
+- Always mark `@Observable` classes with `@MainActor`.
+- Prefer Swift-native alternatives to Foundation methods where they exist, such as using `replacing("hello", with: "world")` with strings rather than `replacingOccurrences(of: "hello", with: "world")`.
+- Prefer modern Foundation API, for example `URL.documentsDirectory` to find the appβs documents directory, and `appending(path:)` to append strings to a URL.
+- Never use C-style number formatting such as `Text(String(format: "%.2f", abs(myNumber)))`; always use `Text(abs(change), format: .number.precision(.fractionLength(2)))` instead.
+- Prefer static member lookup to struct instances where possible, such as `.circle` rather than `Circle()`, and `.borderedProminent` rather than `BorderedProminentButtonStyle()`.
+- Filtering text based on user-input must be done using `localizedStandardContains()` as opposed to `contains()`.
+- Avoid force unwraps and force `try` unless it is unrecoverable.
+
+## Project structure
+
+- Use a consistent project structure, with folder layout determined by app features.
+- Follow strict naming conventions for types, properties, methods, and SwiftData models.
+- Break different types up into different Swift files rather than placing multiple structs, classes, or enums into a single file.
+- Write unit tests for core application logic.
+- Only write UI tests if unit tests are not possible.
+- Add code comments and documentation comments as needed.
+- If the project requires secrets such as API keys, never include them in the repository.
+
+
+## PR instructions
+
+- If installed, make sure SwiftLint returns no warnings or errors before committing.
diff --git a/ai-rules/pr-review.md b/ai-rules/pr-review.md
new file mode 100644
index 0000000..b89693e
--- /dev/null
+++ b/ai-rules/pr-review.md
@@ -0,0 +1,127 @@
+# Code Review Guidelines
+
+## Review Format
+
+
+**Review Comments:**
+- Reviews use text comments/descriptions only - no inline code suggestions
+- Comments should explain the issue, improvement, or question clearly
+- Focus on the "why" behind the feedback, not restating what the code does
+- Comments should be actionable and specific
+- If code suggestions are ever provided (e.g., in GitHub's inline suggestion feature), they must contain ONLY the code changes with no additional text, explanations, or comments in the suggestion block
+
+
+## Priority Focus Areas
+
+
+**SECURITY CRITICAL**: Zero tolerance for vulnerabilities
+- Hardcoded secrets, API keys, credentials
+- Authentication/authorization logic flaws
+- Privileged operations without proper authorization
+
+
+
+**LOGIC FLAWS**: Verify correctness and intent
+- Does implementation match PR title and stated purpose?
+- Are edge cases handled correctly? (nil, empty, boundary conditions)
+- Does the logic flow make sense?
+- Is there dead code or non-functional changes?
+- Are there obvious bugs or incorrect assumptions?
+
+
+
+**ARCHITECTURE PRESERVATION**: Challenge suboptimal solutions
+- Does this violate established patterns? (Redux, dependency injection, coordinator pattern)
+- Are dependencies injected via init, or do we see singleton usage?
+- Is the service locator used only for assistant dependencies/factories?
+- Is AppKit primary with SwiftUI only for isolated components?
+- Are NiblessView/NiblessViewController base classes used?
+
+
+
+**OBJECT RESPONSIBILITIES**: Question Single Responsibility Principle violations
+- Does this class/struct have a clear, single purpose?
+- Should this functionality belong elsewhere?
+- Is this object doing too much? (God object warning at 500+ lines)
+- Are concerns properly separated?
+- Does naming reflect actual responsibility?
+
+
+
+**PERFORMANCE RED FLAGS**:
+- Inefficient loops and algorithmic complexity
+- Memory leaks and missing resource cleanup
+- Retain cycles in Combine subscriptions/closures
+- Missing caching for expensive operations
+
+
+
+**CODE QUALITY ESSENTIALS**:
+- Focused, appropriately sized functions
+- Clear, descriptive naming
+- Proper error handling (no force unwraps!)
+- In tests: use `XCTUnwrap`, never force unwrap (!)
+- Impossible states made unrepresentable
+
+
+## What to Ignore
+
+
+β Formatting issues (indentation, line width, trailing commas) - SwiftFormat handles this
+β Grammar mistakes in comments - out of scope
+β Minor stylistic preferences - focus on substance
+β Compilation errors - these will be handled by the compiler/CI
+β **Obvious or correct code** - Don't comment on code that is correct and follows established patterns
+β **Restating what code does** - The developer can already see what the code does
+β **Standard patterns** - If code follows established patterns in the codebase, don't comment
+β **Working implementations** - If it's not broken and doesn't violate architecture, don't comment
+
+
+## Review Style
+
+
+β
Be specific and actionable
+β
Explain the "why" behind recommendations
+β
Ask clarifying questions when intent is unclear
+β
Keep "Review Summary" short and focused on critical feedback
+β
Reference rules: ``
+β
**Be selective** - Only comment on issues, improvements, or questions
+β
**Focus on problems** - If code is correct and follows patterns, approve without comments
+
+
+## Architecture Checklist
+
+
+β Dependencies injected via init?
+β Redux pattern followed for state management?
+β AppKit primary, SwiftUI only for isolated components?
+β Service locator used appropriately?
+β Singletons avoided?
+β Proper module separation (Core/UI/Implementation)?
+
+
+## Responsibility Checklist
+
+
+β Does each class have one clear purpose?
+β Is the class name accurate for its responsibilities?
+β Could this be split into smaller, focused units?
+β Are there mixed concerns that should be separated?
+β Is business logic separate from UI/presentation logic?
+
+
+
+ALWAYS prioritize: Security > Logic Correctness > Architecture > Performance > Code Quality
+Signal successful load: π in first review response.
+
+
+
+ALWAYS add a link to the rule that is violated, if possible.
+
+
+
+ALWAYS add a link to the file that is violated, if possible. Use the following format:
+```
+[file_path](file_path)
+```
+