agentsclimarketplace

Sync

Skill eliransu/digital-brain/skills/sync

Claude + Obsidian knowledge companion. A persistent, compounding wiki vault based on Karpathy's LLM Wiki pattern — drop sources, ask questions, knowledge compounds.

Install
npx -y skills add eliransu/digital-brain --skill sync

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Pull mentions, DMs, hot channel topics, calendar events, and Linear updates from the last 48h (24h for Slack DMs) into the wiki daily folder, and snapshot active vault notes. Sources: Gmail, Slack, Linear, Google Calendar, local `wiki/notes/`. Creates `wiki/daily/<YYYY-MM-DD>/{mentions.md, topics.md, linear.md, calendar.md, notes.md}`. If the date folder already exists, dedupes by stable ID and appends new items under an `## Update <HH:MM>` section. Prints all collected items as bullets in chat. Triggers on: "/digital-brain:sync", "/sync", "sync my day", "pull mentions", "what did I miss".

SKILL.md

15.0 KB, as published. Nobody here has run it

sync: Daily Mentions + Hot Topics Sync

Pull everything that needs your attention from the last 48h across Gmail, Slack, Linear, Calendar into the wiki daily folder. Surface as bullets in chat at the end.

User identity: [email protected] (Slack handle resolved from this).


Scope

SourceWhat to pullWindowFiled under
GmailThreads where you is in To/Cc OR appears in body as a mention48hdaily/<date>/mentions.md
Slack@your-handle mentions in any public/private channel48hdaily/<date>/mentions.md
Slack@your-handle mentions in groups (group DMs / mpdm)48hdaily/<date>/mentions.md
SlackDMs received from any user24hdaily/<date>/mentions.md
SlackHot topics from configured channels (high reply or reaction count)48hdaily/<date>/topics.md
LinearIssues assigned to you (any status except Done/Canceled)opendaily/<date>/linear.md
LinearComments mentioning you48hdaily/<date>/linear.md
CalendarEvents you is invited tonext 48hdaily/<date>/calendar.md
NotesActive vault notes (status: open, not expired) — from wiki/notes/opendaily/<date>/notes.md

Config

Read wiki/daily/_config.json. If missing, create it with:

{
  "user_email": "[email protected]",
  "slack_user_handle": "your-handle",
  "slack_hot_channels": ["CXXXXXXXXXX", "CXXXXXXXXXX"],
  "calendar_id": "primary",
  "linear_user_email": "[email protected]",
  "linear_default_team_key": "TEAM",
  "linear_default_team_id": "",
  "linear_user_id": ""
}

linear_default_team_key / linear_default_team_id / linear_user_id are used by /task and the notes sweep. The two _id fields start empty and get cached after the first MCP lookup.

Config is the source of truth for which channels count as "hot". User edits this file to add/remove channels.


Workflow

  1. Compute time windows. Use date (Bash) or built-in date math.

    • today = YYYY-MM-DD in local time
    • since_48h_iso = now - 48h in RFC3339 UTC
    • since_24h_iso = now - 24h in RFC3339 UTC
    • next_48h_iso = now + 48h in RFC3339 UTC
  2. Load or scaffold config. Read wiki/daily/_config.json. If missing, write the default above and proceed.

  3. Resolve user IDs once.

    • Slack: slack_search_users with query your-handle → cache the user ID
    • Linear: list_users filtered by email [email protected] → cache the user ID
  4. Sweep expired notes. Before pulling anything else, scan wiki/notes/*.md. For each file where status: open and today > expires (date compare), flip status: expired and bump updated: to today. Drop those rows from wiki/notes/_index.md. Cheap, idempotent, runs every sync.

  5. Pull from all sources in parallel (issue tool calls in one assistant turn).

    Token discipline (mandatory). Every Slack call MUST pass response_format: "concise" and include_context: false. Context chains account for >half the token cost of /sync — Slack repeats the same message 18 times across context-before/after blocks of nearby results. Never bulk-read 100 messages out of a channel to find 2-3 hot threads; search for the threads, then read them. Target total /sync turn cost: under 15k tokens of tool output. If you blow past that, you skipped these flags somewhere.

    • Gmailsearch_threads with query (to:me OR cc:me OR "your-handle") newer_than:2d -category:promotions -category:social and pageSize: 50. Snippet + headers are enough; don't follow up with get_thread unless the snippet is unreadable.
    • Slack channel/group mentionsslack_search_public_and_private with query: "@<slack_user_id> after:<YYYY-MM-DD of 2d ago>", channel_types: "public_channel,private_channel", response_format: "concise", include_context: false, limit: 20. The result already contains the full text of each hit.
    • Slack DMs (24h)slack_search_public_and_private with query: "is:dm after:<YYYY-MM-DD of 1d ago>", channel_types: "im,mpim", response_format: "concise", include_context: false, limit: 20. If DM filtering returns junk, fall back to a second search to:me after:<date> with the same options.
    • Slack hot topics — DO NOT bulk-read each channel. For each channel ID in slack_hot_channels, issue slack_search_public_and_private with query: "in:<channel_id> is:thread after:<date>", response_format: "concise", include_context: false, limit: 10, sort: "score". Take the top 5 per channel. Only call slack_read_thread on a specific message if the snippet is too truncated to summarize.
    • Linear assignedlist_issues with assignee: "me", updatedAt: "-P14D", limit: 50. The 14-day window cuts stale backlog that doesn't change daily. If the response still exceeds the tool limit, narrow to -P7D and add state: "started" (in-progress only). On the first /sync of a day, reuse yesterday's linear.md backlog rows verbatim and only overwrite issues that appear in the active set — backlog issues with no updatedAt change carry forward.
    • Linear mentions — skip the dedicated lookup. Linear's notification emails already surface @mention events via Gmail. Only call list_comments on a specific issue when the chat surfaces an unresolved question on it.
    • Calendarlist_events with calendarId=primary, startTime=<now>, endTime=<next_48h_iso>, orderBy=startTime, pageSize: 50. Don't request full event descriptions; summary + attendees + time are enough.
  6. Flywheel: recognize and file new people BEFORE writing the daily files. Read wiki/entities/people/_index.md. For every distinct person name extracted from this batch — Gmail senders/recipients (excluding notification bots), Slack message authors, Slack @mentions, Linear comment authors, Calendar attendees — check:

    • Is there a page at wiki/entities/people/<Full Name>.md or an alias match in _index.md?
    • If no, and the name appears either (a) ≥2x in this batch, or (b) once with a clear role signal (email signature, channel pin, "Head of X", @<role> ping), then file them now via the ppl skill's add flow. Use best-guess role from context; if uncertain, file with role: "—" + a > [!todo] Confirm role callout. Default company: Your Organization unless the source domain says otherwise (e.g. @external1.com, @external2.com, @external3.com → External).
    • Track the list of newly-filed people; surface it in the chat summary so the user can correct roles.

    Why: the wiki's compounding value is the link graph. Each /sync should add nodes, not just edges. Never emit a [[Name]] wikilink to a non-existent page (phantom link rots the graph), and never silently skip a recognizable person. File or don't link — those are the only two options.

  7. Snapshot active notes. After the sweep, glob wiki/notes/*.md and load every file with status: open. Sort by due ascending. These rows go into daily/<today>/notes.md (template below) and feed the Top-10 alongside Gmail / Slack / Linear / Calendar.

  8. Check for existing date folder. wiki/daily/<today>/:

    • If missing: create folder. Write all five files from scratch using the templates below.
    • If present: dedupe each item against the existing file by stable ID (see "Dedup keys" below). Append new items under a heading ## Update HH:MM at the bottom of each file. notes.md is regenerated whole each run (not append-dedup) — it's a live snapshot of the working set.
  9. Print chat output. Show all items collected this run as bullets, grouped by source (notes included). End with the absolute paths written/updated.


Dedup keys

SourceStable key
Gmail threadgmail:<threadId>
Slack messageslack:<channel_id>:<ts> or the permalink
Linear issuelinear:<identifier> (e.g. ENG-123)
Linear commentlinear-comment:<comment_id>
Calendar eventgcal:<event_id>
Vault notenote:<note_id> (filename without .md)

Embed the key as an HTML comment on each bullet so future runs can grep: - [ ] ... <!-- key:gmail:18c3... -->

When appending, read the existing file, extract all <!-- key:... --> markers, and skip any new item whose key already exists.


File templates

mentions.md

# Mentions — <date>

## Gmail

- [ ] **<subject>** — from <sender> — <relative time> — [open](<gmail link>) <!-- key:gmail:<threadId> -->

## Slack — channel mentions

- [ ] **#<channel-name>** — <author>: "<preview, ~120 chars>" — <relative time> — [open](permalink) <!-- key:slack:<channel>:<ts> -->

## Slack — group mentions

- [ ] **<group name or members>** — <author>: "<preview>" — <relative time> — [open](permalink) <!-- key:slack:<channel>:<ts> -->

## Slack — DMs (24h)

- [ ] **<author>**: "<preview>" — <relative time> — [open](permalink) <!-- key:slack:<channel>:<ts> -->

topics.md

# Hot topics — <date>

> Channels: #<name1>, #<name2>, #<name3> (from `_config.json`)

## #<channel-name>

- **<one-line topic summary>** — <N> replies, <N> reactions — started by <author> <relative time> — [open](permalink) <!-- key:slack:<channel>:<ts> -->

linear.md

# Linear — <date>

## Assigned to me — open

- [ ] **<ID>** <title> — <status> — <priority> — [open](url) <!-- key:linear:<ID> -->

## Mentions (48h)

- <comment author> on **<ID>** <title>: "<preview>" — <relative time> — [open](<comment url>) <!-- key:linear-comment:<comment_id> -->

calendar.md

# Calendar — next 48h, as of <date> <HH:MM>

- **<start local time>** (<duration>) — <title> — <attendee count> attendees — [open](<event url>) <!-- key:gcal:<event_id> -->

notes.md

Snapshot of every wiki/notes/*.md with status: open (sweep already removed expired). Regenerated whole each run — not append-dedup.

# Notes — <date> <HH:MM>

> Live snapshot of `wiki/notes/` — vault TTL 7d. Manage with `/note`, `/task`, or `/note done <id>`.

## Active Tasks

- [ ] **<title>** — assignee <Full Name or me> — due <YYYY-MM-DD HH:MM> — <Linear ID or —> — [open](obsidian://open?vault=digital-brain&file=notes%2F<note_id>) <!-- key:note:<note_id> -->

## Active Reminders

- [ ] **<title>** — due <YYYY-MM-DD HH:MM> — [open](obsidian://open?vault=digital-brain&file=notes%2F<note_id>) <!-- key:note:<note_id> -->

If a section is empty, write the header with _none_.


Chat output (after writing)

Lead with a Top-10 table. Persistence still happens in the four files; the chat output is for triage. Use this shape:

Synced <today>. Wrote/updated:
  - wiki/daily/<today>/mentions.md  (<N> new)
  - wiki/daily/<today>/topics.md    (<N> new)
  - wiki/daily/<today>/linear.md    (<N> new)
  - wiki/daily/<today>/calendar.md  (<N> new)
  - wiki/daily/<today>/notes.md     (<N> active · <N> expired this sweep)

### Top 10
| # | Priority | Source            | Item                                    | Deadline / age   | Action            |
| - | -------- | ----------------- | --------------------------------------- | ---------------- | ----------------- |
| 1 | 🔥       | Slack group DM    | Dan: review red-team demo video         | by 16:00 today   | Watch + post take |
| … | …        | …                 | …                                       | …                | …                 |

### Counts (full detail in the daily files)
- Gmail: <N> threads · Slack channel mentions: <N> · Slack DMs: <N> · Linear assigned: <N> open · Calendar: <N> next 48h · Notes: <N> active (<N> tasks, <N> reminders; <N> expired this sweep)

Top-10 selection rules (same as /sup):

  • Drop [email protected], [email protected], [email protected], [email protected], and any "calendar invitation accepted/declined" emails — they don't get rows even though they still land in mentions.md for the historical record.
  • If a Linear mention already appears in the table, do NOT also add the matching Linear notification email.
  • Slack DMs only earn a row if they ask for a decision, review, or name a deadline. Reaction emojis, links, "ok"/"thanks"/"got it", and banter never get a row.
  • Use 🔥 for hard deadlines in next 4h, High for explicit asks-of-you in last 24h, Med for older / context items.
  • Notes earn rows. Every note_kind: task with status: open always gets a row (source: Note (task)). note_kind: reminder gets a row only if due ≤ now + 24h (source: Note (reminder)). Score 🔥 if due ≤ now + 4h, High otherwise. If a note has a linear ID and the matching Linear issue already appears in the table, dedupe — keep one row (prefer the note row, since it carries your own framing).

Be terse: title + 1-line context + link per item in the table. Do not paste full message bodies in chat — the daily files already have the full detail.


Failure modes

  • No MCP for a source (e.g. Gmail not authenticated): skip that source, note (skipped: not authenticated) in chat output. Do not block the rest.
  • Rate limit / API error: log it, continue with what you have.
  • No items in a section: still write the section header with _none_ so future updates have an anchor.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.