Scan a repository to surface actionable findings about agent performance. Analyzes source code, git history, GitHub data, agent logs, and agent context, then synthesizes cross-referenced findings with targeted actions informed by Tessl product awareness. Supports incremental multi-developer contributions and produces a self-contained HTML report.
70
88%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Advisory
Suggest reviewing before use
Orchestrate a scan that surfaces actionable findings about how a repository affects coding agent performance, and recommends concrete actions to improve it.
The scan runs in two phases:
gh CLI installed and either (a) authenticated via gh auth login with GH_TOKEN exported from your shell profile, or (b) GH_TOKEN / GITHUB_TOKEN set directly. On macOS, Cursor's sandbox can't read the gh keychain, so the env var is effectively required — add export GH_TOKEN="$(gh auth token)" to ~/.zshrc (or ~/.bashrc) once and restart Cursor. See the analyze-github-data skill's "Troubleshooting: sandboxed gh" section for details.Run the initialization script to create directories, resolve metadata, and check prerequisites in one step:
SCAN_CONFIG=$(bash "$(dirname "$0")/scripts/init-scan.sh" --root "$(pwd)")Resolving script path: The path above assumes this skill is read from its tile directory. If run via a
.claude/skills/symlink, locate the script at.tessl/tiles/*/agent-insight-experiment/skills/run-insight-scan/scripts/init-scan.shrelative to the repo root, or pass--username <name>to override the username.
Parse the output to extract variables for the analyzers:
SCAN_ID=$(echo "$SCAN_CONFIG" | grep -o '"scan_id": *"[^"]*"' | cut -d'"' -f4)
INSIGHTS_DIR=$(echo "$SCAN_CONFIG" | grep -o '"insights_dir": *"[^"]*"' | cut -d'"' -f4)
REPO_NAME=$(echo "$SCAN_CONFIG" | grep -o '"repo_name": *"[^"]*"' | cut -d'"' -f4)
USERNAME=$(echo "$SCAN_CONFIG" | grep -o '"username": *"[^"]*"' | cut -d'"' -f4)The script creates the output directory tree ($INSIGHTS_DIR/reports/agent-logs/), checks for git, gh, node, and python3, and outputs all resolved paths as JSON. Pass the full SCAN_CONFIG JSON to each analyzer so they know their output paths.
If the script is unavailable, create the structure manually:
INSIGHTS_DIR="$(pwd)/.tessl-insights-poc"
mkdir -p "$INSIGHTS_DIR/reports/agent-logs"
SCAN_ID="scan-$(date +%Y%m%d-%H%M%S)"
REPO_NAME="$(git remote get-url origin 2>/dev/null | sed 's/.*[:/]\([^/]*\/[^/]*\)\.git$/\1/' || basename "$(pwd)")"Each analyzer should run as a separate subagent, not in the main session. If subagents are available, launch all six simultaneously in parallel. The main session's only job during Phase 1 is to dispatch the analyzers and wait for their results — do not run analyzer logic inline. If subagents are not available, see Fallback: Manual Orchestration.
Before launching the analyzers, read the shared reference files so you can provide their contents as context to each analyzer:
Resolving reference paths: The links above use relative paths (
../../references/...) that work when this skill is read from its tile directory. If those paths do not resolve (e.g. when activated via a.claude/skills/symlink), find the shared references at.tessl/tiles/*/agent-insight-experiment/references/relative to the repository root.
Each analyzer receives these parameters:
scan_id: The shared scan IDrepository: The repository nameoutput_file: Where to save its report (paths below)Skill: analyze-source-code
Output: $INSIGHTS_DIR/reports/source-code.json
Examines the application/business logic code, tests, build configuration, and dependency setup.
Skill: analyze-git-history
Output: $INSIGHTS_DIR/reports/git-history.json
Examines commit history, file churn, contributor patterns, co-change relationships, and revert frequency.
Skill: analyze-github-data
Output: $INSIGHTS_DIR/reports/github-data.json
Examines pull requests, review comments, CI/CD history, and issues via the gh CLI.
Skill: analyze-agent-logs
Output: $INSIGHTS_DIR/reports/agent-logs/<username>-<date>.json
Examines agent conversation histories from Cursor, Claude Code, or other tools. Resolve the username for the filename (caller may pass username= to override):
# Explicit input wins over the git/whoami fallback.
USERNAME="${USERNAME_INPUT:-}"
if [ -z "$USERNAME" ]; then
USERNAME=$(git config user.name 2>/dev/null \
| tr '[:upper:]' '[:lower:]' \
| sed -E 's/[[:space:]]+/-/g; s/[^a-z0-9._-]//g; s/^[-.]+|[-.]+$//g')
fi
[ -z "$USERNAME" ] && USERNAME=$(whoami | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9._-]//g')
[ -z "$USERNAME" ] && USERNAME="unknown-user"
DATE=$(date +%Y%m%d)Pass the full output_file path to the analyzer — it will use exactly that path and not resolve its own.
Skill: analyze-agent-context
Output: $INSIGHTS_DIR/reports/agent-context.json
Examines existing agent configuration: .cursor/rules, AGENTS.md, CLAUDE.md, .claude/ files, MCP configurations, and other agent-facing context files.
Skill: analyze-context-inventory
Output: $INSIGHTS_DIR/reports/context-inventory.json
Produces a per-file inventory of every markdown and config file agents consume — classified by category (entry point / always-on rule / hook / skill / MCP), agent harness (Claude / Cursor / cross-agent), and usefulness. Complements analyze-agent-context: the former emits qualitative insights, this one emits the structured catalogue that renders as a filterable file tree in the HTML report.
Each analyzer should write its report JSON to the output_file path. If an analyzer does not have write permissions (e.g. due to sandboxing), it must return its complete report as structured JSON in its response to the main session. The main session then writes the file on its behalf:
# When dispatching each analyzer, include in its instructions:
"If you cannot write to the output file, return the full JSON report in your
response so the orchestrator can write it for you. Do NOT summarize — return
the full JSON."After launching all six analyzers, you MUST wait for every one to return before proceeding to Phase 2. Do NOT assume analyzers have finished. Do NOT start synthesis until all six are resolved.
As each analyzer returns, check its result:
If an analyzer cannot produce results at all (e.g. no agent logs exist on this machine), note which data source is missing — synthesis needs to know.
Once all six are resolved, verify:
ls -la "$INSIGHTS_DIR"/reports/*.json "$INSIGHTS_DIR"/reports/agent-logs/*.json 2>/dev/null | wc -lDo NOT start this phase until every analyzer from Phase 1 has returned and been handled.
Once all reports are ready, run synthesis in the main session — do NOT launch it as a background task or subagent.
Synthesis depends on all six analyzer reports existing before it can start, so it cannot be launched in parallel with them. Running it inline in the main session means it naturally starts only after all analyzers have completed and the main session has confirmed their outputs exist.
Invoke the synthesize-insights skill directly in the main session.
The synthesizer gets:
$INSIGHTS_DIR/reports/It produces:
$INSIGHTS_DIR/findings.json — synthesized findings with inline actions, an overall score (blocked | constrained | productive), and an executive summary$INSIGHTS_DIR/report.html — standalone HTML report for sharingAfter Phase 2 completes:
overall_score.level and the executive_summary — this is the 30-second read.tessl-insights-poc/ to gitcontribute-agent-logs to add their perspectiveopen "$INSIGHTS_DIR/report.html"If subagents aren't available, provide the user with instructions to run each analyzer as a separate skill invocation:
analyze-source-code skill and save results to .tessl-insights-poc/reports/source-code.json"analyze-git-history skill and save results to .tessl-insights-poc/reports/git-history.json"analyze-github-data skill and save results to .tessl-insights-poc/reports/github-data.json"analyze-agent-logs skill and save results to .tessl-insights-poc/reports/agent-logs/<username>-<date>.json"analyze-agent-context skill and save results to .tessl-insights-poc/reports/agent-context.json"analyze-context-inventory skill and save results to .tessl-insights-poc/reports/context-inventory.json"synthesize-insights skill in this session (not as a background task)"Each skill is designed to work standalone — the orchestrator is a convenience, not a requirement. Synthesis must always run in the main session since it depends on all analyzer reports being complete first.