{% extends "base.html" %} {% block title %}insights · watchmen{% endblock %} {% block content %}

Watchmen insights

LLM-synthesized digest grounded in your corpus across Claude Code, Codex, and pi.dev. Cross-repo patterns, friction signals, untapped coverage. Complements Claude Code's /insights single-agent view.
Looking for raw numbers? See ↗ aggregated metrics for sessions, cost, tool errors, per-agent breakdown.
{{ n_projects }} repos · {{ curated_count }} curated · {{ total_sessions }} sessions
{{ total_skills }} approved skills {% if total_pending %} · {{ total_pending }} pending {% endif %}

Repos

{% for r in repos %} {% endfor %}
Project Skills Pending Sessions (30d) Adapters Tool errors Frustration Unanalyzed
{{ r.key }} {% if r.skills_n %}{{ r.skills_n }}{% else %}0{% endif %} {% if r.pending_n %}{{ r.pending_n }}{% else %}0{% endif %}
{% for agent in ["claude_code", "codex", "pi"] %} {% if r.adapter.get(agent, 0) %} {{ {"claude_code":"cc","codex":"cd","pi":"pi"}[agent] }}: {{ r.adapter[agent] }} {% endif %} {% endfor %} {% if r.tool_errors %}{{ r.tool_errors }}{% else %}0{% endif %} {% if r.frust_count %}{{ r.frust_count }}{% else %}0{% endif %} {% if r.pending_prompts %}{{ r.pending_prompts }}{% else %}0{% endif %}
Tool errors by repo
From sessions.tool_error_count in corpus.db.
{% if errors_chart_data %}
{% else %}
No tool errors recorded.
{% endif %}
Frustration markers by repo
Prompts matching no wait / bruh / :( / wtf / nope / …
{% if frust_chart_data %}
{% else %}
No frustration markers detected.
{% endif %}
{% if cross %}

Cross-repo patterns

Candidate slugs that appear in two or more repos' _candidates.json. Curated in some, only proposed in others.
{% for slug, hits in cross[:12] %} {% endfor %}
{{ slug }} {% for key, status in hits %} {% if status == "curated" %} ✓ {{ key }} {% else %} · {{ key }} {% endif %} {% endfor %}
{% endif %} {% if untapped %}

Untapped corpora

Tracked repos with captured sessions but zero curated skills yet.
{% endif %} {% set frust_repos = repos | selectattr("frust_samples") | list %} {% if frust_repos %}
Frustration samples (click to expand)
{% for r in frust_repos %}
{{ r.key }} ({{ r.frust_count }} markers)
{% for s in r.frust_samples %}
"{{ s }}"
{% endfor %}
{% endfor %}
{% endif %}

Activity by hour & day-of-week

Last 90 days, every coding-agent session in your corpus.
{% if cmp_narrative_html %}

How you use each agent

{% if cmp_narrative_meta and cmp_narrative_meta.generated_at %} Synthesized {{ cmp_narrative_meta.generated_at[:10] }} {% if cmp_narrative_meta.model %}with {{ cmp_narrative_meta.model }}{% endif %} · regenerate from the CLI with watchmen insights --regenerate {% endif %}
{{ cmp_narrative_html|safe }}
{% endif %} {% if digest_html %}

◉ Deep digest

{% if digest_meta.get("generated_at") %} Generated {{ digest_meta["generated_at"] }} with {{ digest_meta.get("model", "?") }} · {{ digest_meta.get("repos_synthesized", "?") }} repos synthesized {% endif %} · regenerate from the CLI with watchmen insights --regenerate
{{ digest_html|safe }}
{% else %}
No cached deep digest yet. Run watchmen insights from the CLI to generate one. It'll cache under ~/.watchmen/insights/ and appear here on next page load.
{% endif %} {% endblock %}