Skip to content

Commit de6b609

Browse files
Port Cursor rules to CLAUDE.md and remove the originals
We're no longer using Cursor, so the Cursor rules can go. They did contain useful project-specific guidance (spec document format, Swift style preferences, testing conventions) that Claude may not have been picking up on, so this ports across the things that Claude judged to be non-obvious — i.e. things it might not intuit from the code alone — into CLAUDE.md files. Testing guidelines go in a separate CLAUDE.md under the test directory so they only load when working with test files. The Cursor rules hardcoded a path for where to find the specification repo. Instead, the CLAUDE.md just says "ask if you haven't been told where to find it", on the basis that the broader working environment (e.g. sdk-workspace [1]) should provide that context. Let's see if this works in practice. What to include was based on Claude's own judgement of what it would and wouldn't already know, and I pretty blindly accepted it. This is a first pass; we can continue to iterate on the content. [1] https://github.com/ably/sdk-workspace Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 4df4816 commit de6b609

5 files changed

Lines changed: 48 additions & 62 deletions

File tree

.cursor/rules/specification.mdc

Lines changed: 0 additions & 14 deletions
This file was deleted.

.cursor/rules/swift.mdc

Lines changed: 0 additions & 28 deletions
This file was deleted.

.cursor/rules/testing.mdc

Lines changed: 0 additions & 20 deletions
This file was deleted.

CLAUDE.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,36 @@ swift run BuildTool lint
2323
```
2424

2525
Use `--fix` to auto-fix where possible.
26+
27+
## Specification Document
28+
29+
The _Specification Document_ (or simply "the specification" or "the spec") specifies much of the behaviour of this codebase. It lives in the `specification` repository. If you need to consult it and you haven't been told where to find a local copy, ask.
30+
31+
- The specification is structured as a list of specification points, each with an identifier such as `OD1`. Some specification points have subpoints, e.g. `REC2a`, which in turn can have subpoints like `REC2a1`. In the specification's Markdown source, the start of specification point `OD1` is represented by `` `(OD1)` ``.
32+
- The LiveObjects functionality is referred to in the specification simply as "Objects". The LiveObjects-specific spec points are in a separate file, `specifications/objects-features.md`.
33+
- If you are given a task that requires knowledge of the specification, you must consult it before proceeding. Never guess its contents.
34+
- If the specification is unclear, mention this.
35+
36+
## Swift style
37+
38+
- Satisfy SwiftLint's `explicit_acl` rule (all declarations must specify access control level keywords explicitly).
39+
- When writing an `extension` of a type, prefer placing the access level on the extension declaration rather than on each individual member.
40+
- This does not apply to test code.
41+
- When the type being initialised can be inferred, use the implicit `.init(…)` form instead of writing the type name explicitly.
42+
- When the enum type can be inferred, use the implicit `.caseName` form instead of writing the type name explicitly.
43+
- When writing `JSONValue` or `WireValue` types, use the literal syntax enabled by their `ExpressibleBy*Literal` conformances where possible.
44+
- When writing a JSON string, use Swift raw string literals instead of escaping double quotes.
45+
- When importing these modules in library (non-test) code:
46+
- Ably: `import Ably`
47+
- `_AblyPluginSupportPrivate`: `internal import _AblyPluginSupportPrivate`
48+
- When writing an array literal that starts with an initialiser expression, start the initialiser on the line after the opening square bracket:
49+
```swift
50+
// Do this:
51+
objectMessages: [
52+
InboundObjectMessage(
53+
id: nil,
54+
55+
// Not this:
56+
objectMessages: [InboundObjectMessage(
57+
id: nil,
58+
```
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Testing guidelines
2+
3+
- Use the Swift Testing framework (`import Testing`), not XCTest.
4+
- Do not use `fatalError` in response to a test expectation failure; use Swift Testing's `#require` macro instead.
5+
- Only add labels to test cases or suites when the label differs from the name of the suite `struct` or test method.
6+
- Follow the guidelines under "Attributing tests to a spec point" in `CONTRIBUTING.md` to tag unit tests with the relevant specification points. Follow the exact comment format described there. Pay particular attention to the difference between `@spec` and `@specPartial`, and do not write `@spec` multiple times for the same specification point.
7+
- Add comments explaining when some piece of test data is not important for the scenario being tested.
8+
- Run the tests to check they pass.
9+
- When importing these modules in test code:
10+
- Ably: `import Ably`
11+
- AblyLiveObjects: `@testable import AblyLiveObjects`
12+
- `_AblyPluginSupportPrivate`: `import _AblyPluginSupportPrivate` (not `internal import`)
13+
- When you need to pass a logger to internal components in tests, pass `TestLogger()`.
14+
- When you need to unwrap an optional value in tests, use `#require` instead of `guard let`.
15+
- When creating `testsOnly_` property declarations, do not write generic comments describing them; their meaning is already well understood.

0 commit comments

Comments
 (0)