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 <noreply@anthropic.com>
This commit is contained in:
Davide Ferrari
2026-01-19 10:24:18 +01:00
parent 4203962ce7
commit 37389a83a6
6 changed files with 333 additions and 1 deletions
+41
View File
@@ -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`
+131
View File
@@ -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
}
```
+82
View File
@@ -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)
+70
View File
@@ -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
<!-- Context: Shown as the title of the drive details screen -->
<string name="drive_details_title">Drive Details</string>
```
## 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
<string name="distance_km">%1$d km away</string>
```
In Kotlin:
```kotlin
stringResource(R.string.distance_km, distance)
```
## Plurals
For quantity strings, use plurals:
```xml
<plurals name="days_count">
<item quantity="one">%d day</item>
<item quantity="other">%d days</item>
</plurals>
```
## After Adding Strings
Remind the user to use `stringResource(R.string.xxx)` in Compose code:
```kotlin
Text(stringResource(R.string.drive_details_title))
```
+5
View File
@@ -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=
+4 -1
View File
@@ -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