From 444a13c724e67fe76c94b0687788c5f708ea3b9c Mon Sep 17 00:00:00 2001 From: adagradschool Date: Thu, 12 Mar 2026 13:52:14 -0400 Subject: [PATCH] Rename plugin to `trace` and prepare v1.0.0 release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename pl-trace-claude-code → trace for a cleaner plugin name, bump version to 1.0.0, rewrite README with Quick Start docs, and update all scripts and manifests to match. Co-Authored-By: Claude Opus 4.6 --- .claude-plugin/marketplace.json | 12 +-- Makefile | 4 +- README.md | 89 ++++++++++--------- .../.claude-plugin/plugin.json | 8 -- plugins/trace/.claude-plugin/plugin.json | 8 ++ .../hooks/hooks.json | 0 .../hooks/lib.sh | 2 +- .../hooks/parse_stop_transcript.py | 0 .../hooks/post_tool_use.sh | 2 +- .../hooks/session_end.sh | 2 +- .../hooks/session_start.sh | 2 +- .../hooks/stop_hook.sh | 2 +- .../hooks/user_prompt_submit.sh | 2 +- .../{pl-trace-claude-code => trace}/setup.sh | 9 +- .../testdata/session_start_input.json | 0 scripts/dev-install.sh | 6 +- scripts/dev-uninstall.sh | 4 +- scripts/e2e_smoke.py | 4 +- scripts/replay-fixtures.sh | 2 +- scripts/validate-manifests.sh | 4 +- 20 files changed, 84 insertions(+), 78 deletions(-) delete mode 100644 plugins/pl-trace-claude-code/.claude-plugin/plugin.json create mode 100644 plugins/trace/.claude-plugin/plugin.json rename plugins/{pl-trace-claude-code => trace}/hooks/hooks.json (100%) rename plugins/{pl-trace-claude-code => trace}/hooks/lib.sh (99%) rename plugins/{pl-trace-claude-code => trace}/hooks/parse_stop_transcript.py (100%) rename plugins/{pl-trace-claude-code => trace}/hooks/post_tool_use.sh (96%) rename plugins/{pl-trace-claude-code => trace}/hooks/session_end.sh (97%) rename plugins/{pl-trace-claude-code => trace}/hooks/session_start.sh (96%) rename plugins/{pl-trace-claude-code => trace}/hooks/stop_hook.sh (99%) rename plugins/{pl-trace-claude-code => trace}/hooks/user_prompt_submit.sh (92%) rename plugins/{pl-trace-claude-code => trace}/setup.sh (94%) rename plugins/{pl-trace-claude-code => trace}/testdata/session_start_input.json (100%) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 7b99c89..cbd8ecd 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -1,17 +1,17 @@ { "$schema": "https://anthropic.com/claude-code/marketplace.schema.json", - "name": "promptlayer-claude-plugin", - "version": "0.1.0", - "description": "PromptLayer Claude Code tracing plugin with OTLP/HTTP JSON transport", + "name": "promptlayer-claude-plugins", + "version": "1.0.0", + "description": "Automatically trace Claude Code conversations to PromptLayer. Captures sessions, user messages, assistant responses, and tool calls for observability.", "owner": { "name": "PromptLayer", "email": "support@promptlayer.com" }, "plugins": [ { - "name": "pl-trace-claude-code", - "description": "Trace Claude Code sessions and send OTLP/HTTP JSON spans to PromptLayer.", - "source": "./plugins/pl-trace-claude-code", + "name": "trace", + "description": "Automatically trace Claude Code conversations to PromptLayer. Captures user messages, assistant responses, and tool calls as structured spans.", + "source": "./plugins/trace", "category": "observability" } ] diff --git a/Makefile b/Makefile index 1729ec2..01a028b 100644 --- a/Makefile +++ b/Makefile @@ -12,8 +12,8 @@ validate: ./scripts/validate-manifests.sh lint: - if command -v shellcheck >/dev/null 2>&1; then shellcheck -x plugins/pl-trace-claude-code/hooks/*.sh plugins/pl-trace-claude-code/setup.sh scripts/*.sh; else echo "shellcheck not installed, skipping"; fi - if command -v shfmt >/dev/null 2>&1; then shfmt -d plugins/pl-trace-claude-code/hooks/*.sh plugins/pl-trace-claude-code/setup.sh scripts/*.sh; else echo "shfmt not installed, skipping"; fi + if command -v shellcheck >/dev/null 2>&1; then shellcheck -x plugins/trace/hooks/*.sh plugins/trace/setup.sh scripts/*.sh; else echo "shellcheck not installed, skipping"; fi + if command -v shfmt >/dev/null 2>&1; then shfmt -d plugins/trace/hooks/*.sh plugins/trace/setup.sh scripts/*.sh; else echo "shfmt not installed, skipping"; fi test: validate lint ./scripts/replay-fixtures.sh diff --git a/README.md b/README.md index c8252a4..ce4599d 100644 --- a/README.md +++ b/README.md @@ -1,73 +1,76 @@ -# PromptLayer Claude Code Plugin Marketplace +# PromptLayer Claude Code Plugin -Open source Claude Code plugin marketplace for PromptLayer tracing. +See every Claude Code session as structured traces in [PromptLayer](https://promptlayer.com) — user messages, assistant responses, tool calls, and token usage, all captured automatically. -## Plugin +## Quick Start -- `pl-trace-claude-code`: traces Claude Code sessions and emits OTLP/HTTP JSON spans to PromptLayer. - -## Prerequisites - -- Claude Code CLI installed -- PromptLayer API key (`PROMPTLAYER_API_KEY`) -- `jq`, `curl`, `uuidgen`, and `python3` available in your shell - -## Install +### 1. Install ```bash -claude plugin marketplace add promptlayer/promptlayer-claude-plugin -claude plugin install pl-trace-claude-code@promptlayer-claude-plugin +claude plugin marketplace add promptlayer/promptlayer-claude-plugins +claude plugin install trace@promptlayer-claude-plugins ``` -## Configure +### 2. Configure Run the setup script from the project where you want tracing enabled: ```bash -$HOME/.claude/plugins/marketplaces/promptlayer-claude-plugin/plugins/pl-trace-claude-code/setup.sh +$HOME/.claude/plugins/marketplaces/promptlayer-claude-plugins/plugins/trace/setup.sh ``` -The script writes `.claude/settings.local.json` with: +You will be prompted for your PromptLayer API key. You can find or create one at [dashboard.promptlayer.com](https://dashboard.promptlayer.com). -- `TRACE_TO_PROMPTLAYER=true` -- `PROMPTLAYER_API_KEY` -- `PROMPTLAYER_OTLP_ENDPOINT` (default: `https://api.promptlayer.com/v1/traces`) -- `PROMPTLAYER_CC_DEBUG` +### 3. Verify -## Verify +1. Start Claude Code: `claude` +2. Send a prompt +3. Check your traces at [dashboard.promptlayer.com](https://dashboard.promptlayer.com) -1. Start Claude Code in the configured directory: `claude` -2. Send a prompt and use at least one tool -3. Check hook logs: `tail -f ~/.claude/state/promptlayer_hook.log` +## What Gets Traced -## Troubleshooting +The plugin hooks into Claude Code's lifecycle and emits [OTLP/HTTP JSON](docs/otlp-mapping.md) spans for: -See [docs/troubleshooting.md](docs/troubleshooting.md). +- **Sessions** — one root span per Claude Code session +- **LLM calls** — model, token counts, prompts, and completions +- **Tool calls** — tool name, input, and output -## Local Development +## Prerequisites + +- Claude Code CLI installed +- A PromptLayer account and API key ([dashboard.promptlayer.com](https://dashboard.promptlayer.com)) +- `jq`, `curl`, `uuidgen`, and `python3` available in your shell -Install from this local repo and run setup: +## Configuration -```bash -make dev -``` +The setup script writes `~/.claude/settings.json` with: -`make dev` symlinks this repo as the marketplace source, installs `pl-trace-claude-code`, and runs the setup script. +| Variable | Purpose | Default | +|----------|---------|---------| +| `TRACE_TO_PROMPTLAYER` | Enable/disable tracing | `true` | +| `PROMPTLAYER_API_KEY` | Your API key | _(required)_ | +| `PROMPTLAYER_OTLP_ENDPOINT` | OTLP ingestion endpoint | `https://api.promptlayer.com/v1/traces` | +| `PROMPTLAYER_CC_DEBUG` | Enable debug logging | `false` | -Remove the local plugin install and cleanup local artifacts: +Because this file lives in your home directory, your API key stays out of version control and tracing is enabled across all projects. -```bash -make uninstall -``` +## OTLP-Native Tracing -Run validation + lint + fixture replay: +This plugin is **OpenTelemetry (OTLP/HTTP JSON)** compatible: -```bash -make test -``` +- **Open standard** — traces follow the [OTLP specification](https://opentelemetry.io/docs/specs/otlp/), not a vendor-specific format +- **Portable** — swap or fan-out to any OTLP-compatible backend (Datadog, Honeycomb, Grafana Tempo, etc.) by changing one endpoint URL +- **No SDK lock-in** — the plugin uses plain `curl` to send `ExportTraceServiceRequest` payloads; no proprietary client libraries required + +## Troubleshooting -Run end-to-end SDK smoke test (requires `ANTHROPIC_API_KEY`): +See [docs/troubleshooting.md](docs/troubleshooting.md). + +## Local Development ```bash -make smoke +make dev # Symlink repo as marketplace source, install plugin, run setup +make uninstall # Remove local install and cleanup artifacts +make test # Validate manifests + lint + fixture replay +make smoke # E2E smoke test (requires ANTHROPIC_API_KEY) ``` diff --git a/plugins/pl-trace-claude-code/.claude-plugin/plugin.json b/plugins/pl-trace-claude-code/.claude-plugin/plugin.json deleted file mode 100644 index a62a0f8..0000000 --- a/plugins/pl-trace-claude-code/.claude-plugin/plugin.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "pl-trace-claude-code", - "description": "Trace Claude Code sessions and emit OTLP/HTTP JSON spans.", - "version": "0.1.0", - "author": { - "name": "PromptLayer" - } -} diff --git a/plugins/trace/.claude-plugin/plugin.json b/plugins/trace/.claude-plugin/plugin.json new file mode 100644 index 0000000..b4eac72 --- /dev/null +++ b/plugins/trace/.claude-plugin/plugin.json @@ -0,0 +1,8 @@ +{ + "name": "trace", + "description": "Automatically trace Claude Code conversations to PromptLayer. Captures user messages, assistant responses, and tool calls as structured spans.", + "version": "1.0.0", + "author": { + "name": "PromptLayer" + } +} diff --git a/plugins/pl-trace-claude-code/hooks/hooks.json b/plugins/trace/hooks/hooks.json similarity index 100% rename from plugins/pl-trace-claude-code/hooks/hooks.json rename to plugins/trace/hooks/hooks.json diff --git a/plugins/pl-trace-claude-code/hooks/lib.sh b/plugins/trace/hooks/lib.sh similarity index 99% rename from plugins/pl-trace-claude-code/hooks/lib.sh rename to plugins/trace/hooks/lib.sh index 5482da7..89bdce5 100755 --- a/plugins/pl-trace-claude-code/hooks/lib.sh +++ b/plugins/trace/hooks/lib.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Shared runtime helpers for pl-trace-claude-code hooks. +# Shared runtime helpers for trace plugin hooks. set -euo pipefail umask 077 diff --git a/plugins/pl-trace-claude-code/hooks/parse_stop_transcript.py b/plugins/trace/hooks/parse_stop_transcript.py similarity index 100% rename from plugins/pl-trace-claude-code/hooks/parse_stop_transcript.py rename to plugins/trace/hooks/parse_stop_transcript.py diff --git a/plugins/pl-trace-claude-code/hooks/post_tool_use.sh b/plugins/trace/hooks/post_tool_use.sh similarity index 96% rename from plugins/pl-trace-claude-code/hooks/post_tool_use.sh rename to plugins/trace/hooks/post_tool_use.sh index 6b40c6f..876bad1 100755 --- a/plugins/pl-trace-claude-code/hooks/post_tool_use.sh +++ b/plugins/trace/hooks/post_tool_use.sh @@ -2,7 +2,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -# shellcheck source=plugins/pl-trace-claude-code/hooks/lib.sh +# shellcheck source=plugins/trace/hooks/lib.sh source "$SCRIPT_DIR/lib.sh" tracing_enabled || exit 0 diff --git a/plugins/pl-trace-claude-code/hooks/session_end.sh b/plugins/trace/hooks/session_end.sh similarity index 97% rename from plugins/pl-trace-claude-code/hooks/session_end.sh rename to plugins/trace/hooks/session_end.sh index 03b118e..21bbe5f 100755 --- a/plugins/pl-trace-claude-code/hooks/session_end.sh +++ b/plugins/trace/hooks/session_end.sh @@ -2,7 +2,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -# shellcheck source=plugins/pl-trace-claude-code/hooks/lib.sh +# shellcheck source=plugins/trace/hooks/lib.sh source "$SCRIPT_DIR/lib.sh" tracing_enabled || exit 0 diff --git a/plugins/pl-trace-claude-code/hooks/session_start.sh b/plugins/trace/hooks/session_start.sh similarity index 96% rename from plugins/pl-trace-claude-code/hooks/session_start.sh rename to plugins/trace/hooks/session_start.sh index e77069d..5bd612a 100755 --- a/plugins/pl-trace-claude-code/hooks/session_start.sh +++ b/plugins/trace/hooks/session_start.sh @@ -2,7 +2,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -# shellcheck source=plugins/pl-trace-claude-code/hooks/lib.sh +# shellcheck source=plugins/trace/hooks/lib.sh source "$SCRIPT_DIR/lib.sh" tracing_enabled || exit 0 diff --git a/plugins/pl-trace-claude-code/hooks/stop_hook.sh b/plugins/trace/hooks/stop_hook.sh similarity index 99% rename from plugins/pl-trace-claude-code/hooks/stop_hook.sh rename to plugins/trace/hooks/stop_hook.sh index fe43a27..8b0e68b 100755 --- a/plugins/pl-trace-claude-code/hooks/stop_hook.sh +++ b/plugins/trace/hooks/stop_hook.sh @@ -2,7 +2,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -# shellcheck source=plugins/pl-trace-claude-code/hooks/lib.sh +# shellcheck source=plugins/trace/hooks/lib.sh source "$SCRIPT_DIR/lib.sh" tracing_enabled || exit 0 diff --git a/plugins/pl-trace-claude-code/hooks/user_prompt_submit.sh b/plugins/trace/hooks/user_prompt_submit.sh similarity index 92% rename from plugins/pl-trace-claude-code/hooks/user_prompt_submit.sh rename to plugins/trace/hooks/user_prompt_submit.sh index f55f688..8383da4 100755 --- a/plugins/pl-trace-claude-code/hooks/user_prompt_submit.sh +++ b/plugins/trace/hooks/user_prompt_submit.sh @@ -2,7 +2,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -# shellcheck source=plugins/pl-trace-claude-code/hooks/lib.sh +# shellcheck source=plugins/trace/hooks/lib.sh source "$SCRIPT_DIR/lib.sh" tracing_enabled || exit 0 diff --git a/plugins/pl-trace-claude-code/setup.sh b/plugins/trace/setup.sh similarity index 94% rename from plugins/pl-trace-claude-code/setup.sh rename to plugins/trace/setup.sh index 9a7d15e..0246a68 100755 --- a/plugins/pl-trace-claude-code/setup.sh +++ b/plugins/trace/setup.sh @@ -123,6 +123,7 @@ if [[ -n "$default_key" ]]; then echo "" api_key="${input_key:-$default_key}" else + echo "You can find or create an API key at: https://dashboard.promptlayer.com" read -r -s -p "Enter PROMPTLAYER_API_KEY (input hidden): " input_key echo "" api_key="$input_key" @@ -156,8 +157,8 @@ else debug="false" fi -mkdir -p .claude -settings_file=".claude/settings.local.json" +mkdir -p "$HOME/.claude" +settings_file="$HOME/.claude/settings.json" if [[ -f "$settings_file" ]] && ! jq empty "$settings_file" >/dev/null 2>&1; then echo "Error: $settings_file exists but is not valid JSON." @@ -196,4 +197,6 @@ echo "Setup complete." echo "Next:" echo " 1. Start Claude Code in this directory: claude" echo " 2. Run one prompt and tool call" -echo " 3. Inspect logs: tail -f ~/.claude/state/promptlayer_hook.log" +echo " 3. View your traces at: https://dashboard.promptlayer.com" +echo "" +echo "Debug logs: tail -f ~/.claude/state/promptlayer_hook.log" diff --git a/plugins/pl-trace-claude-code/testdata/session_start_input.json b/plugins/trace/testdata/session_start_input.json similarity index 100% rename from plugins/pl-trace-claude-code/testdata/session_start_input.json rename to plugins/trace/testdata/session_start_input.json diff --git a/scripts/dev-install.sh b/scripts/dev-install.sh index 081254e..18d2660 100755 --- a/scripts/dev-install.sh +++ b/scripts/dev-install.sh @@ -2,9 +2,9 @@ set -euo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -TARGET="$HOME/.claude/plugins/marketplaces/promptlayer-claude-plugin" -PLUGIN="pl-trace-claude-code@promptlayer-claude-plugin" -SETUP_SCRIPT="$TARGET/plugins/pl-trace-claude-code/setup.sh" +TARGET="$HOME/.claude/plugins/marketplaces/promptlayer-claude-plugins" +PLUGIN="trace@promptlayer-claude-plugins" +SETUP_SCRIPT="$TARGET/plugins/trace/setup.sh" mkdir -p "$(dirname "$TARGET")" rm -rf "$TARGET" diff --git a/scripts/dev-uninstall.sh b/scripts/dev-uninstall.sh index 00912f3..219be61 100755 --- a/scripts/dev-uninstall.sh +++ b/scripts/dev-uninstall.sh @@ -1,8 +1,8 @@ #!/bin/bash set -euo pipefail -PLUGIN="pl-trace-claude-code@promptlayer-claude-plugin" -MARKETPLACE="promptlayer-claude-plugin" +PLUGIN="trace@promptlayer-claude-plugins" +MARKETPLACE="promptlayer-claude-plugins" for scope in user project local; do claude plugin uninstall --scope "$scope" "$PLUGIN" >/dev/null 2>&1 || true diff --git a/scripts/e2e_smoke.py b/scripts/e2e_smoke.py index de8c94c..ab172ef 100755 --- a/scripts/e2e_smoke.py +++ b/scripts/e2e_smoke.py @@ -6,7 +6,7 @@ # ] # /// -"""End-to-end smoke test for pl-trace-claude-code via Claude Agent SDK. +"""End-to-end smoke test for trace plugin via Claude Agent SDK. The smoke test launches a local OTLP HTTP collector, runs a short Claude session with the plugin enabled, then asserts that OTLP payloads were actually received. @@ -28,7 +28,7 @@ REPO_ROOT = Path(__file__).resolve().parents[1] -PLUGIN_PATH = REPO_ROOT / "plugins" / "pl-trace-claude-code" +PLUGIN_PATH = REPO_ROOT / "plugins" / "trace" class _CollectorHandler(BaseHTTPRequestHandler): diff --git a/scripts/replay-fixtures.sh b/scripts/replay-fixtures.sh index c553dce..8e87fd9 100755 --- a/scripts/replay-fixtures.sh +++ b/scripts/replay-fixtures.sh @@ -14,6 +14,6 @@ export PROMPTLAYER_API_KEY="pl_test_key" export PROMPTLAYER_OTLP_ENDPOINT="http://127.0.0.1:9/v1/traces" # Expect failure to send (no server), but script should still run. -cat plugins/pl-trace-claude-code/testdata/session_start_input.json | bash plugins/pl-trace-claude-code/hooks/session_start.sh || true +cat plugins/trace/testdata/session_start_input.json | bash plugins/trace/hooks/session_start.sh || true echo "Fixture replay completed" diff --git a/scripts/validate-manifests.sh b/scripts/validate-manifests.sh index 6307b3c..f1ebc49 100755 --- a/scripts/validate-manifests.sh +++ b/scripts/validate-manifests.sh @@ -11,7 +11,7 @@ validate_json() { } validate_json .claude-plugin/marketplace.json -validate_json plugins/pl-trace-claude-code/.claude-plugin/plugin.json -validate_json plugins/pl-trace-claude-code/hooks/hooks.json +validate_json plugins/trace/.claude-plugin/plugin.json +validate_json plugins/trace/hooks/hooks.json echo "Manifest validation passed"