agentsclimarketplace

Social ledger

Skill jedi4ever/social-skills/skills/social-ledger

Local content + seen-ledger for the social-fetch family. Stores every fetched URL (and any URL the agent records via Claude WebFetch / research tools) in a SQLite + FTS5 store + a markdown mirror tree. Use to answer "have we seen this URL?" / "what did we save about X?" / "store this WebFetch output for next time" — before re-fetching, before re-WebFetching, and after any external content fetch the agent wants to remember.From its SKILL.md

Install
npx -y skills add jedi4ever/social-skills --skill social-ledger

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

2 things to look at

  • 5 stars5 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.
  • runs commandsInstructs the agent to run 8 commands, including `scripts/social-ledger article seen <url>...` and 7 more.

SKILL.md

13.6 KB, ~3.3k tokens by cl100k_base, as published. Nobody here has run it

social-ledger skill

Wraps the social-ledger Go binary at scripts/social-ledger. The ledger is a persistent local memory for every URL the agent has read — automatic when content comes through social-fetch fetch / research / timeline, manual via record for content the agent fetched through other tools (Claude's WebFetch, the research tool's web search, a curl one-off).

Trust the ledger. When the user asks "have we read this before?" or "what did we learn about X recently?" — query the ledger first. Only re-fetch on cache miss. The cache survives across conversations, computer restarts, and Claude versions.

Provenance — know how much to trust each entry. The ledger records who put each item in. Two classes:

  • auto-fetched — entry was ingested by social-fetch fetch / search / ask / timeline / research. We pulled the URL ourselves, ran our own extractor, normalised the markdown. High trust. The source column is one of the platform names: hackernews, reddit, github, x, twitter, linkedin, youtube, bluesky, arxiv, medium, substack, rss, article.

  • agent-recorded — entry was stored via social-ledger article record, meaning an agent fed in content it got from somewhere else (Claude's WebFetch, the research tool, a curl one-off, hand paste). Trust depends on what was fed in. The source column is one of webfetch, manual, research-tool, citation.

Quoting from a webfetch-source entry is fine for "what does the page say at a glance"; for high-stakes citations, prefer auto-fetched entries or re-fetch the URL via social-fetch fetch to get a fresh copy through our extractor. The MCP social_ledger_get tool surfaces this as a provenance field on every retrieval; the CLI shows the source column on list / search / get so you can eyeball it.

Subcommands

scripts/social-ledger article seen <url>...                # is URL(s) in the ledger?
scripts/social-ledger article get <url>                    # full content of one entry
scripts/social-ledger article list [flags]                 # browse newest first
scripts/social-ledger article search "<terms>"             # FTS5 over title/content
scripts/social-ledger article stats                        # counts, sizes
scripts/social-ledger article record <url> [flags]         # store URL+content (stdin)
scripts/social-ledger article forget <url>                 # drop one entry
scripts/social-ledger article filter --skip-seen           # JSONL passthrough drops seen

scripts/social-ledger help <subcommand> for full flag reference.

Decision rules

Before fetching anything, ask the ledger first. If the user mentions a URL or topic that might already be cached, run seen / search before any new fetch:

scripts/social-ledger article seen "https://news.ycombinator.com/item?id=43000000"
# seen   → use `get` to retrieve, no re-fetch
# unseen → fall through to `social-fetch fetch` or WebFetch

For content-bearing queries:

scripts/social-ledger article search "harness engineering"
# returns BM25-ranked hits across every saved item's title /
# summary / content / author / tags

Combine: search to find candidates, get <url> to dump one in full, then summarise.

Recording content from outside social-fetch

DO NOT call record for content fetched via social-fetch. social-fetch fetch / search / ask / timeline / research all auto-ingest into the ledger via the auto-detected sibling binary. Calling record on top creates a duplicate row. The two are mutually exclusive.

DO call record for content fetched outside social-fetch:

  • Claude's WebFetch tool (the built-in one)
  • Claude's research / search tool result snippets
  • Ad-hoc curl, wget, hand-pasted text
  • Any source that didn't go through a social-* binary

When the user asks the agent to fetch content via one of those non-social-fetch paths, the result isn't in the ledger automatically. Add it after, so the next conversation finds it:

# 1. fetch via Claude's WebFetch tool (output: markdown)
# 2. record it:
scripts/social-ledger article record \
  --title "Page Title" \
  --source webfetch \
  "https://example.com/post" <<EOF
# Page Title

Markdown body that came back from WebFetch.
EOF

Required: <url>, --title. Everything else (--summary, --author, --source, --canonical-id, --content FILE) is optional. Source defaults to webfetch; override to research-tool, manual, etc. for cleaner list --source filtering later.

Workflow recipe for the WebFetch case — user asks the agent to read a URL that the agent fetches via Claude's WebFetch tool (NOT social-fetch — if you used social-fetch fetch, skip the record step entirely; it's already in the ledger):

  1. seen <url> → if seen, skip 2-3, use get <url> for the body.
  2. WebFetch the URL → capture markdown.
  3. Write the markdown to a temp file (e.g. /tmp/<slug>.md) using the Write tool. Then record <url> --title "..." --source webfetch --content /tmp/<slug>.md. Don't stream the markdown through stdin or as a JSON string when it's longer than a handful of lines — file paths avoid bloating the agent's token budget and the MCP escape-encoding overhead.
  4. Reason / summarize from the recorded content.

The mirror workflow for the social-fetch case (read this so you don't double-record):

  1. seen <url> → if seen, skip 2, use get <url>.
  2. social-fetch fetch <url> (or search / ask / etc.) — this auto-ingests into the ledger; the agent does NOT need to call record. Verify with seen <url> afterwards if uncertain.
  3. Reason / summarize from the fetched content.

The ledger's deduplication (key = source::canonical_id) means re-recording the same URL with the same content is a no-op (unchanged), and re-recording with new content updates the existing row — agents can run record liberally without worrying about duplicates.

Worked example — record the result of a Claude WebFetch

The agent has been asked to summarize a Vercel blog post that isn't on a platform social-fetch natively recognises. It WebFetches the URL, then records the result so future "have we seen this?" queries hit cache.

Step 1 — check if the ledger already has it:

scripts/social-ledger article seen "https://vercel.com/blog/agent-skills"
# unseen   https://vercel.com/blog/agent-skills

Step 2 — call Claude's WebFetch tool. The agent gets markdown content back. Write it to a temp file with the Write tool rather than holding the entire body in conversation memory:

# (pseudocode for the agent's perspective)
# 1. WebFetch("https://vercel.com/blog/agent-skills")
#    →  markdown body returned
# 2. Write tool: /tmp/vercel-agent-skills.md ← markdown body

Step 3 — record by file path (NOT by streaming the content through). The --content FILE flag reads the body from disk so the markdown never has to round-trip through the agent's prompt or the MCP JSON-escape:

scripts/social-ledger article record \
  --title "Agent Skills on Vercel" \
  --summary "How Vercel ships agent skills via npx skills add" \
  --source webfetch \
  --author "vercel-labs" \
  --content /tmp/vercel-agent-skills.md \
  "https://vercel.com/blog/agent-skills"
# stderr: recorded: https://vercel.com/blog/agent-skills (new)

If the body is genuinely tiny (a one-line description, a tweet quote) and writing-then-reading is overkill, stdin still works:

echo "Short body inline." | scripts/social-ledger article record \
  --title "Quick Note" --source manual "https://example.com/x"

But for any real WebFetch output, prefer the file path — typical blog posts are 5-50 KB of markdown which is wasteful as a JSON-string argument or piped stdin.

Step 4 — confirm + summarize. The ledger now has the entry; a second seen returns seen, and get dumps the markdown back on demand:

scripts/social-ledger article seen "https://vercel.com/blog/agent-skills"
# seen     https://vercel.com/blog/agent-skills

scripts/social-ledger article get "https://vercel.com/blog/agent-skills"
# # Agent Skills on Vercel
# source: webfetch
# url: https://vercel.com/blog/agent-skills
# author: vercel-labs
# (...full body...)

Subsequent conversations that ask "what did we save about Vercel agent skills?" will find this entry via search:

scripts/social-ledger article search "vercel agent skills"
# webfetch    Agent Skills on Vercel    https://vercel.com/blog/agent-skills
#   How Vercel ships agent skills via npx skills add

One-liner template for the common case (file-based, recommended):

# 1. Write tool: /tmp/<slug>.md ← WebFetch markdown
# 2. Record:
scripts/social-ledger article record \
  --title "$TITLE" --source webfetch \
  --content /tmp/<slug>.md \
  "$URL"

The Write-then-record pattern keeps the markdown body off the agent's token budget AND off the MCP JSON-escape path. For multi-page articles this saves thousands of tokens vs. inlining.

Listing + filtering

scripts/social-ledger article list                       # newest 25
scripts/social-ledger article list --source hackernews   # only HN entries
scripts/social-ledger article list --source webfetch     # only Claude-recorded
scripts/social-ledger article list --since 7d            # last week
scripts/social-ledger article list -n 100                # bigger window

stats for an at-a-glance summary:

scripts/social-ledger article stats
# → counts per source, total items, disk usage, oldest/newest

Storage location

Default: $XDG_DATA_HOME/social-ledger (typically ~/.local/share/social-ledger). Override per-call with --data-dir <path>, or globally with SOCIAL_LEDGER_DIR.

The store is a single SQLite file (ledger.db) plus an on-disk markdown mirror tree (tree/by-source/, tree/by-date/, tree/by-url/<host>/) — agents can also grep / Read files under tree/by-source/ directly for fuzzy "did we save anything about X" without going through search.

Output format

list and search emit one item per line:

2026-05-03	hackernews	Y Combinator
  https://news.ycombinator.com/item?id=1

(date \t source \t title, then a indented URL line). Easy to grep through and parse. get emits full content as markdown with frontmatter (source, url, author, score, tags, fetched_at). The JSON output mode for seen (--format json) is the cleanest parse target for agent code:

[{"url":"https://...", "seen":true}, {"url":"...", "seen":false}]

When NOT to use this skill

  • The user explicitly asks for fresh content ("re-fetch X with the latest comments"). Hit social-fetch fetch directly.
  • The ledger is empty or you're certain the URL is new — running seen first is wasteful, just fetch.
  • Bulk delete / migration / restore — out of scope; tell the user to operate on the SQLite file directly.

Influencers — track topic authorities

The ledger doubles as a curated directory of people / companies the agent should treat as authorities on specific topics. Same storage, different source tag (influencer).

scripts/social-ledger influencer add "Andrej Karpathy" \
  --x karpathy --github karpathy \
  --topics ai,research,transformers \
  --description "Former Tesla AI / OpenAI co-founder"

scripts/social-ledger influencer subscribe "Andrej Karpathy" \
  --platform x --topics ai

scripts/social-ledger influencer list --topic ai --followed
scripts/social-ledger influencer show andrej-karpathy
scripts/social-ledger influencer unsubscribe andrej-karpathy --platform x
scripts/social-ledger influencer remove andrej-karpathy

Re-running add for the same name upserts (socials merge, new platform overwrites same key, others kept; topics union; description replaces when non-empty). So "I just learned Jane's mastodon handle" is one line: add jane --social mastodon=@[email protected].

MCP tools mirror the CLI shape for agents that prefer structured calls over shelling out: social_ledger_influencers_{list,get,add,remove,subscribe,unsubscribe}. Use mid-research: when you discover a new authority worth tracking ("the author of this Archon project ships a lot of agent content"), call social_ledger_influencers_add so the next conversation finds them in the directory.

Related

  • social-fetch fetch and friends auto-populate the ledger when SOCIAL_LEDGER is unset/auto/1 and social-ledger is on PATH (or bundled alongside in this skill). No env-var setup needed for this skill — auto-detect handles it.
  • The standalone social-fetch skill covers fetch / search / ask / timeline / research / bridge. Use both: this skill for reading the cache, that one for filling it.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Gives 0 of the 12 instructions most context ai engineering skills give in ~3.3k tokens

Counted across 1,328 of the 2,349 authors here whose files we hold, read 2026-09-06

  • Dispatch a fresh subagent for each taskin 76 of 1328, across 59 files
  • Perform spec compliance review before code quality reviewin 44 of 1328, across 34 files
  • Dispatch a final code reviewer after all tasksin 38 of 1328, across 26 files
  • Answer subagent questions before allowing implementationin 36 of 1328, across 26 files
  • Use the least powerful model capable of the taskin 33 of 1328, across 26 files
  • Create a TodoWrite list for all tasksin 32 of 1328, across 22 files
  • Perform a task review after each implementationin 31 of 1328, across 24 files
  • Extract all tasks and context from the planin 29 of 1328, across 20 files
  • Provide full task text to subagentsin 28 of 1328, across 20 files
  • Use git worktrees for isolated workspacesin 25 of 1328, across 20 files
  • Specify the model explicitly when dispatching a subagentin 23 of 1328, across 18 files
  • Execute all tasks from the plan without stoppingin 21 of 1328, across 16 files

Said here and by no other author read

  • query the ledger before fetching any URL
  • use get to retrieve content on cache hit
  • write WebFetch markdown to a temp file
  • record non-social-fetch content using the record command
  • use file paths for recording content to save tokens
  • use search to find candidates for content-bearing queries

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 325,949. 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.