Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,31 @@ jobs:
echo "::error::Found {{SKILLS_DIR}} in plugins/. This is the npx-skills install-time placeholder and is NOT substituted by Claude Code. Use \${CLAUDE_PLUGIN_ROOT}/skills/<skill-name>/... instead."
exit 1
fi

- name: Validate skills index.json (OpenCode)
run: |
set -e
INDEX=plugins/tsuga/skills/index.json
jq empty "$INDEX"

# Every skill dir must have an entry in index.json
fail=0
for d in plugins/tsuga/skills/*/; do
name=$(basename "$d")
[ "$name" = "index.json" ] && continue
if ! jq -e ".skills[] | select(.name == \"$name\")" "$INDEX" >/dev/null 2>&1; then
echo "::error file=$INDEX::skill '$name' missing from index.json"
fail=1
fi
done

# Every file referenced in index.json must exist on disk
jq -r '.skills[] | .name as $s | .files[] | "\($s)/\(.)"' "$INDEX" | \
while IFS= read -r f; do
if [ ! -f "plugins/tsuga/skills/$f" ]; then
echo "::error file=$INDEX::index.json references missing file: $f"
fail=1
fi
done

exit $fail
22 changes: 20 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This repo distributes **one plugin**, `tsuga`, from a single marketplace using t
.claude-plugin/marketplace.json ← marketplace listing; each plugin points to its own subdir via source
plugins/tsuga/
.claude-plugin/plugin.json ← per-plugin manifest
skills/index.json ← OpenCode skills index (lists every skill + its files)
skills/<skill-name>/SKILL.md ← skills auto-discovered by Claude Code / Codex
```

Expand All @@ -20,7 +21,8 @@ Notes:
## When changing a skill

1. Edit `plugins/tsuga/skills/<skill>/SKILL.md` (or files under its `references/`).
2. **Bump versions in lockstep.** Two places:
2. **Update `plugins/tsuga/skills/index.json`** — if files were added or removed, update the `files[]` array for that skill.
3. **Bump versions in lockstep.** Two places:
- `.claude-plugin/marketplace.json` → `metadata.version`
- `plugins/tsuga/.claude-plugin/plugin.json` → `version`

Expand All @@ -34,7 +36,8 @@ Notes:
## When adding a new skill

1. Create `plugins/tsuga/skills/<new-skill>/SKILL.md` with proper frontmatter (`name:`, `description:`).
2. Use existing naming patterns:
2. **Add the skill to `plugins/tsuga/skills/index.json`** — add an entry with `name`, `description`, and `files[]` listing every file in the skill directory (use relative paths, e.g. `references/foo.md`).
3. Use existing naming patterns:
- `otel-*` for SDK, Collector, and code-facing OpenTelemetry guidance.
- `tsuga-*` for live Tsuga workflows, dashboards, audits, telemetry debug workflows, and CLI-backed tasks.
- Unprefixed names for platform-agnostic advisory skills.
Expand Down Expand Up @@ -91,6 +94,20 @@ done

# No stray top-level skills/ directory
[ -d skills ] && echo "FAIL: skills/ should be empty/absent — move into plugins/tsuga/skills/"

# index.json is valid JSON and every skill dir has an entry
jq empty plugins/tsuga/skills/index.json
for d in plugins/tsuga/skills/*/; do
name=$(basename "$d")
jq -e ".skills[] | select(.name == \"$name\")" plugins/tsuga/skills/index.json >/dev/null 2>&1 || \
echo "FAIL: $name missing from index.json"
done

# Every file in index.json files[] exists on disk
jq -r '.skills[] | .name as $s | .files[] | "\($s)/\(.)"' plugins/tsuga/skills/index.json | \
while IFS= read -r f; do
[ -f "plugins/tsuga/skills/$f" ] || echo "FAIL: index.json references missing file: $f"
done
```

## Release
Expand All @@ -112,6 +129,7 @@ claude plugin tag ./plugins/tsuga
- Don't add a `skills[]` array to marketplace.json. Skills auto-discover from the plugin's subdir.
- Don't restore standalone telemetry packaging.
- Don't rename a skill folder without grepping the repo for cross-references (`tsuga-cli`, `otel-instrumentation`, etc.).
- Don't let `plugins/tsuga/skills/index.json` drift — every skill directory must have a matching entry, and `files[]` must list every file on disk.

## Skill authoring rules

Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,26 @@ codex plugin marketplace add tsuga-dev/agent-plugins
codex plugin add tsuga@tsuga
```

### OpenCode

> [!IMPORTANT]
This has only been tested with opencode v1, as v2 is still in beta.

Add the skills URL to your `opencode.json`:

```json
{
"$schema": "https://opencode.ai/config.json",
"skills": {
"urls": ["https://raw.githubusercontent.com/tsuga-dev/agent-plugins/main/plugins/tsuga/skills/"]
}
}
```

You can replace `main` with any valid SHA of the repository to pin the skills if you want to opt-out of "auto update".

The trailing slash is required. OpenCode fetches `index.json` from that URL, discovers all skills, and downloads them to `~/.cache/opencode/skills/`.

## Ownership & contributions

Tsuga owns and maintains this plugin — anything generic about operating Tsuga or instrumenting with OpenTelemetry belongs here, and installs with `autoUpdate` receive new versions automatically.
Expand Down
277 changes: 277 additions & 0 deletions plugins/tsuga/skills/index.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
{
"skills": [
{
"name": "build-incident-history",
"description": "One-shot procedure for turning a raw incident dump into a populated incident-history archive.",
"files": [
"RECOMMENDED_PROMPT.md",
"SKILL.md",
"references/INPUT_LAYOUT.md",
"references/LESSONS.md",
"references/PROCEDURE.md",
"references/SUBAGENT_PROMPT.md",
"references/SUMMARY_TEMPLATE.md",
"references/VERIFICATION.md"
]
},
{
"name": "build-knowledge-company",
"description": "One-shot procedure for turning a live Tsuga account + codebase list into the knowledge-company tree.",
"files": [
"RECOMMENDED_PROMPT.md",
"SKILL.md",
"references/CLI_TRANSLATION.md",
"references/INPUT_LAYOUT.md",
"references/LESSONS.md",
"references/PROCEDURE.md",
"references/SERVICE_KNOWLEDGE_TEMPLATE.md",
"references/SKILL_TEMPLATE.md",
"references/SUBAGENT_PROMPT.md",
"references/TEAM_KNOWLEDGE_TEMPLATE.md",
"references/VERIFICATION.md"
]
},
{
"name": "check-skill-health",
"description": "Use when linting Tsuga skill bundles after editing runtime skills, generated archives, or references.",
"files": [
"SKILL.md",
"references/CHECKLIST.md",
"references/RULES.md",
"scripts/check-forbidden-tokens.sh",
"scripts/check-frontmatter.sh",
"scripts/check-incident-history.sh",
"scripts/check-knowledge-company.sh",
"scripts/check-skill-length.sh",
"scripts/lint-all.sh",
"scripts/sample-execute-commands.sh"
]
},
{
"name": "gh",
"description": "GitHub CLI for inspecting workflow runs, PRs, commits, releases, and deployments.",
"files": [
"SKILL.md"
]
},
{
"name": "incident-investigation",
"description": "Primary entry point for active-incident investigation, post-incident RCA, or recurring-degradation triage.",
"files": [
"SKILL.md",
"agents/openai.yaml",
"references/branch-change-correlation.md",
"references/branch-telemetry-sweep.md",
"references/case-manifest.md",
"references/investigation-record.md",
"references/tsuga-rules.md",
"references/playbooks/auth-tls.md",
"references/playbooks/data-quality.md",
"references/playbooks/database.md",
"references/playbooks/deploy-drift.md",
"references/playbooks/kubernetes.md",
"references/playbooks/queue-backpressure.md"
]
},
{
"name": "knowledge-technology",
"description": "Per-technology reference bundles with metric names, incident shapes, derived signals, and log patterns.",
"files": [
"SKILL.md",
"references/apache/README.md",
"references/apache/metrics.csv",
"references/apache/queries.md",
"references/aws-api-gateway/README.md",
"references/aws-api-gateway/metrics.csv",
"references/aws-api-gateway/queries.md",
"references/aws-docdb/README.md",
"references/aws-docdb/metrics.csv",
"references/aws-docdb/queries.md",
"references/aws-dynamodb/README.md",
"references/aws-dynamodb/metrics.csv",
"references/aws-dynamodb/queries.md",
"references/aws-ecs/README.md",
"references/aws-ecs/metrics.csv",
"references/aws-ecs/queries.md",
"references/aws-efs/README.md",
"references/aws-efs/metrics.csv",
"references/aws-efs/queries.md",
"references/aws-elasticache/README.md",
"references/aws-elasticache/metrics.csv",
"references/aws-elasticache/queries.md",
"references/aws-elb/README.md",
"references/aws-elb/metrics.csv",
"references/aws-elb/queries.md",
"references/aws-eventbridge/README.md",
"references/aws-eventbridge/metrics.csv",
"references/aws-eventbridge/queries.md",
"references/aws-firehose/README.md",
"references/aws-firehose/metrics.csv",
"references/aws-firehose/queries.md",
"references/aws-lambda/README.md",
"references/aws-lambda/metrics.csv",
"references/aws-lambda/queries.md",
"references/aws-nat-gateway/README.md",
"references/aws-nat-gateway/metrics.csv",
"references/aws-nat-gateway/queries.md",
"references/aws-privatelink/README.md",
"references/aws-privatelink/metrics.csv",
"references/aws-privatelink/queries.md",
"references/aws-rds/README.md",
"references/aws-rds/metrics.csv",
"references/aws-rds/queries.md",
"references/aws-sqs/README.md",
"references/aws-sqs/metrics.csv",
"references/aws-sqs/queries.md",
"references/caddy/README.md",
"references/caddy/metrics.csv",
"references/caddy/queries.md",
"references/cassandra/README.md",
"references/cassandra/metrics.csv",
"references/cassandra/queries.md",
"references/envoy/README.md",
"references/envoy/metrics.csv",
"references/envoy/queries.md",
"references/gcp-pubsub/README.md",
"references/gcp-pubsub/metrics.csv",
"references/gcp-pubsub/queries.md",
"references/gcp-storage/README.md",
"references/gcp-storage/metrics.csv",
"references/gcp-storage/queries.md",
"references/haproxy/README.md",
"references/haproxy/metrics.csv",
"references/haproxy/queries.md",
"references/istio/README.md",
"references/istio/metrics.csv",
"references/istio/queries.md",
"references/jvm/README.md",
"references/jvm/metrics.csv",
"references/jvm/queries.md",
"references/kafka/README.md",
"references/kafka/metrics.csv",
"references/kafka/queries.md",
"references/kubernetes/README.md",
"references/kubernetes/metrics.csv",
"references/kubernetes/queries.md",
"references/kubernetes/runbooks.md",
"references/litespeed/README.md",
"references/litespeed/metrics.csv",
"references/litespeed/queries.md",
"references/mysql/README.md",
"references/mysql/metrics.csv",
"references/mysql/queries.md",
"references/nginx/README.md",
"references/nginx/metrics.csv",
"references/nginx/queries.md",
"references/nvidia-gpu/README.md",
"references/nvidia-gpu/metrics.csv",
"references/nvidia-gpu/queries.md",
"references/openai/README.md",
"references/openai/metrics.csv",
"references/openai/queries.md",
"references/otel-collector/README.md",
"references/otel-collector/metrics.csv",
"references/otel-collector/queries.md",
"references/postgres/README.md",
"references/postgres/metrics.csv",
"references/postgres/queries.md",
"references/quickwit/README.md",
"references/quickwit/metrics.csv",
"references/quickwit/queries.md",
"references/rabbitmq/README.md",
"references/rabbitmq/metrics.csv",
"references/rabbitmq/queries.md",
"references/redis/README.md",
"references/redis/metrics.csv",
"references/redis/queries.md"
]
},
{
"name": "otel-collector",
"description": "Use when Collector YAML, Helm values, OTLP exporters, receiver binding, pipeline topology, or OTTL expressions are involved.",
"files": [
"SKILL.md"
]
},
{
"name": "otel-instrumentation",
"description": "Use when adding, fixing, generating, or auditing OpenTelemetry app SDK setup across nine languages.",
"files": [
"SKILL.md"
]
},
{
"name": "signal-choice-advisor",
"description": "Use when choosing an OpenTelemetry signal, instrument, or telemetry name.",
"files": [
"SKILL.md",
"references/signal-choice.md"
]
},
{
"name": "tsuga-analyze-trace-latency",
"description": "Use when asked about slow requests, high latency, latency spikes, p95/p99 trace duration, or slow spans.",
"files": [
"SKILL.md"
]
},
{
"name": "tsuga-audit-monitor-coverage",
"description": "Use when asked to check monitor coverage, services without monitors, alerting gaps, or notification routing.",
"files": [
"SKILL.md"
]
},
{
"name": "tsuga-audit-telemetry-quality",
"description": "Use when auditing telemetry quality for logs, metrics, traces, or resource identity.",
"files": [
"SKILL.md"
]
},
{
"name": "tsuga-build-dashboard",
"description": "Use when asked to create, update, validate, or review a Tsuga dashboard or its widgets.",
"files": [
"SKILL.md",
"references/layout-rules.md",
"references/widget-reference.md"
]
},
{
"name": "tsuga-cli",
"description": "Use when a task involves Tsuga CLI commands, TQL search, aggregation bodies, or service ownership.",
"files": [
"SKILL.md",
"references/app-deep-links.md",
"references/aws-translator.md",
"references/azure-translator.md",
"references/gcp-translator.md",
"references/kubectl-translator.md",
"references/playbooks/find-owner-and-context.md",
"references/playbooks/reliability-review.md"
]
},
{
"name": "tsuga-debug-telemetry-ingestion",
"description": "Use when telemetry is missing, sparse, delayed, or not visible in Tsuga.",
"files": [
"SKILL.md"
]
},
{
"name": "tsuga-investigate-errors",
"description": "Use when asked about service errors, error spikes, exception patterns, or anomalous error volume.",
"files": [
"SKILL.md"
]
},
{
"name": "tsuga-investigate-service-health",
"description": "Use when investigating active incidents, service health checks, degraded service reports, or error spikes.",
"files": [
"SKILL.md"
]
}
]
}
Loading