unfairly
v0.8.1
Published
CLI + stdio MCP + library SDK for the Unfairly multiplayer context layer — sync vaults, run agents, emit events
Maintainers
Readme
unfairly
CLI + stdio MCP for syncing Unfairly vaults to local markdown.
Quick start
cd ~/path/to/your/repo
npx unfairly@latestThat's it. One command — auto-detects state and:
- pops a browser for OAuth (skipped if you already have a token)
- wires Claude Desktop, Claude Code, and Codex to the Unfairly MCP server
- writes
UNFAIRLY_MCP_TOKENinto your shell rc - binds
.unfairly/to your repo (pulls all accessible vaults) - stitches
@.unfairly/CLAUDE.mdinto your repo'sCLAUDE.md
Re-run any time inside the repo for a daily check-in card showing what your team's been up to.
Power-user commands
unfairly setup (machine wiring only), unfairly init (workspace bind only), unfairly pull, unfairly push, unfairly status, unfairly watch, unfairly mcp, unfairly login. The bare command above delegates to these — they're available when you want fine-grained control.
Commands
unfairly init— set up.unfairly/in cwd, prompt for token, run first pullunfairly pull [vault]— paginated diff from cloud, write/update markdown files, propagate deletesunfairly push [vault]— send dirty files to cloud with stale-check; conflicts get<<<<<<< local / >>>>>>> cloudmarkers in-placeunfairly status— per-vault last-pulled timestamp + modified-locally countunfairly resolve <path>— mark a conflicted file as resolved (after editing out merge markers)unfairly watch— opt-in fs watcher; debounced 5s auto-push on saveunfairly mcp— stdio MCP server exposingpull_vault,push_vault,sync_statustools to agent hosts (Claude Code, Codex, cowork)
Local store layout
.unfairly/
├── manifest.json # vault list + per-doc sha map; atomic writes
├── .gitignore # generated; ignores cache/
├── unfairly-app/ # repo-bound vault, git-tracked
│ └── canon/
│ └── system.md
└── cache/ # gitignored bucket for personal/sensitive vaults
└── hq/
└── people/
└── founders.mdPer-vault git-tracking is server-side via rooms.track_in_git. Tracked vaults live at the root; untracked vaults live under cache/.
Library usage
unfairly also ships a TypeScript library surface for building agent
runtimes against the hosted REST API. Same package, no extra install.
import { createUnfairlyClient } from "unfairly";
const client = createUnfairlyClient({ apiKey: process.env.UNFAIRLY_API_KEY });
// Identify yourself + list reachable vaults
const me = await client.me();
// Search a vault
const hits = await client.vault("growth").search("burn rate", { matchCount: 8 });
// Read a document
const doc = await client.vault("growth").readDocument("operating-plan");
// Save a checkpoint (server derives identity from the token — do NOT pass actor_email)
await client.vault("growth").checkpoint({
built: "Shipped new growth funnel widget",
decided: "Use Inngest for delivery; keep auto-checkpoint synchronous",
});
// Emit a closed-allowlist event into the Unfairly Inngest queue
await client.event.emit("growth-agent/signal.detected", {
signal_id: "abc",
source: "x-listener",
trust_tier: "gold",
dedupe_key: "abc:1",
payload: { text: "..." },
});Subpath imports are available for advanced consumers:
import { ALLOWED_EVENT_NAMES, EVENT_PAYLOAD_SCHEMAS } from "unfairly/events";
import type { CheckpointInput, SearchResponse } from "unfairly/types";ESM-only. Requires Node 20+.
Design
See docs/superpowers/specs/2026-05-07-local-context-sync-design.md in the main repo for architecture, conflict resolution, and integration with the cloud /api/mcp endpoint.
