Shepherd

Shepherd for agents

Your connected sources as a read-only, versioned filesystem ($SOURCES), a private writable scratch ($SCRATCH) and read-only SQL over structured records such as Messages, email and tickets, for any agent: through the shepherd CLI, its MCP server, and an installable agent skill. Everything runs as you and sees only your own data. You need only your Shepherd account with sources connected: no cloud account, API key or deployment.

1 · Install the CLI and sign in

One self-contained file, Node.js 22.13 or later. It talks to https://sources-api.askshepherd.ai by default.

mkdir -p ~/.local/bin
curl -fsSL https://sources.askshepherd.ai/downloads/shepherd.mjs -o ~/.local/bin/shepherd
chmod +x ~/.local/bin/shepherd
shasum -a 256 ~/.local/bin/shepherd   # expect b0ad8f683ab339cb195514ce1de2d24a35bb6c7c0d00e6f8987200f90f3a65d3
export PATH="$HOME/.local/bin:$PATH"

sha256 b0ad8f683ab339cb195514ce1de2d24a35bb6c7c0d00e6f8987200f90f3a65d3 (also in the download's x-content-sha256 header)

shepherd login     # opens your browser to sign in; nothing to paste
shepherd whoami

The refreshable token stays in ~/.config/shepherd/credentials.json (0600) on your machine. Agents never need it in their config, and you never paste it anywhere. shepherd login --no-browser prints the sign-in link instead.

2 · Connect an MCP client

The CLI runs a stdio MCP server as you. Add it with one command:

Claude Code
claude mcp add shepherd -- node ~/.local/bin/shepherd mcp --server https://sources-api.askshepherd.ai
Codex CLI
codex mcp add shepherd -- node ~/.local/bin/shepherd mcp --server https://sources-api.askshepherd.ai
Pi
pi mcp add shepherd -- node ~/.local/bin/shepherd mcp --server https://sources-api.askshepherd.ai
Cursor · Claude Desktop · other clients (shepherd mcp-config prints this with your real path)
{
  "mcpServers": {
    "shepherd": {
      "command": "node",
      "args": [
        "/Users/<you>/.local/bin/shepherd",
        "mcp",
        "--server",
        "https://sources-api.askshepherd.ai"
      ]
    }
  }
}

The tool names and parameters follow the familiar coding-agent set (read, ls, find, grep, write, edit, as in Pi and Claude Code), so agents use them without new instructions. The service also exposes a remote MCP endpoint at https://sources-api.askshepherd.ai/mcp for clients that sign in with OAuth themselves; the stdio route above is the tested one.

3 · Install the agent skill

The shepherd-sources skill teaches an agent when to use files versus SQL, how to continue bounded answers, and the permission rules. It installs into ~/.agents/skills (Pi and other Agent Skills clients) and, when present, ~/.claude/skills and ~/.codex/skills.

With the CLI
shepherd skill install
Without the CLI
d=~/.agents/skills/shepherd-sources; mkdir -p "$d/references"
for f in SKILL.md references/setup.md references/sql.md references/tools.md; do
  curl -fsSL "https://sources.askshepherd.ai/downloads/skills/shepherd-sources/$f" -o "$d/$f"
done

Files: SKILL.md · references/sql.md · references/tools.md · references/setup.md

The filesystem

  • $SOURCES/<provider>/…: one directory per connected integration (imessage, gmail, slack, google-docs, notion, linear, granola, coding-sessions, …), then account, workspace or mailbox directories. Personal sources sit in your own owner directory (@u-…) that only you can list.
  • Readable projections (.md), the provider's raw records as JSON (_raw/), and exact attachment bytes.
  • Every file keeps its versions and deletions (sources_history). It is a captured copy: check sources_status for coverage and freshness.
  • $SCRATCH/…: your private, persistent, writable space, shared by this website (Files → Scratch), the CLI, MCP and sandboxes.
shepherd ls '$SOURCES'                      # one directory per connected provider
shepherd status                              # coverage and freshness per provider
shepherd find '$SOURCES/notion' '*.md'
shepherd grep -i "launch plan" '$SOURCES/google-docs' --limit 20
shepherd read '$SOURCES/imessage/<owner>/conversations/<chat>/2026-10.md' --offset 1 --limit 80

Files or SQL

Use SQL to count, filter, sort and join structured records (messages, emails, events, issues). Every row carries path, the exact $SOURCES file it came from, so an agent can open the source. Use grep/read for text inside documents and transcripts, and for fields no view models: the raw JSON keeps every provider field (json_extract(data, '$.field') on records).

shepherd schema                              # tables and views, row counts, completeness
shepherd schema imessage_messages            # columns, source layout, example queries
shepherd sql "SELECT name, last_message_at, conversation_id FROM imessage_conversations
              ORDER BY last_message_at DESC LIMIT 10"
shepherd sql "SELECT sent_at, coalesce(sender_name, sender_handle) AS who, text
              FROM imessage_messages WHERE conversation_id = ? AND is_reaction = 0
              ORDER BY sent_at DESC" --param '<conversation_id>' --max-rows 50
shepherd sql "SELECT subject, from_header, projection_path FROM gmail_messages
              ORDER BY internal_date DESC" --max-rows 20 --offset 20     # page 2
Results to scratch
shepherd sql "SELECT path, size FROM files WHERE provider = 'linear'" --format csv > /tmp/f.csv
shepherd put /tmp/f.csv '$SCRATCH/reports/linear-files.csv'
echo "# notes" | shepherd write '$SCRATCH/notes.md'

Tool reference

The same tools and receipts in the hosted MCP endpoint, the CLI's stdio MCP server and the CLI. Paths start with $SOURCES or $SCRATCH.

Read and search

MCP toolParametersCLIWhat it does
lspath, limit, aftershepherd ls PATHList a directory: providers at $SOURCES, then accounts/workspaces/mailboxes.
readpath, offset, limit | byteOffset, byteLimitshepherd read PATH · shepherd cat PATH · shepherd get PATHLines of a text file at any depth, or exact byte ranges of any file; PNG/JPEG/GIF/WebP come back as images.
findpattern, path, limit, aftershepherd find PATH PATTERNPaths by glob (names, or relative paths when the glob has '/').
greppattern, path, literal, ignoreCase, glob, context, limit, aftershepherd grep PATTERN PATH [-C N]Matching lines in text files (regex or literal), with context lines.
sources_statusprovidershepherd statusWhat is connected, coverage (complete/partial/blocked) and freshness.
sources_historypath, limit, before, versionId, byteOffset, byteLimitshepherd history PATHEvery version of a file, including deletions; read any prior version.

Search by meaning

MCP toolParametersCLIWhat it does
semantic_searchquery, providers, pathPrefixes, roles, conversationIds, driveFolderIds, documentIds, updatedAfter/Before, versions, limit, cursorshepherd search "…"Find text by meaning across sources you can read, with the exact source range of each hit (hosted server).
semantic_statusprovider, state, pathPrefix, after, limit, facetsshepherd search-statusWhat search by meaning covers: indexed/pending/unsupported counts with reasons, and the filter values you have.

SQL

MCP toolParametersCLIWhat it does
sql_schemaprovider, tableshepherd schema [TABLE]Tables and views with row counts and completeness; one table's columns and example queries.
sql_querysql, params, maxRows, offset, seq, maxCellChars, timeoutMsshepherd sql "SELECT …" --param VOne read-only SELECT with ? parameters; page with offset = nextOffset; long values in full with maxCellChars.

Scratch (the only writes)

MCP toolParametersCLIWhat it does
writepath, contentshepherd write PATH < file · shepherd put FILE PATHCreate or replace a file below $SCRATCH.
editpath, edits[{oldText, newText}]—Exact-text replacements in a $SCRATCH file.
scratch_mkdirpathshepherd mkdir PATHCreate a $SCRATCH directory.
scratch_movefrom, to, overwriteshepherd mv FROM TOMove or rename within $SCRATCH.
scratch_deletepath, recursiveshepherd rm PATH [-r]Delete from $SCRATCH.

SQL views

Read-only SQLite over a private snapshot of the files you can read; it refreshes as sources change. sql_schema lists every table with its columns; these are the ones agents use most:

  • imessage_messages — One row per iMessage/SMS message: sender, resolved name, text and original text, replies (reply_to), tapbacks with actor, target message and removal, edits, unsends, attachment count.
  • imessage_message_versions — Every version of edited messages as Messages recorded it (version 0 = original).
  • imessage_conversations — Conversations (direct/group), names, first/last message, directory.
  • imessage_participants — Handles in each conversation with names and message counts.
  • imessage_attachments — Attachment byte state (stored/pending/unavailable + reason), the stored file's path, and bytes_verified against the file's sha256 and size.
  • imessage_conversation_months — The readable monthly transcript file of each conversation.
  • imessage_contacts — Address-book names the Mac synced.
  • imessage_message_edits — Earlier text of edited or unsent messages.
  • gmail_messages — Mailbox, thread, labels, folder, Subject/From/To and snippet.
  • gmail_attachments — Attachment parts and their stored files.
  • slack_messages — Slack messages from the raw ledger (channel, ts, thread, user id, text).
  • slack_conversations — Channels and DMs with access/history state.
  • calendar_events — Current Google Calendar events.
  • linear_issues — Linear issues with state, assignee and dates.
  • jira_issues — Jira issues with status, people and dates.
  • activity_events — Every provider's raw event ledger with the full raw payload.
  • files — Every readable file: path, provider, size, hash, capture time.
  • records — Every JSON document (query fields with json_extract).

Message names are what your Mac resolved from Contacts when it uploaded; a missing name means none was available. Attachments that were only in iCloud show state = 'unavailable' with the reason; stored ones have file_path and bytes_verified = 1. read returns PNG, JPEG, GIF and WebP files to the model as images; shepherd get downloads any file byte-exactly.

Bounded answers

Every answer has a size bound, and nothing is dropped silently: the receipt says what is missing and how to continue.

truncated + nextAfter (ls, find, grep)Repeat the call with after = nextAfter. truncatedReason says whether your limit or a per-call server bound stopped it.
matchesMayContinueIn (grep)That file may hold more matches than were returned: grep it alone.
skipped.binary / skipped.tooLarge (grep)Files that are not line-searchable; read them by byte range or use SQL.
nextOffset · nextByteOffset · lineCut (read)The file continues: read again from that line or byte; lineCut.restByteOffset is where a cut line continues.
nextOffset · snapshotMoved (sql_query)More rows: same sql and params with offset = nextOffset and seq = snapshot.seq (with ORDER BY); snapshotMoved says the data changed between pages.
complete: false · pending · errors (SQL)Some files are not indexed yet, or cannot be rows; the answer may be partial.
cellsCut (SQL)Values over maxCellChars (default 16384) are listed with their full length: ask again with a larger maxCellChars (up to 4194304) or page one value with substr().
lineChars (grep)A matching line longer than 500 characters is shown clipped; read the file at that line for all of it.

Permissions and privacy

  • The website, CLI, both MCP servers, SQL and sandboxes apply the same per-person access rule, from your verified sign-in only. Other people's data is indistinguishable from absent.
  • $SOURCES refuses every write; agents write only below $SCRATCH. Nothing is written back to a provider.
  • SQL runs one SELECT with ? parameters in an isolated read-only process; writes, PRAGMA, ATTACH, extensions and file functions are refused.
  • Provider credentials stay in the collector and are never sent to agents or sandboxes.

Sandboxes (optional)

For heavy processing, Modal sandboxes mount all your sources read-only at /sources, your scratch at /scratch and the SQL index, with no network and no credentials; the shepherd CLI works inside them. Enable them on the Sandboxes page (this keeps a read-only mirror of your sources on the service's Modal storage), then:

shepherd modal start
shepherd modal exec <id> -- shepherd sql "SELECT count(*) FROM imessage_messages"
shepherd modal stop <id>

MCP clients get the same through one tool; it runs only in a workspace you started and never starts one itself:

MCP toolParametersCLIWhat it does
sandbox_execcommand, sessionId, timeoutMsshepherd modal exec ID -- CMDRun one command in the Modal workspace you started (never starts one): /sources read-only, /scratch, SQL, no network.

Sign in · Privacy · Terms