agentleFS
marcogallucciomarcogalluccio/company-brain-os/skills/daily-briefing/SKILL.md

daily-briefing

Skill7 starsChanged 48 days agoMITView on GitHub

Daily operational briefing built from memory and the last 5 logged days of daily logs, read-only on project files except for backstopping today's log. Use when the operator says: briefing, /daily-briefing, morning briefing, what matters today.

35 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use crm-lookup, spotify and 10 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • QuixiAISkill

    crm-lookup

    Search, view, update, and merge contacts in the local CRM

    Also in 3 projects that use this

  • QuixiAISkill

    spotify

    Search Spotify, inspect current playback and devices, and control playback with explicit approval

    Also in 3 projects that use this

  • MicrosoftSkill

    inbox-triage

    Use this skill whenever the user asks to clean up, triage, declutter, or archive low-value Outlook inbox mail - "clean up my inbox", "triage my mail", "declutter my inbox", "sort out newsletters", "archive old resolved threads", "/inbox-triage" - to group only newsletters, auto-notifications, past-event meeting logistics, resolved threads, and redundant duplicates into reviewable move-proposals presented for per-bucket approval before any message moves. Do not use for reading mail, drafting or sending replies, deleting mail, executing moves without explicit per-bucket approval, or acting on messages from the user's manager, direct reports, active threads, flagged mail, or labelled/HR/Legal/Finance/Security senders.

    Also in 4 projects that use this

  • MicrosoftSkill

    image-gen

    Also in 3 projects that use this

  • AnthropicSkill

    weather

    The optional standing status report ("the weather"): compile open incidents, build health, merge-queue stats, and deploy lag into one always-current report page, and post to the channel only when a defined event fires. Use when the weather routine fires, or when someone asks to run/update the weather report.

    Also in 3 projects that use this

  • SentrySkill

    notion

    Search, fetch, create, update, and move Notion pages and data sources. Use when users ask to look up docs, specs, notes, meeting notes, project context, roadmaps, trackers, or internal references stored in Notion, or when they explicitly ask to create or edit Notion content.

    Also in 3 projects that use this

  • +2 more from QuixiAI

The file

We split this skill into the rules it gives an agent

11 rules. 0 are common, 6 are distinctive, and 5 are very specific to this project.

  • 0

    Common

    Most of the 32 edited versions we read keep these.

  • 6

    Distinctive

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Read what memory and the last few logged days already know, and turn it into one page of "what matters today." This skill is read-only on …

    line 12
  2. Distinctive:

    Run the steps in order.

    line 23
  3. Very specific:

    Advanced layer, if adopted: If the team has adopted docs/ADVANCED.md, project files carry salience and last_touched frontmatter fields.

    line 125
  4. Very specific:

    Check the state before promoting: Before an open thread goes to Today, read the current state of the thing it names: the project file's ## …

    line 210
  5. Distinctive:

    If the team has calendar or email MCP connectors, fetch today's events and unanswered threads into Today or Watch.

    line 260
  6. Distinctive:

    No item appears in more than one section.

    line 281
  7. Very specific:

    Write the briefing to ${TMPDIR:-/tmp}/brain-briefing.html using the standard template from skills/html-preview/SKILL.md (title "Daily …

    line 291
  8. Very specific:

    If the check reports the file is missing, create it with the Write tool (not a heredoc, to match how every other skill writes file content) …

    line 330
  9. Distinctive:

    Never overwrite an existing file.

    line 345
  10. Distinctive:

    Omit empty sections: Do not render a heading with nothing under it.

    line 365
  11. Distinctive:

    Ask instead of guessing: When a project's status is ambiguous, or a daily-log bullet is not clearly resolved or still open, say so and ask …

    line 368

“Common” is measured: kept by at least 6 in 10 of the 32 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Daily Briefing

Read what memory and the last few logged days already know, and turn it into one page of "what matters today." This skill is read-only on memory/ and daily-log/ with one narrow exception: if today's log does not exist yet, it creates the empty skeleton so the file is there even on a day that starts with a briefing and nothing else.

The briefing is written FOR the current operator, but it reads every operator's daily logs, not just their own: this is a shared workspace, and a handoff sitting in a teammate's log two days ago is exactly the kind of thing a briefing exists to bring forward.

Run the steps in order.


Step 0: Resolve the operator

cd "$(git rev-parse --show-toplevel)"
GIT_NAME="$(git config user.name)"
if [ -z "$GIT_NAME" ]; then
  echo "IDENTITY ERROR: git config user.name is empty. Set it as described in operators/ONBOARDING.md Step 4."
  exit 1
fi
MATCHES=""
for f in operators/*.md; do
  case "$f" in
    operators/CLAUDE.md|operators/ONBOARDING.md|operators/operator_template.md) continue ;;
  esac
  if awk '/^---$/{if(f)exit;f=1;next} f' "$f" | sed 's/^[[:space:]]*//' | grep -qxF -- "- $GIT_NAME"; then
    MATCHES="$MATCHES $f"
  fi
done
N=$(echo $MATCHES | wc -w | tr -d ' ')
if [ "$N" != "1" ]; then
  echo "IDENTITY ERROR: git user.name \"$GIT_NAME\" matches $N operator files:$MATCHES"
  echo "Exactly one operators/<slug>.md must claim this value in git_names."
  echo "Fix your identity or the registry (see operators/CLAUDE.md), then rerun."
  exit 1
fi
SLUG="$(basename $MATCHES .md)"
TODAY="$(date +%Y-%m-%d)"
echo "operator=$SLUG today=$TODAY"

On IDENTITY ERROR, stop the skill and show the message to the operator as it came out. Do not continue with a guessed slug, and do not invent one from the git name. The registry rule in operators/CLAUDE.md is binding:

Resolve the active operator by matching git config user.name against every registry file's git_names. Exactly one match: proceed. Zero or multiple matches: stop and tell the user how to fix their identity or the registry. Never guess, never derive a slug from the name itself.

SLUG and TODAY from this step drive Step 2's prioritization (whose open threads count as "own") and Step 6's backstop filename.


Step 0.5: Freshness check

A briefing built from a stale local copy of memory/ is worse than no briefing: it reports state a teammate already changed on origin. Check before reading anything.

if ! git remote get-url origin >/dev/null 2>&1; then
  echo "NO-REMOTE: local-only brain, nothing to compare against."
elif git fetch origin main --quiet; then
  AHEAD=$(git rev-list --count origin/main..HEAD)
  BEHIND=$(git rev-list --count HEAD..origin/main)
  echo "ahead=$AHEAD behind=$BEHIND"
  if [ "$AHEAD" -gt 0 ] && [ "$BEHIND" -gt 0 ]; then
    DUP=$(git cherry origin/main HEAD | grep -c '^-' || true)
    echo "diverged: $DUP of $AHEAD ahead commit(s) are patch-identical to commits already on origin"
  fi
else
  echo "FETCH FAILED: could not reach origin; freshness unknown."
fi
  • BEHIND > 0: recommend running /sync before trusting this briefing. Local memory/ is stale.
  • AHEAD > 0 and BEHIND = 0: note in the briefing that local main is ahead by N commits (a deferred push from an earlier session, most likely), so the shared copy does not have it yet.
  • AHEAD > 0 and BEHIND > 0: local main has diverged, and "ahead" no longer means "not on origin". Never report those commits as missing from the shared copy. The diverged: line counts the ones git already recognizes as duplicates of commits on origin: report them as "duplicates, will drop on realign". The rest may well be on origin too, under different hashes (the usual residue of a push through a temporary worktree), which only a check by content can tell: recommend /sync, which verifies each commit by content before proposing anything. Never recommend a rebase from the briefing.
  • FETCH FAILED: say plainly that freshness could not be checked. Never treat a failed fetch as "up to date": that reads the last successful fetch's state, which may be hours or days old, as current.

This step is read-only. It never fetches to change anything, only to compare.


Step 1: Read memory

memory/MEMORY.md is the primary source. If it has a ## Areas section, the team runs federated memory roots (docs/ADVANCED.md section 8): read every area MEMORY.md it points to as well, and treat their rows like the primary's. Without that section there is one index and nothing changes. For every 🔴 or 🟠 row, read the linked project file and pull its ## Status, ## Next action, and deadline frontmatter (if set). Skip memory/*_template.md and any file whose stem ends in _example, per the shipped convention.

Advanced layer, if adopted. If the team has adopted docs/ADVANCED.md, project files carry salience and last_touched frontmatter fields. Rank the top 5 by live salience and open the briefing with a "Top 5 now" list ahead of the Today section. Take the numbers from the sweep script when it is available (read-only, writes nothing):

cd "$(git rev-parse --show-toplevel)"
if command -v python3 >/dev/null 2>&1 && [ -f scripts/salience_sweep.py ]; then
  python3 scripts/salience_sweep.py | python3 -c '
import json, sys
d = json.load(sys.stdin)
for s in sorted(d["scores"], key=lambda s: (-s["computed"], s["file"]))[:5]:
    computed, root, file = s["computed"], s["root"], s["file"]
    print(f"{computed} {root}/{file}")
'
else
  echo "sweep script unavailable: recompute by hand with the formula in docs/ADVANCED.md"
fi

Without the script, apply the formula by hand to every project file; the result must be the same numbers. If those fields are not present, the team has not adopted the layer: skip this silently, with no mention of it anywhere in the output.


Step 2: Read the last 5 logged days

"Last 5 logged days" means the 5 most recent dates that actually have a log file, not the 5 calendar days ending today. In a workspace with a logging gap, those two are not the same thing, and there is no portable way to close that gap by computing calendar dates (the portability rule bans date -d, date -v, and date -j). Say what this actually selects, not what it would select if every day had a log.

cd "$(git rev-parse --show-toplevel)"
DATES="$(ls daily-log/ 2>/dev/null \
  | grep -E '^[0-9]{4}-[0-9]{2}-[0-9]{2}-.+\.md$' \
  | sed -E 's/^([0-9]{4}-[0-9]{2}-[0-9]{2})-.*/\1/' \
  | sort -u | tail -5)"
for d in $DATES; do
  for f in daily-log/${d}-*.md; do
    [ -f "$f" ] && echo "$f"
  done
done
PREV_LOGGED="$(printf '%s\n' $DATES | awk -v t="$TODAY" '$0 < t' | tail -1)"
echo "previous_logged_day=${PREV_LOGGED:-none}"

DATES is a date filter, not an operator filter: read every file each date produces, regardless of whose slug is in the filename, per the shared-workspace awareness noted above. PREV_LOGGED is the most recent logged date strictly before TODAY, found by plain string comparison on the ISO-formatted dates (which sorts chronologically with no arithmetic); empty means no earlier log exists yet, on a brand-new brain.

Staleness check. Compare PREV_LOGGED to TODAY yourself, as two ISO date strings already in hand: deciding whether they are consecutive calendar dates needs no date command, just reading them. If they are not consecutive (any gap, even one day), say so plainly at the very top of the briefing, before anything else, e.g. "most recent prior log is YYYY-MM-DD, the workspace has a logging gap." Never let an old thread from a gapped log read as fresh just because it happened to be selected into this window.

Extract, in priority order, and tag every item with its source date (the YYYY-MM-DD the filename it came from):

  • ## Open threads bullets, tagged with their source date: candidates for Today. Prioritize bullets from the current operator's own file (daily-log/*-${SLUG}.md) first.
  • Bullets in another operator's log that name the current operator by name or slug (a cross-operator handoff, e.g. "waiting on jane to send..."), tagged with their source date: Today, since it names someone specific to act on it.
  • ## What happened bullets from the file at PREV_LOGGED (any operator), tagged with that date: the Previous logged day recap. If PREV_LOGGED is empty, there is nothing to recap.
  • An open thread that reads as substantially the same item across 2 or more of the window's logged dates (same operator repeating it day to day, or the same blocker named by two different operators), tagged with its earliest source date: flag 🔴 stuck rather than routing it to Watch as a fresh item.

Check the state before promoting. Before an open thread goes to Today, read the current state of the thing it names: the project file's ## Status and ## Updates (not only its index line), or the artefact's own status file when the thread names one. A thread logged late in a day is often closed by a later session the same day, and the log never says so. Closed there: drop it. Unclear: route it to Watch, not Today.

Teammates since your last logged day. What the other operators pushed while you were away is the part of the brain you cannot know without asking, so the briefing asks. The window opens on the most recent date in DATES where you (SLUG) actually logged (MINE, recomputed here since it needs your own slug specifically, not any operator's) and falls back to a fortnight; the fetch already ran in Step 0.5, so this is read-only on what it brought. Skip the block silently when Step 0.5 printed NO-REMOTE, and skip it too, saying so in the briefing, when it printed FETCH FAILED: a stale origin/main would misreport what a teammate actually pushed.

. scripts/lib/operator-registry.sh
MINE="$(printf '%s\n' $DATES | while IFS= read -r d; do [ -f "daily-log/${d}-${SLUG}.md" ] && echo "$d"; done | awk -v t="$TODAY" '$0 < t' | tail -1)"
SINCE="${MINE:-14 days ago}"
while IFS= read -r f; do
  OSLUG="$(basename "$f" .md)"
  [ "$OSLUG" = "$SLUG" ] && continue
  set --
  while IFS= read -r NAME; do [ -n "$NAME" ] && set -- "$@" --author="$NAME"; done < <(operator_git_names "$OSLUG")
  [ "$#" -eq 0 ] && { echo "TEAMMATE $OSLUG: no git_names in the registry"; continue; }
  N="$(git log origin/main "$@" --since="$SINCE" --oneline 2>/dev/null | wc -l | tr -d ' ')"
  MEM="$(git log origin/main "$@" --since="$SINCE" --name-only --pretty=format: 2>/dev/null | grep -E '^(memory/|areas/[^/]+/memory/)' | sort -u | tr '\n' ' ')"
  DATES_NOLOG="$(git log origin/main "$@" --since="$SINCE" --date=short --pretty=format:'%ad' 2>/dev/null | sort -u | while IFS= read -r d; do
      [ -n "$d" ] || continue
      if [ -f "daily-log/${d}-${OSLUG}.md" ]; then continue; fi
      if git ls-tree -r --name-only origin/main -- "daily-log/${d}-${OSLUG}.md" 2>/dev/null | grep -q .; then continue; fi
      echo "$d"
    done | tr '\n' ' ')"
  echo "TEAMMATE $OSLUG since $SINCE: $N commits; memory files: ${MEM:-none}; dates with commits and no log: ${DATES_NOLOG:-none}"
done < <(registry_files)

Render it as one "Teammates" line per operator in the Notes section (or in Today, when a teammate touched a memory file you are about to update, since your debrief would otherwise write over their change). A date with commits and no log is worth one line in Watch, with a ready-to-send note: "you pushed on <date> and I cannot find daily-log/<date>-<slug>.md; could you note in your next log what those commits were for?" Send it or not: the operator's call.


Step 3: Optional connectors

If the team has calendar or email MCP connectors, fetch today's events and unanswered threads into Today or Watch. Skip silently when none are configured: no errors, no placeholder sections.


Step 4: Prioritize

Sort what Steps 1 through 3 gathered into sections. Every item carries the source date Step 2 tagged it with:

  • Today (max 5-7 concrete actions, most urgent first): 🔴 memory projects first, then the current operator's own open threads, then items flagged 🔴 stuck, then anything else that is actionable today.
  • Watch: monitoring items, anything waiting on an external reply, 🟠/🟡 memory projects that need attention soon but not today.
  • Previous logged day (PREV_LOGGED): the recap pulled in Step 2. Omit this section entirely when PREV_LOGGED is empty.
  • Upcoming: items with a deadline in memory within the next 30 days.
  • Notes: context that does not fit above but is worth keeping visible.

No item appears in more than one section. Omit any section with nothing in it rather than showing it empty. An item waiting on someone else's reply is a Watch item, not a Today action: "waiting" is a status, not a task. If Step 2 flagged a staleness gap, that notice leads the briefing ahead of every section below, not folded into one of them.


Step 5: Render

Write the briefing to ${TMPDIR:-/tmp}/brain-briefing.html using the standard template from skills/html-preview/SKILL.md (title "Daily Briefing"; do not duplicate its <style> block here, reference it and reuse it as-is). Order: the staleness notice from Step 2 first, if any; then the optional "Top 5 now" list from Step 1 when the advanced layer is adopted; then Today, Watch, Previous logged day (PREV_LOGGED), Upcoming, Notes, each only if it has content.

FILE="${TMPDIR:-/tmp}/brain-briefing.html"
cat > "$FILE" <<'HTML'
<!-- the rendered briefing, using the standard html-preview template -->
HTML

Open it with the portable open block:

( open "$FILE" 2>/dev/null || xdg-open "$FILE" 2>/dev/null || start "" "$FILE" 2>/dev/null ) \
  || echo "Open this file in your browser: $FILE"

Then close with a 3-line chat summary: how many actions are in Today, how many are urgent (🔴), and anything odd worth flagging (a stale sync, a fetch failure, an ambiguous project status that got skipped rather than guessed).


Step 6: Backstop today's log

LOG="daily-log/${TODAY}-${SLUG}.md"
if [ -f "$LOG" ]; then
  echo "BACKSTOP: $LOG already exists, left untouched"
else
  echo "BACKSTOP: creating $LOG"
fi

If the check reports the file is missing, create it with the Write tool (not a heredoc, to match how every other skill writes file content) using the exact skeleton daily-log/CLAUDE.md defines, with ${TODAY} and ${SLUG} substituted for the literal values Step 0 printed:

# ${TODAY} - ${SLUG}

## What happened

## Decisions

## Open threads

Never overwrite an existing file. If Step 6 finds one already there, an earlier session today (a debrief, a meeting debrief, or an earlier briefing) already owns it, and this step is a no-op.


Rules

  • Read-only, with exactly one exception: the log backstop in Step 6. This skill never creates or edits a memory file, never edits another operator's log, and never writes anything into today's log beyond the empty skeleton.
  • Lookback is the last 5 logged days, the most recent dates that actually have a log file, not a 5-calendar-day window. A logging gap can pull old threads into that window, which is why every extracted item carries its source date and a gap before PREV_LOGGED gets flagged at the top rather than presented as fresh.
  • Max 5-7 items in Today. Prioritize ruthlessly; move the rest to Watch or Notes rather than padding Today past what is actually urgent.
  • No duplicates across sections. Each item appears exactly once.
  • Omit empty sections. Do not render a heading with nothing under it.
  • Graceful degradation. Missing calendar/email connectors produce silence in Step 3, never an error and never an empty section.
  • Ask instead of guessing. When a project's status is ambiguous, or a daily-log bullet is not clearly resolved or still open, say so and ask rather than placing it in a section on a guess.
  • English for all output, regardless of the language a source log or memory file was written in.

Self-improvement

At the end of the run, check it against these friction triggers: avoidable round-trip · improvisation · breakage · token waste · operator correction (full definitions in skills/_improvements/capture.md). If at least one fired, ask the operator "there was friction on X, should I log it?"; on their ok, append an entry to skills/_improvements/friction-log.md in the format capture.md defines. Clean run: say nothing. Never self-edit this skill; improvements go through /skill-improve.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.