From 37389a83a66ffbb1f58b81e42f42d9ffa697fa71 Mon Sep 17 00:00:00 2001 From: Davide Ferrari Date: Mon, 19 Jan 2026 10:24:18 +0100 Subject: [PATCH] feat: add Claude Code skills for common tasks - check-api: Query Teslamate API to inspect JSON response format - release: Bump version, update changelog, tag and push - translate: Add strings to all 4 locale files - new-screen: Scaffold a new Compose screen Also adds .env.example for API URL configuration and fixes .gitignore to allow .claude/skills/release/ directory. Co-Authored-By: Claude Opus 4.5 --- .claude/skills/check-api/SKILL.md | 41 +++++++++ .claude/skills/new-screen/SKILL.md | 131 +++++++++++++++++++++++++++++ .claude/skills/release/SKILL.md | 82 ++++++++++++++++++ .claude/skills/translate/SKILL.md | 70 +++++++++++++++ .env.example | 5 ++ .gitignore | 5 +- 6 files changed, 333 insertions(+), 1 deletion(-) create mode 100644 .claude/skills/check-api/SKILL.md create mode 100644 .claude/skills/new-screen/SKILL.md create mode 100644 .claude/skills/release/SKILL.md create mode 100644 .claude/skills/translate/SKILL.md create mode 100644 .env.example diff --git a/.claude/skills/check-api/SKILL.md b/.claude/skills/check-api/SKILL.md new file mode 100644 index 0000000..58c9760 --- /dev/null +++ b/.claude/skills/check-api/SKILL.md @@ -0,0 +1,41 @@ +--- +name: check-api +description: Check Teslamate API response format for a given endpoint. Use when you need to understand the JSON structure returned by the API. +allowed-tools: Read, WebFetch +--- + +# Check Teslamate API + +Query the Teslamate API to inspect JSON response format for endpoints. + +## Configuration + +The API URL should be set in a `.env` file at the project root (gitignored): + +``` +TESLAMATE_API_URL=https://your-teslamate-api.example.com +``` + +If no `.env` file exists, ask the user for their Teslamate API URL. + +## Common Endpoints + +- `/api/v1/cars` - List all cars +- `/api/v1/cars/{id}` - Car details with current state (battery, location, climate, etc.) +- `/api/v1/cars/{id}/drives` - Drive history (supports `?start_date=` and `?end_date=`) +- `/api/v1/cars/{id}/charges` - Charge history (supports `?start_date=` and `?end_date=`) +- `/api/v1/cars/{id}/drives/{drive_id}` - Single drive details with positions +- `/api/v1/cars/{id}/charges/{charge_id}` - Single charge details with charging curve + +## Instructions + +1. Read the `.env` file to get `TESLAMATE_API_URL` +2. If not found, ask the user for the URL +3. Use WebFetch to query the requested endpoint +4. Present the JSON structure clearly, highlighting relevant fields + +## Date Format + +The API's parseDateParam function only accepts: +- RFC3339 format: `2024-12-07T00:00:00Z` +- DateTime format: `2024-12-07 00:00:00` diff --git a/.claude/skills/new-screen/SKILL.md b/.claude/skills/new-screen/SKILL.md new file mode 100644 index 0000000..afecaf5 --- /dev/null +++ b/.claude/skills/new-screen/SKILL.md @@ -0,0 +1,131 @@ +--- +name: new-screen +description: Scaffold a new Jetpack Compose screen following project patterns. Use when creating a new screen or view in the app. +allowed-tools: Read, Write, Edit, Glob +--- + +# New Screen Skill + +Create a new Jetpack Compose screen following MateDroid's patterns. + +## Project Structure + +Screens are located in `app/src/main/java/com/matedroid/ui/screens/`: +``` +screens/ +├── dashboard/ +│ └── DashboardScreen.kt +├── drives/ +│ ├── DrivesScreen.kt +│ └── DriveDetailScreen.kt +├── charges/ +│ ├── ChargesScreen.kt +│ └── ChargeDetailScreen.kt +├── settings/ +│ └── SettingsScreen.kt +└── {feature}/ + └── {Feature}Screen.kt +``` + +## Process + +1. Ask the user for: + - Screen name (e.g., "Battery Health") + - Brief description of what it displays + - Whether it needs navigation parameters + +2. Read an existing screen as reference (e.g., `DashboardScreen.kt`) + +3. Create the new screen file following the pattern + +## Screen Template + +```kotlin +package com.matedroid.ui.screens.{feature} + +import androidx.compose.foundation.layout.* +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.matedroid.R + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun {Feature}Screen( + onNavigateBack: () -> Unit, + modifier: Modifier = Modifier +) { + Scaffold( + topBar = { + TopAppBar( + title = { Text(stringResource(R.string.{feature}_title)) }, + navigationIcon = { + IconButton(onClick = onNavigateBack) { + Icon( + imageVector = Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = stringResource(R.string.back) + ) + } + } + ) + } + ) { paddingValues -> + Column( + modifier = modifier + .fillMaxSize() + .padding(paddingValues) + .padding(16.dp) + ) { + // Screen content here + } + } +} +``` + +## After Creating the Screen + +1. Add string resources for the screen title using the translate skill +2. Add navigation route to the app's navigation graph +3. Remind the user to wire up the navigation + +## Common Patterns + +### Loading State +```kotlin +var isLoading by remember { mutableStateOf(true) } + +if (isLoading) { + CircularProgressIndicator() +} else { + // Content +} +``` + +### API Data Fetching +```kotlin +LaunchedEffect(Unit) { + // Fetch data from TeslamateApiService +} +``` + +### Pull to Refresh +```kotlin +val pullRefreshState = rememberPullToRefreshState() +PullToRefreshBox(state = pullRefreshState, isRefreshing = isRefreshing) { + // Content +} +``` + +### Cards +```kotlin +Card( + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant + ) +) { + // Card content +} +``` diff --git a/.claude/skills/release/SKILL.md b/.claude/skills/release/SKILL.md new file mode 100644 index 0000000..136c0ad --- /dev/null +++ b/.claude/skills/release/SKILL.md @@ -0,0 +1,82 @@ +--- +name: release +description: Create a new release. Bumps version, updates changelog, creates fastlane changelog, commits, tags, and pushes. +allowed-tools: Read, Edit, Write, Bash, Glob +--- + +# Release Skill + +Create a new release for MateDroid. + +## Pre-flight Checks + +1. Ensure you're on the `main` branch with no uncommitted changes +2. Verify the `[Unreleased]` section in `CHANGELOG.md` has content to release + +## Release Process + +### 1. Determine Version + +Ask the user what type of release: +- **patch** (0.10.0 → 0.10.1): Bug fixes only +- **minor** (0.10.0 → 0.11.0): New features, backwards compatible +- **major** (0.10.0 → 1.0.0): Breaking changes (requires explicit user confirmation) + +### 2. Update Version in build.gradle.kts + +Edit `app/build.gradle.kts`: +- Increment `versionCode` by 1 +- Update `versionName` to the new version + +### 3. Update CHANGELOG.md + +1. Change `## [Unreleased]` to `## [X.Y.Z] - YYYY-MM-DD` (today's date) +2. Add a new empty `## [Unreleased]` section above it +3. Add the new version link at the bottom: + ``` + [X.Y.Z]: https://github.com/vide/matedroid/compare/vPREVIOUS...vX.Y.Z + ``` +4. Update the `[Unreleased]` link to compare from the new version + +### 4. Create Fastlane Changelog + +Create `fastlane/metadata/android/en-US/changelogs/{versionCode}.txt` with the release notes. + +Format (max 500 chars for Play Store): +``` +Added: +- Feature 1 +- Feature 2 + +Changed: +- Change 1 + +Fixed: +- Fix 1 +``` + +Keep it concise - this appears in Play Store and F-Droid. + +### 5. Commit and Tag + +```bash +git add -A +git commit -m "chore: release vX.Y.Z" +git tag -a vX.Y.Z -m "Release X.Y.Z" +``` + +### 6. Push + +```bash +git push origin main +git push origin vX.Y.Z +``` + +### 7. Create GitHub Release + +Use `gh release create vX.Y.Z --title "vX.Y.Z" --notes-file -` with the changelog content. + +The GitHub Actions workflow will automatically: +- Build APK and AAB +- Upload to GitHub release +- Deploy to Google Play (alpha track) diff --git a/.claude/skills/translate/SKILL.md b/.claude/skills/translate/SKILL.md new file mode 100644 index 0000000..e1171e7 --- /dev/null +++ b/.claude/skills/translate/SKILL.md @@ -0,0 +1,70 @@ +--- +name: translate +description: Add a new translatable string to all locale files (English, Italian, Spanish, Catalan). Use when adding user-visible text to the app. +allowed-tools: Read, Edit +--- + +# Translate Skill + +Add a new string resource to all 4 locale files. + +## String Resource Files + +| Locale | File | +|---------|-----------------------------------------------| +| English | `app/src/main/res/values/strings.xml` | +| Italian | `app/src/main/res/values-it/strings.xml` | +| Spanish | `app/src/main/res/values-es/strings.xml` | +| Catalan | `app/src/main/res/values-ca/strings.xml` | + +## Process + +1. Ask the user for: + - The string name (use `snake_case`, e.g., `drive_details_title`) + - The English text + - Context for translators (optional but recommended) + +2. Generate translations for Italian, Spanish, and Catalan + +3. Add to all 4 files with an XML comment for context: + ```xml + + Drive Details + ``` + +## Guidelines + +- Use `snake_case` for string names (e.g., `settings_title`, `drive_history`) +- Add XML comments above strings to provide context for translators +- Technical terms like AC, DC, kW, kWh should NOT be translated +- Format specifiers (`%s`, `%d`, `%1$s`) must be preserved in translations +- Keep translations natural - don't be overly literal + +## String with Parameters + +For strings with parameters, use positional format specifiers: +```xml +%1$d km away +``` + +In Kotlin: +```kotlin +stringResource(R.string.distance_km, distance) +``` + +## Plurals + +For quantity strings, use plurals: +```xml + + %d day + %d days + +``` + +## After Adding Strings + +Remind the user to use `stringResource(R.string.xxx)` in Compose code: +```kotlin +Text(stringResource(R.string.drive_details_title)) +``` diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..dc92f8c --- /dev/null +++ b/.env.example @@ -0,0 +1,5 @@ +# Copy this file to .env and fill in your values +# Used by Claude Code skills (check-api) + +# Your Teslamate API URL (e.g., https://teslamate-api.example.com) +TESLAMATE_API_URL= diff --git a/.gitignore b/.gitignore index 529eb04..4fbefd3 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,7 @@ bin/ gen/ out/ -release/ +/release/ # Gradle files .gradle/ @@ -95,3 +95,6 @@ mockups/ # Logo source files (generated icons are in res/mipmap-*) matedroid-logo*.png + +# Local environment configuration +.env