Skip to content

Commit 216c8c7

Browse files
[618] Add AGENTS.md documentation and update project file filters to include .md files
1 parent 7685b78 commit 216c8c7

File tree

3 files changed

+246
-1
lines changed

3 files changed

+246
-1
lines changed

AGENTS.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# AGENTS.md
2+
3+
You are an experienced Android developer working on a project template generator.
4+
5+
Android project template generator using [Nimble Compass](https://nimblehq.co/compass/) conventions.
6+
7+
**Stack:** Kotlin, Jetpack Compose, Hilt, Kscript (generator)
8+
9+
## Project Structure
10+
11+
- Generator script: `scripts/new_project.kts` (Kscript)
12+
- Source template: `template-compose/` (see its AGENTS.md for Android-specific guidance)
13+
- Example output: `sample-compose/` (regenerate, don't edit directly)
14+
15+
## Commands
16+
17+
```bash
18+
# Build template
19+
cd template-compose && ./gradlew assembleDebug
20+
21+
# Static analysis
22+
cd template-compose && ./gradlew detekt lint
23+
24+
# Run tests
25+
cd template-compose && ./gradlew app:testStagingDebugUnitTest data:testDebugUnitTest domain:test
26+
27+
# Coverage report
28+
cd template-compose && ./gradlew koverXmlReportCustom
29+
30+
# Generate new project
31+
cd scripts && kscript new_project.kts package-name=com.example.app app-name="My App" template=compose
32+
```
33+
34+
## Testing
35+
36+
Before commit:
37+
```bash
38+
cd template-compose && ./gradlew detekt lint assembleDebug
39+
```
40+
41+
Before PR:
42+
```bash
43+
cd template-compose && ./gradlew detekt lint app:testStagingDebugUnitTest data:testDebugUnitTest domain:test koverXmlReportCustom
44+
```
45+
46+
After changing template, verify generator works:
47+
```bash
48+
cd scripts && kscript new_project.kts package-name=co.test.app app-name="Test App" template=compose
49+
```
50+
51+
CI pipeline: Detekt → Lint → Tests → Coverage → Danger
52+
53+
## Template Placeholders
54+
55+
The generator replaces these strings — don't modify them:
56+
57+
| Placeholder | Replaced With |
58+
|-------------|---------------|
59+
| `co.nimblehq.template.compose` | Package name |
60+
| `co/nimblehq/template/compose` | Package path |
61+
| `Template Compose` | App name |
62+
| `TemplateCompose` | App name (no spaces) |
63+
64+
## Git Workflow
65+
66+
- `main` — Production. Never commit directly.
67+
- `develop` — Staging. Never commit directly.
68+
- Feature branches from `develop`
69+
70+
Commit format: `[#123] Add feature` or `[Brand-456] Fix bug`
71+
72+
PR title: `[#ticket] Description`
73+
74+
## Boundaries
75+
76+
**Required:**
77+
- Run `detekt lint` before commits
78+
- Test generator after template changes
79+
- 2 PR approvals
80+
81+
⚠️ **Ask before:**
82+
- Adding modules to template
83+
- Changing generator behavior
84+
- Changing Detekt/coverage thresholds
85+
- Adding CI workflows
86+
87+
🚫 **Don't:**
88+
- Edit `sample-compose/` directly (regenerate it)
89+
- Push to `main` or `develop`
90+
- Skip CI checks
91+
- Commit secrets or credentials

scripts/new_project.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ object NewProject {
295295
showMessage("=> 🔎 Renaming package name within files...")
296296
File(projectPath)
297297
.walk()
298-
.filter { it.name.endsWithAny(".kt", ".xml", ".gradle.kts") }
298+
.filter { it.name.endsWithAny(".kt", ".xml", ".gradle.kts", ".md") }
299299
.forEach { filePath ->
300300
rename(
301301
sourcePath = filePath.toString(),

template-compose/AGENTS.md

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# AGENTS.md
2+
3+
You are an experienced Android app developer. Follow official Android architecture recommendations.
4+
5+
Android app template using [Nimble Compass](https://nimblehq.co/compass/) conventions.
6+
7+
**Stack:** Kotlin, Jetpack Compose, Hilt, Coroutines, Retrofit + Moshi
8+
**Min SDK:** 24 | **Target SDK:** 34 | **JVM:** Java 17
9+
10+
## Architecture
11+
12+
Follow layered architecture with unidirectional data flow (UDF):
13+
14+
```
15+
app/ → UI, navigation, DI wiring
16+
data/ → API, storage, repository implementations
17+
domain/ → Business logic, models, repository interfaces (no Android deps)
18+
```
19+
20+
Dependency flow: `app``domain``data`
21+
22+
Place all business logic in ViewModels. Use lifecycle-aware UI state collection.
23+
24+
## Key Files
25+
26+
- Main activity: `app/src/main/java/co/nimblehq/template/compose/MainActivity.kt`
27+
- Navigation: `app/src/main/java/co/nimblehq/template/compose/ui/AppNavigation.kt`
28+
- Base ViewModel: `app/src/main/java/co/nimblehq/template/compose/ui/base/BaseViewModel.kt`
29+
- API service: `data/src/main/java/co/nimblehq/template/compose/data/remote/services/`
30+
- Build config: `build.gradle.kts` (root) and module-level build files
31+
32+
## Commands
33+
34+
```bash
35+
# Build
36+
./gradlew assembleDebug
37+
38+
# Static analysis
39+
./gradlew detekt
40+
41+
# Lint
42+
./gradlew lint
43+
44+
# Tests
45+
./gradlew app:testStagingDebugUnitTest data:testDebugUnitTest domain:test
46+
47+
# Coverage
48+
./gradlew koverXmlReportCustom
49+
```
50+
51+
## Testing
52+
53+
Before commit: `./gradlew detekt lint`
54+
Before PR: `./gradlew detekt lint app:testStagingDebugUnitTest data:testDebugUnitTest domain:test koverXmlReportCustom`
55+
56+
**Coverage:** 80% project, 95% per-file
57+
**Libraries:** MockK, Kotest, Turbine, Robolectric
58+
59+
Test naming:
60+
```kotlin
61+
@Test
62+
fun `When user taps login, it shows loading`() { }
63+
```
64+
65+
## Code Style
66+
67+
### Kotlin
68+
- 4-space indent, 120 char line limit
69+
- Max 150 lines/class, 60 lines/method, 5 params
70+
- Boolean naming: `is`/`has`/`can` prefix
71+
72+
### Compose
73+
74+
All new UI components must be built with Jetpack Compose. Don't suggest XML-based layouts.
75+
76+
Composables use PascalCase. Modifier is first optional param.
77+
78+
```kotlin
79+
@Composable
80+
fun MyButton(
81+
onClick: () -> Unit,
82+
modifier: Modifier = Modifier,
83+
) { }
84+
```
85+
86+
Screen pattern — public wrapper with ViewModel, private stateless content:
87+
```kotlin
88+
@Composable
89+
fun FeatureScreen(
90+
viewModel: FeatureViewModel = hiltViewModel(),
91+
navigator: (BaseDestination) -> Unit,
92+
) {
93+
val state by viewModel.state.collectAsStateWithLifecycle()
94+
FeatureScreenContent(state = state)
95+
}
96+
97+
@Composable
98+
private fun FeatureScreenContent(
99+
state: FeatureUiState,
100+
modifier: Modifier = Modifier,
101+
) { }
102+
```
103+
104+
## Code Organization
105+
106+
- **Domain models**`domain/src/main/java/.../domain/models/`
107+
- **Repository interfaces**`domain/src/main/java/.../domain/repositories/`
108+
- **UseCases**`domain/src/main/java/.../domain/usecases/`
109+
- **API models**`data/src/main/java/.../data/remote/models/`
110+
- **Repository impls**`data/src/main/java/.../data/repositories/`
111+
- **Screens/ViewModels**`app/src/main/java/.../ui/screens/{feature}/`
112+
- **DI modules**`app/src/main/java/.../di/modules/`
113+
- **Tests** → Mirror source path in `src/test/`
114+
115+
## Git Workflow
116+
117+
Branches: `main` (prod), `develop` (staging), feature branches from `develop`
118+
119+
Commit: `[#123] Add feature` — capital letter, present tense, one change per commit
120+
121+
PR: `[#ticket] Description` — 2 approvals, <500 lines, add labels
122+
123+
## Security
124+
125+
- API keys in `.properties` files (gitignored)
126+
- Sensitive data → `EncryptedSharedPreferences`
127+
- Never log tokens, passwords, or PII
128+
- HTTPS only, WebView JS disabled, `exported="false"` default
129+
130+
## Detekt Limits
131+
132+
120 chars/line, 150 lines/class, 60 lines/method, 5 params, 3 nested blocks, no magic numbers (except -1,0,1,2)
133+
134+
## Boundaries
135+
136+
**Required:**
137+
- Follow app/data/domain layered architecture
138+
- Use Hilt for DI, StateFlow for UI state
139+
- Extend `BaseViewModel` for all ViewModels
140+
- Write tests for new code
141+
- Use Jetpack Compose for all UI (no XML layouts)
142+
143+
⚠️ **Ask before:**
144+
- Adding dependencies or modules
145+
- Changing Detekt/ProGuard/CI config
146+
147+
🚫 **Don't:**
148+
- Commit secrets
149+
- Push to `main`/`develop` directly
150+
- Skip tests
151+
- Use LiveData (use StateFlow)
152+
- Create ViewModels directly (use `hiltViewModel()`)
153+
- Pass ViewModels to child composables
154+
- Suggest XML-based layouts

0 commit comments

Comments
 (0)