Skip to content
Back to skills

Factory Trends

ASecurity

Turn your factory usage for a sprint into a short report you share with the factory's owner, with what you'd add, change or drop. A daily run reads the day before's numbers, names at most three trends, recommends one change and, with your yes, puts it to the team as tomorrow's pulse question. Reads your own local usage log, Claude Code's token counts, the loop's own records and the dashboard's numbers, and the sprint run reads the team's pulse counts. You read every report before it goes anyw...

  • 3 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 11, 2026
ai-agentspythongobashgitapi

Works with

  • claude code
  • cli
  • api

Security analysis

A100/100

Scanned November 11, 2026

npx -y skills add SanvioLabs/sanvio-harness-starter --skill factory-trends --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Factory Trends?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Factory Trends
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/sanviolabs-factory-trends/badge)](https://www.skillsdirectory.com/skills/sanviolabs-factory-trends)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: factory-trends
description: Turn your factory usage for a sprint into a short report you share with the factory's owner, with what you'd add, change or drop. A daily run reads the day before's numbers, names at most three trends, recommends one change and, with your yes, puts it to the team as tomorrow's pulse question. Reads your own local usage log, Claude Code's token counts, the loop's own records and the dashboard's numbers, and the sprint run reads the team's pulse counts. You read every report before it goes anywhere, and nothing goes to the pulse folder without your yes. Use at the end of a sprint, or when someone asks for "factory trends", "how did yesterday go", "what should we change in the factory", "my factory report", "what did I use this sprint", "sprint follow-up", "what should we add to the factory", "token burn", "how many tokens", or "what did the loop cost".
license: MIT. From Sanvio Factory by Sanvio Labs, https://github.com/SanvioLabs/sanvio-factory
---

# Factory trends

Each person's usage log stays on their own machine. This turns it into the one
thing that's shared: a short report, with the person's own proposals, that they
send to the factory's owner themselves. The report is gitignored and never
committed. The owner reads the sprint's reports together and decides what goes
into the factory.

The daily run is smaller. It compares yesterday with the six days before it,
recommends one change to the factory, and with the person's yes asks the team
about it in tomorrow's pulse. Its note stays in [`reports/trends/`](../../reports/trends/) on the
machine that wrote it, and the sprint report collects the notes and the team's
votes.

The log is written by [`.claude/hooks/usage_log.py`](../../.claude/hooks/usage_log.py). It holds names and counts,
never prompts, paths or code. The token counts come from Claude Code's own
transcripts on your machine, read by [`scripts/token_report.py`](../../scripts/token_report.py), which prints
only numbers, model names, session ids and issue names. The one dollar figure,
the loop's, comes from the estimate the loop records for each run. The plugin
list comes from `claude plugin list --json`, read by
[`scripts/plugin_report.py`](../../scripts/plugin_report.py), which prints each enabled plugin's id,
version and scope and no path.

## Steps

1. **Choose the run.** The sprint run is for a factory report, a sprint
   follow-up, tokens or the loop's cost, or any period longer than a day.
   Anything else is the daily run.

### Sprint run

1. **Pick the period.** Use the date of their last report in
   [`reports/usage/`](../../reports/usage/) (the newest file with their name) as the start. If there
   isn't one, ask how long their sprint is, and default to 14 days.
2. **Run the summary:**

   ```bash
   python3 scripts/usage_report.py --since <YYYY-MM-DD> --previous reports/usage/<their last report>
   ```

   Leave out `--previous` if there isn't a last report. With it, the summary
   adds an `Unused two sprints running:` line naming the skills on both that
   report's `Never used here:` line and this one's.

   If it says there's no log, tell them why it might be missing (the hook isn't
   wired, or `SANVIO_USAGE_LOG` is off) and stop. Don't guess at their usage.

   Then the tokens, from the same date:

   ```bash
   python3 scripts/token_report.py --since <YYYY-MM-DD>
   ```

   It reads Claude Code's own transcripts and prints tokens for conversations
   here, for each repo under [`projects/`](../../projects/) and for each issue the loop built,
   Claude Code only. It also prints each loop issue's cost as the loop recorded
   it: an estimate at API prices, not what was billed, low wherever a run
   recorded none, and counted by when the loop picked the issue up. A
   conversation's transcript carries no cost, so conversations stay in tokens.

   Then the plugins and mods, with their last report (step 1) to compare with:

   ```bash
   python3 scripts/plugin_report.py --previous reports/usage/<their last report>
   ```

   Leave out `--previous` if there isn't one. It lists the enabled plugins and
   mods and says which changed version, arrived or went since that report. If
   it can't read them it says so in a line, and the report carries that line.
3. **Show them the summary.** If it has an `Unused two sprints running:` line
   other than `none`, ask about each skill on it first, one at a time: drop it,
   keep it, or test it. For "test it", name the evals in `skill-creator` if
   that skill is installed, and otherwise say no eval skill is installed here.
   Don't run an eval. Record each answer under `## Proposals` in their words.
   If they skip, the line stays in the summary and nothing is recorded. Then
   ask, one at a time:
   - What worked well enough that the team should use it?
   - Where did you work around the factory: a skill you skipped, a guard you
     kept saying yes to, a step you did by hand?
   - One or two proposals. For each: add, change or drop what, and why.
   Use their words. Point at the numbers where they back a proposal up ("asked
   12 times, said yes 12 times" argues for loosening that ask). Don't invent a
   proposal they didn't make.
4. **Review what changed, if they own this factory.** Ask once: "Do you own
   this factory?" On a no, or if the plugin output has no `Changed since` line,
   skip this step. On a yes, run `stelliad:review-skill` on the installed folder
   of each changed or new plugin, or [`skills/review-skill/`](../review-skill/SKILL.md) where Stelliad isn't
   installed. Read each folder from `claude plugin list --json` yourself, and
   never put it in the report. There is no old version on disk to diff against,
   so the review reads the whole folder and its changelog if it has one. The
   findings go under `## Changed plugins` in the report. Don't ask again for
   this report, and don't record the answer.
5. **Write the report** to `reports/usage/<YYYY-MM-DD>-<user>.md`: the summary
   as printed, then a `## Tokens and loop cost` section with the token summary
   as printed, then the plugin output as printed (it starts with its own
   `## Plugins and mods` heading), then `## Changed plugins` if step 4 ran,
   then a `## Daily recommendations` section, then a `## Proposals` section
   with their answers. Leave nothing unfilled.

   `## Daily recommendations` lists each file in [`reports/trends/`](../../reports/trends/) dated in
   the period, one line each, with its date and its recommendation. Then the
   team's vote on it, if the pulse skill's step 1 finds the `Pulse folder` row
   in `company/DATA.md` cleared. Run, from the period's start to today:

   ```bash
   python3 scripts/pulse.py summary --since <YYYY-MM-DD> --until <YYYY-MM-DD>
   ```

   For each file, find the summary entry headed
   `## <the file's date plus one day>: Factory`, or
   `## <that date>: trend-<that date>` for a question since removed from the
   bank. Copy that entry's option counts. Write
   `Fewer than three answered.` where the summary says that, and `No answers.`
   where there's no entry. The skill never copies an Other answer. If the row
   isn't cleared, list the recommendations and write
   `Pulse folder not cleared.` once, under them.
6. **Have them read it.** It's going to the owner. They can cut anything.
7. **Say how to share it:** they send the file to the factory's owner
   themselves, the way the team passes documents around. It stays in
   [`reports/usage/`](../../reports/usage/) on their machine, gitignored, where step 1 finds it next
   sprint.

### Daily run

Dates are written `YYYY-MM-DD`: today, yesterday, and tomorrow, the day the
question would be asked.

1. **Check the report is ignored.** Run:

   ```bash
   git check-ignore -q reports/trends/<today>.md
   ```

   On a non-zero exit, say the file isn't ignored, write nothing, and stop.
2. **Get the numbers.** Run, with the day 7 days before today:

   ```bash
   python3 scripts/dashboard_data.py --json --since <YYYY-MM-DD>
   ```

   Compare only the `by_day` entries in `loop_history`, `loop_spend` and
   `conversations` (its `factory` and `loop` sides each have one). Yesterday's
   entry is compared against the sum of the six entries before it, never
   today's: today isn't over. A day in `loop_spend` whose `cost_usd` is `null`
   is named, not summed. `activity` and `loop_rework` are cited only as totals
   for the period, never as a trend. A section whose `value` is `null` is named
   with its `why`, and nothing is filled in for it.
3. **Name the trends.** At most three, each one sentence giving yesterday's
   figure and the six days' sum. In two cases say `No trend yesterday.`, write
   the report (step 7) with that line and `Proposed: no, no trend`, and stop:
   - every compared section is `null`
   - every compared field is 0 or `null` both yesterday and across the six days
4. **Recommend one change.** Add, change or drop one thing in the factory,
   named as people say it (for example "the pulse skill"), never by its path,
   and say which trend it answers. Never more than one.
5. **Draft the question** in the bank's format, and show it exactly as it will
   be written:

   ```text
   ## trend-<tomorrow>
   Chip: Factory
   Question: <Should we make the change, in one line?>
   - Yes: Make this change
   - Not yet: Ask again later
   - No: Leave the factory as it is
   ```

   The `Question:` line is one line naming only the change, with no figure,
   title, project name or issue name. There's no `Date:` line: `propose`
   refuses a file with one, and takes the date from `--date`.
6. **Propose it.** Only when the pulse skill's step 1 finds the
   `Pulse folder` row in `company/DATA.md` cleared, and the person says yes to
   this one step. If the row isn't cleared, say so and propose nothing. On a
   yes:
   - Write the question to `local-data/pulse-proposal.md` with the Write tool.
   - Run:

     ```bash
     python3 scripts/pulse.py propose --file local-data/pulse-proposal.md --date <tomorrow>
     ```

   - Delete `local-data/pulse-proposal.md` whether or not `propose` succeeded.
   - On a non-zero exit, show the reason it gave and don't retry.
7. **Write the report last** to `reports/trends/<today>.md`. It holds the
   trends, the recommendation and the question, and ends `Proposed: yes` or
   `Proposed: no, <reason>`. The reason is one of: not cleared, declined, or
   the reason `propose` gave.

## For the owner

Read the sprint's reports together, not one at a time. A pattern across
people is the signal: the same skill never used, the same ask answered yes
every time, the same workaround. For each proposal you take, make the change
in its own PR with a [`CHANGELOG.md`](../../CHANGELOG.md) entry, so "what's new" tells everyone. For
one you don't, tell its author why.

## Rules

- Never read or quote another person's log. Each report comes from its
  author's own machine.
- Never add a prompt, a file path, a command or code to the report, even if
  they mention one. Describe it instead ("a deploy script", not the script).
- Never commit anything under `.sanvio/`. The raw log stays local.
- Never commit a report, force-add it, or send it anywhere. It's gitignored,
  and the author sends it.
- A drafted question never holds a figure, a title, a project or issue name, a
  prompt, a file path, a command or code.
- A daily report holds no prompt, file path, command or code.
- Never run `propose` without a yes given in this session, and never write to
  the shared folder any other way.

## Output

For the sprint run, the report file, read by its author, and the commands that
share it. For the daily run, the note in [`reports/trends/`](../../reports/trends/), and the
question in tomorrow's pulse if the person said yes.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

View all in ai-agents →

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.