docs

docs.

everything the agent, the CLI, and the web app share is one /v1 contract. start with the quickstart, then keep the api reference handy.

overview.

what scimap is, and the one rule that holds it together.

scimap is a durable record for autonomous research. your coding agent writes every hypothesis, run, and decision through one HTTP API into a typed graph — so the work survives the chat that produced it, and stays forkable, auditable, and re-derivable.

there is one funnel for results: run:record. it is idempotent, so a retried job never double-writes. the web app, the agent, and the terminal all speak the same /v1 contract — they cannot drift.

base urlhttps://api.scimap.dev/v1
authBearer key in the Authorization header (BYOK)
formatJSON request + response bodies; UTF-8

quickstart.

from zero to a recorded run in four steps.

01install the CLI
ships as scimap-cli on npm. install it globally with whichever package manager you have.
npm i -g scimap-cli
02sign in with your key
create a key on the api keys page, then sign the CLI in with it — it's cached in ~/.scimap/config.json (along with the API URL) and used for every call. on a fresh machine pointing at a self-hosted API, pass --api-url once (or run scimap config set api-url <url>); login remembers it.
scimap login --key sk_live_…
03initialize a graph
run init in a repo to find-or-create a project (its root node is your research question) and bind the repo (writes scimap.json). add --autoresearch to seed it instantly with a fast local char-LM run, so the graph starts rich and connected.
scimap init --title "train a better LM"
04record a run
funnel each result back into the graph through run:record — the one idempotent write. pass the metrics + outcome (and the commit/seed that make it reproducible); wildly different configs become directly comparable.
scimap run:record --project <id> \
  --commit a1f3c9e --seed 1337 \
  --metric val_bpb=0.812 --outcome success
you usually don't type step 04 — your coding agent calls it through the scimap skill as experiments finish. the CLI command exists for CI and manual records.

cli.

the shipped scimap commands — the agent-facing front door, same /v1 contract.

the CLI is a thin client over /v1: global flags (--json, --api-url, --api-key) are inherited by every subcommand, and the runtime key + URL resolve from flags, env (SCIMAP_API_URL / NEXT_PUBLIC_API_URL), the repo's scimap.json, then ~/.scimap/config.json. these are the verbs that actually ship.

scimap login --key sk_…store the sk_ key (and the resolved API URL) in ~/.scimap/config.json. use scimap config set api-url <url> to set a default API base without re-passing --api-url.
scimap init --title "…"find-or-create a project and bind this repo (writes scimap.json). --project <id> binds an existing one instead. add --autoresearch [--budget N] to seed the new graph with a fast local char-LM autoresearch loop (real recorded runs, ~1-2 min on CPU).
scimap node:create --kind … --title …create a node, routed by --kind (hypothesis | plan | decision | note | any kind_vocab) to the matching /v1 endpoint. --parent <id> attaches lineage; created intent nodes are hung under the project root so they're reachable.
scimap run:record --project <id> …the idempotent funnel: record a run's --metric k=v (repeatable), --outcome, and the --commit/--seed that make it reproducible. pass --plan / --hypothesis / --control to link lineage. re-recording the same key never double-writes.
scimap autoresearch --goal "…"the one-command loop: a control node (the goal) → an optimize campaign on the real local CPU char-LM runner → live SSE stream → an N-seed referee t-test → a verdict. --mode local (default) | mock | batch, --budget, --metric, --n-seeds.
scimap campaign:verify --control <id>the referee on its own: re-run the best candidate across --n-seeds and one-sided t-test the mean against --threshold, flipping --claim <id> to supported/weakened only if it passes. the claimable number is the verified mean, never the best single run.
reads (brief, runs, leaderboard, map:tree, link:parents/children) and other writes (link:create, log:append, job / job:stream, campaign) are also shipped — run scimap --help for the full list. these six are the spine of the workflow.

authentication.

BYOK — you hold the key; scimap never holds a balance.

every request authenticates with an API key in the Authorization header. create and scope keys on the api keys page; reads need graph:read, writes need graph:write, recording a run needs run:record, and starting a campaign needs optimize:start.

Authorization: Bearer sk_live_…
keys are shown once at creation — store them immediately. the server keeps only a prefix + hash and can never show a key again. revoke a leaked key from the api keys page; revocation is immediate.

api reference.

the /v1 endpoints the agent and the app share. all paths are relative to the base url.

run:record is the heart of the contract and the one write you should understand first.

curl https://api.scimap.dev/v1/runs \
  -H "Authorization: Bearer sk_live_…" \
  -H "Idempotency-Key: a1f3c9e:1337" \
  -d '{"hypothesis_id":"…","config":{…},
       "seed":1337,"code_commit":"a1f3c9e",
       "metrics":{"val_bpb":0.812},
       "outcome":"success"}'

→ 201 · node dry-dawn-9050 · supported
→ brief recomputed · exactly-once
run:record is idempotent: pass an Idempotency-Key (the convention is <commit>:<seed>). a retry with the same key returns the same node instead of writing a duplicate — safe under crashes and re-queues.
POST/runswrite · scoped
record a run — the funnel (idempotent)
send metrics + outcome (+ commit/seed/config). returns the created/updated node. honor the Idempotency-Key header.
GET/runs?project={id}read
list a project's runs
GET/runs/compare?a={id}&b={id}read
per-metric deltas between two runs
POST/runs/{id}/verify-commitwrite · scoped
confirm a run's pinned commit exists in its repo
GET/projectsread
list your graphs (RLS-scoped)
GET/projects/{id}/treeread
the full graph — nodes + links
GET/projects/{id}/briefread
the smallest packet to continue the work
open questions, what not to repeat, the best result so far — the context an agent loads to resume.
GET/projects/{id}/search?q=read
keyword search over node text
GET/projects/{id}/library/search?q=&mode=read
semantic retrieval over indexed sources (vector | hybrid | grep)
POST/nodes/{id}/forkwrite · scoped
branch a node into an editable copy, keeping lineage
POST/nodes/{id}/reproducewrite · scoped
re-run a node at its pinned commit + seed
POST/nodes/{id}/evaluatewrite · scoped
ask the referee to (re)grade a claim across seeds
POST/sourceswrite · scoped
register a source for indexing
POST/campaignswrite · scoped
dispatch an optimize campaign over a control node (→ 202, job_id)
subscribe to /jobs/{job_id}/stream for live started → progress → done events.
GET/api-keysread
list your developer keys
errors come back as JSON with a string detail and a standard status code (401 unauthenticated, 403 out-of-scope, 404 not found, 409 idempotency conflict, 422 validation). handle them, don't retry blindly — except idempotent writes, which are safe to retry with the same key.

primitives.

two node types, a typed graph, and one funnel.

the graph is the product. it has two node types you reason about — claims and evidence — connected by typed links, and every result carries enough state to be re-derived from scratch.

claims + evidencea claim is a conclusion the graph is testing; evidence (runs, sources) links to it for or against. the referee verifies a claim across N seeds before it's allowed to read as supported.
the typed graphnodes (root, hypothesis, plan, empirical, decision, insight, control, claim, source) and typed links (derived_from, tests, executes, basis, supports, refutes). recursive-CTE lineage + pgvector retrieval live in one store.
run:recordthe single idempotent funnel for every result — agent-posted or job-produced. a retried job never double-writes. managed campaigns are just this same write with a durable runner in front.
the briefthe smallest high-signal packet an agent loads to continue: what's open, what not to repeat, the best result so far. recomputed on every write.
reproducethe trust button. re-run any node at its pinned commit + seed; the result is pass/fail plus the delta. the claimable number is the verified mean, never the best single run.