CLAUDE LABJP
TEACHERS — Anthropic launches Claude for Teachers, giving verified US K-12 educators free premium access, teaching skills, and curriculum links aligned to standards in all 50 statesADMIN — The Admin API is now in beta for every Claude Enterprise organization: member and invite calls need no beta header, while group and custom-role calls doM365 — The Microsoft 365 connector gains write tools — draft, send, and organize email, manage calendar events and mailbox settings, and create or update files in OneDrive and SharePointMCP — Fixed servers from --mcp-config or .mcp.json ignoring a per-server request_timeout_ms, which left long-running tool calls timing out at the 60s default in fresh sessionsSUBAGENT — A new --forward-subagent-text flag and CLAUDE_CODE_FORWARD_SUBAGENT_TEXT variable include subagent text and thinking in stream-json outputDEADLINE — Opus 4.7 fast mode is removed on July 24, seven days out. speed: "fast" will error, so confirm your move to Opus 4.8TEACHERS — Anthropic launches Claude for Teachers, giving verified US K-12 educators free premium access, teaching skills, and curriculum links aligned to standards in all 50 statesADMIN — The Admin API is now in beta for every Claude Enterprise organization: member and invite calls need no beta header, while group and custom-role calls doM365 — The Microsoft 365 connector gains write tools — draft, send, and organize email, manage calendar events and mailbox settings, and create or update files in OneDrive and SharePointMCP — Fixed servers from --mcp-config or .mcp.json ignoring a per-server request_timeout_ms, which left long-running tool calls timing out at the 60s default in fresh sessionsSUBAGENT — A new --forward-subagent-text flag and CLAUDE_CODE_FORWARD_SUBAGENT_TEXT variable include subagent text and thinking in stream-json outputDEADLINE — Opus 4.7 fast mode is removed on July 24, seven days out. speed: "fast" will error, so confirm your move to Opus 4.8
Articles/Cowork
Cowork/2026-07-17Advanced

It Worked on My Machine, but Nobody Could Trigger It — Four Assumptions I Stripped Out of a Cowork Plugin

I bundled four working automation skills into a plugin and shared it. Only one of them ever fired. Here is how I measured skill trigger rate, and the four assumptions — vocabulary, paths, connections, and naming — I had to strip out before it was portable.

cowork13plugin2skill2mcp18automation95distribution

Premium Article

Working as an indie developer, I had accumulated four automation skills over six months, written a piece at a time between other work. All of them ran beautifully on my machine. So I packaged them into a plugin and handed it to a friend doing similar work.

His reply, a few days later, was short. "Installed it. Nothing happens."

Works here. Doesn't work there. An old story — but peeling the layers off one at a time showed me exactly what I had been quietly assuming. This is that record.

Break "it doesn't work" into stages

"It doesn't work" covers at least three different failures.

StageSymptomHow you spot it
Never firesClaude answers normally, skill is never invokedNo Skill tool call appears in the log
Fires, then diesInvoked, then stops on an errorPath, token, or permission errors surface
Finishes, wrong outputRuns to completion, result is offEvery step logs success; only the artifact is wrong

What was happening on his machine was the first one. If you skip past that and start debugging the body of the skill, you will dig in the wrong place for a long time.

I did exactly that. I suspected the connectors, then the permissions, and burned about an hour. The skill had never been called once, so nothing inside it mattered. When you are the only tester on your own tools, getting the order of suspicion wrong costs you the whole afternoon.

Turn trigger rate into a number

Arguing from intuition goes nowhere. "The description is probably bad" gives you no way to tell whether you fixed it.

So I wrote a small harness: replay a list of plausible utterances, record which skill gets picked. It runs claude -p headless and pulls the skill name out of the tool calls.

Test cases go in a JSONL file, one per line.

{"utterance": "pull together last week's sales into a report", "expect": "weekly-report"}
{"utterance": "generate the weekly report", "expect": "weekly-report"}
{"utterance": "can I get a summary for this week", "expect": "weekly-report"}
{"utterance": "sort through the issues that piled up", "expect": "issue-triage"}
{"utterance": "label the new issues that came in", "expect": "issue-triage"}
{"utterance": "draft the release notes", "expect": "release-notes"}
{"utterance": "check today's billing", "expect": "billing-check"}

expect is the skill you want chosen for that phrasing. Mix in the same intent said several different ways, not just the way you happen to say it. That matters more than it looks.

Here is the runner.

#!/usr/bin/env bash
# skill-trigger-check.sh — record which skill gets picked for each sample utterance
# usage: ./skill-trigger-check.sh cases.jsonl trigger-report.tsv
set -euo pipefail
 
CASES="${1:?usage: skill-trigger-check.sh <cases.jsonl> [out.tsv]}"
OUT="${2:-trigger-report.tsv}"
 
: > "$OUT"
 
while IFS= read -r line; do
  [ -z "$line" ] && continue
  utterance=$(jq -r '.utterance' <<<"$line")
  expected=$(jq -r '.expect'     <<<"$line")
 
  # One turn only. We want to know whether it fires, not to let it
  # actually relabel a real issue every time we test.
  actual=$(claude -p "$utterance" \
             --output-format stream-json --verbose --max-turns 1 2>/dev/null \
           | jq -rs '[ .[]
                       | select(.type == "assistant")
                       | .message.content[]?
                       | select(.type == "tool_use" and .name == "Skill")
                       | .input.skill ] | first // "none"')
 
  if [ "$actual" = "$expected" ]; then status="MATCH"; else status="MISS"; fi
  printf '%s\t%s\t%s\t%s\n' "$status" "$expected" "$actual" "$utterance" >> "$OUT"
done < "$CASES"
 
awk -F'\t' '
  { n++; if ($1 == "MATCH") m++ }
  END { printf "trigger rate: %d/%d (%.0f%%)\n", m, n, (n ? m*100/n : 0) }
' "$OUT"

--max-turns 1 keeps the test from doing real work. All I want to know is whether the skill gets picked, so I stop the moment it is. jq -rs collects the stream into an array, grabs the first Skill call, and falls back to none when there isn't one.

On my machine: 18 of 20 matched. 90%. No wonder it felt smooth.

On his machine, same cases: 5 of 20. 25%. Of four skills, exactly one was responding at all.

The moment there was a number, the conversation got concrete. Fifteen MISS rows tell you plainly what is going on.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
A headless `claude -p` harness that replays 20 sample utterances and records which skill was picked — tracking the move from 25% to 85%
Three rules for rewriting a SKILL.md description from prose into routing input, with a concrete before and after
A bash preflight script, CI-ready as-is, that catches absolute paths, raw credentials, undocumented env vars, and collision-prone skill names
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Cowork2026-05-04
Why Cowork Scheduled Tasks Stop Mid-Run and How to Recover
A systematic guide to diagnosing and recovering from Cowork scheduled task failures — covering permission dialog lockups, bash-only file operations, disk space exhaustion, and git lock conflicts.
Cowork2026-04-29
Designing the One Page You Open Every Morning — Building Living Dashboards with Cowork Artifacts and MCP
Cowork Artifacts promote a chat answer into a re-openable page that fetches live MCP data. Here is how I design pages that replace recurring questions.
Cowork2026-03-27
Cowork Skills × Scheduling: Advanced Automation Patterns and Techniques
Master Cowork's skill and scheduling capabilities. Learn 5 real-world automation patterns: sales reports, daily standups, KPI monitoring, meeting notes, and smart customer follow-ups.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →