# Daily Brief OS — one morning brief across everything you run

A sanitised reference implementation. Drop it into Claude Code, point it at your own
sources, adapt the summary prompt. Generic on purpose: no business specifics, no real
credentials.

## The idea

If you run more than one thing, the status you need is scattered. A bit in the bank, a
bit in the accounting tool, a bit in a spreadsheet, a bit in your inbox. Most mornings
start with you assembling that picture by hand before you can decide anything.

This layer does the assembly for you. Every morning, before you sit down, it pulls from
each source, writes a short plain language brief, and pushes it to one place you already
look. You read six lines instead of opening six tabs.

```
[source A] ┐
[source B] ┼──> [collect] ──> [summarise: what changed, what needs me] ──> push to phone
[source C] ┘
```

## Minimal reference implementation

The shape that matters is the collector contract. Each source is a small function that
returns a few facts. You add sources without touching the rest.

```python
# daily_brief.py — reference only. Swap in your own sources + LLM + push channel.

def collect():
    """Return a dict of source -> a few plain facts. Keep each collector tiny and
    independent, so one failing source never blocks the brief."""
    facts = {}
    for name, fn in SOURCES.items():
        try:
            facts[name] = fn()            # e.g. {"balance": 1234, "unpaid": 3}
        except Exception as e:
            facts[name] = {"error": str(e)}   # degrade, never crash the whole brief
    return facts

BRIEF_PROMPT = """You write a daily operator brief from the facts below.
Six lines maximum. Lead with anything that needs a decision today, then what changed
since yesterday, then a one line all clear if nothing is urgent. Plain language, no
filler, no metrics the operator did not ask for."""

def build_brief(facts, llm_text):
    return llm_text(system=BRIEF_PROMPT, user=json_dumps(facts))

def run(llm_text, push):
    facts = collect()
    brief = build_brief(facts, llm_text)
    push(brief)                            # Telegram, email, Slack, whatever you read

# register your own; each returns a small dict of facts
SOURCES = {
    # "bank":      lambda: {...},
    # "invoices":  lambda: {...},
    # "inbox":     lambda: {...},
}
```

Run it on a schedule so it lands before you wake up.

## Why it works

- **Independent collectors.** One source down degrades to a single error line; the brief
  still ships. No single point of failure.
- **Summarise, do not dashboard.** A dashboard makes you go and look. A brief comes to
  you and tells you what changed. Decisions come from the second one.
- **Push to where you already are.** The brief is worthless in a tool you have to open.
  Send it to the phone surface you check anyway.

## Adapt it

- Start with two sources, not ten. Add one a week as you notice what you keep checking
  by hand.
- Keep the prompt ruthless about length. The value is that it is short.
- Add a weekly variant that trends the daily facts, so you see drift as well as state.

Built for my own multi entity group, runs every morning before I am up; this is the
generalised version. Take it, wire in your own sources, tell me what you would add.
