How TeamAI Tracks Usage Statistics and Generates Weekly Digests
TeamAI CLI automatically captures every skill invocation via IDE hooks, aggregates those events with team-reported YAML statistics, and compiles a formatted weekly digest showing team health, usage trends, and recent learnings.
TeamAI CLI, the open-source command-line tool developed by Tencent, provides engineering teams with detailed visibility into AI-assisted coding workflows. Understanding how TeamAI tracks usage statistics and generates weekly digests allows teams to monitor skill adoption, measure productivity impacts, and identify coaching opportunities across their organization.
The Three-Stage Analytics Pipeline
The usage tracking system operates through a sophisticated three-stage pipeline that flows from raw event capture to high-level team reporting.
Stage 1: Capturing Raw Usage Events
Every skill invocation begins its journey in src/usage-tracker.ts, where PostToolUse and UserPromptSubmit hooks feed JSON payloads into the teamai track command. The system normalizes tool input through extractSkillName(), which parses fields like skill, skill_name, command, or file paths to identify the canonical skill identifier.
The isValidSkillName() function validates the extracted name against SKILL_NAME_REGEX before persistence. Valid events are written via appendUsageEvent() to ~/.teamai/usage.jsonl as newline-delimited JSON records containing the skill name, ISO timestamp, and tool identifier. Simultaneously, updateKnownSkills() maintains a durable reference set in known-skills.json, ensuring skill history survives even if the JSONL file is truncated.
// src/usage-tracker.ts – core tracking logic
export async function track(rawToolName: string, toolInput: string, tool?: string) {
const toolName = normalizeToolName(rawToolName);
if (toolName !== 'Skill') return;
const skillName = extractSkillName(toolInput);
if (!skillName || !isValidSkillName(skillName)) return;
const event: UsageEvent = {
skill: skillName,
timestamp: new Date().toISOString(),
tool: tool ?? 'claude'
};
await appendUsageEvent(event);
await updateKnownSkills(skillName);
}
Stage 2: Aggregating Local and Reported Statistics
When users run teamai stats, the system invokes showStats() in src/stats.ts to merge local telemetry with team-wide data. The process begins with readUsageEvents(), which robustly parses the local JSONL file while skipping malformed lines. These raw events feed into aggregateUsage(), which constructs a Map<string, SkillStats> keyed by skill name and sorted by usage frequency.
The pipeline then loads reported statistics via loadReportedStats(), reading per-user YAML files (e.g., alice.yaml) from the repository's stats/ directory. These files store cumulative counts, last-used timestamps, and intervention metrics. The mergeLocalAndReported() function overlays unreported local counts onto the reported totals, presenting a unified view of pending and committed data.
Additional session-level metrics arrive through readEvents() and aggregateSessionMetrics(), which process dashboard events from events.jsonl to calculate conversation turns, token consumption, and intervention rates.
// src/stats.ts – merging local and reported data
export async function showStats(options: ShowStatsOptions = {}): Promise<void> {
const events = await readUsageEvents();
const localStats = aggregateUsage(events); // ← raw JSONL → per‑skill
const reported = await loadReportedStats(); // ← YAML files
const stats = mergeLocalAndReported(localStats, reported);
// ... renders comprehensive console output
}
Stage 3: Building the Weekly Team Digest
The teamai digest command triggers generateDigest() in src/digest.ts, orchestrating a multi-source analysis that produces the weekly report. The function first calls loadTeamStats() to ingest all YAML files under the stats/ directory, then calculates team health scores via calculateTeamStats() and trend comparisons through summarizeTeamTrends().
The digest compiler gathers contextual data by scanning the repository structure: getRecentSessions() pulls markdown files from the sessions/ folder, getRecentLearnings() scans learnings/ for weekly updates, and getRecentSkillChanges() executes git log queries to classify skill modifications as new or updated. Finally, summarizeInterventions() and summarizeConversation() compute aggregate metrics before the system emits a formatted ASCII report directly to stdout.
// src/digest.ts – digest generation orchestration
export async function generateDigest(options: GlobalOptions): Promise<void> {
const projectConfig = await detectProjectConfig();
const localConfig = projectConfig ?? (await requireInit()).localConfig;
const repoPath = localConfig.repo.localPath;
const teamStats = await loadTeamStats(reportsRoot);
const health = calculateTeamHealth(teamStats);
const sessions = await getRecentSessions(reportsRoot);
const trends = summarizeTeamTrends(teamStats); // 7d vs prior 7d
console.log('📈 Session trends (7d vs prior 7d):');
if (trends) for (const line of formatTrendLines(trends)) console.log(line);
// ... additional report sections
}
Key Source Files and Functions
src/usage-tracker.ts: Containstrack(),extractSkillName(), andisValidSkillName()for hook-based event capture and validation.src/stats.ts: ImplementsshowStats(),aggregateUsage(), andmergeLocalAndReported()for local and remote data fusion.src/digest.ts: HousesgenerateDigest(),loadTeamStats(), andcalculateTeamHealth()for weekly report generation.src/dashboard-collector.ts: Persists low-level session events toevents.jsonlfor token and intervention tracking.src/session-trends.ts: Provides 7-day window comparisons used in digest trend analysis.src/skill-health.ts: Calculates usage frequency and recency rankings for the "Most Used Skills" digest section.
Practical CLI Workflows
Manual Skill Tracking
While normally invoked automatically by IDE hooks, you can manually track usage for testing or scripting:
echo '{"tool_name":"Skill","tool_input":{"skill":"tdd"}}' | \
teamai track --stdin --tool claude
Viewing Aggregated Statistics
Display local usage combined with previously reported team data:
teamai stats --by-repo --by-time
Generating the Weekly Digest
First synchronize with the team repository, then generate the report:
teamai pull # gathers latest reported stats from remote
teamai digest # outputs formatted weekly digest to console
Debugging Raw Telemetry
Inspect the local event stream for troubleshooting:
cat ~/.teamai/usage.jsonl | jq .
Summary
- Automatic Capture: Hook-driven tracking in
src/usage-tracker.tsvalidates and persists every skill invocation to~/.teamai/usage.jsonl. - Hybrid Aggregation: The
showStats()function merges local JSONL events with per-user YAML reports from thestats/directory. - Comprehensive Digesting:
generateDigest()synthesizes usage data, session metrics, learnings, and git history into a formatted weekly report. - Persistent Storage: Skills are tracked in both ephemeral JSONL logs and durable
known-skills.jsonfiles to prevent data loss. - Team Visibility: The three-stage pipeline transitions from individual telemetry to team-wide analytics through standardized YAML reporting.
Frequently Asked Questions
Where does TeamAI store local usage data before it is reported?
TeamAI writes raw usage events to ~/.teamai/usage.jsonl as newline-delimited JSON records, while maintaining a deduplicated skill list in known-skills.json. These files reside in the user's home directory and persist data until explicitly cleared or reported to the team repository via teamai push.
Can TeamAI track usage when working offline?
Yes, the CLI captures all usage events locally through the hook system regardless of network connectivity. The usage.jsonl file accumulates events continuously, and teamai stats displays aggregated data from both local storage and any previously synchronized YAML reports. Synchronization to the team repository occurs only when you explicitly run teamai push.
How does the weekly digest determine "recent" sessions and learnings?
The digest generator uses configurable time windows (defaulting to 7 days) when scanning directories. The getRecentSessions() function examines file modification times in the sessions/ folder, while getRecentLearnings() filters markdown files in learnings/ by date. Skill changes are detected via git log queries filtered to the relevant subdirectory, ensuring the digest reflects only the current week's activity.
What is the difference between teamai stats and teamai digest?
teamai stats displays immediate, personalized usage metrics combining your local usage.jsonl with your individual reported statistics, ideal for checking personal productivity. teamai digest generates a comprehensive team-wide report that aggregates data from all members' YAML files in the stats/ directory, including trends, health scores, and collective learnings suitable for weekly team reviews.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →