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
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ not per individual commit.

## [Unreleased]

### Added

- Claude Code plugin telemetry. A plugin hook sends `agent_invocation` and
`subagent_invocation` events for Konductor's own agents, in the CLI's format, with
`claude-plugin` as the harness. It is on by default and shares the machine ID in
`~/.konductor/telemetry.json` with the CLI. Turn it off with the plugin's
`telemetry_enabled` option or any existing opt-out.

### Fixed

- The Claude Code plugin release candidate could include untracked build output (`cli/`,
Expand Down
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
# target's own script first and renders plugin.json/
# .mcp.json at the flat tree's root afterward -- there
# is no separate repo-root plugin layout.
# claude-plugin-check PR-time smoke test: assembles the flat branch tree
# claude-plugin-check PR-time smoke test: runs the plugin telemetry hook's
# node tests, assembles the flat branch tree
# (scripts/assemble-claude-plugin-branch.sh, which
# calls claude-plugin's own generation first) into a
# scratch directory, then validates it (--strict) when
Expand Down Expand Up @@ -189,6 +190,8 @@ claude-plugin:
# (see assemble-claude-plugin-branch.sh and claude-plugin's own comment
# above).
claude-plugin-check:
@echo "=== [claude-plugin-check] Running the plugin telemetry hook tests ==="
node --test tests/scripts/claude-plugin-telemetry-hook.test.js
$(MAKE) -C cli build TARGET=$(TARGET)
@test -x "$(KONDUCTOR_BIN)" || { echo "error: $(KONDUCTOR_BIN) not found; run 'make -C cli build' first" >&2; exit 1; }
@validated=1; \
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -441,13 +441,19 @@ that stays the same across all projects on your machine.
UUID and stores it in `$HOME/.konductor/telemetry.json`. Every project on that machine sends the same
UUID, so events from different projects can be linked to one machine, though not to which projects.

**Claude Code plugin.** The marketplace plugin sends `agent_invocation` and
`subagent_invocation` the same way, through a plugin hook, with `claude-plugin` as the runtime. It
shares the machine identifier in `$HOME/.konductor/telemetry.json` with the CLI. See
[Install via the Claude Code plugin marketplace](docs/user-guide/tasks/install-claude-plugin-marketplace.md#telemetry).

**Opting out**

| To stop reporting for | Do this |
| --- | --- |
| One project | Run `konductor install` or `konductor update` with `--no-telemetry`, or set `telemetry.enabled: false` in `.konductor/config.yml` |
| Any process with the variable set (a shell, a CI job, a fleet) | Set `KONDUCTOR_TELEMETRY=off` |
| The whole machine | Set `"telemetry_consent": false` in `$HOME/.konductor/telemetry.json` |
| The Claude Code plugin | Turn off the plugin's `telemetry_enabled` option. The variable, `config.yml` and machine settings above also apply; `--no-telemetry` doesn't |

- `--no-telemetry` also removes an opt-in record left by an earlier install, and stops a global
install's hooks from reporting in that project.
Expand Down
4 changes: 2 additions & 2 deletions docs/telemetry-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@
"string",
"null"
],
"description": "Populated only on cli_error events, copied verbatim from the identity record. Null on every other eventType -- package_uninstalled/package_installed/package_version_updated carry their harness value through targetName instead, not through this field."
"description": "Populated on cli_error events, copied verbatim from the identity record. agent_invocation/subagent_invocation from the Claude Code marketplace plugin carry \"claude-plugin\"; the CLI sends null on those. Null on every other eventType -- package_uninstalled/package_installed/package_version_updated carry their harness value through targetName instead, not through this field."
},
"agentVersion": {
"type": [
"string",
"null"
],
"description": "The installed CONTENT's own version (distinct from the outer envelope's Version, which is always the CLI binary's own env!(\"CARGO_PKG_VERSION\")) -- populated only on package_installed and package_version_updated, sourced from that install's <target_dir>/.konductor/install-info.json record. Null on every other eventType (agent_invocation, subagent_invocation, mcp_tool_call, cli_error, package_uninstalled), and also null on package_installed/package_version_updated when the install source predates the VERSION-in-dist/ convention or that file could not be read -- never a fabricated version string."
"description": "The installed CONTENT's own version (distinct from the outer envelope's Version, which is the CLI binary's own env!(\"CARGO_PKG_VERSION\") on CLI events and the plugin manifest version on Claude Code plugin events) -- populated only on package_installed and package_version_updated, sourced from that install's <target_dir>/.konductor/install-info.json record. Null on every other eventType (agent_invocation, subagent_invocation, mcp_tool_call, cli_error, package_uninstalled), and also null on package_installed/package_version_updated when the install source predates the VERSION-in-dist/ convention or that file could not be read -- never a fabricated version string."
},
"TimeStamp": {
"type": "string",
Expand Down
29 changes: 29 additions & 0 deletions docs/user-guide/tasks/install-claude-plugin-marketplace.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,35 @@ npx playwright install chromium

Add `--scope user` to make that server available across projects.

## Telemetry

The plugin sends usage telemetry to AWS by default. A hook runs when a
session starts with a Konductor agent and when a Konductor agent is
delegated to. Each event carries the agent name, the delegating Konductor
agent's name when Claude Code exposes it, the plugin version, a hashed
session ID, and `claude-plugin` as the harness so plugin events can be told
apart from CLI ones. Your own agents and Claude Code's built-in agents are never
reported. Prompts, file paths, and tool inputs are never sent.

Events also carry the machine ID stored in `~/.konductor/telemetry.json`.
The plugin creates that file if it is missing. The Konductor CLI uses the
same file, so plugin and CLI events from one machine share one ID.

To opt out, do any one of these:

- Turn off the plugin's `telemetry_enabled` option in `/config`.
- Set `KONDUCTOR_TELEMETRY=off` in your environment.
- Set `telemetry.enabled: false` in `.konductor/config.yml` in the project,
any directory above it, or `$HOME`.
- Set `"telemetry_consent": false` in `~/.konductor/telemetry.json`. This
also stops the CLI from reporting on this machine.

The plugin always sends to the default endpoint. It ignores
`KONDUCTOR_METRICS_ENDPOINT` and `telemetry.endpoint`.

See [Data Collection](../../../README.md#data-collection) for the full
details and the event schema.

## Related

- [Install for Claude Code](install-claude-code.md)
Expand Down
29 changes: 29 additions & 0 deletions generated/claude-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ The published branch contains:
.mcp.json
agents/
skills/
hooks/hooks.json
hooks/konductor-telemetry.js
docs/telemetry-schema.json
README.md
LICENSE.txt
```
Expand Down Expand Up @@ -111,6 +114,32 @@ mcp__plugin_konductor_aws-mcp__*
Bring-your-own servers, including `playwright-mcp`, keep their bare grants and
must be configured by the user.

## Telemetry

The plugin ships a telemetry hook. It is on by default and has no npm
dependencies; Claude Code runs it with `node`.

- `scripts/claude-plugin-telemetry-hook.js` is copied to
`hooks/konductor-telemetry.js`. It reports `agent_invocation` on
`SessionStart` (`startup|clear`) and `subagent_invocation` on
`SubagentStart`, only for Konductor's own agents, in the same format as
`konductor __telemetry-hook` (`docs/telemetry-schema.json`, also copied
into the tree). It prints nothing and always exits 0.
- `scripts/render-claude-plugin-hooks-json.py` writes `hooks/hooks.json`.
The `SubagentStart` matcher lists every file in the assembled `agents/`,
as `konductor:<agent>` only. Bare names come from a CLI install, whose own
hook reports them, so an agent is never counted twice.
- The machine ID is shared with the CLI through `~/.konductor/telemetry.json`.

Users opt out with the plugin's `telemetry_enabled` option,
`KONDUCTOR_TELEMETRY=off`, `telemetry.enabled: false` in
`.konductor/config.yml`, or `"telemetry_consent": false` in
`~/.konductor/telemetry.json`. See the
[install guide](../../docs/user-guide/tasks/install-claude-plugin-marketplace.md#telemetry)
and the root README's [Data Collection](../../README.md#data-collection)
section. Tests: `node --test tests/scripts/claude-plugin-telemetry-hook.test.js`,
also run by `make claude-plugin-check`.

## Kiro CLI

Kiro CLI renders `clientConfig.kiroCli.mcpServers`, not an agent's
Expand Down
10 changes: 10 additions & 0 deletions scripts/assemble-claude-plugin-branch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,14 @@ python3 "$REPO_ROOT/scripts/rewrite-claude-plugin-agent-grants.py" \
--agents-dir "$OUT/agents" \
--plugin-json "$OUT/.claude-plugin/plugin.json"

# Telemetry hook. hooks.json is generated from the assembled agents/ so the
# SubagentStart matcher covers every agent shipped.
mkdir -p "$OUT/hooks" "$OUT/docs"
cp "$REPO_ROOT/scripts/claude-plugin-telemetry-hook.js" "$OUT/hooks/konductor-telemetry.js"
cp "$REPO_ROOT/docs/telemetry-schema.json" "$OUT/docs/telemetry-schema.json"
python3 "$REPO_ROOT/scripts/render-claude-plugin-hooks-json.py" \
--agents-dir "$OUT/agents" \
--plugin-json "$OUT/.claude-plugin/plugin.json" \
--output "$OUT/hooks/hooks.json"

echo "=== [assemble-claude-plugin] Done: flat plugin tree at $OUT ==="
Loading
Loading