# @leumas/memory-web — memory.leumas.tech

memory.leumas.tech — knowledge banks a person owns, and the scoped agent tokens that let Cursor, Claude, Ollama and Leviathan read exactly the parts they were given.


Knowledge banks a person owns, and the scoped agent tokens that let Cursor, Claude, Ollama and
Leviathan read exactly the parts they were given.

A thin React shell. Everything it does is `/api/knowledge`, served by
[`@leumas/knowledge-service`](../../shared/services/knowledge) — read that package first if you are
changing behaviour rather than layout.

```
pnpm dev memory          # http://127.0.0.1:5088  (needs `pnpm dev api` for the API)
pnpm -F @leumas/memory-web build
pnpm smoke:memory        # the routes, over real HTTP
pnpm check:memory-access # the permission rules, against real SQLite
```

## Pages

| Route | What it is |
|---|---|
| `/` | The front door. The only page that works signed out. |
| `/banks` | Your banks, with inline creation. Built-in reference banks sit behind a second tab. |
| `/banks/:id` | One bank — Content (with the drop surface), Variables, Push, Access. |
| `/search` | Cross-bank search. Scoping is entirely server-side. |
| `/agents` | Mint, list and revoke agent tokens. The secret is shown once. |
| `/connect` | Paste-ready setup per client, plus the webhook and live-stream recipes. Public. |
| `/activity` | What agents did, including what they were refused. |
| `/pricing` | Reads `GET /membership/plans`. Never hard-codes a price. |

## Four things that will bite you

**Never introduce a base URL.** Every path in `src/api.js` is relative, because the httpOnly
`leumas_session` cookie only travels same-origin. In production the Imperium worker proxies `/api`
and `/auth` to leumas-api; in dev the Vite proxy forwards the same list. Setting `VITE_API_BASE`
makes every call cross-origin, the cookie is dropped, and the whole app renders as permanently
signed out with nothing in the console to explain it.

**The site row is provisioned by the API, not by this deploy target.** `ensureMemorySite` runs at
leumas-api boot. `pnpm deploy:memory` alone ships the frontend and leaves the subdomain 404ing until
leumas-api is released too.

**Media never travels as JSON.** A document is posted to `/banks/:bank/ingest` as `{ filename, text }`
and parsed into items. An image or video goes to `/api/storage/upload` as multipart (512MB) and is
then LINKED to an item by reference. Putting a video in a JSON body is how upload broke in the media
manager.

**`Button` takes no `as` prop.** It renders a real `<button>` and spreads the rest onto it, so
`as={Link}` is silently ignored — the control renders, looks right, and does nothing. Navigate with
`useNavigate`.

## Ports

`memory` is **5088** in `ops/infra/scripts/ports.mjs`, which both `dev.mjs` and `vite.config.js` read.
It was authored as 5080 on the branch it was built on; `workflows` has that number now.


---
Source: products/leumas-memory/README.md
Canonical: https://docs.leumas.tech/p/products/memory-web
