Logs and scores skill usage quality, tracking output effectiveness, user satisfaction signals, and improvement opportunities. Expert in skill analytics, quality metrics, feedback loops, and continuous improvement. Activate on "skill logging", "skill quality", "skill analytics", "skill scoring", "skill performance", "skill metrics", "track skill usage", "skill improvement". NOT for creating skills (use agent-creator), skill documentation (use skill-coach), or runtime debugging (use debugger skills).
npx skills add https://github.com/curiositech/some_claude_skills --skill skill-logger
Track, measure, and improve skill quality through systematic logging and scoring.
Use for:
NOT for:
┌────────────────────────────────────────────────────────────────┐
│ SKILL LOGGING PIPELINE │
├────────────────────────────────────────────────────────────────┤
│ │
│ 1. CAPTURE 2. ANALYZE 3. SCORE │
│ ├─ Invocation ├─ Output parse ├─ Quality metrics │
│ ├─ Input context ├─ Token usage ├─ User satisfaction │
│ ├─ Output ├─ Tool calls ├─ Goal completion │
│ └─ Timing └─ Error patterns └─ Efficiency │
│ │
│ 4. AGGREGATE 5. ALERT 6. IMPROVE │
│ ├─ Per-skill stats ├─ Quality drops ├─ Identify patterns │
│ ├─ Trend analysis ├─ Error spikes ├─ Suggest changes │
│ └─ Comparisons └─ Underuse └─ Track experiments │
│ │
└────────────────────────────────────────────────────────────────┘
{
"invocation_id": "uuid",
"timestamp": "ISO8601",
"skill_name": "wedding-immortalist",
"skill_version": "1.2.0",
"input": {
"user_query": "Create a 3D model from my wedding photos",
"context_tokens": 1500,
"files_referenced": ["photos/", "config.json"]
},
"execution": {
"duration_ms": 45000,
"tool_calls": [
{"tool": "Bash", "count": 5},
{"tool": "Write", "count": 3}
],
"tokens_used": {
"input": 8500,
"output": 3200
},
"errors": []
},
"output": {
"type": "code_generation",
"artifacts_created": ["pipeline.py", "config.yaml"],
"response_length": 3200
}
}
QUALITY_SIGNALS = {
# Implicit signals (automated)
'completion': 'Did the skill complete without errors?',
'token_efficiency': 'Output quality per token used',
'tool_success_rate': 'Tool calls that succeeded',
'retry_count': 'How many retries needed?',
# Explicit signals (user feedback)
'user_edit_ratio': 'How much did user modify output?',
'user_accepted': 'Did user accept/use the output?',
'follow_up_needed': 'Did user need to ask for fixes?',
'explicit_rating': 'Thumbs up/down if available',
# Outcome signals (delayed)
'code_ran_successfully': 'Did generated code work?',
'tests_passed': 'Did it pass tests?',
'reverted': 'Was the output later reverted?',
}
def calculate_skill_score(invocation_log):
"""Score a skill invocation 0-100."""
scores = {
# Completion (25%)
'completion': (
25 if invocation_log['errors'] == [] else
15 if invocation_log['recovered'] else
0
),
# Efficiency (20%)
'efficiency': min(20, 20 * (
BASELINE_TOKENS / invocation_log['tokens_used']
)),
# Output Quality (30%)
'quality': (
30 if invocation_log['user_accepted'] else
20 if invocation_log['user_edit_ratio'] < 0.2 else
10 if invocation_log['user_edit_ratio'] < 0.5 else
0
),
# User Satisfaction (25%)
'satisfaction': (
25 if invocation_log['explicit_rating'] == 'positive' else
15 if invocation_log['no_follow_up'] else
5 if invocation_log['follow_up_resolved'] else
0
),
}
return sum(scores.values())
| Score Range | Quality Level | Action |
|-------------|---------------|--------|
| 90-100 | Excellent | Document as exemplar |
| 75-89 | Good | Monitor for consistency |
| 50-74 | Acceptable | Review for improvements |
| 25-49 | Poor | Prioritize fixes |
| 0-24 | Failing | Immediate intervention |
CREATE TABLE skill_invocations (
id TEXT PRIMARY KEY,
skill_name TEXT NOT NULL,
skill_version TEXT,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
-- Input
user_query TEXT,
context_tokens INTEGER,
-- Execution
duration_ms INTEGER,
tokens_input INTEGER,
tokens_output INTEGER,
tool_calls_json TEXT,
errors_json TEXT,
-- Output
output_type TEXT,
artifacts_json TEXT,
response_length INTEGER,
-- Quality signals
user_accepted BOOLEAN,
user_edit_ratio REAL,
follow_up_needed BOOLEAN,
explicit_rating TEXT,
-- Computed
quality_score REAL,
INDEX idx_skill_name (skill_name),
INDEX idx_timestamp (timestamp),
INDEX idx_quality (quality_score)
);
CREATE TABLE skill_aggregates (
skill_name TEXT,
period TEXT, -- 'daily', 'weekly', 'monthly'
period_start DATE,
invocation_count INTEGER,
avg_quality_score REAL,
error_rate REAL,
avg_tokens_used INTEGER,
avg_duration_ms INTEGER,
PRIMARY KEY (skill_name, period, period_start)
);
{
"logs_version": "1.0",
"skill_name": "wedding-immortalist",
"entries": [
{
"id": "uuid",
"timestamp": "2025-01-15T14:30:00Z",
"input": {...},
"execution": {...},
"output": {...},
"quality": {
"signals": {...},
"score": 85,
"computed_at": "2025-01-15T14:35:00Z"
}
}
]
}
-- Overall skill rankings
SELECT
skill_name,
COUNT(*) as uses,
AVG(quality_score) as avg_quality,
AVG(tokens_output) as avg_tokens,
SUM(CASE WHEN errors_json != '[]' THEN 1 ELSE 0 END) * 100.0 / COUNT(*) as error_rate
FROM skill_invocations
WHERE timestamp > datetime('now', '-30 days')
GROUP BY skill_name
ORDER BY avg_quality DESC;
-- Quality trend (weekly)
SELECT
skill_name,
strftime('%Y-%W', timestamp) as week,
AVG(quality_score) as avg_quality,
COUNT(*) as uses
FROM skill_invocations
GROUP BY skill_name, week
ORDER BY skill_name, week;
-- Problem detection
SELECT skill_name, COUNT(*) as failures
FROM skill_invocations
WHERE quality_score < 50
AND timestamp > datetime('now', '-7 days')
GROUP BY skill_name
HAVING failures >= 3
ORDER BY failures DESC;
def identify_improvement_opportunities(skill_name, logs):
"""Analyze logs to suggest skill improvements."""
opportunities = []
# Pattern 1: Common follow-up questions
follow_ups = extract_follow_up_patterns(logs)
if follow_ups:
opportunities.append({
'type': 'missing_capability',
'description': f'Users frequently ask: {follow_ups[0]}',
'suggestion': 'Add guidance for this common need'
})
# Pattern 2: High edit ratio in specific output types
edit_patterns = analyze_edit_patterns(logs)
if edit_patterns['code'] > 0.4:
opportunities.append({
'type': 'code_quality',
'description': 'Users frequently edit generated code',
'suggestion': 'Review code examples and templates'
})
# Pattern 3: Repeated errors
error_patterns = cluster_errors(logs)
for error_type, count in error_patterns:
if count >= 3:
opportunities.append({
'type': 'recurring_error',
'description': f'{error_type} occurred {count} times',
'suggestion': 'Add error handling or documentation'
})
return opportunities
# hooks/skill_logger.py
import json
import sqlite3
from datetime import datetime
from pathlib import Path
LOG_DB = Path.home() / '.claude' / 'skill_logs.db'
def log_skill_invocation(
skill_name: str,
user_query: str,
output: str,
tool_calls: list,
duration_ms: int,
tokens: dict,
errors: list = None
):
"""Log a skill invocation to the database."""
conn = sqlite3.connect(LOG_DB)
cursor = conn.cursor()
cursor.execute('''
INSERT INTO skill_invocations
(id, skill_name, timestamp, user_query, duration_ms,
tokens_input, tokens_output, tool_calls_json, errors_json,
response_length)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (
str(uuid.uuid4()),
skill_name,
datetime.utcnow().isoformat(),
user_query,
duration_ms,
tokens.get('input', 0),
tokens.get('output', 0),
json.dumps(tool_calls),
json.dumps(errors or []),
len(output)
))
conn.commit()
conn.close()
def collect_quality_signals(invocation_id: str, signals: dict):
"""Update an invocation with quality signals."""
conn = sqlite3.connect(LOG_DB)
cursor = conn.cursor()
# Update with user feedback
cursor.execute('''
UPDATE skill_invocations
SET user_accepted = ?,
user_edit_ratio = ?,
follow_up_needed = ?,
explicit_rating = ?,
quality_score = ?
WHERE id = ?
''', (
signals.get('accepted'),
signals.get('edit_ratio'),
signals.get('follow_up'),
signals.get('rating'),
calculate_score(signals),
invocation_id
))
conn.commit()
conn.close()
ALERT_CONDITIONS = {
'quality_drop': {
'condition': 'avg_quality_7d < avg_quality_30d * 0.8',
'message': 'Skill {skill} quality dropped 20%+ in past week',
'severity': 'warning'
},
'error_spike': {
'condition': 'error_rate_24h > error_rate_7d * 2',
'message': 'Skill {skill} error rate doubled in past 24h',
'severity': 'critical'
},
'underused': {
'condition': 'uses_7d < uses_30d_avg * 0.5',
'message': 'Skill {skill} usage down 50%+ this week',
'severity': 'info'
},
'high_performer': {
'condition': 'avg_quality_7d > 90 AND uses_7d > 10',
'message': 'Skill {skill} performing excellently',
'severity': 'positive'
}
}
Wrong: Logging complete input/output for every invocation.
Why: Privacy concerns, storage explosion, noise.
Right: Log metadata, summaries, and opt-in detailed logging.
Wrong: Calculating quality score immediately after completion.
Why: Misses delayed signals (did code work? was it reverted?).
Right: Collect signals over time, recalculate periodically.
Wrong: Only tracking average quality scores.
Why: Hides distribution, misses failure modes.
Right: Track percentiles, failure rates, and patterns.
Wrong: Measuring quality without establishing baselines.
Why: Can't detect improvement or regression.
Right: Establish baselines per skill, compare trends.
# Skill Health Report - Week of 2025-01-13
## Overview
- Total invocations: 247
- Average quality: 78.3 (up 2.1 from last week)
- Error rate: 4.2% (down 1.8%)
## Top Performers
1. **wedding-immortalist** - 92.1 avg quality, 18 uses
2. **skill-coach** - 89.4 avg quality, 34 uses
3. **api-architect** - 87.2 avg quality, 22 uses
## Needs Attention
1. **legacy-code-converter** - 52.3 avg quality (down 15%)
- Common issue: Missing dependency detection
- Suggested fix: Add dependency scanning step
## Improvement Opportunities
- `partner-text-coach`: Users frequently ask for tone adjustment
- `yard-landscaper`: High edit ratio on plant recommendations
Core Philosophy: What gets measured gets improved. Skill logging transforms intuition about skill quality into actionable data, enabling continuous improvement of the entire skill ecosystem.
Meta-skill for publication-ready figures. Use when creating journal submission figures requiring multi-panel layouts, significance annotations, error bars, colorblind-safe palettes, and specific journal formatting (Nature, Science, Cell). Orchestrates matplotlib/seaborn/plotly with publication styles. For quick exploration use seaborn or plotly directly.
Coding Agent Account Manager - Sub-100ms account switching for AI coding CLIs with fixed-cost subscriptions. Vault profiles, isolated profiles for parallel sessions, smart rotation with health scoring, cooldown tracking, automatic failover, TUI dashboard. Go CLI.
Use this umbrella skill when the request spans multiple Cloud Claw user-facing domains, especially launching a new AltClaw or OpenClaw VM and then managing lifecycle, logs, renewal, or dashboard access through the local altllm cloud-claw-* commands in this repository.
Creating interactive data visualisations using d3.js. This skill should be used when creating custom charts, graphs, network diagrams, geographic visualisations, or any complex SVG-based data visua...
Use this skill when you need to report on a troubleshooting session
Query and browse evaluation results stored in MLflow. Use when the user wants to look up runs by invocation ID, compare metrics across models, fetch artifacts (configs, logs, results), or set up the MLflow MCP server. ALWAYS triggers on mentions of MLflow, experiment results, run comparison, invocation IDs in the context of results, or MLflow MCP setup.
Guided journey from an app people sign up for and then quietly abandon to a sealed retention engine with a habit loop, an activated first run, and one metric the whole team trusts. Orchestrates eight skills phase by phase - hooked-ux, improve-retention, continuous-discovery, lean-ux, inspired-product, lean-analytics, microinteractions, drive-motivation - asking the user questions at every decision point and recording results in the project docs/ folder (PRODUCT.md, METRICS.md, GROW-APP-PLAN.md) so the journey resumes across sessions. Use when the user wants to lift activation and retention, design a habit loop, fix a leaky onboarding funnel, or says ''users sign up then disappear''. Do not use to fix broken UX or performance that no engagement mechanic can paper over - run improve-app first; if there is no app yet, use create-app. For one framework in isolation, invoke that skill directly.
Guided journey from a stalled, plateaued business to one with an honest diagnosis, a working operating rhythm, and offers repriced to real value. Orchestrates eight skills phase by phase - good-strategy-bad-strategy, traction-eos, high-output-management, team-topologies, drive-motivation, lean-analytics, negotiation, monetizing-innovation - asking the user questions at every decision point and recording results in the project docs/ folder (STRATEGY.md, OPERATIONS.md, METRICS.md, IMPROVE-BUSINESS-PLAN.md) so the journey resumes across sessions. Use when the user wants to fix a business that has plateaued, diagnose why growth stalled, tighten strategy and execution, re-motivate a team, or says ''revenue is flat and I do not know why''. Starting from scratch with no customers: use create-business. Once the fundamentals work and the goal is expansion: use grow-business. When the product itself drags the business down: use improve-app. For one framework in isolation, invoke that skill directly.
Take curiositech/skill-logger from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.