Getting started
From a new account to a model that remembers, in seven steps — sign up, verify your address, make an API key, install the package, sign in from the terminal, remember and recall, and see your memory in the console. Each step has a recording of it running.
The short answer
Make an account with your e-mail address, install statejar, run statejar login once, then call ingest to store what a message says and recall to get the memory a question needs. recall gives you memory_context, which you put in front of your own model as its system message. Your code calls your model, and its key never reaches StateJar.
Every recording on this page is a real run of StateJar on one machine, in one throwaway account: the site at localhost:18173 and the API at 127.0.0.1:18100, where statejar.com has statejar.com and api.statejar.com. Each caption says when it was recorded and how.
1. Sign up
Open the sign-up page and enter your e-mail address, then choose Send me a code. StateJar e-mails you a one-time code. Your account is made only when you type that code in, so every account starts from an address that was proved.

If the sign-up page offers only a password, that server cannot send mail yet. Sign up with a password and go on to step 3.
2. Verify your e-mail
The message holds an 8-digit code that works for 10 minutes, once. Type it in and choose Create my account. You are signed in, and the account exists from this moment. The next page asks for a display name and the like, all optional.

The recording reads the code from a test inbox on the same machine: the server sent the message over SMTP to a mail receiver there, not to the internet. Yours arrives in your own inbox. If it does not, look in the spam folder, or choose Send a new code.
3. Create an API key
A developer key is how your code calls StateJar from a server or CI. On API keys, under Developer API, give the key a name, choose how long it lives (7 days, 30 days, 1 year or never), and choose Generate key. The key is shown once: copy it into your secret store, or into STATEJAR_API_KEY. StateJar keeps only its SHA-256 hash.

On your own machine you do not have to copy a key: step 5 stores one for you.
4. Install the package
pip install statejar
The package is the Python SDK and the statejar command. For JavaScript, npm install statejar gives you the Node SDK (Node 20.3 or later).
pip install of statejar 0.7.0 as built from StateJar's repository (taken from ~/dist, which the recording lists first), then statejar --version. From PyPI, pip install statejar installs the current release, 0.6.0, until 0.7.0 is published. Recorded 27 Oct 2026 against a local StateJar server; the output is real, with pauses over 3 s cut to 3 s. Full sizeThe recording (.cast)5. Sign in from the terminal
statejar login
statejar whoami
statejar login prints a link with a code, opens it in your browser where it can, and waits. On that page, signed in, check the code and the device's name, and choose Approve. The terminal then receives a developer key for this machine. The key lasts a year, reaches only the memory API, and is stored in your keychain or in a file only you can read. Your password never goes through the terminal.
statejar login prints the approval link with its code and waits. The code is approved on the site (the next recording), the terminal stores a key and prints its last four characters, and statejar whoami names the account. Recorded 27 Oct 2026 against a local StateJar server; the output is real, with pauses over 3 s cut to 3 s. Full sizeThe recording (.cast)
statejar login printed: the code and the device's name shown, Approve pressed, and the new key's last four characters and expiry. Recorded 27 Oct 2026 in Chromium, on this site built from the same code, against a local StateJar server: every frame is a screenshot of the real page; waits for the server are shortened. Full size6. Remember and recall
ingest stores the facts a message states, as typed fields, never the message itself. recall returns the memory a question needs as memory_context. With no key in the code, the SDK uses the one statejar login stored.
from statejar import StateJar
# the key comes from `statejar login` or STATEJAR_API_KEY; one tag per conversation
sj = StateJar(session_tag="user-42")
sj.ingest("I'm Meera from Pune and I prefer email.") # typed facts, no transcript
sj.ingest("My budget is ₹3,500.")
hit = sj.recall("What is my budget?", audit=True) # what the question needs
print(hit["handle_used"]) # shm_… — a SHA-256 of the canonical state
print(hit["memory_context"]) # the system message for YOUR model, nothing else
statejar login stored, on statejar 0.7.0 as built from StateJar's repository (PyPI's 0.6.0 has the same calls): two messages in, one question out, then the handle and the memory_context your model gets, the whole state since it is small. The account already held these facts from the terminal, so nothing new is stored and the handle is the one statejar add printed. Recorded 27 Oct 2026 against a local StateJar server; the output is real, with pauses over 3 s cut to 3 s. Full sizeThe recording (.cast)The same in JavaScript, with the key in STATEJAR_API_KEY:
import { StateJarClient } from "statejar";
const sj = new StateJarClient({
baseUrl: process.env.STATEJAR_BASE_URL ?? "https://api.statejar.com/api/v1",
// apiKey: STATEJAR_API_KEY is read automatically in Node (never in a browser)
});
const tag = "user-42"; // one tag per conversation
await sj.ingest({ sessionTag: tag, text: "I'm Meera from Pune and I prefer email." });
await sj.ingest({ sessionTag: tag, text: "My budget is ₹3,500." });
const query = "What is my budget?";
const hit = await sj.recall({ sessionTag: tag, query, audit: true });
console.log(hit.handle_used); // shm_…
console.log(hit.memory_context); // the system message for your model
npm install of the statejar package 0.3.0 as built from StateJar's repository (npm serves 0.2.1, which has the same calls), then the first-turn example in JavaScript, its key the one statejar login stored, read into STATEJAR_API_KEY. Same account and facts as the Python run, so it ends on the same handle. Recorded 27 Oct 2026 against a local StateJar server; the output is real, with pauses over 3 s cut to 3 s. Full sizeThe recording (.cast)The handle (shm_…) is the SHA-256 of the stored facts, so the same facts give the same handle on any machine. That is why the Python and JavaScript runs end on the same handle. To put memory_context in front of Claude, OpenAI, Gemini or a model on your own machine, see any LLM provider.
7. See your memory in the console
The Dashboard counts your sessions, versions and disclosures, and lists the newest handles with the scope each came from. The Audit log lists every disclosure with its handle and the fields it sent. Replay on an entry re-derives the handle from the stored state and shows the exact facts the model was given.

Questions
- There is no browser on this machine (a server, SSH, CI). Run
statejar login --no-browserand open the link it prints on any device where you are signed in. Or setSTATEJAR_API_KEYto a key from step 3. - Can I remember and recall from the terminal alone? Yes, with
statejar addandstatejar searchin statejar 0.7.0, which is not on PyPI yet; the statejar command shows them running. - I use an assistant or an agent, not my own code. Use the plugin for Claude Code, Codex, OpenCode, OpenClaw or Hermes Agent, or add the MCP server to any client that speaks MCP.
401 invalid or missing API key. The key is not set, was revoked, or belongs to another server (staging and production keys differ).statejar whoamisays which account a stored key belongs to;STATEJAR_API_KEYwins over the stored key.401 API key expired. Keys fromstatejar loginlast a year, and keys from the API keys page as long as you chose. Runstatejar loginagain or make a new key.stored: false, handle: null. Not an error: the message held no fact to store, such as a greeting or a question.memory_contextstill comes back when earlier versions exist.confirmations: [...]. An amount with no claim attached ("i have 5000 rs") is asked about, not stored. Callconfirm(id, accept), or ignore it: nothing is written until you do (the Python SDK shows it running).429 Too Many Requests. Your plan's limit, or too many requests a minute from one key. Wait for the window (what each limit counts).StateJarConnectionError. The request never reached StateJar: DNS, a proxy, orSTATEJAR_BASE_URLpointing at something that is not an API root ending in/api/v1.
This page as Markdown: /docs/getting-started.md