Skip to content

Latest commit

 

History

History
858 lines (701 loc) · 30.6 KB

File metadata and controls

858 lines (701 loc) · 30.6 KB

Rootly Claude Plugin - Architecture Overview

Overview

This Claude Code plugin layers opinionated, developer-friendly workflows on top of Rootly's MCP server for the full incident lifecycle: prevent, respond, learn. The implementation is primarily prompt engineering and workflow orchestration. Incident data flows through the Rootly MCP server at mcp.rootly.com, while hooks use minimal direct REST API calls for low-latency checks.


Directory Structure

rootly-claude-plugin/
├── .claude-plugin/
│   ├── plugin.json                          # Plugin manifest (required)
│   └── marketplace.json                     # Repo-hosted marketplace metadata
├── .mcp.json                                # Rootly MCP server reference
├── skills/
│   ├── setup/
│   │   └── SKILL.md                         # /rootly:setup (first-run experience)
│   ├── deploy-check/
│   │   └── SKILL.md                         # /rootly:deploy-check
│   ├── respond/
│   │   └── SKILL.md                         # /rootly:respond
│   ├── oncall/
│   │   └── SKILL.md                         # /rootly:oncall
│   ├── retro/
│   │   └── SKILL.md                         # /rootly:retro
│   ├── status/
│   │   └── SKILL.md                         # /rootly:status
│   ├── ask/
│   │   └── SKILL.md                         # /rootly:ask
│   ├── brief/
│   │   └── SKILL.md                         # /rootly:brief (stakeholder communication)
│   └── handoff/
│       └── SKILL.md                         # /rootly:handoff (shift transitions)
├── agents/
│   ├── incident-investigator.md             # Deep incident investigation agent
│   ├── deploy-guardian.md                   # Deployment risk analysis agent
│   └── retro-analyst.md                     # Post-incident pattern analysis agent
├── hooks/
│   └── hooks.json                           # SessionStart + PreToolUse hooks
├── scripts/
│   ├── check-active-incidents.sh            # Lightweight pre-commit check
│   ├── validate-token.sh                    # SessionStart token validation
│   └── register-deploy.sh                   # Optional: post-push deployment registration
├── README.md
└── LICENSE

Component Specifications

1. Plugin Manifest (.claude-plugin/plugin.json)

{
  "name": "rootly",
  "version": "1.1.0",
  "description": "Full-lifecycle incident management from your IDE. Prevent incidents before deploy, respond in real-time, and learn from post-mortems -- powered by Rootly.",
  "author": {
    "name": "Rootly AI Labs",
    "email": "support@rootly.com",
    "url": "https://rootly.com"
  },
  "homepage": "https://rootly.com/integrations/claude",
  "repository": "https://github.com/Rootly-AI-Labs/rootly-claude-plugin",
  "license": "Apache-2.0",
  "userConfig": {
    "ROOTLY_API_TOKEN": {
      "description": "Rootly API token used for MCP access and incident workflow hooks",
      "sensitive": true
    }
  },
  "keywords": [
    "incident-management",
    "on-call",
    "sre",
    "devops",
    "deploy-safety",
    "retrospectives",
    "rootly"
  ]
}

2. Marketplace Entry (.claude-plugin/marketplace.json)

This file provides the repo-hosted marketplace metadata for the plugin.

{
  "name": "rootly-plugins",
  "owner": {
    "name": "Rootly AI Labs",
    "email": "support@rootly.com"
  },
  "metadata": {
    "description": "Official Rootly plugins for Claude Code",
    "version": "1.1.0"
  },
  "plugins": [
    {
      "name": "rootly",
      "source": "./",
      "description": "Full-lifecycle incident management: deploy safety, incident response, on-call management, and retrospectives.",
      "version": "1.1.0",
      "author": {
        "name": "Rootly AI Labs"
      },
      "license": "Apache-2.0",
      "keywords": ["incident-management", "on-call", "sre", "devops", "rootly"]
    }
  ]
}

3. MCP Server Reference (.mcp.json)

This file references Rootly's hosted MCP server. The plugin does not bundle a server binary.

{
  "mcpServers": {
    "rootly": {
      "type": "http",
      "url": "https://mcp.rootly.com/mcp",
      "headers": {
        "Authorization": "Bearer ${CLAUDE_PLUGIN_OPTION_ROOTLY_API_TOKEN}"
      }
    }
  }
}

Authentication: The plugin declares ROOTLY_API_TOKEN in userConfig, so Claude Code prompts for it when the plugin is enabled and automatically exports it as CLAUDE_PLUGIN_OPTION_ROOTLY_API_TOKEN. The MCP config and hook scripts both use this environment variable with fallback to ROOTLY_API_TOKEN for local development with --plugin-dir.

Alternative configurations (also documented in the README for advanced users):

  • CLI setup: claude mcp add rootly --transport http https://mcp.rootly.com/mcp --header "Authorization: Bearer YOUR_TOKEN"
  • Local MCP server (for self-hosted Rootly or offline use):
    {
      "mcpServers": {
        "rootly": {
          "command": "uvx",
          "args": ["--from", "rootly-mcp-server", "rootly-mcp-server"],
          "env": {
            "ROOTLY_API_TOKEN": "${user_config.ROOTLY_API_TOKEN}"
          }
        }
      }
    }

4. Skills (Slash Commands)

Each skill lives in skills/<name>/SKILL.md with YAML frontmatter.


4a. /rootly:setup -- First-Run Experience

skills/setup/SKILL.md

Purpose: Guide new users through plugin configuration.

Frontmatter:

name: setup
description: Set up the Rootly plugin. Checks for API token, verifies MCP server connection, and guides through configuration. Run this after installing the plugin.
disable-model-invocation: true
allowed-tools:
  - Bash
  - mcp__rootly__*

Workflow:

  1. Check if a plugin-configured token or local ROOTLY_API_TOKEN fallback is available
  2. If not set, provide step-by-step instructions:
    • Where to get an API token in the Rootly dashboard (Settings > API Keys)
    • How to update the plugin configuration with the token
    • How to use export ROOTLY_API_TOKEN=... only as a local development fallback
  3. If set, test the MCP connection by calling get_server_version (lightweight read-only tool)
  4. Confirm success or diagnose failure (invalid token, network issue, etc.)
  5. Check for .claude/rootly-config.json -- if missing, help create one by listing Rootly services and letting the user pick which map to this repo
  6. Show quick-start guide for available commands

4b. /rootly:deploy-check -- Pre-Deploy Intelligence

skills/deploy-check/SKILL.md

Purpose: Evaluate deployment safety before pushing code.

Frontmatter:

name: deploy-check
description: Evaluate deployment risk by analyzing code changes against incident history, active incidents, and on-call readiness. Use when a developer is about to deploy, push, or merge code.
argument-hint: [branch-name]
disable-model-invocation: true
context: fork
agent: rootly:deploy-guardian
allowed-tools:
  - Bash
  - mcp__rootly__*

Workflow (encoded in SKILL.md prompt):

  1. Get current git diff via dynamic context injection (!git diff --stat HEAD``)
  2. Identify affected services using the resolution chain:
    • Read .claude/rootly-config.json if present
    • Otherwise match git repo name against Rootly services via search_incidents
    • Fall back to asking the user
  3. Call search_incidents for those services (last 90 days)
  4. Call find_related_incidents with the change summary
  5. Check for active P1/P2 incidents on affected services
  6. Call get_oncall_handoff_summary to check on-call availability
  7. Handle edge case: if git diff is empty, report "no changes to evaluate" and exit
  8. Synthesize into a structured deployment brief:
    • Risk level (low/medium/high/critical)
    • Active incidents on affected services
    • On-call status and availability
    • Similar past incidents and what resolved them
    • Go/no-go recommendation with reasoning

Dynamic context (injected before Claude sees the prompt):

## Current changes
!`git diff --stat HEAD`

## Current branch
!`git branch --show-current`

## Recent commits
!`git log --oneline -5`

4c. /rootly:respond -- Incident Response

skills/respond/SKILL.md

Purpose: Investigate and coordinate incident response from the IDE.

Frontmatter:

name: respond
description: Investigate and respond to a production incident. Pulls context, finds similar past incidents, suggests solutions, and enables coordination -- all from the terminal. Use when paged or when an incident needs attention.
argument-hint: [incident-id]
disable-model-invocation: true
context: fork
agent: rootly:incident-investigator
allowed-tools:
  - Bash
  - mcp__rootly__*

Workflow:

  1. Accept incident ID from $ARGUMENTS. If not provided, call search_incidents filtered to active and list for the user to choose.
  2. If many active incidents, filter by severity (critical/high first) with pagination.
  3. Call getIncident for full incident context
  4. Call get_alert_by_short_id or search alerts via OpenAPI tools for alert details
  5. Call find_related_incidents for historical matches
  6. Call suggest_solutions for resolution recommendations
  7. Call get_oncall_handoff_summary for team status
  8. Present structured response brief:
    • Incident summary and timeline
    • Related historical incidents (with confidence scores)
    • Suggested solutions (with confidence scores and sources)
    • Current responders and on-call team
    • Available actions (update severity, add responder, post status update)
  9. Human-in-the-loop: ALWAYS present write operations as recommendations. Require explicit user confirmation before executing any mutation (updateIncident, escalate, add responder, etc.)

Error handling in prompt:

  • If MCP tools return errors, report the specific error and suggest manual steps
  • If find_related_incidents returns low confidence (< 0.3), flag and suggest manual investigation
  • If no incidents are active, report "no active incidents" cleanly

Note: context: fork runs this in an isolated subagent to avoid polluting the main coding context with incident data, and agent: rootly:incident-investigator explicitly routes the workflow through the shipped specialist agent.


4d. /rootly:oncall -- On-Call Dashboard

skills/oncall/SKILL.md

Purpose: Quick view of on-call status and health metrics.

Frontmatter:

name: oncall
description: Show current on-call status, shift metrics, and health indicators for your team. Use to check who's on-call, handoff context, or on-call workload.
argument-hint: [team-name]
disable-model-invocation: true
allowed-tools:
  - mcp__rootly__*

Workflow:

  1. Call get_oncall_handoff_summary for current/next on-call
  2. Call get_oncall_shift_metrics for workload data
  3. Call check_oncall_health_risk for fatigue indicators
  4. Present compact dashboard:
    • Current on-call (name, since when, incidents handled this shift)
    • Next on-call (name, handoff time)
    • Shift health (hours worked, fatigue risk)
    • Recent incidents during this shift

4e. /rootly:retro -- Retrospective Generator

skills/retro/SKILL.md

Purpose: Generate a structured post-incident retrospective.

Frontmatter:

name: retro
description: Generate a structured post-incident retrospective from incident data. Use after an incident is resolved to document what happened, why, and action items.
argument-hint: [incident-id]
disable-model-invocation: true
context: fork
agent: rootly:retro-analyst
allowed-tools:
  - mcp__rootly__*

Workflow:

  1. Accept incident ID from $ARGUMENTS
  2. Call getIncident for full incident record
  3. Check incident status -- if still started, warn user that retro is typically done post-resolution and ask to confirm
  4. Call get_alert_by_short_id or alert search tools for alert timeline
  5. Call find_related_incidents for pattern context
  6. Generate structured retrospective:
    • Summary (1-2 sentences)
    • Impact (duration, affected users/services, severity)
    • Timeline (key events from alert data)
    • Root cause analysis
    • Contributing factors
    • What went well
    • What could be improved
    • Action items (with owners if identifiable)
    • Pattern note (if similar incidents recur -- "This is the Nth incident of this type in the last 90 days")
  7. Output as markdown to terminal (copy-pasteable)

4f. /rootly:status -- Service Health Overview

skills/status/SKILL.md

Purpose: Quick service health dashboard.

Frontmatter:

name: status
description: Show a compact service health overview including active incidents by severity. Use for a quick health check of your services.
argument-hint: [service-name]
disable-model-invocation: true
allowed-tools:
  - mcp__rootly__*

Workflow:

  1. Call search_incidents filtered to active (started) status
  2. Group by service and severity
  3. Present compact table:
    • Services with active incidents
    • Severity breakdown (critical/high/medium/low)
    • Time-in-incident for each

4g. /rootly:ask -- Natural Language Query

skills/ask/SKILL.md

Purpose: Free-form questions against incident data.

Frontmatter:

name: ask
description: Ask natural language questions about incidents, on-call, services, and reliability data. Translates your question into Rootly API calls and returns structured answers.
argument-hint: [your question]
disable-model-invocation: true
allowed-tools:
  - mcp__rootly__*

Workflow:

  1. Parse the natural language question from $ARGUMENTS
  2. First, call list_endpoints to discover available Rootly MCP tools
  3. Select the most appropriate tools for the question
  4. Execute queries (may require multiple calls)
  5. Synthesize and present answer with supporting data
  6. If the question can't be answered with available tools, say so explicitly rather than hallucinating

4h. /rootly:brief -- Stakeholder Communication

skills/brief/SKILL.md

Purpose: Generate concise executive/stakeholder briefs for incidents.

Frontmatter:

name: brief
description: Generate a concise stakeholder brief for an incident. Creates executive summary with key details, impact, timeline, and current status.
argument-hint: [incident-id]
disable-model-invocation: true
allowed-tools:
  - mcp__rootly__*

Workflow:

  1. Parse incident ID from $ARGUMENTS
  2. Call mcp__rootly__getIncident for full incident details
  3. Call mcp__rootly__listIncidentAlerts for associated alerts
  4. Generate structured brief with business-focused language:
    • Executive summary with impact and current status
    • Service impact and timeline
    • Next steps and resolution approach
  5. Format for non-technical stakeholders (under 200 words)

Use Cases: CEO updates, customer communications, legal/compliance documentation, cross-team notifications.


4i. /rootly:handoff -- Shift Transitions

skills/handoff/SKILL.md

Purpose: Prepare incident or on-call handoff documents for shift changes.

Frontmatter:

name: handoff
description: Prepare an incident or on-call handoff document. Creates structured summary for shift changes or incident commander transitions.
argument-hint: [incident-id]
disable-model-invocation: true
allowed-tools:
  - mcp__rootly__*

Workflow:

  1. Determine handoff type based on $ARGUMENTS:
    • Incident handoff (with incident ID): Call mcp__rootly__getIncident and mcp__rootly__listIncidentAlerts
    • On-call handoff (no ID): Call mcp__rootly__get_oncall_handoff_summary and mcp__rootly__search_incidents
  2. Generate structured handoff document with:
    • Current situation summary
    • Actions taken and next steps
    • Key contacts and escalation paths
    • Critical context and monitoring points
  3. Format for seamless knowledge transfer

Use Cases: Shift changes, incident commander transitions, on-call handoffs, team coordination.


5. Agents

Agent frontmatter uses comma-separated string format for tools field (matching documented examples).

5a. incident-investigator -- Deep Investigation Agent

agents/incident-investigator.md

Frontmatter:

name: incident-investigator
description: Deep production-incident investigator for root-cause analysis, evidence gathering, and remediation planning beyond the initial response brief.
model: sonnet
tools: Read, Grep, Glob, Bash, mcp__rootly__*

System prompt responsibilities:

  1. Gather all alerts, responder actions, and timeline events via getIncident and alert tools
  2. Search codebase for recent git commits in affected service directories (git log --since="3 days ago" -- <paths>)
  3. Find top 5 similar historical incidents via find_related_incidents
  4. Extract resolution patterns from each similar incident
  5. Build root cause hypothesis tree with evidence chains
  6. Rank hypotheses by confidence
  7. Recommend specific remediation steps
  8. Output structured investigation report

5b. deploy-guardian -- Deployment Safety Agent

agents/deploy-guardian.md

Frontmatter:

name: deploy-guardian
description: Deployment safety specialist for blast-radius analysis, downstream dependency checks, and cross-team coordination planning.
model: sonnet
tools: Read, Grep, Glob, Bash, mcp__rootly__*

System prompt responsibilities (differentiated from /rootly:deploy-check):

  1. Analyze full diff and identify all affected services
  2. Map downstream service dependencies (what else breaks if this service has issues)
  3. Check active incidents, deployment freezes, on-call gaps
  4. Evaluate blast radius across dependent services (not just the changed service)
  5. Cross-reference with incident history for ALL affected services (direct + downstream)
  6. Assess on-call readiness and fatigue for all impacted teams
  7. Identify cross-team coordination needs (do other teams need to be notified?)
  8. Produce go/no-go recommendation with full reasoning and a coordination checklist

5c. retro-analyst -- Pattern Analysis Agent

agents/retro-analyst.md

Frontmatter:

name: retro-analyst
description: Reliability pattern analyst for retrospectives, recurring-incident clustering, and systemic improvement recommendations.
model: sonnet
tools: Read, Grep, Glob, mcp__rootly__*

System prompt responsibilities:

  1. Pull incidents for the requested scope (service, team, time period) via search_incidents
  2. Identify recurring root causes and failure modes
  3. Cluster incidents by pattern (same service, same error type, same trigger)
  4. Calculate frequency trends (getting better or worse?)
  5. Identify systemic issues requiring architectural fixes
  6. Correlate with code changes where possible (via Read/Grep on the codebase)
  7. Produce structured report with prioritized recommendations

6. Hooks

hooks/hooks.json

{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/validate-token.sh"
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "if": "Bash(git commit *)",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/check-active-incidents.sh"
          },
          {
            "type": "command",
            "if": "Bash(git push *)",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/check-active-incidents.sh"
          }
        ]
      }
    ]
  }
}

Hook 1: SessionStart -- Token Validation

  • Runs once when Claude Code starts
  • Checks for a configured plugin token, then falls back to ROOTLY_API_TOKEN for local development
  • If missing, outputs a brief setup message directing user to /rootly:setup
  • If set, pings the API to validate (with 2s timeout)
  • Never blocks -- informational only

Hook 2: PreToolUse on Bash -- Active Incident Warning

  • Uses hook-level if conditions so the script only spawns for git commit and git push
  • If git commit/push, makes one REST API call to check active incidents (< 2s)
  • Returns warning via stdout if active critical/high incidents found, empty otherwise
  • Exit code 0 always (warn, never block)

Design trade-off: Hook scripts make direct REST calls to api.rootly.com rather than going through the MCP server. This is intentional -- hooks need to be fast (< 2 seconds) and cannot invoke MCP tools. The REST calls are simple, read-only checks. This means the plugin depends on both the MCP server (for skills/agents) and the REST API (for hooks).

Why conservative hook design: Hooks run on every matching event. A noisy or slow hook degrades the entire IDE experience. Only the session-start validation and pre-commit incident check are enabled by default. The post-push deployment registration is provided as an opt-in script.


7. Scripts

Runtime dependencies: Scripts use curl for REST calls and either jq or python3 for lightweight JSON parsing. If no parser is available, they fail silently per the graceful degradation principle.

scripts/validate-token.sh

#!/bin/bash
# SessionStart hook: check if a Rootly API token is configured.
# Prefer plugin-managed configuration and fall back to the legacy env var
# for local development with --plugin-dir.

ROOTLY_TOKEN="${CLAUDE_PLUGIN_OPTION_ROOTLY_API_TOKEN:-${ROOTLY_API_TOKEN:-}}"
ROOTLY_URL="${ROOTLY_API_URL:-https://api.rootly.com}"

if [ -z "$ROOTLY_TOKEN" ]; then
  echo "Rootly plugin: No API token found. Configure the plugin and then run /rootly:setup."
  exit 0
fi

# Quick validation ping (with strict timeout)
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
  -H "Authorization: Bearer $ROOTLY_TOKEN" \
  "$ROOTLY_URL/v1/users/me" \
  --max-time 2 2>/dev/null)

if [ "$HTTP_CODE" = "401" ] || [ "$HTTP_CODE" = "403" ]; then
  echo "Rootly plugin: API token appears invalid (HTTP $HTTP_CODE). Update the plugin config and run /rootly:setup again."
fi

exit 0

scripts/check-active-incidents.sh

#!/bin/bash
# PreToolUse hook: warn about active incidents before git commit/push.
# hooks/hooks.json filters to the relevant Bash commands, so this script
# only needs to perform the incident check.

ROOTLY_TOKEN="${CLAUDE_PLUGIN_OPTION_ROOTLY_API_TOKEN:-${ROOTLY_API_TOKEN:-}}"
if [ -z "$ROOTLY_TOKEN" ]; then
  exit 0  # Silent if not configured
fi

# Check for active high-severity incidents
# Uses JSON:API filter syntax per Rootly REST API spec
# Configurable base URL via ROOTLY_API_URL for self-hosted instances
ROOTLY_URL="${ROOTLY_API_URL:-https://api.rootly.com}"
RESPONSE=$(curl -s \
  -H "Authorization: Bearer $ROOTLY_TOKEN" \
  -H "Content-Type: application/vnd.api+json" \
  "$ROOTLY_URL/v1/incidents?filter[status]=started&filter[severity]=critical&page[size]=50" \
  --max-time 2 2>/dev/null)

if [ $? -ne 0 ]; then
  exit 0  # Silent on network failure
fi

# Count incidents from JSON:API response (data is an array)
if command -v jq &>/dev/null; then
  COUNT=$(echo "$RESPONSE" | jq '.data | length' 2>/dev/null)
elif command -v python3 &>/dev/null; then
  COUNT=$(echo "$RESPONSE" | python3 -c "
import sys, json
try:
    data = json.load(sys.stdin)
    print(len(data.get('data', [])))
except:
    print('0')
" 2>/dev/null)
else
  exit 0
fi

if [ "$COUNT" != "0" ] && [ "$COUNT" != "null" ] && [ -n "$COUNT" ]; then
  echo "WARNING: $COUNT active critical incident(s) detected. Run /rootly:status for details before deploying."
fi

scripts/register-deploy.sh

#!/bin/bash
# Optional: Register a deployment event with Rootly
# NOT wired into hooks by default. Provided as a convenience script.
#
# To enable as a post-push hook, add to your .claude/hooks.json:
# {
#   "hooks": {
#     "PostToolUse": [{
#       "matcher": "Bash",
#       "hooks": [{
#         "type": "command",
#         "command": "<plugin-root>/scripts/register-deploy.sh"
#       }]
#     }]
#   }
# }

# Read stdin (PostToolUse hook input) -- check if this was a git push
INPUT=$(cat)
if command -v jq &>/dev/null; then
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
else
  COMMAND=$(echo "$INPUT" | python3 -c "
import sys, json
try: print(json.load(sys.stdin).get('tool_input',{}).get('command',''))
except: print('')
" 2>/dev/null)
fi

if [[ "$COMMAND" != *"git push"* ]]; then
  exit 0
fi

ROOTLY_TOKEN="${CLAUDE_PLUGIN_OPTION_ROOTLY_API_TOKEN:-${ROOTLY_API_TOKEN:-}}"
if [ -z "$ROOTLY_TOKEN" ]; then
  exit 0
fi

ROOTLY_URL="${ROOTLY_API_URL:-https://api.rootly.com}"
COMMIT_SHA=$(git rev-parse HEAD 2>/dev/null)
BRANCH=$(git branch --show-current 2>/dev/null)
REPO=$(basename "$(git rev-parse --show-toplevel 2>/dev/null)")

curl -s -X POST "$ROOTLY_URL/v1/deployments" \
  -H "Authorization: Bearer $ROOTLY_TOKEN" \
  -H "Content-Type: application/vnd.api+json" \
  -d "{\"commit_sha\": \"$COMMIT_SHA\", \"branch\": \"$BRANCH\", \"repository\": \"$REPO\"}" \
  --max-time 3 2>/dev/null

exit 0

8. Service-to-Repo Mapping (.claude/rootly-config.json)

Skills like deploy-check need to know which Rootly services correspond to the current repo. Resolution chain (in priority order):

  1. Explicit config: .claude/rootly-config.json in the project:
    {
      "services": ["auth-service", "auth-worker"],
      "team": "platform-team"
    }
  2. Repo name matching: Match the git repo name against Rootly service names
  3. User prompt: Ask the user which service(s) this repo maps to, then suggest they create the config file

The /rootly:setup skill helps create this config file.


MCP Tool Reference

The hosted Rootly MCP server exposes many tools, but this plugin depends on a focused subset. Skills and agents reference these by exact name:

Tool Name Used By Purpose
find_related_incidents deploy-check, respond, retro, incident-investigator TF-IDF similarity matching against historical incidents
suggest_solutions respond, incident-investigator Mine past resolutions for actionable recommendations
search_incidents deploy-check, status, ask, retro-analyst Search/filter incidents by status, severity, service
getIncident respond, retro, incident-investigator Get full details of a specific incident (camelCase)
updateIncident respond (with human approval) Update incident fields (camelCase)
get_oncall_handoff_summary deploy-check, respond, oncall Current/next on-call with shift context
get_oncall_shift_metrics oncall Shift hours, counts, grouped by user/team
check_oncall_health_risk oncall, deploy-guardian Fatigue and workload risk indicators
get_alert_by_short_id respond, retro Get alert details by short ID
get_shift_incidents oncall Incidents during a specific shift window
get_oncall_schedule_summary deploy-guardian Schedule overview for coordination
check_responder_availability deploy-guardian Whether responders are available
list_endpoints ask Discover available API endpoints
get_server_version setup Lightweight connectivity test
list_shifts oncall List on-call shifts
create_override_recommendation oncall (optional) Suggest schedule overrides

Note: getIncident and updateIncident use camelCase (exceptions to the snake_case convention). All other tools use snake_case.


Design Principles

1. MCP for Data, REST for Speed

Skills and agents access incident data through the MCP server. Hook scripts make direct REST calls for simple, time-sensitive checks such as active-incident warnings. This is a pragmatic split: MCP is the primary data channel, and REST is used only where hooks need sub-2-second responses.

2. Progressive Disclosure

  • Hooks (automatic): Ambient awareness, zero effort
  • Skills (one command): Quick answers for specific questions
  • Agents (deep): Multi-step investigation when you need thoroughness

3. Human-in-the-Loop for Write Operations

All skills that modify Rootly data (updateIncident, change severity, add responder) require explicit user approval. The prompt instructions enforce this -- recommendations are presented, but actions require confirmation.

4. Graceful Degradation

  • No configured token? SessionStart hook guides to /rootly:setup, skills explain how to configure, and local development can still use ROOTLY_API_TOKEN as a fallback.
  • MCP server unreachable? Skills report the specific error and suggest manual steps.
  • Low-confidence results from find_related_incidents or suggest_solutions? Flag explicitly, suggest manual investigation.
  • Hooks fail silently on error -- never block the developer's workflow.
  • No jq or python3? Hook scripts exit 0 silently.

5. Conservative Hook Design

Only the session-start validation and pre-commit incident check are enabled by default. Both are fast, high-value, and fail silent. Everything else is opt-in.


Authentication Flow

  1. User loads the plugin in Claude Code, either from a marketplace install or locally with claude --plugin-dir
  2. Claude Code prompts for ROOTLY_API_TOKEN from the plugin's userConfig
  3. SessionStart hook validates the configured token and points the user to /rootly:setup if it is missing or invalid
  4. /rootly:setup verifies the MCP connection with get_server_version and helps with service mapping
  5. Plugin .mcp.json passes ${user_config.ROOTLY_API_TOKEN} to the hosted MCP server
  6. Hook scripts read CLAUDE_PLUGIN_OPTION_ROOTLY_API_TOKEN, with ROOTLY_API_TOKEN kept only as a local development fallback
  7. Users can still set ROOTLY_API_URL for self-hosted REST endpoints (defaults to https://api.rootly.com)

No credentials stored in plugin files. No interactive OAuth flow.


What the Plugin Does NOT Do

  • Bundle or run the MCP server -- points to hosted endpoint
  • Store persistent state -- no databases, no caches
  • Auto-execute write operations -- always requires user confirmation
  • Block developer workflow -- hooks fail silent, skills are on-demand
  • Assume specific Rootly deployment -- supports self-hosted via ROOTLY_API_URL

Validation Checklist

  • Schema validation: Run claude plugin validate when the Claude CLI is available.
  • Local loading: From the repo root, run claude --plugin-dir . during development.
  • Reload loop: Use /reload-plugins after manifest, skill, agent, or hook changes.
  • Functional checks: Exercise each skill against a test Rootly organization with a valid token.
  • Edge cases: Validate missing token, invalid token, network timeout, empty incident history, no on-call configured, self-hosted ROOTLY_API_URL, active incident during retro generation, and clean git working tree on deploy-check.