Authentication and workspaces

How accounts, tokens, workspaces, and repo linking fit together in Shepherd.

Quickstart and Connect your agent show you how to get a token and paste it into a client. This page explains the model underneath: what the two token kinds actually mean, how accounts, workspaces, and repos relate, and how a repo moves from "just cloned" to "coordinating with the team."

Two credential kinds, one shape

Every Shepherd MCP server is configured with HUB_URL and a bearer token. The variable name for the token depends on your deployment, and for Korso-hosted users the dashboard hands back both values already filled into a paste-in config — there's nothing to look up separately:

  • SHEPHERD_TOKEN — a Korso-hosted hub. This is an account-scoped token: sign in to the Korso dashboard with Google or GitHub, open the Connect Agent panel, optionally name the token, and click Generate token. The raw value is shown once — copy it immediately, since it can't be retrieved again. One token works across every workspace your account belongs to, so there's no per-repo or per-workspace re-tokening. You can name, list (with created/last-used timestamps), and individually revoke tokens from the same panel at any time.
  • TEAM_TOKEN — a self-hosted hub. This is a single shared, workspace-wide secret that whoever runs the hub distributes to their team. It isn't scoped per agent or per person — anyone holding it has full authority over that hub's one workspace.

The @korso/shepherd MCP server accepts either variable, and requires at least one at startup — without one, it fails immediately with a clear error. If both happen to be set, SHEPHERD_TOKEN wins.

WORKSPACE is ignored on the hosted path, since your SHEPHERD_TOKEN already carries your account's workspace memberships. It only matters for self-host, where it must exactly match the hub's configured workspace.

TEAM_TOKEN is a shared password, not an identity. Treat it accordingly: never commit it, distribute it through a secret manager, and rotate it if a teammate with access leaves.

Account, workspace, and repo

Three concepts sit underneath every Shepherd deployment:

  • Account — you, or your team on a self-hosted deployment. On a hosted hub, your account is whatever you signed in with (Google or GitHub). On self-host, the "account" is effectively whoever holds the TEAM_TOKEN.
  • Workspace — a coordination space your account belongs to, typically one per team or project. A hosted account can belong to several workspaces at once. A self-hosted deployment serves exactly one.
  • Repo — a git repository that opts into exactly one workspace via a committed .shepherd marker file. Committing that marker is what lets your whole team auto-coordinate the moment they clone the repo, without each teammate authenticating per repo.

The token answers "who are you and which workspaces can you reach." The .shepherd marker answers "which one of those workspaces does this repo use."

The repo-linking lifecycle

The first time an agent is about to make an edit in a repo that isn't yet linked to a workspace, Shepherd nudges it to decide between two tools: link (opt in) or decline (opt out, for now, locally). On clients that support MCP elicitation, the same moment can instead surface as a direct popup ("Coordinate this repo with Shepherd?") with the workspace choices and a "don't ask again" option — same outcome, no tool call required from the agent. See Connect your agent for how that nudge reaches the agent on clients without elicitation.

link writes the .shepherd marker and activates coordination immediately — no restart needed. It takes an optional workspace slug:

  • Called with no argument, and the account (or self-hosted deployment) belongs to exactly one workspace, Shepherd picks it automatically.
  • Called with no argument, and the account belongs to several, Shepherd lists the slugs and asks the agent to check with its human before calling link again with the chosen one.

The marker only ever names the workspace — never a token — so it's safe to commit. That's what makes linking a one-time, team-wide action: once it's in the repo, anyone who clones it afterward coordinates automatically.

unlink removes the marker and stops coordination for everyone on that repo, since the marker is committed and repo-wide. It also silently records a local decline, so the agent that called it isn't immediately re-nagged to link again. If a session was live, its presence and claims drop right away rather than lingering until the session goes stale (~2 minutes without a heartbeat).

decline

decline is the local, personal opt-out. It never writes or commits anything, so it only affects your own sessions — a teammate can still link the same repo for themselves and everyone else. Use it when you don't want to be asked about linking again, without changing anything for the rest of the team.

See the MCP tool reference for link, unlink, and decline for the full input and output contract of each.

The advisory nudge

Until a repo is linked (and not declined), work, done, announce, and sync return a one-line advisory nudging the agent toward link or decline instead of their normal result. This is advisory, never blocking — the agent can ignore it and keep coding uncoordinated.

Fail-open, by design

None of the above is a hard gate. Consistent with Shepherd's fail-open design principles, an unreachable hub, an unlinked repo, or a missing token never blocks an agent from working — it just proceeds uncoordinated, and Shepherd says so.