{% extends "base.html" %} {% block title %}Sources{% endblock %} {% block body %}

Sources

Explicit allowlist: only what is turned on is read. Claude Code sessions in {{ root }}.

Processing now

{% include "_now.html" %}

Claude Code sessions

One chat per row, by the title you see in the app. A new chat shows up turned off: turn on only the ones worth it. Renaming or resuming a chat does not duplicate anything.

{% for p in projects %}{% set s = stats.get(p.source_id) %} {% else %} {% endfor %}
ChatLast activityUnits
{{ p.title }}{% if p.archived %} archived{% endif %}
{{ p.project or '—' }} · {{ p.files|length }} session {{ 'file' if p.files|length == 1 else 'files' }}{% if p.origin == 'terminal' %} · terminal{% elif p.origin == 'removed from disk' %} · removed from disk{% endif %}
{{ p.last_activity|dt if p.last_activity else '—' }} {% if s %} {% set total = s.pending + s.processed + s.triaged_out + s.failed %}
{{ s.processed }} processed · {{ s.triaged_out }} discarded at triage · {{ s.pending }} pending{% if s.failed %} · {{ s.failed }} failed{% endif %} {% if s.in_backfill %}
in backfill {{ s.in_batch }} stages in the batch · synthesis deferred for {{ s.deferred }} entities{% endif %} {% else %}—{% endif %}
{% if p.added %}
{% else %}
{% endif %}
No chat found in {{ root }}.

GitHub

PRs come in when merged, closed, or open and idle; later activity becomes a delta. Backfill of the last months, from newest to oldest.

{% for r in repos %}{% set s = stats.get(r.id) %} {% else %}{% endfor %}
RepositoryWhat to readBackfill costState
{{ r.config.repo }}
{{ r.prs }} PRs seen
days
{% if r.backfill_until %} {% if s and s.in_backfill %}in progress{% else %}backfill complete{% endif %} · {{ r.prs }} PRs · cost US${{ '%.2f'|format(r.spent) }} {% if r.estimate and r.estimate.new %}
+{{ r.estimate.new }} PRs to read ≈ US${{ '%.2f'|format(r.estimate.usd_new) }}{% endif %} {% elif r.estimate %}{{ '' if r.estimate.exact else '≥ ' }}{{ r.estimate.prs }} PRs × US${{ '%.2f'|format(r.estimate.avg_cost) }} ≈ US${{ '%.2f'|format(r.estimate.usd) }}
measured average per PR; the batch (50%) and deferred synthesis tend to lower it{% else %}calculating…{% endif %}
{% if r.error %}{{ r.error.error }}{% elif s %}{{ s.processed }} processed · {{ s.triaged_out }} discarded · {{ s.pending }} pending{% endif %}{% if s and s.in_backfill %}
in backfill {{ s.in_batch }} stages in the batch · synthesis deferred for {{ s.deferred }} entities{% endif %}
No repository on the allowlist.

Adding comes in paused: the estimate shows up and you turn it on when you want. Pausing keeps what was read; Remove retracts it.

incident.io catalog

Entity seed (people, teams, systems, repositories) with external identifiers. No LLM on read; the relations go through integration.

{% if not catalog_state.has_key %}

no key set the API key in Settings.

{% endif %} {% if catalog_state.error %}

{{ catalog_state.error.error }}

{% endif %}

{{ catalog_state.entities }} anchored entities in the catalog{% if catalog_state.last %} · last sync {{ catalog_state.last.at }} ({{ catalog_state.last.entities_created }} created, {{ catalog_state.last.entities_updated }} updated, {{ catalog_state.last.claims }} claims){% endif %}

Synced types: {% for t, e in catalog_state.types.items() if e %}{{ t }} → {{ e }}{{ ', ' if not loop.last }}{% endfor %} (adjust in Settings)

Slack

Threads and loose channel messages come in when the conversation goes idle; a new reply after that becomes a delta. Read with your user token, no bot. Backfill of the last days, from newest to oldest.

{% if not slack_state.has_token %}

no token set the token in Settings.

{% endif %} {% if slack_state.error %}

{{ slack_state.error.error }}

{% endif %} {% for r in channels %}{% set s = stats.get(r.id) %} {% else %}{% endfor %}
ConversationBackfillBackfill costState
{{ r.name }}
{{ r.config.kind }} · {{ r.conversations }} conversations seen
days
{% if r.backfill_until %} {% if s and s.in_backfill %}in progress{% else %}backfill complete{% endif %} · cost US${{ '%.2f'|format(r.spent) }} {% if r.estimate and r.estimate.new and (r.config.state or {}).get('full_rescan') %}
+{{ r.estimate.new }} messages to read ≈ US${{ '%.2f'|format(r.estimate.usd_new) }}{% endif %} {% elif r.estimate %}{{ r.estimate.messages }} messages + {{ r.estimate.replies }} replies ≈ US${{ '%.2f'|format(r.estimate.usd) }}
measured average cost per character; the batch (50%) and deferred synthesis tend to lower it{% elif slack_state.has_token %}calculating…{% else %}—{% endif %}
{% if r.error %}{{ r.error.error }}{% elif s %}{{ s.processed }} processed · {{ s.triaged_out }} discarded · {{ s.pending }} pending{% endif %}{% if s and s.in_backfill %}
in backfill {{ s.in_batch }} stages in the batch · synthesis deferred for {{ s.deferred }} entities{% endif %}
No conversation on the allowlist.

Adding comes in paused: the estimate shows up and you turn it on when you want. Pausing keeps what was read; Remove retracts it.

{% if slack_state.has_token %}
{% if slack_state.at %}list from {{ slack_state.at|dt }}{% else %}the list appears after you save the token{% endif %}
{% set labels = {'channel': 'Channels', 'private': 'Private channels', 'dm': 'Direct messages', 'group': 'Group conversations'} %} {% for kind, label in labels.items() %}{% set items = slack_state.available|selectattr('kind', 'equalto', kind)|list %} {% if items %}
{{ label }} ({{ items|length }})
{% for c in items %}{% endfor %}
{{ c.name }}{% if c.archived %} archived{% endif %}
{% endif %} {% else %}

No conversation.

{% endfor %} {% endif %}

Confluence

Whole spaces or page trees. Backfill reads the current version; afterwards, only the sections that change. An edit does not erase what came from the previous version: the adjudicator decides whether it still holds, evolved or was wrong.

{% if not cf_state.has_token %}

no token set site, email and token in Settings.

{% endif %} {% if cf_state.error %}

{{ cf_state.error.error }}

{% endif %} {% for r in cf_sources %}{% set s = stats.get(r.id) %} {% else %}{% endfor %}
WhatBackfill costState
{{ r.name }}
{{ r.pages }} pages read
{% if r.backfill_until %} {% if s and s.in_backfill %}in progress{% else %}backfill complete{% endif %} · cost US${{ '%.2f'|format(r.spent) }} {% if r.estimate and r.estimate.new %}
+{{ r.estimate.new }} pages to read ≈ US${{ '%.2f'|format(r.estimate.usd_new) }}{% endif %} {% elif r.estimate %}{{ r.estimate.pages }} pages ≈ US${{ '%.2f'|format(r.estimate.usd) }}
measured average cost per character (without comments); the batch and deferred synthesis tend to lower it {% elif cf_state.has_token %}calculating…{% else %}—{% endif %}
{% if r.error %}{{ r.error.error }}{% elif s %}{{ s.processed }} processed · {{ s.triaged_out }} discarded · {{ s.pending }} pending{% endif %}{% if s and s.in_backfill %}
in backfill {{ s.in_batch }} stages in the batch · synthesis deferred for {{ s.deferred }} entities{% endif %}
Nothing from Confluence on the allowlist.
{% if cf_state.has_token %}
{% if cf_state.at %}list from {{ cf_state.at|dt }}{% else %}the list appears after you save the token{% endif %}
{% if cf_state.space %} {% set sp = (cf_state.spaces|selectattr('key', 'equalto', cf_state.space)|list|first) %}
{% if (cf_state.space, None) in cf_state.added %}whole space on the allowlist {% else %}
{% endif %}
{% if cf_state.outline %}
{% for pg in cf_state.outline["items"] %}{% endfor %}
{{ '📁 ' if pg.folder }}{{ pg.title }} {% if (cf_state.space, pg.id) in cf_state.added %}on the allowlist{% else %}
{% endif %}
{% elif cf_state.space %}

loading the space's pages…

{% endif %} {% endif %} {% endif %}
{% if failed %}

Recent failures

{% for f in failed %}
#{{ f.id }} {{ f.kind }} · {{ f.finished_at|dt }} · {{ f.last_error }}
{% endfor %}
{% endif %}

Planned: Zoom.

{% endblock %}