Korely

CLI

The Korely memory API from a shell, a fraction of the tokens. The CLI is what you reach for when you already know what to pull: cron jobs, CI prep, editor commands, shell pipelines, and any workflow where you drive the query yourself instead of waiting for an agent to.

Subcommands mirror the REST endpoints and SDK methods, so anything you learn on one surface transfers to the other. Output is human-readable by default and JSON with --json when you want to script. The same three scoping keys (--user-id, --agent-id, --run-id) mean the same thing here as in the SDK.

Install and authenticate

The CLI ships inside the Python package. One install gives you both the korely_memory import and the korely command. Get a key with one command: korely init --agent mints a free Hobby key and saves it to ~/.korely/config.json, so every command just works. Key precedence is --api-key > KORELY_API_KEY > ~/.korely/config.json.

korely cli zsh
# Install: gives you both the Python package and the korely command
$ pip install korely-memory

$ korely --version
korely 0.1.2

# Sign up — mint a free Hobby key, saved to ~/.korely/config.json
$ korely init --agent
You're set — a free hobby key was minted and saved to ~/.korely/config.json (chmod 600).
  tier    hobby    region eu-hel1

# Already have a key? Set it in the environment instead
$ export KORELY_API_KEY=kor_live_...
$ korely auth
 Authenticated  key kor_live_…  base https://api.korely.ai
  0 end user(s) stored.

# Or pass the key inline for one-off commands
$ korely search "any topic" --api-key kor_live_... --limit 3

Command map

Every subcommand maps to a REST endpoint and the matching SDK method. Scoping options use --dashes; positional arguments (query text, memory ID) are plain words.

CommandSDK equivalentWhat it does
korely init --agent Mint a free Hobby key and save it locally. The one command that needs no key.
korely add "..." korely.add() Write a memory. Graph + temporal extraction included.
korely context "..." korely.get_context() Assembled, prompt-ready context block. The recall path that uses the typed facts — reach for this first.
korely facts korely.get_facts() Bi-temporal typed facts as a flat list. Two-stage contradiction resolution included.
korely search "..." korely.search() Semantic vector search over the raw memories.
korely profile korely.get_profile() Assembled profile of one end user.
korely get <id> korely.get() Full content of one memory by ID.
korely users korely.users() End users you have stored data for.
korely delete <id> korely.delete() Forget one memory (audited).
korely delete-all --user-id ... --yes korely.delete_all() GDPR forget: every memory + fact for one end user.

Write a memory and search it

Scope every call with --user-id (your end user, unlimited on every tier) and --agent-id (your application's namespace). Filters are additive: a search scoped to a --user-id never sees another user's memories.

korely cli zsh
# Write: graph + temporal extraction included in the call
$ korely add "Prefers invoices as PDF, replies fastest before 10am CET" \
    --user-id customer-4812 --agent-id billing-bot
stored  mem_8f3a21c...

# Facts are extracted asynchronously — typed triples land shortly after
# Read it back, scoped to the same end user
$ korely search "invoice preferences" --user-id customer-4812
[0.930] "Prefers invoices as PDF, replies fastest before 10am CET"
        mem_8f3a21c...
[0.810] "Asked for a consolidated monthly invoice, finance@ in CC"
        mem_3b1d90a...

Reads are retrieval, not generation. Most read subcommands are deterministic SQL lookups over your typed facts, zero AI calls. search embeds the query (a fraction of a hundredth of a cent) and retrieves by semantic vector similarity. No generative model composes output on the read path; the model in your pipeline does the reasoning. That is why read quotas are an order of magnitude more generous than write quotas. Full detail in Architecture.

Query facts

korely facts returns typed (subject, predicate, object) triples with bi-temporal validity as a flat list. A facts read is deterministic and typically returns in under 50 ms. Works on every tier, including the free Hobby plan. For the same facts grouped by predicate family, use korely profile.

korely cli zsh
# Current state only: invalidated facts are excluded by default
# Predicates are normalized — "prefers" is stored as "likes" (raw verb in predicate_raw)
$ korely facts --user-id customer-4812
  customer-4812 · likes · PDF invoices [from 2026-06-11]
  customer-4812 · likes · replies before 10am CET [from 2026-06-11]

# JSON for scripts: pipe straight into jq (facts are under .facts)
$ korely facts --user-id customer-4812 --json \
    | jq -r '.facts[] | "\(.predicate): \(.object)"'
likes: PDF invoices
likes: replies before 10am CET

Add --include-invalidated to see the full history, with superseded facts included. How invalidation works, and why the stale fact never reaches your agent by default, is covered in Temporal facts.

Search, retrieve, pipe

The pattern for "answer a question from memory" from a shell: assemble a compact, prompt-ready block with context — the recall path that stitches together your end user's active typed facts — then hand it to whatever model you already run, local or hosted. Reach for raw search when you want the underlying memories instead of the assembled view. Either way you pull exactly what you need instead of letting an agent explore, and the same answer costs a fraction of the tokens.

korely cli zsh
$ korely search "EU pricing decision" --user-id alice --limit 3
[0.920] "Approved the move to the 50 euro per month plan, effective July."
        mem_9f2c1a...
[0.870] "Plan change approval signed by finance."
        mem_3b1d9...
[0.810] "Q2 budget retro: EU contracts renewed."
        mem_7a4c2...

$ korely get mem_9f2c1a
mem_9f2c1a  (2026-06-11T09:12:44)
Approved the move to the 50 euro per month plan, effective July.
Marco signs off on the renewal quote; finance updates the forecast...

# Hand a compact context block to a local model
$ korely context "EU pricing decision" --user-id alice | ollama run llama3.1 "summarize the decision"
The team approved moving to the 50 euro per month plan, effective
July, with Marco signing off on the renewal quote.

Scoping and output flags

FlagApplies toMeaning
--user-id add, search, context, facts, profile, delete-all Your end user's identifier. Free-form, unlimited on every tier.
--agent-id add, search, context, facts, users Your application's namespace. One app, one --agent-id.
--run-id add One session. Useful for episodic recall inside a single run.
--limit N search, facts, users Result count. Keep it small; you are paying for your own model's context.
--api-key all commands Override KORELY_API_KEY for this call.
--base-url all commands Override the API base URL (default https://api.korely.ai).
--json all commands JSON on stdout instead of human-readable text. Built for jq, scripts, and CI.
--entity facts Filter facts where this string appears as subject OR object.
--subject facts Filter facts by subject only (more precise than --entity).
--family facts Predicate family to filter by. The taxonomy is limited; many verbs map to other, so prefer --entity or --subject when in doubt.
--as-of DATE facts, profile Point-in-time query. Returns only facts valid on that ISO date.
--include-invalidated facts Include superseded facts in output. Off by default.

A worked example for scripts: a cron job that dumps open action items every Monday, ready for any pipeline.

Terminal window
# crontab: every Monday at 07:00
0 7 * * 1 korely search "open action items" --user-id team --json > /var/data/weekly.json

End-to-end: onboard, enrich, and query a customer

This example walks the full lifecycle of one end user from a shell: write memories during onboarding, extract and inspect the typed facts, search by topic, assemble a prompt-ready context block, and erase everything on request. Each step is a single command.

end-to-end zsh
# ── 1. Authenticate ───────────────────────────────────────────────
$ export KORELY_API_KEY=kor_live_...
$ korely auth
 Authenticated  key kor_live_…  base https://api.korely.ai
  0 end user(s) stored.

# ── 2. Store onboarding context ───────────────────────────────────
$ korely add "Works at Northwind Hosting as head of infrastructure." \
    --user-id customer-4812 --agent-id support-bot
stored  mem_8f2c1a

$ korely add "Current plan costs 50 euro per month. Renewed on June 1." \
    --user-id customer-4812 --agent-id support-bot
stored  mem_b91e3d

# ── 3. Write a contradicting fact — facts extract asynchronously, ─
#    and the old price is superseded once they land ───────────────
$ korely add "Upgraded to the 75 euro per month plan on June 15." \
    --user-id customer-4812 --agent-id support-bot
stored  mem_f4a890

# ── 4. Inspect current typed facts ────────────────────────────────
$ korely facts --user-id customer-4812 --subject customer-4812
  customer-4812 · works_at · Northwind Hosting [from 2026-06-11]
  customer-4812 · role · head of infrastructure [from 2026-06-11]

$ korely facts --user-id customer-4812 --entity Northwind Hosting
  Northwind Hosting · costs · 75 euro per month [from 2026-06-15]
  (1 superseded — run --include-invalidated to see)

# ── 5. Point-in-time: what did we know before the upgrade? ────────
$ korely facts --user-id customer-4812 \
    --entity Northwind Hosting --as-of 2026-06-12
  Northwind Hosting · costs · 50 euro per month [from 2026-06-01, invalid 2026-06-15]

# ── 6. Semantic vector search ─────────────────────────────────────
$ korely search "plan pricing" --user-id customer-4812 --limit 3
[0.950] "Upgraded to the 75 euro per month plan on June 15."
        mem_f4a890
[0.880] "Current plan costs 50 euro per month. Renewed on June 1."
        mem_b91e3d
[0.760] "Works at Northwind Hosting as head of infrastructure."
        mem_8f2c1a

# ── 7. One-call context block, ready to paste into a system prompt
$ korely context "billing question" --user-id customer-4812
--- korely context (642 tokens, 3 sources) ---
[fct_b91e] Northwind Hosting · costs · 75 euro per month (from 2026-06-15)
[fct_3d0f] customer-4812 · works_at · Northwind Hosting (from 2026-06-11)
[mem_f4a890] Upgraded to the 75 euro per month plan on June 15.
[mem_b91e3d] Current plan costs 50 euro per month. Renewed on June 1.
----------------------------------------------

# ── 8. GDPR: erase one end user in full ──────────────────────────
$ korely delete-all --user-id customer-4812 --yes
forgotten  3 memories, 4 facts  audit aud_3d0f

Error reference

The CLI exits non-zero and prints a one-line error on stderr. Pass --json to get a machine-readable object with a code field for scripts.

Exit / codeWhen it happensHow to fix it
401 invalid_key Key is missing, malformed, or revoked. Check KORELY_API_KEY. Rotate if needed in the dashboard.
403 agent_cap_exceeded The --agent-id is a new namespace and you are at your plan's agent limit (2 on Hobby, 10 on Developer, 100 on Team, 500 on Scale). Delete an unused agent or upgrade your plan.
404 not_found korely get or korely delete was called with an id that does not exist or was already forgotten. Verify the id with korely search first.
409 stale_write An update was rejected because another writer changed the record since you last read it. Re-fetch with korely get and retry. Only relevant to programmatic update calls, not shell pipelines.
422 invalid_request Malformed request: a required field is missing or a value is the wrong type. Message reads <field>: Field required. Check flag spelling and required positional arguments.
429 quota_exceeded Your monthly write or query quota is exhausted. The write-quota response carries no Retry-After; the per-second rate-limit response does (a Retry-After header, in integer seconds). Wait until the month rolls over, or upgrade your plan. Reads are an order of magnitude more generous — most scripts hit the write limit first.

No overage charges, ever. At 80% of quota you receive an email warning. Past 100% there is a +10% grace window so a busy day does not break your script. Past that, commands fail with 429 until the month rolls over or you upgrade. Your bill is always exactly the tier price: Hobby free, Developer €19, Team €79, Scale €249.

Related

  • Surfaces overview: when to reach for the CLI versus the SDK versus the REST API directly.
  • SDK: the same operations from Python or Node, with typed return values and structured exceptions.
  • API reference: the REST contract the CLI calls under the hood, with full request and response shapes.
  • Temporal facts: the bi-temporal model behind korely facts and --as-of.
  • Cookbook: chatbot that remembers: a working loop using context and add.
  • Architecture: why read quotas are an order of magnitude more generous than write quotas.