Skip to content

Reports ​

Reports is a feed of results. Agents and scripts post a report when they finish a piece of work - a markdown summary, a chart, a CSV - and Clusto keeps it in one place instead of leaving it buried in terminal output. When a scheduled task run fails or times out, the daemon posts an Error report on its own, so a broken automation shows up as a red card rather than a silent exit code.

A report has a title, a level (Info, Success, Warning, or Error), an optional markdown body, optional attachments, and optional tags. Reports posted from inside a task run are linked to that task and run automatically; reports posted from inside a terminal session are linked to that session's project.

The Reports view ​

Route: /reports (a single report opens at /reports/<id>). The Reports item in the navigation shows a badge with the number of unread reports.

  • Inbox - All, Unread, Pinned, and Archived.
  • Search - matches the title, body, task name, and tags (case-insensitive).
  • Filters - open the Filters sheet to narrow by level (pick any mix of Info, Success, Warning, Error), project, task, tag, time (last 24 hours, 7 days, 30 days), who posted it (agents and scripts, or system notices), and, in a cluster, the node that stores it. Active filters show as chips under the search box; tap a chip to remove it. Reset filters clears them all.
  • Group by - none, Project, Task, or Day. Each group header shows its count, its unread count, and a Mark read button.
  • The search, inbox, filters, and grouping live in the page URL, so the back button and links keep them.
  • Cards - each card shows the level, title, project, task name, the node that stored it (when you are connected to a cluster), the time, and its tags. Reports the daemon posted itself carry a System badge. Tap a tag to show only reports with that tag.
  • Expand a card to read the body and see its attachments.
  • Actions - mark read or unread, Pin (pinned reports are never pruned), and Archive. The More menu holds Edit tags, Copy body, Copy report ID, All reports of this task, Open session (while the session that posted it is still running), and Delete.
  • Mark all read clears the unread badge in one go. While a search or filter is active it reads Mark shown read and only marks the matching reports.

Archive ​

Archiving takes a report out of the feed and the unread count without deleting it. Archived reports are listed under the Archived inbox, where search and filters work as usual, and Unarchive moves one back. Archived reports follow the normal retention rules below; pin a report to keep it.

Select several reports ​

Tap Select in the header to show a checkbox on every card. A bar at the bottom then acts on the selection: Read or Unread, Pin, Archive or Unarchive, and Delete (with a confirmation). Select all takes every loaded report.

Tags ​

Tags are short lowercase labels such as nightly or prod. Add them when posting (--tag, or tags in MCP) or later with Edit tags on a card. Spaces become dashes, a report holds at most 10 tags, and each tag is at most 32 characters.

In a cluster the feed merges reports from every node, so you see all results in one list regardless of which node ran the task.

Body and attachments ​

  • The body is rendered as markdown. A fenced code block tagged mermaid renders as a diagram. Raw HTML in the body is escaped, not rendered.
  • Image attachments (PNG, JPEG, GIF, WebP, SVG) render inline; tap or click one for a full-size preview. Any other file (CSV, PDF, logs, archives) is offered as a download.

From a task ​

Each row in the Tasks view has a Show reports button that opens the feed filtered to that task.

Notifications ​

A new report posted by an agent or script raises a toast while you are using the app, and a system notification while the app is in the background. Tap it to open the report. On Android, background notifications also deliver reports while the app is closed.

Choose which reports alert you in Settings -> Notifications -> Reports:

  • All reports, Warnings and errors, Errors only, or Off as the default.
  • Per-project overrides - give one project a different rule, for example errors only for a noisy project and all reports for the one you watch. The same control is in the project's edit dialog.

These rules belong to the device, so your phone and your desktop can differ. They apply to the in-app toast, the system notification, and Android background notifications. Automatic failure notices are not affected; they follow each task's own Notify on failure setting.

F1 command palette ​

  • Go to Reports
  • Show archived reports
  • Report notification settings
  • Mark all reports read
  • Show reports for <task> - one command per task
  • Inside the Reports view: Search reports, Filter reports, Select reports, Show error reports, Clear report filters, the inbox views (all, unread, pinned, archived), Group reports by project / task / day, Ungroup reports, and Refresh reports

Posting reports from the CLI ​

bash
clusto report post --title "Nightly build" \
  [--body TEXT | --body-file PATH|-] \
  [--level info|success|warning|error] \
  [--attach PATH ...] [--tag TAG ...] \
  [--task UUID] [--run UUID] [--project UUID] [--json]
  • --body takes markdown inline; --body-file reads it from a file, or from stdin with -.
  • --level defaults to info.
  • --attach can be repeated to attach several files.
  • --tag can be repeated (at most 10 tags).
  • --task and --run link the report explicitly. Inside a task run they default to the ids the daemon provides (see below).
  • --project groups the report under a project. It defaults to CLUSTO_PROJECT_ID, and otherwise to the project of the terminal session the command runs in.
  • --json prints the stored report as JSON; otherwise the command prints the report id and attachment count.

Change or extend a report you posted earlier:

bash
clusto report update <REPORT_ID> [--title TEXT] [--body TEXT | --body-file PATH|-] [--level LEVEL] [--tag TAG ...]
clusto report attach <REPORT_ID> <FILE>...

--tag on update replaces the report's tags.

Search the feed from a script or agent:

bash
clusto report ls [--query TEXT] [--level LEVEL ...] [--task UUID] \
  [--project UUID] [--tag TAG] [--unread] [--archived] [--limit N] [--json]

Each line shows the report id, level, UTC time, title (a leading * marks an unread report), task name, and tags. --limit defaults to 20.

A long-running job can post an Info report when it starts and later update it to Success or Error with the final numbers.

Inside a scheduled task ​

Every task session gets these environment variables from the daemon:

VariableMeaning
CLUSTO_TASK_IDThe task that is running
CLUSTO_TASK_RUN_IDThis specific run
CLUSTO_PROJECT_IDThe task's project (only when it has one)

The daemon also sets the local connection details (socket and token), so clusto report post inside a task needs no host, token, --task, or --run flags - the report is linked to the run automatically.

MCP server for agents ​

clusto report mcp serves the same operations as MCP tools over stdio:

ToolDoes
report_postPost a new report (title, body, level, attachments, tags)
report_updateChange the title, body, level, or tags of an earlier report
report_attachAttach more files to an earlier report
report_listSearch earlier reports (query, level, tag, limit), for example to compare with the last run

Wire it into a Claude task command like this:

bash
claude -p "Summarize today's error logs and post a report" \
  --mcp-config '{"mcpServers":{"clusto-report":{"command":"clusto","args":["report","mcp"]}}}'

Any agent that can run shell commands can also call clusto report post directly instead of using MCP.

clusto guide reports and clusto guide mcp print the same instructions in an agent-friendly form, including install commands for Claude Code and Codex.

Automatic failure notices ​

When a scheduled run fails or times out and no retry is pending, the daemon posts an Error report marked System. It contains the exit code, the attempt number, the run duration, and the tail of the captured output (about 4 KB). Runs that will still be retried do not post a notice; only the final failure does.

Example: daily app-usage stats ​

Create a task on the node that has access to your analytics:

  • Schedule: cron 0 0 8 * * * (every day at 08:00 UTC; task cron has a seconds field)
  • Command:
bash
claude -p "Pull yesterday's app usage stats, render a daily-users chart to \
usage.png, then call report_post with a short summary as the body and \
usage.png attached. Use level success, or warning if usage dropped more than 20%." \
  --mcp-config '{"mcpServers":{"clusto-report":{"command":"clusto","args":["report","mcp"]}}}'

Each morning a new card appears in Reports with the summary and the chart inline. If the agent crashes, the stats source is down, or the run hits its timeout, the daemon's automatic notice shows up as a red Error card with the end of the output, so you know the report is missing and why.

The same thing works without an agent - a plain script can render the chart and post it:

bash
./collect-stats.sh > summary.md && \
  clusto report post --title "App usage $(date +%F)" \
    --body-file summary.md --level success --attach usage.png

Limits and retention ​

LimitValue
Title200 characters
Body256 KB
Attachment size10 MB each
Attachments per report20
  • Unpinned reports older than 90 days are pruned.
  • At most 100 unpinned reports are kept per task; older ones are pruned first.
  • Pinned reports are never pruned. Archiving does not protect a report from pruning; pinning does.

Storage ​

A report is stored on the node that received it. Attachments are saved as files under reports/ in the daemon's data directory. Reports are not replicated between nodes; the app queries every node and merges the results into one feed, so reports from an offline node reappear when it reconnects.

Clusto - remote AI coding agents over WebSocket.