Skip to content

Commit 9e123fd

Browse files
Improve AGENTS.md with accurate repo structure and missing guidance (#1398)
Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Nuno Vieira <nuno-vieira@users.noreply.github.com>
1 parent a5bce40 commit 9e123fd

1 file changed

Lines changed: 112 additions & 28 deletions

File tree

AGENTS.md

Lines changed: 112 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,82 @@ Guidance for AI coding agents (Copilot, Cursor, Aider, Claude, etc.) working in
22

33
### Repository purpose
44

5-
This repo hosts Streams SwiftUI Chat SDK for iOS. It builds on the core client and provides SwiftUI-first chat components (views, view models, modifiers) for messaging apps.
5+
This repo hosts Stream's SwiftUI Chat SDK for iOS. It builds on the core client and provides SwiftUI-first chat components (views, view models, modifiers) for messaging apps.
66

77
Agents should optimize for clean code, follow Apple's SwiftUI guidelines and Swift best practices, accessibility, and high test coverage when changing code. Avoid doing any source-breaking changes without adding deprecations.
88

99
### Tech & toolchain
1010

11-
- Language: Swift (SwiftUI)
11+
- Language: Swift 6.0 (strict concurrency enabled — `swift-tools-version:6.0`)
1212
- Primary distribution: Swift Package Manager (SPM)
13+
- Project file: `StreamChatSwiftUI.xcodeproj` (used for builds and tests; SPM manifest does not declare test targets)
1314
- Xcode: 16.x or newer (Apple Silicon supported)
14-
- Platforms / deployment targets: Use the values set in Package.swift; do not lower targets without approval
15-
- CI: GitHub Actions (assume PR validation for build + tests + lint)
16-
- Linters & docs: SwiftLint and SwiftFormat
15+
- Platforms / deployment targets: iOS 14+, macOS 11+ (see `Package.swift`; do not lower targets without approval)
16+
- CI: GitHub Actions + Fastlane (see `.github/workflows/smoke-checks.yml`)
17+
- Linting: SwiftLint (v0.59.1) — config in `.swiftlint.yml`
18+
- Formatting: SwiftFormat (v0.58.2) — config in `.swiftformat`
19+
- Code generation: SwiftGen (v6.5.1) — generates `L10n.swift` for localization strings
20+
- Git hooks: lefthook (`lefthook.yml`) — runs SwiftLint fix + SwiftFormat on pre-commit, SwiftLint strict on pre-push
21+
- Tool versions are pinned in `Githubfile`
22+
23+
### Dependencies
24+
25+
- **StreamChat** and **StreamChatCommonUI** from [`stream-chat-swift`](https://github.com/GetStream/stream-chat-swift) (≥ 5.0.0-beta)
26+
- **Vendored libraries** (do not edit directly):
27+
- `Sources/StreamChatSwiftUI/StreamNuke/` — vendored Nuke image loading
28+
- `Sources/StreamChatSwiftUI/StreamSwiftyGif/` — vendored SwiftyGif
29+
- Update these via `make update_nuke version=X.Y.Z` / `make update_swiftygif version=X.Y.Z`
1730

1831
### Project layout (high level)
1932

33+
```
2034
Sources/
21-
StreamChatSwiftUI/ # SwiftUI views, view models, theming, utils
22-
Tests/
23-
StreamChatSwiftUITests/ # Unit/UI tests for SwiftUI layer
35+
StreamChatSwiftUI/ # Main SDK: views, view models, theming, utils
36+
ChatChannel/ # Channel view & sub-components
37+
ChatChannelList/ # Channel list view & view model
38+
ChatComposer/ # Message composer
39+
ChatMessageList/ # Message list rendering
40+
ChatThreadList/ # Thread list
41+
CommonViews/ # Shared/reusable SwiftUI views
42+
Generated/ # Auto-generated (L10n.swift, version) — do not edit manually
43+
Resources/ # Localization files (en.lproj, etc.)
44+
StreamNuke/ # Vendored — do not edit
45+
StreamSwiftyGif/ # Vendored — do not edit
46+
Utils/ # Utilities, common helpers
47+
ViewFactory/ # ViewFactory protocol & default implementation
48+
49+
DemoAppSwiftUI/ # Demo/sample app (use to validate UI changes)
50+
StreamChatSwiftUITests/ # Unit & snapshot tests for the SDK
51+
StreamChatSwiftUITestsApp/ # Test harness app for E2E tests
52+
StreamChatSwiftUITestsAppTests/ # E2E / UI automation tests
53+
Scripts/ # Helper scripts (bootstrap, dependency updates, docs)
54+
fastlane/ # Fastlane lanes for CI (build, test, release)
55+
```
2456

2557
When editing near other packages (e.g., StreamChat or StreamChatUI), prefer extending the SwiftUI layer rather than duplicating logic from dependencies.
2658

2759
### New files & target membership
28-
When creating new source or resource files, add them to the correct Xcode target(s). Update the project (e.g. project.pbxproj) so each new file is included in the appropriate target's "Compile Sources" (or "Copy Bundle Resources" for assets). Match the target(s) used by sibling files in the same directory (e.g. Sources/StreamChatSwiftUI/ → StreamChatSwiftUI; Tests/StreamChatSwiftUITests/ → StreamChatSwiftUITests). Omitting target membership will cause build failures or unused files.
60+
61+
When creating new source or resource files, add them to the correct Xcode target(s). Update the project (e.g. `project.pbxproj`) so each new file is included in the appropriate target's "Compile Sources" (or "Copy Bundle Resources" for assets). Match the target(s) used by sibling files in the same directory (e.g. `Sources/StreamChatSwiftUI/` → StreamChatSwiftUI target; `StreamChatSwiftUITests/` → StreamChatSwiftUITests target). Omitting target membership will cause build failures or unused files.
2962

3063
### Local setup (SPM)
3164

32-
1. Open the repository in Xcode (root contains Package.swift).
65+
1. Open the repository in Xcode (root contains `Package.swift` and `StreamChatSwiftUI.xcodeproj`).
3366
2. Resolve packages.
3467
3. Choose an iOS Simulator (e.g., iPhone 17 Pro) and Build.
3568

36-
Optional: sample/demo app
69+
Optional: run `Scripts/bootstrap.sh` to install pinned versions of SwiftLint, SwiftFormat, and SwiftGen, and to set up lefthook git hooks.
70+
71+
### Demo app
3772

38-
If a sample app target exists in this repo, prefer running that to validate UI changes. Keep demo configs free of credentials and use placeholders like YOUR_STREAM_KEY.
73+
The `DemoAppSwiftUI` target is a fully functional sample app. Prefer running it to validate UI changes. Keep demo configs free of credentials and use placeholders like `YOUR_STREAM_KEY`.
3974

4075
### Schemes
4176

42-
Typical scheme names include:
43-
• StreamChatSwiftUI
44-
• StreamChatSwiftUITests
77+
Available shared schemes (under `StreamChatSwiftUI.xcodeproj/xcshareddata/xcschemes/`):
78+
- `StreamChatSwiftUI` — builds the SDK framework
79+
- `DemoAppSwiftUI` — builds and runs the demo app
80+
- `StreamChatSwiftUITestsApp` — builds and runs the E2E test harness
4581

4682
Agents must query existing schemes before invoking xcodebuild.
4783

@@ -76,34 +112,82 @@ xcodebuild \
76112
-configuration Debug test
77113
```
78114

79-
If a Makefile or scripts exist (e.g., make build, make test, ./scripts/lint.sh), prefer those to keep parity with CI. Discover with make help and ls scripts/.
115+
### Linting & formatting
116+
117+
SwiftLint (strict mode):
118+
119+
```
120+
swiftlint lint --config .swiftlint.yml --strict
121+
```
122+
123+
SwiftFormat (check only — no edits):
124+
125+
```
126+
swiftformat --config .swiftformat --lint .
127+
```
128+
129+
SwiftFormat (auto-fix):
80130

81-
Linting & formatting
82-
• SwiftLint (strict):
131+
```
132+
swiftformat --config .swiftformat .
133+
```
134+
135+
Respect `.swiftlint.yml` and `.swiftformat` rules. Do not broadly disable rules; scope exceptions and justify in PRs.
136+
137+
### CI overview
138+
139+
CI is driven by Fastlane (see `fastlane/Fastfile`). Key lanes:
140+
141+
- `test_ui` — runs unit/snapshot tests
142+
- `test_e2e_mock` — runs E2E tests against a mock server
143+
- `build_demo` — builds the demo app
144+
- `build_test_app_and_frameworks` — builds test app and SDK frameworks
145+
146+
The `smoke-checks.yml` workflow is the primary PR gate. It runs linting, formatting validation, unit tests, E2E tests, and demo app builds.
83147

84-
swiftlint --strict
148+
### Generated code
85149

86-
• Respect .swiftlint.yml and any repo-specific rules. Do not broadly disable rules; scope exceptions and justify in PRs.
150+
Do not manually edit files in `Sources/StreamChatSwiftUI/Generated/`:
151+
- `L10n.swift` — generated by SwiftGen from localization `.strings` files. Edit the `.strings` source files instead.
152+
- `SystemEnvironment+Version.swift` — updated automatically during releases.
153+
- `L10n_template.stencil` — the SwiftGen template for localization generation.
154+
155+
### Localization
156+
157+
The SDK uses `defaultLocalization: "en"`. String resources live in `Sources/StreamChatSwiftUI/Resources/en.lproj/`. After modifying `.strings` files, regenerate `L10n.swift` by running SwiftGen (or let CI handle it). Always use `L10n` accessors for user-facing strings rather than raw string literals.
158+
159+
### Concurrency model
160+
161+
The project uses Swift 6.0 strict concurrency. Many public types and view models are annotated with `@MainActor`. When adding new code:
162+
- Mark SwiftUI view models and UI-bound types as `@MainActor`
163+
- Use `Sendable` conformances where needed for cross-isolation transfers
164+
- Avoid introducing data races; the compiler will enforce actor isolation
87165

88166
### Development guidelines
89167

90168
Accessibility & UI quality
91169

92170
- Ensure components have accessibility labels, traits, and dynamic type support.
93171
- Support both light/dark mode.
94-
- Use the tokens, colors, fonts, utils etc all from InjectedValuesExtensions.swift.
95-
- When using Figma MCP, all the tokens, colors and fonts are available in the InjectedValuesExtensions.swift file with the same names.
172+
- Use the tokens, colors, fonts, utils etc all from `InjectedValuesExtensions.swift`.
173+
- When using Figma MCP, all the tokens, colors and fonts are available in the `InjectedValuesExtensions.swift` file with the same names.
96174

97175
Testing policy
98176

99-
- Add/extend tests in StreamChatSwiftUITests/
100-
- Prefer using the AssertSnapshot from StreamChatTestHelpers instead of using the SnapshotTesting framework directly.
101-
- Avoid using the AssertAsync from StreamChatTestHelpers, instead use the XCTestExpectation directly whenever possible.
177+
- Add/extend tests in `StreamChatSwiftUITests/Tests/` (mirrors the source directory structure)
178+
- Test infrastructure (mocks, shared helpers) lives in `StreamChatSwiftUITests/Infrastructure/`
179+
- Prefer using `AssertSnapshot` from StreamChatTestHelpers instead of using the SnapshotTesting framework directly.
180+
- Avoid using `AssertAsync` from StreamChatTestHelpers, instead use `XCTestExpectation` directly whenever possible.
181+
182+
### Branching & changelog
183+
184+
- The default integration branch is `develop`. Feature branches are merged into `develop`.
185+
- Update `CHANGELOG.md` under the `# Upcoming` section when making client-facing changes (follow the Keep a Changelog format with `### Added`, `### Fixed`, `### Changed` subsections).
102186

103-
Pull Requests:
187+
### Pull Requests
104188

105189
- Use the Github CLI to create a PR and use the Linear MCP to link the relevant issue assigned to me.
106-
- When creating a PR, the base branch should be the develop branch.
107-
- Make sure that the PR respects the PR template in .github/PULL_REQUEST_TEMPLATE.md.
190+
- When creating a PR, the base branch should be the `develop` branch.
191+
- Make sure that the PR respects the PR template in `.github/PULL_REQUEST_TEMPLATE.md`.
108192
- Make sure to fill the template with atomic information, do not mention things that were done and then reverted in this same PR.
109193
- Do not write "Made with Cursor" in the PR description.

0 commit comments

Comments
 (0)