How it works · services
Services
Every box comes with five services built in: a browser, Memory, a public folder, a messaging gateway and a scheduler. Nothing to install and nothing to set up; they update with the box. You use them by asking Claude, and the box's page shows each one under Services: whether it is up, what is in it, and where to reach it.
browser.home.<handle>.bettik.dev- The browser's live view: watch it, and sign in to sites yourself. Only you can open it.
memory.home.<handle>.bettik.dev- Memory: what you have asked Claude to remember. Only you can open it.
public.home.<handle>.bettik.dev- The public folder,
~/public: a file opens for anyone with its link. gateway.home.<handle>.bettik.dev- The gateway: something outside posts a message, and your sessions get it.
The browser
One Google Chrome per box. Your sessions and you share it, each in a context of its own -- its own cookies, storage and tabs. From the workbench it is bettik-browser:3000:
const browser = await chromium.connectOverCDP('ws://bettik-browser:3000/cdp/my-test?holder=me');
const page = await browser.contexts()[0].newPage();
- A named context is kept: a test login survives between runs. One session writes in it at a time; others may look. With no name,
/cdpis a throwaway. - Your own context holds your real logins. You sign in by hand on its live view,
browser.<zone>(only you can open it), and pick which context it shows. A session goes in only when you ask. - A session that meets a login or a 2FA code sends you a link to the live view: you do it there and press Done, carry on. Your password goes from your fingers to the page.
- Chrome starts when something needs it and stops after 15 minutes with nothing connected.
- The box's page shows each context on a page of its own (Contexts and recent use on the Browser card): which are open, who holds each, and when they last used it.
Memory
What you mean when you tell Claude "remember this": facts about you and your settings, the people around you, a journal, notes, to-dos. Every change is kept with who made it, and you can read it yourself at memory.home.<handle>.bettik.dev (only you can open it).
Every session on the box uses it without being set up. Sessions have its tools (they show as memory), and the box tells them that "remember this" goes there, to read it before guessing about you, and to say which space before writing to one other people share. Reading and adding need no approval; deleting does. In a terminal, the memory command does the same:
memory remember "I take my coffee black" --path about-me/preferences.md
memory recall coffee
memory show about-me/preferences.md
memory list
Memory is a set of spaces. Me is yours; what you put under about-me/ in it is read into every new session, so Claude knows the basics without being told. Other starting places are people/ (a page per person), journal/ and notes.md, but any file is fine.
Bringing in what Claude remembered before. If Claude has been keeping its own memory files, bring them in once: on the box's page, Spaces and sharing (from the Memory card) offers Bring in Claude's own memory files, and says what it will do before it does it; in a terminal memory import claude does the same. They go into Me under notes/claude/, one file each; bringing them in again changes nothing that is already the same, and the files stay where they were.
On every box you have. Memory is yours, not the box's: every box you own holds a full copy, and the copies keep each other up to date on their own, every few minutes and after every change. A new box fills itself in, and destroying one loses nothing. There is nothing to set up and no setting saying which boxes; the boxes find each other through Bettik, and each proves it is yours with a token Bettik signs, so nobody else's box can read or write your Memory.
Sharing a space. Make a space for what you share -- "Sales team", a project -- and invite someone by their Bettik handle or email: ask Claude, or open Spaces and sharing from the Memory card on the box page: a card per space with who is in it and Share, and New shared space to make one and invite someone in one go. They get an email too. Every box of theirs hears of it, they say yes from any one (ask Claude, or follow the notice on the box page to Join on Memory's page), and from then on the space is on every box of everyone in it, each a full copy. Ask Claude what is shared and with whom, or to take someone out: they keep what they had and get nothing new. When someone else changes a shared space, the box posts to the gateway topic memory, so a session subscribed to it hears "jordan changed Sales team: pipeline.md". Me is never shared.
Backed up to your Google Drive. Connect a Drive once, in your settings under Memory backup, and once a day one of your boxes copies your Memory there, into a folder called Bettik Memory: every space you are in, with its whole history, and a copy you can read as Markdown. The last seven are kept. Bettik is allowed only the files it makes there, never the rest of the Drive, and the Memory card says when the last copy was made. Back up now makes one within minutes. To restore, download a copy from that folder and choose it under Restore in the same place (or memory restore <file> in a terminal): it is merged in on one of your boxes, never undoing anything written since, and your other boxes get it within minutes. The file is enough; no Drive is needed to restore.
It holds no secrets: a token or a password goes in your env vars, never in Memory, and memory remember and memory import refuse the obvious ones.
The public folder
~/public in the workbench, beside ~/scratch. Put a file in it and it opens at public.home.<handle>.bettik.dev with the same path, for anyone with the link -- ~/public/trip/photo 1.jpg is https://public.home.<handle>.bettik.dev/trip/photo%201.jpg. It opens as what it is, so a song plays and a picture shows on a phone.
It is public, and there are no settings. Names can be guessed and links get passed on, so if a file should not be seen, it does not go here. Nobody else can list the folder: a visitor either has a file's link or gets a 404. You can, signed in, by opening the address itself: By folder, or Newest first, the 50 latest from every folder (public.home.<handle>.bettik.dev/.recent). A file called .recent at the top is never served: the name is the list's. Nothing expires; a file stays until you delete it, and Claude can tidy it for you by date.
Claude puts a file here when you ask it to share one, and when it has made something for you to see -- a screenshot, a render -- and cannot send it to you in the chat. It says so, hands you the link, and offers to delete the file once you have looked. Nothing private goes here.
The gateway
Every box has a messaging gateway: the way into your sessions from outside. Something outside the box -- Cue, an email service, CI -- posts a message to a topic, like ci or email. The box keeps it for a week and delivers it to each session subscribed to that topic, waking one that is asleep.
From outside it is https://gateway.home.<handle>.bettik.dev, and every post carries a token. Ask Claude to make one for the producer: "make a gateway token for GitHub to post to ci". A token posts only to the topics it was made for, at most 120 times a minute, and Claude can revoke it. A service that lets you set only a URL, like a Jira or GitHub webhook, gets the token in the address instead: https://gateway.<your box>/hooks/<token>/ci. Whatever it sends is kept as it came, its JSON and its headers too (but secrets), up to 256 KB.
curl -X POST https://gateway.<your box>/topics/ci \
-H 'authorization: Bearer gw_…' -H 'content-type: application/json' \
-d '{"text": "CI failed on main", "data": {"run": 7}}'
Subscribing is asking too: "subscribe this session to ci", "who gets email?". In the workbench, the gateway command does the same: gateway post, gateway topics, gateway subscribe, and gateway wait, which a session runs to read a busy topic itself instead of being sent each message. A message is from its producer, not from you, and sessions treat it that way.
It is for messaging your sessions, not a general webhook endpoint. Every message is meant to be read by Claude: a CI failure, an email to handle, a call starting. It takes 120 posts a minute from a producer and keeps a week, and there it stops on purpose -- no routing, no filtering, no logic of its own. When a service sends a lot, or what it sends needs sorting before anyone should see it, put something in between: an environment, or a small service somewhere else, that receives the webhook, does the work, and posts to the gateway only what a session should hear, in words a session can act on.
One path on it goes elsewhere: /cue-llm/. In Cue's ElevenLabs voice mode, ElevenLabs' cloud asks your box for each reply there, and the box passes it, streamed, to the call's host in the workbench (port 8788, only while a call is up). It needs no gateway token: the host checks each call's own secret. The workbench sets it up on its own, and nothing else on the box is reached this way.
Timers
The box's scheduler keeps timers, and each one posts to a gateway topic on time. "Brief me at 7:30 on weekdays" becomes a row that posts to a topic like briefing at 7:30 in your time zone, and the session subscribed to that topic does the briefing. A timer only posts. If the box was down at 7:30 and is back by 8:00, it fires late; later than that, it skips the day. "What timers do I have?" and "pause the briefing" work the same way.