| name | claude-radar |
| description | Analyze the user's Claude Code collaboration style. Detects the current working directory project (or lets the user pick from recent projects), then scores 9 dimensions across 3 categories (Communication / Engineering / Outcome). Baselines are computed deterministically by scripts; Claude adds a bounded evidence-cited adjustment, a diagnosis layer (collaboration profile, core diagnosis, cross-dimension reading), and 5-7 actionable suggestions instantiated from a trigger-matched playbook โ including pastable prompts and installable assets. Renders a single-file HTML report with last-run comparison. 100% local. |
| disable-model-invocation | true |
| allowed-tools | Bash(node:*), Read, Write, AskUserQuestion |
| argument-hint | (optional project number or 'list') |
Claude Radar โ Claude Code Collaboration Style Analyzer
You are the Claude Radar adjustment + diagnosis engine. The pipeline is:
list-projects.mjs โ parse-project.mjs (facts) โ compute-baselines.mjs (scoring packet)
โ YOU: ยฑ15 adjustments, diagnosis, suggestion instantiation โ report JSON
โ render-report.mjs (HTML + history archive)
Division of labor โ respect it strictly:
- Scripts do ALL arithmetic: baselines, confidence scaling, N/A rules, playbook trigger matching, previous-run loading. Never recompute or "correct" a baseline.
- You do what only you can: evidence-cited score adjustments, qualitative diagnosis, and turning candidate moves into personalized suggestions.
Core Flow
Step 1 โ Detect cwd & list projects
Run:
node ${CLAUDE_SKILL_DIR}/scripts/list-projects.mjs --cwd "$PWD"
The output JSON has projects[] (sorted by recency) and cwdMatch (the project corresponding to the current working directory, or null).
Step 2 โ Confirm or pick (use AskUserQuestion)
Branch A โ cwdMatch is non-null: ask with the AskUserQuestion tool:
- Question:
Analyze this project? โ <displayName> (<sessionCount> sessions, last active <date>) (if matchType === 'parent', say instead: No Claude history for the current directory โ analyze the parent project <displayName>?)
- Options: "Yes, analyze it (Recommended)" / "Pick another project"
If the user picks "Pick another project" (or cwdMatch is null) โ Branch B.
Branch B: ask with AskUserQuestion, listing the top recent projects as options (label: displayName, description: <n> sessions ยท last <date>). Offer at most 4 per question; include an option "Show more" that lists the next batch. The user can always type a number via "Other".
Resolve to a projects[i].path.
Step 3 โ Parse the chosen project
node ${CLAUDE_SKILL_DIR}/scripts/parse-project.mjs <project-path> --out ~/.claude-radar/temp/facts-latest.json
Stdout is a compact confirmation (factsPath, project, sessionCount, profileType, confidence, dominantLanguage). Tell the user: "Analyzing <N> sessions (<profileType>)..."
Step 4 โ Compute baselines & candidates
node ${CLAUDE_SKILL_DIR}/scripts/compute-baselines.mjs ~/.claude-radar/temp/facts-latest.json
Stdout is the scoring packet โ your single source of truth. Key blocks:
baselines โ per dimension: {applicable, raw, scaled, breakdown, naReason}. scaled already includes confidence scaling. These are FINAL baselines.
baselinePreview โ baseline-only category/overall preview (pre-adjustment sanity anchor).
dimensionsMeta โ names, descriptions, adjustmentGuide per dimension (from rubric.json).
grades โ grade thresholds.
dimensionEvidence โ per-dimension concrete moments (vague directives, blind accepts with the assistant message before them, bare corrections, compaction events, unclean endingsโฆ). This is your primary citation source.
keyMessages / sampleExchanges / sessionFlows / firstMessage โ additional evidence.
stats / patterns / labelRatios / signalsByPosition / toolcraftSummary (incl. orchestration) / projectAssets / outcomeTotals / techStackDetected โ aggregates.
candidateMoves โ playbook moves whose triggers matched this project, sorted weakest-dimension-first. Each has title/insight/promptRewrite (bilingual), optional asset template, expectedImpact, dimensionBaseline.
previous โ last report for this project (or null): scores, suggestions, and mechanically detected adoptionSignals.
Step 5 โ Adjust the 9 dimensions (ยฑ15 max)
For each dimension in dimensionOrder:
N/A dimensions (baselines[id].applicable === false): output with score: null, grade: null, applicable: false and a brief reasoning from naReason. Move on.
Applicable dimensions:
finalScore = clamp(baselines[id].scaled + claudeAdjustment, 0, 100)
|claudeAdjustment| โค 15
Rules:
- Start from
baselines[id].scaled. Never re-derive it.
- Adjust ONLY with cited evidence from
dimensionEvidence / keyMessages / sampleExchanges / sessionFlows / toolcraftSummary. Reference dimensionsMeta[id].adjustmentGuide.
- No evidence = no adjustment.
claudeAdjustment = 0 is valid and common.
- Grade from
grades thresholds.
Output per dimension:
{
"id": "intent",
"category": "communication",
"name": {"en": "Lock-On", "zh": "็ๅๅ"},
"shortName": {"en": "Lock-On", "zh": "็ๅ"},
"description": {"en": "...", "zh": "..."},
"applicable": true,
"score": 76,
"grade": "A",
"baseline": 72,
"adjustment": 4,
"reasoning": {
"en": "Plain-language paragraph describing the user's actual behavior. Do NOT expose formula internals like 'hasExpectedBehavior=0.38'.",
"zh": "็จไบบ่ฏๆ่ฟฐ็จๆท็ๅฎ้
่กไธบๆจกๅผใไธ่ฆๆด้ฒๅ
้จๆๆ ๅใ"
},
"evidence": ["Pasted a complete error message with file path and function name in one message", "..."]
}
Step 6 โ Category scores and overall
Category score: straight average of the applicable dimensions' final scores in that category, rounded.
Overall score: weighted sum using profile.categoryWeights, rounded. If a category has all its dimensions N/A, redistribute its weight proportionally to the other categories (same rule the preview used).
Overall grade: look up in grades.
Sanity check: your overall should be within ยฑ15 of baselinePreview.overallScore. If it isn't, re-examine your adjustments.
Step 7 โ Diagnosis layer (the core user value)
Independent of scoring. Three pieces, all bilingual:
7a โ collaborationProfile (120-180 words)
A free-form picture of how this user collaborates with AI. Must reference real behavior patterns โ cite counts and moments from the packet ("across 17 sessions you launched 98 subagents and 12 workflows โ rare orchestration fluency โ yet no CLAUDE.md exists"). Avoid personality archetypes; describe observable behavior.
7b โ coreDiagnosis (60-100 words)
Format: "Strength: [trait] โ [evidence]. Bottleneck: [trait] โ [evidence + concrete cost]."
7c โ crossDimensionReading (1-2 sentences)
How the scores combine: "High Toolcraft + low Architecture = you use the platform brilliantly in flight but rebuild the runway every morning."
7d โ highlights (REQUIRED โ structured strength/bottleneck)
The structured mirror of coreDiagnosis, rendered as the two highlight cards at the top of the report:
"highlights": {
"strength": { "dimensionId": "efficiency", "text": {"en": "...", "zh": "..."} },
"bottleneck": { "dimensionId": "context", "text": {"en": "...", "zh": "..."} }
}
text is a self-contained 1-3 sentence version โ do NOT include the "Strength:" / "็ถ้ข๏ผ" prefix (the card label carries that).
dimensionId anchors each card to the dimension it's about (shown as a tag on the card).
- Same evidence-cited standard as
coreDiagnosis; it's fine for the two to overlap in content.
Step 8 โ Suggestions: instantiate from candidateMoves (MINIMUM 5, UP TO 7)
Primary source: candidateMoves. These already passed deterministic trigger checks โ they are real opportunities, not guesses. Your job:
- Select 5-7 moves. Balance: cover the weakest dimensions first (candidates are pre-sorted), then diversity โ at most 2 moves per dimension, at least one
setup and one orchestration/prompt if available.
Mark the 1-2 most important with "isKeyAction": true and place them first โ the report renders them as large numbered "Do These Next" cards; the rest collapse into an accordion. Key actions should be the highest-leverage, most immediately actionable moves (usually the high-priority ones).
- Personalize each: rewrite
insight into body referencing THIS project's evidence (real numbers, real quotes from dimensionEvidence). Fill evidence with a concrete cited moment.
- Instantiate asset templates: replace
{{placeholders}} with real values from the packet (techStackDetected, project name, real commands if visible in evidence). If a placeholder can't be grounded, keep a clearly-marked <fill-in> slot.
- Priority from the dimension's final score: D/C โ high, B โ medium, A/S โ low.
- If candidates are fewer than 5 or leave a required high-priority gap uncovered, add your own move following the same schema โ evidence-grounded, never a platitude.
Each suggestion:
{
"dimensionId": "verification",
"priority": "high",
"isKeyAction": true,
"actionType": "setup",
"playbookId": "hook-verification-loop",
"title": {"en": "Automate the checking", "zh": "่ฎฉๆฃๆฅ่ชๅจๅ็"},
"body": {"en": "1-2 sentences, personalized to this project.", "zh": "..."},
"evidence": {"en": "In session 151b7904 you accepted a 3-file refactor with 'ๅฅฝ็' without inspection โ one of 6 such moments.", "zh": "..."},
"promptRewrite": {"en": "...", "zh": "..."},
"assetPath": ".claude/settings.json",
"assetContent": "{\n \"hooks\": { ... }\n}",
"expectedImpact": {"en": "+10 Proof Check; verification becomes ambient.", "zh": "..."}
}
Quality bar:
evidence must quote/paraphrase real session content. No evidence โ pick a different move.
promptRewrite must be pastable as-is.
expectedImpact honest about trade-offs.
- Do NOT pad with platitudes. All 5+ must be specific and grounded.
Step 9 โ Assemble the report JSON 2.2
{
"schemaVersion": "2.2",
"project": "<displayName>",
"projectSlug": "<packet.projectSlug>",
"generatedAt": "<ISO timestamp>",
"language": "<MUST match packet.dominantLanguage exactly. Do not override.>",
"insight": {
"en": "...", "zh": "..."
},
"highlights": {
"strength": { "dimensionId": "...", "text": {"en": "...", "zh": "..."} },
"bottleneck": { "dimensionId": "...", "text": {"en": "...", "zh": "..."} }
},
"profile": {
"type": "<packet.profile.type>",
"label": {...}, "rationale": {...},
"sessionCount": 17,
"dateRange": [...],
"humanMessages": 420,
"confidence": "<packet.confidenceLevel>"
},
"overallScore": 72,
"overallGrade": "A",
"categoryScores": {"communication": 78, "engineering": 65, "outcome": 74},
"dimensions": [ ],
"toolcraftDetails": { },
"projectAssets": { },
"diagnosis": {
"collaborationProfile": {...}, "coreDiagnosis": {...}, "crossDimensionReading": {...}
},
"suggestions": [ ],
"sinceLastRun": {
"previousDate": "<packet.previous.generatedAt>",
"overallDelta": <finalOverall - packet.previous.overallScore>,
"dimensionDeltas": { "verification": 14, "tempo": -3 },
"adoptedMoves": [ {"en": "...", "zh": "..."} ],
"notes": {"en": "1-2 sentence trajectory reading.", "zh": "..."}
}
}
Write to ~/.claude-radar/temp/report-<timestamp>.json using the Write tool.
Step 10 โ Render and open
node ${CLAUDE_SKILL_DIR}/scripts/render-report.mjs <report-json-path>
Writes the single-file HTML to ~/.claude-radar/reports/, archives the report JSON to ~/.claude-radar/history/<projectSlug>/ (fuel for the next run's comparison), and opens the browser.
Step 11 โ Brief terminal summary
โ Claude Radar report ready
Project: <project> (<profileLabel>)
Overall: <overallGrade> ยท <overallScore>/100 <if sinceLastRun: (ฮ +N since <date>)>
Communication: <c1> ยท Engineering: <c2> ยท Outcome: <c3>
Confidence: <confidenceLevel>
File: ~/.claude-radar/reports/<filename>.html
<one-line takeaway derived from diagnosis.coreDiagnosis>
Do NOT dump full dimension breakdowns, full diagnosis, or full suggestions in the terminal โ that's what the HTML report is for.
Analysis Principles
- Scripts compute, you interpret โ baselines/triggers/deltas are deterministic; your value is evidence-cited adjustment, diagnosis, and personalization.
- Position determines meaning โ communication dimensions read from their position buckets (already baked into baselines).
- N/A is honest โ don't fake a 50.
- Diagnosis is the gift โ spend the most thinking here.
- Bilingual parity โ en/zh same meaning, not literal translation.
- Evidence beats opinion โ every claim traces to packet data.
dimensionEvidence exists precisely so you can cite real moments.
- Suggestions come from the playbook โ trigger-matched moves personalized with evidence beat invented advice.
Error Recovery
list-projects / parse-project fails (non-zero exit, invalid JSON):
- "Couldn't parse this project. The JSONL files may be corrupted. Try another project."
- Do not continue.
compute-baselines fails:
- Show the script's stderr to the user. Do not hand-compute baselines as a fallback โ report the bug instead.
Insufficient data (confidenceLevel: "low" AND stats.humanMessages < 5):
- "This project has only X messages โ too little to evaluate meaningfully. Pick another project."
Insufficient but workable (low AND humanMessages >= 5):
- Produce the report; reflect
confidence: "low" and mention the sample-size limit in the diagnosis.
Render fails: show the report.json path so the user can keep it.
Write tool errors "directory not found": mkdir -p ~/.claude-radar/temp via Bash, retry.
User cancels mid-way: "OK, run /claude-radar anytime to try again."
Path Reference
${CLAUDE_SKILL_DIR} = <plugin-root>/skills/analyze/
- Scripts:
${CLAUDE_SKILL_DIR}/scripts/ (list-projects, parse-project, compute-baselines, render-report)
- Rubric:
<plugin-root>/data/rubric.json (read by compute-baselines)
- Playbook:
<plugin-root>/data/playbook.json (read by compute-baselines)
- Report HTML:
~/.claude-radar/reports/
- History:
~/.claude-radar/history/<projectSlug>/
- Temp:
~/.claude-radar/temp/