Skip to content

Commit 29950e3

Browse files
antonisclaude
andauthored
docs: Migrate AGENTS.md to nested structure with agents.toml (#5758)
Split the monolithic AGENTS.md into directory-scoped files following the agents.md standard (as in sentry-javascript). The root file becomes a lightweight index with pointers to nested files. New files: - packages/core/AGENTS.md — TS/JS code style, testing, patterns - packages/core/android/AGENTS.md — Java/Kotlin conventions - packages/core/ios/AGENTS.md — ObjC/Swift conventions - samples/react-native/AGENTS.md — sample app usage - samples/expo/AGENTS.md — Expo sample usage - agents.toml — agents.md standard config - .agents/skills/.gitkeep — skills directory placeholder Refs #5745 Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 98e9b2d commit 29950e3

8 files changed

Lines changed: 358 additions & 573 deletions

File tree

.agents/skills/.gitkeep

Whitespace-only changes.

AGENTS.md

Lines changed: 52 additions & 573 deletions
Large diffs are not rendered by default.

agents.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version = 1
2+
gitignore = false
3+
agents = ["claude", "cursor"]
4+
5+
[trust]
6+
github_orgs = ["getsentry"]

packages/core/AGENTS.md

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# packages/core — TypeScript/JavaScript SDK
2+
3+
## Build & Test
4+
5+
```bash
6+
yarn build:sdk:watch # Watch mode for development
7+
yarn test:watch # Jest watch mode
8+
yarn test:sdk # SDK tests only
9+
yarn test:tools # Tools tests only
10+
```
11+
12+
## Code Style
13+
14+
- **Single quotes** for strings
15+
- **Arrow functions** preferred for callbacks
16+
- **async/await** is allowed (React Native bundle size isn't a concern)
17+
- Use **optional chaining** (`?.`) and **nullish coalescing** (`??`)
18+
- Maximum line length: **120 characters**
19+
- Trailing commas: **always**
20+
- Arrow parens: **avoid** when possible (`x => x` not `(x) => x`)
21+
22+
## Type Annotations
23+
24+
- Explicitly type function parameters and return types
25+
- Use TypeScript strict mode conventions
26+
- Prefer `interface` over `type` for object shapes
27+
- Use `unknown` instead of `any` when possible
28+
29+
```typescript
30+
interface UserData {
31+
id: string;
32+
name: string;
33+
email?: string;
34+
}
35+
36+
const processUser = (user: UserData): string => {
37+
return user.email ?? 'no-email@example.com';
38+
};
39+
```
40+
41+
## Import Ordering
42+
43+
1. External packages (e.g., `@sentry/core`, `react-native`)
44+
2. Internal absolute imports
45+
3. Relative imports
46+
4. Type imports (can be inline with `import type`)
47+
48+
## Test Naming Convention
49+
50+
Use `describe/it` blocks (preferred) or flat `test()` calls:
51+
52+
```typescript
53+
describe('functionName', () => {
54+
it('returns expected value when input is valid', () => {
55+
// Arrange
56+
const input = 'test';
57+
58+
// Act
59+
const result = functionName(input);
60+
61+
// Assert
62+
expect(result).toBe('expected');
63+
});
64+
});
65+
```
66+
67+
## Test Code Style
68+
69+
**Arrange-Act-Assert pattern** — always structure tests with clear sections.
70+
71+
**Use specific Jest matchers:**
72+
73+
```typescript
74+
// Good
75+
expect(value).toBe(true);
76+
expect(array).toHaveLength(3);
77+
expect(object).toMatchObject({ key: 'value' });
78+
expect(fn).toThrow(Error);
79+
expect(promise).resolves.toBe('success');
80+
81+
// Avoid
82+
expect(value === true).toBe(true);
83+
expect(array.length).toBe(3);
84+
```
85+
86+
**Mock cleanup:**
87+
88+
```typescript
89+
describe('MyComponent', () => {
90+
afterEach(() => {
91+
jest.clearAllMocks();
92+
});
93+
});
94+
```
95+
96+
## Common Patterns
97+
98+
### Error Handling
99+
100+
```typescript
101+
try {
102+
const result = await riskyOperation();
103+
return result;
104+
} catch (error) {
105+
logger.error('Operation failed', error);
106+
// Don't throw - log and return fallback
107+
return fallbackValue;
108+
}
109+
```
110+
111+
### Native Bridge (JS side)
112+
113+
```typescript
114+
import { NativeModules } from 'react-native';
115+
116+
const { RNSentry } = NativeModules;
117+
118+
export async function nativeOperation(param: string): Promise<boolean> {
119+
if (!RNSentry) {
120+
logger.warn('Native module not available');
121+
return false;
122+
}
123+
124+
try {
125+
return await RNSentry.nativeOperation(param);
126+
} catch (error) {
127+
logger.error('Native operation failed', error);
128+
return false;
129+
}
130+
}
131+
```
132+
133+
### Platform-Specific Code
134+
135+
```typescript
136+
import { Platform } from 'react-native';
137+
138+
const platformSpecificValue = Platform.select({
139+
ios: 'iOS value',
140+
android: 'Android value',
141+
default: 'Default value',
142+
});
143+
```
144+
145+
### Mocking Native Modules in Tests
146+
147+
```typescript
148+
jest.mock('react-native', () => ({
149+
NativeModules: {
150+
RNSentry: {
151+
nativeOperation: jest.fn(() => Promise.resolve(true)),
152+
},
153+
},
154+
Platform: {
155+
OS: 'ios',
156+
},
157+
}));
158+
```

packages/core/android/AGENTS.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# packages/core/android — Java & Kotlin
2+
3+
## Formatting & Linting
4+
5+
| Task | Command |
6+
|------|---------|
7+
| Java format (Google Java Format) | `yarn fix:android` |
8+
| Kotlin format (ktlint) | `yarn fix:kotlin` |
9+
| Java lint check | `yarn lint:android` |
10+
| Kotlin lint check | `yarn lint:kotlin` |
11+
| PMD static analysis | `yarn java:pmd` |
12+
13+
## Code Conventions
14+
15+
### Java
16+
17+
- Use **Google Java Format** (enforced by CI)
18+
- Package structure: `io.sentry.react.*`
19+
- Null safety: Use `@Nullable` and `@NonNull` annotations
20+
21+
### Kotlin
22+
23+
- Use **ktlint** formatting (enforced by CI)
24+
- Prefer Kotlin idioms (data classes, extension functions, etc.)
25+
26+
## Architecture Variants
27+
28+
Android native code supports both old and new React Native architectures:
29+
- `src/oldarch/` — Legacy bridge implementation
30+
- `src/newarch/` — TurboModule / Fabric implementation
31+
- `src/main/` — Shared code
32+
33+
## Native Bridge Pattern (Java)
34+
35+
```java
36+
@ReactMethod
37+
public void nativeOperation(String param, Promise promise) {
38+
try {
39+
boolean result = performOperation(param);
40+
promise.resolve(result);
41+
} catch (Exception e) {
42+
promise.reject("OPERATION_FAILED", "Operation failed: " + e.getMessage(), e);
43+
}
44+
}
45+
```
46+
47+
## Working with Local sentry-java
48+
49+
1. Build sentry-java: `cd sentry-java && make dryRelease`
50+
2. Add `mavenLocal()` to sample's `android/build.gradle`
51+
3. Update version to locally published version

packages/core/ios/AGENTS.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# packages/core/ios — Objective-C & Swift
2+
3+
## Formatting & Linting
4+
5+
| Task | Command |
6+
|------|---------|
7+
| ObjC/C++ format (clang-format) | `yarn fix:clang` |
8+
| Swift format (swiftlint) | `yarn fix:swift` |
9+
| ObjC/C++ lint check | `yarn lint:clang` |
10+
| Swift lint check | `yarn lint:swift` |
11+
12+
## Code Conventions
13+
14+
### Objective-C
15+
16+
- Use **clang-format** (enforced by CI)
17+
- Prefix classes with **`RNSentry`**
18+
- Use nullability annotations (`nullable`, `nonnull`)
19+
20+
### Swift
21+
22+
- Use **swiftlint** (enforced by CI)
23+
- Follow Swift API design guidelines
24+
25+
## Error Handling Pattern
26+
27+
```objc
28+
NSError *error = nil;
29+
BOOL success = [self performOperation:&error];
30+
if (!success) {
31+
[SentryLog logWithMessage:[NSString stringWithFormat:@"Operation failed: %@", error]
32+
andLevel:kSentryLevelError];
33+
return fallback;
34+
}
35+
```
36+
37+
## Native Bridge Pattern (Objective-C)
38+
39+
```objc
40+
RCT_EXPORT_METHOD(nativeOperation:(NSString *)param
41+
resolver:(RCTPromiseResolveBlock)resolve
42+
rejecter:(RCTPromiseRejectBlock)reject)
43+
{
44+
@try {
45+
BOOL result = [self performOperation:param];
46+
resolve(@(result));
47+
} @catch (NSException *exception) {
48+
reject(@"OPERATION_FAILED", exception.reason, nil);
49+
}
50+
}
51+
```
52+
53+
## Working with Local sentry-cocoa
54+
55+
1. Build sentry-cocoa: `cd sentry-cocoa && make init`
56+
2. Edit `RNSentry.podspec` to remove version constraint
57+
3. Add local pod to sample's Podfile:
58+
```ruby
59+
pod 'Sentry/HybridSDK', :path => '../../../../sentry-cocoa'
60+
```

samples/expo/AGENTS.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# samples/expo — Expo Sample App
2+
3+
## Running
4+
5+
```bash
6+
yarn start
7+
```
8+
9+
Follow the Expo CLI prompts to open on iOS simulator, Android emulator, or a physical device.

samples/react-native/AGENTS.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# samples/react-native — React Native Sample App
2+
3+
## Running
4+
5+
```bash
6+
yarn start # Start Metro bundler
7+
yarn ios # Run iOS app (separate terminal)
8+
yarn android # Run Android app (separate terminal)
9+
```
10+
11+
## Troubleshooting
12+
13+
**General build failures:**
14+
- Clear node_modules and reinstall: `rm -rf node_modules && yarn install`
15+
16+
**iOS:**
17+
- Clean build folder in Xcode: Cmd+Shift+K
18+
- Reinstall pods: `npx pod-install`
19+
- Full pod refresh: `cd ios && pod install --repo-update`
20+
21+
**Android:**
22+
- Clean Gradle: `cd android && ./gradlew clean`

0 commit comments

Comments
 (0)