usrkey.dev / guides / no-sdk

The format is the API.

No SDK, no service, no schema library. A USRKey is markdown files at a known path — here is a complete reader in ~20 lines, in both languages, run before publishing.

Node

// Read a USRKey — the whole "integration" is a directory of markdown files.
import { readFile } from "node:fs/promises";
import { join } from "node:path";
import { homedir } from "node:os";

const DIR = process.env.USRKEY_DIR ?? join(homedir(), ".usrkey");
const PAGES = ["identity", "stack", "now", "history"];
// boundaries.md is opt-in by rule - read it only when the user explicitly grants it

const found = [];
for (const page of PAGES) {
  try {
    found.push(await readFile(join(DIR, page + ".md"), "utf8"));
  } catch {
    /* a missing page is the user's choice - never invent or backfill it */
  }
}

if (found.length) {
  console.log(
    "Context the user chose to share. Use it as-is - don't re-ask what's already here.\n\n" +
    found.join("\n---\n")
  );
}

Python

# Read a USRKey in Python - same contract, zero dependencies.
import os
from pathlib import Path

DIR = Path(os.environ.get("USRKEY_DIR", Path.home() / ".usrkey"))
PAGES = ["identity", "stack", "now", "history"]
# boundaries.md is opt-in by rule - read it only when the user explicitly grants it

found = [p.read_text() for page in PAGES if (p := DIR / f"{page}.md").exists()]

if found:
    print(
        "Context the user chose to share. Use it as-is - don't re-ask what's already here.\n\n"
        + "\n---\n".join(found)
    )

The contract you just implemented

Read fresh, keep nothing. The user edits files; your next read sees it. Caching, syncing, or training on the content breaks the deal that makes users willing to write these files at all.

A missing page is an answer. stack.md not there? The user chose that. Don't infer it, don't ask them to "complete their profile."

boundaries.md is opt-in. It describes how to treat the user — read it only when they explicitly grant it, which is why it isn't in the default page list above.

Prefer not to hand-roll it? The MCP connector is this same logic behind one tool call, for clients that speak MCP.