From da4ae8dd1bb3ea11dcaf18d7d8772485c6f0598f Mon Sep 17 00:00:00 2001 From: Ritvik Jayaswal Date: Thu, 2 Jul 2026 14:34:27 -0400 Subject: [PATCH] feat: opt-in install scripts with anonymous usage telemetry Add scripts/install.ps1 and scripts/install.sh that install skills and, only when explicitly opted in (-Telemetry/--telemetry or DDBKIT_TELEMETRY=1), send one anonymous skill_install event to Application Insights. Document collection in TELEMETRY.md and reference from README. Telemetry is off by default and never blocks installs. --- README.md | 21 +++++++ TELEMETRY.md | 59 +++++++++++++++++++ scripts/install.ps1 | 135 ++++++++++++++++++++++++++++++++++++++++++++ scripts/install.sh | 134 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 349 insertions(+) create mode 100644 TELEMETRY.md create mode 100644 scripts/install.ps1 create mode 100644 scripts/install.sh diff --git a/README.md b/README.md index 50a47da..9bc6f83 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,27 @@ Skills follow the [Agent Skills](https://agentskills.io/) format and the kit shi 👉 **Capabilities and skill catalog:** [`docs/SKILLS.md`](docs/SKILLS.md) +### Install scripts (with optional usage telemetry) + +Cross-platform installers copy or symlink the `skills/` folder into your agent's +skills directory: + +```powershell +# Windows / PowerShell +./scripts/install.ps1 -Target claude-user +``` + +```bash +# macOS / Linux +./scripts/install.sh --target claude-user +``` + +These installers can send **anonymous, opt-in** usage telemetry (which skills +were installed) to help maintainers prioritize. Telemetry is **off by default** +and only sent when you pass `-Telemetry` / `--telemetry` (or set +`DDBKIT_TELEMETRY=1`). See [TELEMETRY.md](TELEMETRY.md) for exactly what is and +is not collected. + ## Repo Structure ``` diff --git a/TELEMETRY.md b/TELEMETRY.md new file mode 100644 index 0000000..9c84568 --- /dev/null +++ b/TELEMETRY.md @@ -0,0 +1,59 @@ +# Usage Telemetry + +The documentdb-agent-kit installers (`scripts/install.ps1`, `scripts/install.sh`) +can send **anonymous, opt-in** usage telemetry so the maintainers can see which +skills are actually installed and prioritize accordingly. + +## Opt-in only — off by default + +Telemetry is **never** sent unless you explicitly enable it: + +- PowerShell: `./scripts/install.ps1 -Target claude-user -Telemetry` +- Bash: `./scripts/install.sh --target claude-user --telemetry` +- Or set the environment variable `DDBKIT_TELEMETRY=1`. + +If you do nothing, no network call is made. A telemetry failure never blocks or +fails an install. + +## What is collected + +A single `skill_install` event with these fields: + +| Field | Example | Purpose | +|---|---|---| +| `kitVersion` | `1.0.0` | Which kit version was installed | +| `target` | `claude-user` | Which agent/target folder | +| `osFamily` | `windows` / `macos` / `linux` | Coarse platform mix | +| `method` | `copy` / `symlink` | How skills were installed | +| `skills` | `data-modeling,indexing,…` | Which skill folders were installed | +| `skillCount` | `16` | Number of skills installed | +| `invocationId` | random GUID | De-duplicate a single run; **not** stable across runs | + +## What is NOT collected + +- No file contents, source code, or query data. +- No connection strings, credentials, or App Insights keys. +- No usernames, hostnames, IP-derived identity, MAC addresses, or any stable + machine/user identifier. `invocationId` is random per run and cannot be + correlated across installs. + +## Where it goes + +Events are sent to an Azure Application Insights resource via its ingestion +endpoint (`https://dc.services.visualstudio.com/v2/track`). The installers ship +**without** a live key — the `INSTRUMENTATION_KEY` is a ``. To +enable telemetry against your own resource, provide an ingestion-only +instrumentation key through the `DDBKIT_AIKEY` environment variable: + +```bash +DDBKIT_AIKEY="" ./scripts/install.sh --target claude-user --telemetry +``` + +If no key is configured, the installer skips the telemetry send even when +`--telemetry` is passed. + +## Opting out permanently + +Simply never pass `--telemetry` / `-Telemetry` and leave `DDBKIT_TELEMETRY` +unset (or set it to `0`). You can also delete the telemetry block at the bottom +of the install scripts. diff --git a/scripts/install.ps1 b/scripts/install.ps1 new file mode 100644 index 0000000..dff7113 --- /dev/null +++ b/scripts/install.ps1 @@ -0,0 +1,135 @@ +<# +.SYNOPSIS + Install the documentdb-agent-kit skills into an agent's skills directory, + with OPTIONAL, opt-in usage telemetry. + +.DESCRIPTION + Copies (or symlinks) the skills/ folder into a target agent directory. + Telemetry is OFF by default. It is only sent when you explicitly pass + -Telemetry, or set the environment variable DDBKIT_TELEMETRY=1. + + When enabled, a single anonymous "install" event is sent to Azure + Application Insights recording: which target agent was used, the list of + skill names installed, kit version, and coarse OS family. No file contents, + no personal data, no connection strings, and no machine identifiers beyond a + random per-invocation id are collected. See TELEMETRY.md for the full schema. + +.PARAMETER Target + Where to install: 'claude-user', 'claude-project', or a custom path. + +.PARAMETER Telemetry + Opt in to sending the anonymous install event. + +.PARAMETER Symlink + Symlink instead of copy (requires privilege/developer mode on Windows). + +.EXAMPLE + ./scripts/install.ps1 -Target claude-project + +.EXAMPLE + ./scripts/install.ps1 -Target claude-user -Telemetry +#> +[CmdletBinding()] +param( + [ValidateNotNullOrEmpty()] + [string]$Target = 'claude-project', + [switch]$Telemetry, + [switch]$Symlink +) + +$ErrorActionPreference = 'Stop' + +# --- Config ----------------------------------------------------------------- +$KitVersion = '1.0.0' +# App Insights ingestion key. Supply your own via the DDBKIT_AIKEY environment +# variable. An instrumentation key is an ingestion-only identifier; it is kept +# out of source control here so the repo ships without a live endpoint. +$InstrumentationKey = if ($env:DDBKIT_AIKEY) { $env:DDBKIT_AIKEY } else { '' } +$IngestionEndpoint = 'https://dc.services.visualstudio.com/v2/track' + +$RepoRoot = Split-Path -Parent $PSScriptRoot +$SkillsRoot = Join-Path $RepoRoot 'skills' + +if (-not (Test-Path $SkillsRoot)) { + throw "skills/ not found at '$SkillsRoot'. Run this from inside the documentdb-agent-kit repo." +} + +# --- Resolve target directory ---------------------------------------------- +switch ($Target) { + 'claude-project' { $Dest = Join-Path $RepoRoot '.claude/skills' } + 'claude-user' { $Dest = Join-Path $HOME '.claude/skills' } + default { $Dest = $Target } +} + +New-Item -ItemType Directory -Force -Path $Dest | Out-Null + +# --- Install ---------------------------------------------------------------- +$installed = @() +Get-ChildItem -Path $SkillsRoot -Directory | ForEach-Object { + $name = $_.Name + $linkPath = Join-Path $Dest $name + if (Test-Path $linkPath) { Remove-Item $linkPath -Recurse -Force } + + if ($Symlink) { + New-Item -ItemType SymbolicLink -Path $linkPath -Target $_.FullName | Out-Null + } + else { + Copy-Item -Path $_.FullName -Destination $linkPath -Recurse -Force + } + $installed += $name +} + +Write-Host "Installed $($installed.Count) skills into $Dest" -ForegroundColor Green +$installed | ForEach-Object { Write-Host " - $_" } + +# --- Opt-in telemetry ------------------------------------------------------- +$telemetryOn = $Telemetry -or ($env:DDBKIT_TELEMETRY -eq '1') + +if (-not $telemetryOn) { + Write-Host '' + Write-Host 'Usage telemetry: OFF. Re-run with -Telemetry (or set DDBKIT_TELEMETRY=1) to' -ForegroundColor DarkGray + Write-Host 'help the maintainers see which skills are installed. See TELEMETRY.md.' -ForegroundColor DarkGray + return +} + +if ($InstrumentationKey -like '<*>') { + Write-Host '' + Write-Host 'Telemetry requested but no App Insights key configured. Set DDBKIT_AIKEY to enable. Skipping.' -ForegroundColor DarkYellow + return +} + +try { + $osFamily = if ($IsWindows) { 'windows' } elseif ($IsMacOS) { 'macos' } elseif ($IsLinux) { 'linux' } else { 'unknown' } + + $payload = @{ + name = 'Microsoft.ApplicationInsights.Event' + time = (Get-Date).ToUniversalTime().ToString('o') + iKey = $InstrumentationKey + tags = @{ 'ai.cloud.role' = 'documentdb-agent-kit-installer' } + data = @{ + baseType = 'EventData' + baseData = @{ + ver = 2 + name = 'skill_install' + properties = @{ + kitVersion = $KitVersion + target = $Target + osFamily = $osFamily + method = if ($Symlink) { 'symlink' } else { 'copy' } + skills = ($installed -join ',') + invocationId = [guid]::NewGuid().ToString() + } + measurements = @{ skillCount = $installed.Count } + } + } + } | ConvertTo-Json -Depth 6 -Compress + + Invoke-RestMethod -Uri $IngestionEndpoint -Method Post -Body $payload -ContentType 'application/json' -TimeoutSec 10 | Out-Null + Write-Host '' + Write-Host 'Anonymous install event sent. Thank you!' -ForegroundColor Green +} +catch { + # Telemetry must never break an install. + Write-Host '' + Write-Host "Telemetry send failed (ignored): $($_.Exception.Message)" -ForegroundColor DarkYellow +} diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100644 index 0000000..23111db --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,134 @@ +#!/usr/bin/env bash +# +# Install the documentdb-agent-kit skills into an agent's skills directory, +# with OPTIONAL, opt-in usage telemetry. +# +# Telemetry is OFF by default. It is only sent when you pass --telemetry or set +# DDBKIT_TELEMETRY=1. When enabled, one anonymous "install" event is sent to +# Azure Application Insights: target agent, list of skill names, kit version, +# and OS family. No file contents, personal data, or machine identifiers beyond +# a random per-invocation id. See TELEMETRY.md. +# +# Usage: +# ./scripts/install.sh [--target claude-project|claude-user|] [--symlink] [--telemetry] +# +set -euo pipefail + +# --- Config ----------------------------------------------------------------- +KIT_VERSION="1.0.0" +# App Insights ingestion key. Supply your own via the DDBKIT_AIKEY environment +# variable. An instrumentation key is an ingestion-only identifier; it is kept +# out of source control here so the repo ships without a live endpoint. +INSTRUMENTATION_KEY="${DDBKIT_AIKEY:-}" +INGESTION_ENDPOINT="https://dc.services.visualstudio.com/v2/track" + +TARGET="claude-project" +SYMLINK=0 +TELEMETRY=0 + +while [[ $# -gt 0 ]]; do + case "$1" in + --target) TARGET="$2"; shift 2 ;; + --symlink) SYMLINK=1; shift ;; + --telemetry) TELEMETRY=1; shift ;; + *) echo "Unknown option: $1" >&2; exit 1 ;; + esac +done + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +SKILLS_ROOT="$REPO_ROOT/skills" + +if [[ ! -d "$SKILLS_ROOT" ]]; then + echo "skills/ not found at '$SKILLS_ROOT'. Run this from inside the documentdb-agent-kit repo." >&2 + exit 1 +fi + +# --- Resolve target directory ---------------------------------------------- +case "$TARGET" in + claude-project) DEST="$REPO_ROOT/.claude/skills" ;; + claude-user) DEST="$HOME/.claude/skills" ;; + *) DEST="$TARGET" ;; +esac + +mkdir -p "$DEST" + +# --- Install ---------------------------------------------------------------- +installed=() +for dir in "$SKILLS_ROOT"/*/; do + name="$(basename "$dir")" + link="$DEST/$name" + rm -rf "$link" + if [[ "$SYMLINK" -eq 1 ]]; then + ln -s "$dir" "$link" + else + cp -R "$dir" "$link" + fi + installed+=("$name") +done + +echo "Installed ${#installed[@]} skills into $DEST" +for s in "${installed[@]}"; do echo " - $s"; done + +# --- Opt-in telemetry ------------------------------------------------------- +if [[ "$TELEMETRY" -ne 1 && "${DDBKIT_TELEMETRY:-}" != "1" ]]; then + echo "" + echo "Usage telemetry: OFF. Re-run with --telemetry (or set DDBKIT_TELEMETRY=1) to" + echo "help the maintainers see which skills are installed. See TELEMETRY.md." + exit 0 +fi + +case "$INSTRUMENTATION_KEY" in + "<"*">") echo "" ; echo "Telemetry requested but no App Insights key configured. Set DDBKIT_AIKEY to enable. Skipping." ; exit 0 ;; +esac + +if ! command -v curl >/dev/null 2>&1; then + echo "" ; echo "curl not found; skipping telemetry." ; exit 0 +fi + +case "$(uname -s)" in + Linux*) OS_FAMILY="linux" ;; + Darwin*) OS_FAMILY="macos" ;; + MINGW*|MSYS*|CYGWIN*) OS_FAMILY="windows" ;; + *) OS_FAMILY="unknown" ;; +esac + +method=$([[ "$SYMLINK" -eq 1 ]] && echo "symlink" || echo "copy") +skills_csv="$(IFS=,; echo "${installed[*]}")" +now="$(date -u +%Y-%m-%dT%H:%M:%SZ)" +invocation_id="$(cat /proc/sys/kernel/random/uuid 2>/dev/null || echo "$RANDOM-$RANDOM-$RANDOM")" + +payload=$(cat </dev/null 2>&1; then + echo "" ; echo "Anonymous install event sent. Thank you!" +else + echo "" ; echo "Telemetry send failed (ignored)." +fi