Synthèse automatique
Guide pas à pas pour ajouter une nouvelle carte de rapport analytique à l'application macOS ClaudeBar, en suivant un flux parseur → analyseur → modèle de rapport → carte, avec développement piloté par les tests.
Points forts
- Impose une phase de conception d'architecture obligatoire avec validation par l'utilisateur avant toute écriture de code
- Associe chaque couche (Domain, Infrastructure, App, Intégration) à un emplacement de fichier précis
- S'appuie sur une implémentation de référence existante (le motif DailyUsage) pour ancrer le patron
- Découpe le travail en phases TDD Rouge→Vert avec une vérification finale de tous les tests
Limites
- Très couplé au code Swift de ClaudeBar et à ses conventions de nommage et d'interface (cartes glassmorphism, statsGrid)
- Dépend du fichier references/daily-usage-pattern.md pour être réellement actionnable
- La phase vue de carte et intégration ne précise pas de stratégie de test UI spécifique
À utiliser lorsqu'il faut ajouter à ClaudeBar une carte de rapport ou d'analyse qui lit des données locales et affiche des deltas entre périodes.
À éviter pour des fonctionnalités SwiftUI sans rapport avec l'analyse de données, ou qui ne suivent pas le flux parse → agrégation → rapport → carte (par exemple des vues temps réel alimentées par une API).
Analyse de sécurité
SûrThe skill is pure documentation/guidance for adding a Swift UI report card to a local app. It declares no allowed-tools, contains no shell commands, network calls, destructive operations, or secret handling. It merely describes file locations and coding patterns.
Aucun point d'attention détecté
Comment cette analyse est faiteExemples
Add a weekly cost breakdown card to ClaudeBar that reads ~/.claude/projects/*.jsonl and compares this week's spend against last week's, following the DailyUsage pattern.Create a model-breakdown report card that aggregates token usage per Claude model from local JSONL sessions and shows today vs yesterday deltas.Add a session stats card showing average session duration and session count today versus the previous day, wired into statsGrid.name: add-report description: > Guide for adding new report cards to ClaudeBar that analyze local data sources and display metrics with comparison deltas. Use this skill when: (1) Adding a new report/analytics card (e.g., weekly summary, model breakdown, session stats) (2) Creating data analysis features that read local files and display aggregated metrics (3) Adding comparison cards that show "today vs previous" style deltas (4) Building any feature that follows the DailyUsage pattern (parse → aggregate → report → card)
Add Report Card to ClaudeBar
Add new report cards that analyze local data sources, compute metrics with comparison deltas, and display them in the existing card UI style using TDD.
When to Use
This skill covers adding report-style features — cards that:
- Read and parse local data files (JSONL, JSON, CSV, etc.)
- Aggregate metrics (cost, tokens, time, counts)
- Compare periods (today vs yesterday, this week vs last week)
- Display results in glassmorphism cards matching the existing UI
Architecture Pattern
Every report feature follows this data flow:
Data Source → Parser → Analyzer → Report Model → UsageSnapshot → Card View
Mapped to the codebase layers:
| Layer | Location | What to Create |
|-------|----------|----------------|
| Domain | Sources/Domain/{Feature}/ | Rich models + @Mockable protocol |
| Infrastructure | Sources/Infrastructure/{Provider}/ | Parser + Analyzer implementation |
| App | Sources/App/Views/ | Card view(s) |
| Integration | Provider class + statsGrid | Wire analyzer → snapshot → UI |
Reference implementation: See
references/daily-usage-pattern.mdfor the complete DailyUsage feature as a working example of this pattern.
Workflow
Phase 0: Architecture Design (get user approval)
↓
Phase 1: Domain Models + Tests (TDD Red→Green)
↓
Phase 2: Infrastructure Parser + Analyzer + Tests
↓
Phase 3: Card View + Integration
↓
Phase 4: Verify all tests pass
Phase 0: Architecture Design (MANDATORY)
Before writing code, design the feature and get user approval.
Step 1: Define the Report
Answer these questions:
- What data source? (JSONL sessions, API response, local DB, etc.)
- What metrics? (cost, tokens, time, counts, etc.)
- What comparison period? (today vs yesterday, this week vs last, etc.)
- Which provider? (Claude, Codex, or generic across all?)
- How many cards? (one per metric, or a single combined card?)
Step 2: Create Architecture Diagram
Example: Adding a weekly cost breakdown report
┌─────────────────────────────────────────────────────────┐
│ Data Source Infrastructure Domain │
│ │
│ ~/.claude/ → WeeklyParser → WeeklyStat │
│ projects/ (reads JSONL) (per-day cost) │
│ *.jsonl │
│ WeeklyAnalyzer → WeeklyReport │
│ (aggregates by (this week vs │
│ week, implements last week) │
│ protocol) │
│ ↓ ↓ │
│ Provider.refresh() → UsageSnapshot │
│ .weeklyReport │
│ ↓ │
│ statsGrid() → WeeklyCardView │
└─────────────────────────────────────────────────────────┘
Step 3: Document Components
| Component | Purpose | Inputs | Outputs |
|-----------|---------|--------|---------|
| {Name}Stat | Single period's data | Raw aggregated values | Formatted strings, isEmpty |
| {Name}Report | Period comparison | Two Stats | Deltas, percentages, progress |
| {Name}Analyzing | Protocol | Date/config | Report |
| {Name}Analyzer | Implementation | File paths | Report |
| {Name}CardView | UI card | Report + metric | Glassmorphism card |
Step 4: Get User Approval
Use AskUserQuestion to confirm the design before proceeding.
Phase 1: Domain Models (TDD)
1a. Create the Stat Model
The stat model represents one period's aggregated data with rich formatting behavior.
Location: Sources/Domain/{Feature}/{Name}Stat.swift
Pattern to follow:
import Foundation
public struct {Name}Stat: Sendable, Equatable {
public let date: Date
// Add your metrics here
public let metricA: Decimal
public let metricB: Int
// Formatting — encapsulate in the model, not the view
public var formattedMetricA: String { /* currency, compact number, duration, etc. */ }
public var formattedMetricB: String { /* ... */ }
public var isEmpty: Bool { /* all zeros check */ }
public static func empty(for date: Date) -> Self { /* zero-valued instance */ }
}
Key rules:
- Use
Decimalfor monetary values (not Double — floating point errors) - Use
TimeIntervalfor durations - Use
Locale(identifier: "en_US")for currency formatting (noten_US_POSIXwhich adds a space) - All formatting lives in the model — views just read formatted strings
isEmptyuses&&(all zeros = empty), not||
1b. Create the Report Model
The report model compares two periods and computes deltas.
Location: Sources/Domain/{Feature}/{Name}Report.swift
Pattern to follow:
public struct {Name}Report: Sendable, Equatable {
public let current: {Name}Stat // e.g., today, this week
public let previous: {Name}Stat // e.g., yesterday, last week
// Delta calculations
public var metricADelta: Decimal { current.metricA - previous.metricA }
public var metricAChangePercent: Double? {
guard previous.metricA > 0 else { return nil } // nil when previous is zero
// ...
}
// Formatted deltas with sign: "+$5.00", "-1.2M"
public var formattedMetricADelta: String { /* ... */ }
// Progress for bar display (0-1 ratio of current vs total)
public var metricAProgress: Double {
let total = /* current + previous */
guard total > 0 else { return 0 }
return current / total
}
}
Key rules:
- Change percent returns
nilwhen previous is zero (avoid division by zero) - Formatted deltas always include sign (
+or-) - Progress is
current / (current + previous), clamped to 0-1 - Use
abs()for formatted values, prepend sign separately
1c. Create the Protocol
Location: Sources/Domain/{Feature}/{Name}Analyzing.swift
import Mockable
@Mockable
public protocol {Name}Analyzing: Sendable {
func analyze() async throws -> {Name}Report
}
1d. Write Tests First
Location: Tests/DomainTests/{Feature}/
Create two test files following Chicago School TDD (test state, not interactions):
{Name}StatTests.swift— Test formatting, isEmpty, edge cases{Name}ReportTests.swift— Test deltas, percentages, nil cases, progress
import Foundation
import Testing
@testable import Domain
@Suite
struct {Name}StatTests {
@Test func `formats metric as expected`() {
let stat = {Name}Stat(date: Date(), metricA: 14.26, ...)
#expect(stat.formattedMetricA == "$14.26")
}
// ...
}
After writing tests → implement the models → run tests → all green.
Phase 2: Infrastructure (TDD)
2a. Create the Parser (if reading files)
If the report reads local files (JSONL, JSON, CSV), create a parser.
Location: Sources/Infrastructure/{Provider}/{Name}Parser.swift
Pattern: Parser is a struct (not protocol) since it's a pure data transformation.
struct {Name}Parser {
func parse(fileURL: URL) throws -> [{Name}Record] { /* ... */ }
func parse(content: String) -> [{Name}Record] { /* for testing */ }
}
2b. Create the Analyzer
Location: Sources/Infrastructure/{Provider}/{Provider}{Name}Analyzer.swift
The analyzer implements the domain protocol and orchestrates:
- Find relevant files (filter by modification date for performance)
- Parse files into records
- Partition records by time period
- Aggregate into stat models
- Return report
Performance rule: Only scan files modified within the relevant time window. With 2000+ JSONL files, scanning all of them is too slow.
public struct {Provider}{Name}Analyzer: {Name}Analyzing, Sendable {
public func analyze() async throws -> {Name}Report {
let files = findRecentFiles(since: periodStart) // Performance!
// parse → partition → aggregate → return
}
}
2c. Write Infrastructure Tests
Location: Tests/InfrastructureTests/{Provider}/
- Parser tests: valid input, missing fields, malformed data, timestamps
- Analyzer tests: use temp directories with JSONL content, test date partitioning
Phase 3: Card View + Integration
3a. Create the Card View
Location: Sources/App/Views/{Name}CardView.swift
The card must match the existing glassmorphism style. Use WrappedStatCard as the reference:
struct {Name}CardView: View {
let metric: {Name}Metric // enum for each displayable metric
let report: {Name}Report
let delay: Double // for cascading entrance animation
@Environment(\.appTheme) private var theme
var body: some View {
VStack(alignment: .leading, spacing: 6) {
// 1. Header: icon + LABEL (uppercased)
// 2. Large value (e.g., "$14.26" or "19.5M")
// 3. Progress bar (animated)
// 4. Delta comparison line (e.g., "Vs Mar 10 -$27.47 (4.9%)")
}
.padding(12)
.background(/* theme.cardGradient + theme.glassBorder stroke */)
.scaleEffect(isHovering ? 1.015 : 1.0)
.onHover { isHovering = $0 }
}
}
Card styling checklist:
.padding(12)on the VStacktheme.cardGradientfill +theme.glassBorderstroke (1pt)theme.cardCornerRadiusfor cornerstheme.fontDesignon all texttheme.textPrimary/theme.textSecondary/theme.textTertiaryfor text hierarchytheme.progressTrackfor bar background- Hover scale effect (1.015)
- Animated progress bar with
delayparameter
3b. Add to UsageSnapshot
Add an optional field for the report:
// In Sources/Domain/Provider/UsageSnapshot.swift
public let {name}Report: {Name}Report?
// Add to init with default nil
3c. Wire into Provider
Inject the analyzer into the provider that owns this data:
// In the provider's init:
private let {name}Analyzer: (any {Name}Analyzing)?
// In refresh():
snapshot = await attach{Name}Report(to: newSnapshot)
// Helper method:
private func attach{Name}Report(to snapshot: UsageSnapshot) async -> UsageSnapshot {
guard let analyzer = {name}Analyzer,
let report = try? await analyzer.analyze(),
!report.current.isEmpty else { return snapshot }
return UsageSnapshot(/* copy all fields, add report */)
}
3d. Render in statsGrid
Add to MenuContentView.statsGrid(snapshot:):
if let report = snapshot.{name}Report {
let baseDelay = Double(snapshot.quotas.count + 1) * 0.08
// Render card(s) in LazyVGrid or standalone
}
3e. Register in ClaudeBarApp
Pass the analyzer when creating the provider:
{Provider}Provider(
probe: ...,
settingsRepository: settingsRepository,
{name}Analyzer: {Provider}{Name}Analyzer()
)
Phase 4: Verify
tuist generate- Run all tests:
xcodebuild test -scheme ClaudeBar-Workspace ... - Build the app and verify the cards appear
- Check logs for analyzer output
Checklist
Phase 0: Architecture
- [ ] Define data source, metrics, comparison period, provider
- [ ] Create architecture diagram
- [ ] Get user approval
Phase 1: Domain (TDD)
- [ ] Write
{Name}StatTests(formatting, isEmpty, edge cases) - [ ] Implement
{Name}Stat— make tests green - [ ] Write
{Name}ReportTests(deltas, percentages, progress) - [ ] Implement
{Name}Report— make tests green - [ ] Create
{Name}Analyzingprotocol with@Mockable
Phase 2: Infrastructure (TDD)
- [ ] Write parser tests (valid input, missing fields, malformed data)
- [ ] Implement parser — make tests green
- [ ] Write analyzer tests (temp dirs, date partitioning)
- [ ] Implement analyzer with file modification date filtering
- [ ] Run all infrastructure tests green
Phase 3: Integration
- [ ] Create
{Name}CardViewmatching glassmorphism style - [ ] Add
{name}Reportfield toUsageSnapshot - [ ] Wire analyzer into provider's
refresh()viaattach{Name}Report - [ ] Render cards in
statsGrid - [ ] Register analyzer in
ClaudeBarApp
Phase 4: Verify
- [ ]
tuist generatesucceeds - [ ] All tests pass
- [ ] App builds and cards render correctly
- [ ] Logs show analyzer activity
Du fichier au premier essai
Le téléchargement contient exactement le contenu affiché sur cette fiche. Cette copie peut différer de la dernière version du dépôt source.
Consulter la source et ses fichiers annexesCe téléchargement contient uniquement SKILL.md. Les scripts, références, modèles et dépendances éventuels ne sont pas inclus. Récupérez les fichiers nécessaires depuis la source en conservant leur arborescence avant de poursuivre.
1. Télécharger le fichier
Télécharger SKILL.mdDepuis la racine d’un projet de test, enregistrez le fichier sous .skill-downloads/add-report-card-to-claudebar-mryiqie6/SKILL.md, ou utilisez la commande suivante. Ce dossier sert à examiner la skill avant son installation.
Commande pour macOS/Linux ou WSL : un shell POSIX et curl sont nécessaires. Sous Windows sans WSL, utilisez le bouton de téléchargement et créez le dossier manuellement.
mkdir -p '.skill-downloads/add-report-card-to-claudebar-mryiqie6' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/add-report-card-to-claudebar-mryiqie6/download' --output '.skill-downloads/add-report-card-to-claudebar-mryiqie6/SKILL.md.part' && mv '.skill-downloads/add-report-card-to-claudebar-mryiqie6/SKILL.md.part' '.skill-downloads/add-report-card-to-claudebar-mryiqie6/SKILL.md'2. Vérifier les prérequis
Lisez SKILL.md avant de l’utiliser. Si le fichier cite des scripts ou services externes, examinez-les et préparez les accès nécessaires dans votre environnement de test.
Aucune section de prérequis reconnue dans ce fichier. Cela ne signifie pas qu’il est autonome : les bibliothèques, outils et accès peuvent être cités ailleurs dans le contenu ou dans le dépôt source.
Les plateformes de la fiche sont des indications du catalogue. Les chemins ci-dessous suivent la documentation des outils ; ils ne prouvent pas que cette skill y a été exécutée. Aucune version minimale de ces outils n’est attestée pour cette fiche.
3. Charger la skill
Après vérification, copiez le dossier complet dans le projet avec l’une des commandes ci-dessous, puis ouvrez une nouvelle session de l’outil. La commande s’arrête si un dossier du même nom existe déjà : comparez les fichiers avant de le remplacer.
Claude Code
test -f '.skill-downloads/add-report-card-to-claudebar-mryiqie6/SKILL.md' && test -s '.skill-downloads/add-report-card-to-claudebar-mryiqie6/SKILL.md' && mkdir -p '.claude/skills' && test ! -e '.claude/skills/add-report' && cp -R '.skill-downloads/add-report-card-to-claudebar-mryiqie6' '.claude/skills/add-report'Cursor
test -f '.skill-downloads/add-report-card-to-claudebar-mryiqie6/SKILL.md' && test -s '.skill-downloads/add-report-card-to-claudebar-mryiqie6/SKILL.md' && mkdir -p '.cursor/skills' && test ! -e '.cursor/skills/add-report' && cp -R '.skill-downloads/add-report-card-to-claudebar-mryiqie6' '.cursor/skills/add-report'Codex
test -f '.skill-downloads/add-report-card-to-claudebar-mryiqie6/SKILL.md' && test -s '.skill-downloads/add-report-card-to-claudebar-mryiqie6/SKILL.md' && mkdir -p '.agents/skills' && test ! -e '.agents/skills/add-report' && cp -R '.skill-downloads/add-report-card-to-claudebar-mryiqie6' '.agents/skills/add-report'OpenSkills
OpenSkills doit déjà être installé. La procédure locale install/read est contrôlée avec OpenSkills 1.5.0, qui exige Node.js ≥ 20.6.0. Aucun slug du catalogue n’est résolu automatiquement.
Installation officielle d’OpenSkillsopenskills install './.skill-downloads/add-report-card-to-claudebar-mryiqie6'openskills read 'add-report-card-to-claudebar-mryiqie6'La lecture doit afficher le contenu du fichier installé et son dossier de base. Elle ne lance ni la skill ni ses dépendances.
Pour un agent qui lit AGENTS.md, synchronisez ensuite l’index. Cette commande modifie AGENTS.md : relisez le diff avant de l’utiliser.
openskills syncMode manuel ou autre outil : joignez SKILL.md à une conversation, ou ouvrez-le dans un agent capable de lire les fichiers. Ajoutez les ressources annexes nécessaires. Il n’existe pas de dossier universel reconnu par tous les outils.
4. Faire un premier essai
Utilisez une entrée courte et fictive : un endpoint d’API, un petit document ou un brief d’interface. Dans une nouvelle conversation, joignez le fichier ou donnez son chemin à l’agent, puis adaptez cette demande :
Lis .skill-downloads/add-report-card-to-claudebar-mryiqie6/SKILL.md et applique ses instructions à cet exemple : [décrire une entrée de test]. Indique les fichiers, dépendances ou accès qui manquent. Produis le résultat demandé par la skill sans inventer de données ni exécuter de script non examiné.Résultat attendu : une sortie correspondant aux instructions de la skill, ou une liste précise des prérequis manquants. Une simple confirmation de lecture ne valide pas le premier usage. Si une ressource externe est indisponible, ce parcours reste à tester.
Bonnes pratiques React Hook Form
Developpement
Maîtrisez React Hook Form : évitez les anti-patterns, gérez les abonnements, et traitez correctement reset, dirty state et entrées contrôlées.
Migration Emotion vers Mantine
Developpement
Migrer les styled-components Emotion vers des composants Mantine avec style props et modules CSS. Pour convertir .styled.tsx ou supprimer les imports @emotion.
Détecteur de dérive de périmètre
Developpement
Analyse les diffs git par rapport à une intention pour détecter la dérive de périmètre, fichiers non liés et PR trop larges, puis suggère de garder, diviser ou justifier.