What's New
Release notes for K2. Updates are published to GitHub.
v0.46.2
Latest0.46.2 — The tunnel stays up
K2 Connect
.k2.dev unreachable until you turned the tunnel back on by hand. K2 also gives the certificate service up to 4 minutes per request, up from 1, and tells it how long it will wait, so the service's new DNS checks and retry have time to finish.Projects
k2 project read) or post in it (k2 project msg) only when its workspace is a member of that project; any other project's chat answers not_a_member. An agent also always posts as its own workspace. You, your Connect logins and the desktop app see and post in every project's chat as before, and App guests still can't.GET /cli/project-group/messages takes before_seq and limit (up to 500) to page back through a project's chat, so the phone can scroll back instead of showing only what it already has. Servers advertise it as project-chat-paging-v1.Chat
v0.46.1
0.46.1 — Apps leave preview
Apps: the wall
--cmd services run in a wall. On a server with the App runtime set up, a new k2 publish run --cmd … becomes an open-path App: a container with a fresh copy of your folder at each start. Keep anything that must last in $K2_APP_DATA (/data). Your --port stays the port inside, it can go out to the internet through its own proxy (every host it reaches is logged), and it reaches K2 through its own door. Run it again to deploy your changes; k2 publish stop|start|rm work as before. k2 app list labels it Open (container) and says how to move it to guarded. Services you already published keep running exactly as they do today. On a Mac, or a server not set up for Apps, --cmd works as before and says why.--cmd service needs "Allow this agent to manage Apps" and "…and publish open Apps" on its workspace; without them it waits for you in k2 app approvals.build, k2 app build and k2 app deploy --folder run it in a container, never on the server itself: only the command you declared, a lockfile is required next to a package.json, only the package registries are reachable, and on guarded Apps a dependency's install scripts never run.k2 app config --memory 1G ); with a limit, Node's heap gets half of it. An App that runs out of memory stops whole and restarts, it never swaps, and each deployment's log is capped at 50 MB (k2 app logs).k2 app doctor shows it.k2 app box prepare --install-podman downloads K2's Podman bundle from K2's mirror (mirror.alakazamlabs.com, with a second way in) and installs it only when it matches the pinned checksum and carries K2's signature; the source code of its GPL parts sits beside it. Offline, --podman-from takes the tarball and its .minisig.k2 app engine install): this release speaks a new engine protocol, and k2 app doctor says so until you do.K2_APP_ORIGIN (its main public https address: a custom domain bound to it, else https://..k2.dev ) and K2_APP_ORIGINS (all of them), so it can check where requests and websockets come from. Bind a custom domain to an App with k2 domain name add app.example.com --role app:; the App sees changes on its next deploy or restart. An App with no public address gets neither.Apps: the door
k2 app suspend ends every pass the App holds at once, so its very next call to K2 is refused, stops it and freezes its deploys and starts. Anyone who can see the App may do it, its agent included; only you bring it back, with k2 app resume from a terminal outside K2.k2 app audit shows them (--since 1h, --denied, --verb), and --verify checks that no line was changed or removed. The record lives in its own file, ~/.k2/apps/app-audit.db; after 30 days it is kept as daily totals for a year.k2 app quota shows them; lowering one applies at once, raising one is yours (an agent's raise waits for you).k2 app approvals while the running version keeps serving, even when you deploy it yourself. The App's pass carries only what you approved. Apps already behind the wall keep what they have.k2 app doctor does too.k2 app token rotate gives an App that runs on another machine its own pass for K2: it expires (30 days by default), carries only the App's approved permissions, works on K2's main address and tunnel but never at an App's door, and is ended by suspend. k2 app remote-pass lists and ends them.Apps: the server SDK, guest rooms, members and folders
sdk/server (@k2/server, TypeScript, Node 22.18 or newer, no dependencies) is how an App's server talks to K2. fromEnv() reads K2_GATEWAY_URL, the App pass file (K2_PASS_FILE, /run/k2/pass in a wall) and K2_APP_ID/K2_APP_NAME. k2.login({username, password}) logs a guest in through your App; after that every call acts as the guest of the request you're serving (k2.withGuest(pass, …) or k2.middleware()), and a call with no guest fails guest_required instead of quietly acting as the App. Acting as the App is always written out: k2.asApp(). It covers the Thread (with a live socket), files (including resumable uploads), k2 db (db.query, db.rows and row writes, with the guest's identity for your RLS), tickets, the wiki, heartbeats, activity and the agent's name and picture, plus your App's users and rooms through the App key. Answers are typed, and fields K2 doesn't promise (host paths, session ids) are dropped. K2 rotates the App pass every hour; the SDK reads the file again each call and retries once when K2 says the pass is stale.path is relPath). k2 study app-api lists every one with its method, route and permission.GET /cli/skin/me tells a guest or an App its kind, its rooms with the permissions it has in each, and which features this server has (k2.me.get() in the SDK).GET /cli/thread/latest now answers App guests and Apps for their own rooms: the last message per room in one call, up to 50 rooms. A room the pass doesn't hold answers the same skin_room as one that doesn't exist.k2 app grant --kind guests-rooms [--room ]… , and its server can read and reset its own guests' rooms with its own pass (k2.asApp().guests.setRooms({username, rooms}), or GET|POST /cli/skin/guests/rooms). It reaches only its own guests, only the rooms you listed plus its own, and never more than a guest's role allows. Setting the same rooms again changes nothing, every change is recorded with before and after (k2 app history ), and an App may make 60 of these calls a minute. Agents do the same within your grant with k2 app guest rooms [set …] . A Garden widget can too (k2.guests.setRooms, for any App on this computer), and K2 asks you on its own sheet before every change.db/query, db/rows) are pinned as contract tests that run through the SDK against a real daemon, outside the wall and from inside it.room:members, off by default; grant it per room like any other (k2 app role room --caps thread:read,room:members ). An App sees only its own guests. In any room you can hide guests' names from Apps with k2 app room-names hide ; you still see every name, and so do your Gardens. Agents read the list with k2 app members, and an App hears room_members_changed on the room's live socket when it changes.app.self tells an App its id, the version that is live, whether it is running, and when it went live; app.usage gives its limits, its live connections and how many calls it made to each K2 action (from its own call record). Each App sees only its own; asking about another App gets the same answer as asking about one that doesn't exist. You and its agent read the same with k2 app self and k2 app usage , and the App hears app_deployed when a new version goes live.k2.room.members(…) (with every name, since a Garden acts as you), k2.app.self(…) and k2.app.usage(…) for any App on this computer, and k2.widget.self() for its own id, live version, who made it and its last seven days of saves. k2 study app-surfaces has the details.k2 app role paths --read jobs/J1/,jobs/J3/ --write jobs/J1/photos/ limits that role's logins to those folders in that room. It works on any room the role holds, not only a login's own room, and agent logins (k2 app user agent) get exactly the same walls as people. Anything else in the room is refused with the same answer as a missing permission, whether or not it exists. A listing shows only the way down to the granted folders, a link inside a granted folder can't reach outside it, live file updates carry only those folders, and k2.me.get() lists them. --clear gives the whole room back. --upload-dir sets where an upload lands when it names no folder.files.stat (GET /cli/fs/stat) returns a file's or folder's kind, size, modified time, extension and content type, under the same folder rules, so an App doesn't have to list the parent folder to show a download's size.Sew chat and calls
k2 app grant --kind chat ) gets a short-lived chat pass, on each App's own link, several Apps per box. Removing a grant or a login ends its Sew sessions, and Connect logins can sign in to Sew too.k2 hostchat upgrade and rollback move the voice engine with the core; a refused upgrade now says why.k2 front enable puts a small router on the box's port 443 so people on networks that only allow 443 can join calls (Sew 0.2.1's TURN passthrough behind the :443 front), with Caddy behind it and hosted mail optional (--mail).k2 front enable restarts the K2 daemon once to take port 443 (systemd hands it the socket); if port 443 is already in use, it names what's holding it.k2 hostchat meet bind points meet..k2.dev at your Meet App; unbind takes it back.k2 hostchat status (and enable) warn until Sew's public URL is set, and show the command that sets it, so password setup links and invites open from outside the box.k2 hostchat purge, rollback and restore hints point at k2 hostchat backups and k2 hostchat restore, and the PostgreSQL hint no longer names a setup flag that doesn't exist.--voice, --voice-url and --node-ip only apply to k2 hostchat enable, and --media-tarball to enable, upgrade and rollback; elsewhere K2 now stops and points you at k2 hostchat media install --tarball.Mail and calendars
k2 calendar works on its calendars (list, events, create, update, delete, free/busy); Settings adds a calendar to a link that was consented for mail only (k2 mail link calendars).k2 calendar works on a linked Google account too, including a calendar-only link. Writes never send invitations.k2 hostmail status shows the certificate mail apps really get. It now checks ports 443, 465 and 993 with the mail hostname and reports the worst one, so a self-signed fallback on 465 or 993 no longer reads as issued. A certificate for the wrong name or an expired one says so. The ACME task state is read fresh, and a task older than the certificate now served reads unknown instead of a stale Pending.k2 hostmail doctor unlocks direct sending for that domain. It runs every server check too, so you no longer need a separate bare k2 hostmail doctor first. When direct is still locked, the message names the exact command to run.k2 hostmail domain show stops recommending records that can't work yet. On a domain whose DNS isn't on K2's nameservers, the MTA-STS and mail-client autoconfig records now say "skip for now" and are left out of the zone file, because those names can't get a certificate there yet. The DMARC record it lists always includes rua=mailto:postmaster@.k2 hostmail create (the old k2 mail create moved).Phones: previews, unread counts and Homes
k2 thread unread shows yours, and a Thread or project chat can be muted.after_seq), oldest first, along with any card answered, voided or expired since then, so K2 Companion shows a chat at once and catches up behind it (feature thread-delta-v1).Secrets between agents
k2 vault send NAME --to (or k2 msg … --secret NAME) sends a secret to another agent, on this server or another one, sealed vault to vault; the receiver accepts or declines (k2 vault incoming, accept, accept-from), and asks, replies and unsend work too. The value is never in a Thread or a file. Settings → Logs → Access Audit has a "Vault handoffs" filter.k2 vault carry export, you get a ticket naming the agent, the secrets (names only, never values) and where they went. Settings → Logs → Access Audit highlights the export.Gardens
look = "garden" under the board's [widget.props.config].k2:*@2 cards take several sources, soft warn and crit levels and named lists; sources gain age, version and field-compare rules with per-rule thresholds, and k2 sources secret a b c NAME sets one secret for several sources at once.~/.k2 and check, preview and write it whole (k2 zen validate --dir, k2 zen widget preview --dir, k2 zen widget put --dir); a plain validate no longer signs and "pending" exits 0.thread:post and store:write it asks for, reads a neighbour's data with manifest reads and {from}, and a page holds 10 custom widgets with [[widget]] weight. The widget SDK has typed errors, subscriptions that re-subscribe on their own, shape guards and uPlot charts.Messaging
k2 agent identity --color '#22c55e' --image me.png (or --clear-image), and every client updates at once. It can change only its own look, never its name or handle (it's told to ask you), and at most 20 changes every ten minutes. k2 agent identity with no flags shows the current look; from your terminal it still sets any agent's name, color and picture. k2 workspace set-agent-identity keeps working and points to the new command.rpm cort finds Cortana on rpm), and use ↑/↓ and Enter. Agents you already connect to show checked, and the picker stays open so you can add several. A server that doesn't answer within 5 seconds shows Offline with Retry, instead of a long wait followed by a message blaming its settings; a server paired with the older code shows Re-pair. k2 fed peers and Settings → Connected Servers list paired servers in the same A-to-Z order.k2 thread "The report is ready" --file docs/report.pdf --file src/session.rs:212 puts a file chip under the message (up to 10; three or more become a list); click one to open the file at its line. A chip points at the workspace's own file, it isn't a copy: it gets an amber dot when the file has changed since it was sent, and offers Find in Files when the file has moved. Only files inside the agent's workspace can be attached, and anything that looks like a secret (.env, keys, tokens, credentials in the text) is refused. App guests see a file only when their own file access already covers it; otherwise they see "A file (not shared with you)". Push notifications say [file], never the file's name. The server is ready for K2 Companion to preview and download them on the phone.*.pem, *.key, *.p12, ssh keys), .ssh/, .npmrc, .netrc and similar unless you choose to carry secrets, and retiring an agent warns about them.Compute
k2 compute run inside .claude/worktrees/x finds its workspace (even with no K2 session), runs that worktree's own commit, and --dirty sends that worktree's changes. Each run prints which code it sent, and the "uncommitted changes" note no longer appears with --sha.k2 compute wait … blocks until jobs end and exits with the job's exit code. --max-wait 9m stops waiting first. k2 compute run … --wait prints the job id, then waits, and sends no second [compute] message.--force, and k2 compute get shows who cancelled.k2 compute nodes shows free CPU, free memory and your grant.k2 compute status. Every node at a glance: state, foreign-lock waits, running and queued jobs, free CPU and memory, load, and disk against its floor, plus this Mac's free disk and Time Machine snapshot count.--timeout over the grant is refused before anything is sent, with the grant and the command to raise it. A job too big for its node is refused at submit; one already queued is failed with the reason and you get its message. A job killed for memory gets a hint.k2 compute manage on --workspace ), lets that agent add and confirm machines, rename, pause, drain, resume, retire and route them, and grant or revoke them for any workspace, without asking you. Every act is in Access Audit, and adding or confirming a machine sends you an inbox note. Turning compute on or off, removing a machine and the switch itself stay yours. It's off by default, only you (the owner) can turn it on, and it only works for agents on this computer.Project settings
k2 project rename, pin and delete. Rename or pin a project from the terminal; k2 project delete --yes deletes one (owner or admin only).CLI fixes
k2 msg who only ever looks up a sender. An id that didn't start with m_ used to send a live message to a workspace named "who".k2 settings from an agent now says it needs the owner or an admin instead of showing blank settings. k2 inbox read with an unknown id says so. k2 users list from an agent points to k2 connections list --users. k2 compute get with an unknown job exits 4. k2 sources shows one hint, not two.k2 activity takes --help and --json, and shows dates. Before, those flags were read as the number of events. Errors from the server now show instead of "No activity.".k2 hostmail status on a computer without hosted mail says so in one line. Hosted mail runs on Linux K2 servers; for linked inboxes use k2 mail inboxes.k2 compute jobs shows the whole reason a job waits. k2 app token list says "No App tokens.". k2 zen widget errors says what it checked, and two errors at the same moment no longer share a number. Help text names the right commands and variables.Polish
k2 thread … --file, so agents attach the files they mention.v0.46.0
0.46.0 — Runtime for Apps
Getting your Apps ready for 0.46.1 (nothing is taken away yet)
k2 app deploy … --engine guarded) run behind the wall. Your existing k2 publish run --cmd services keep running as before (legacy, unwalled), with clean mode to opt in early and warnings for what they rely on. In 0.46.1 their inherited environment ends; the wall for them comes when you move them over with k2 app adopt. This release takes nothing away; it adds the new ways and tells you what each service still needs. k2 app warnings (or every server App at once) reads the App's code and lists, with file and line, the environment variables it only gets from K2, any read of K2's own files (like the owner token file), the programs it finds only through your own PATH (like node in ~/.local/bin), and, on Linux, each K2 call it made with the owner token. Each line comes with the fix. Owner-token tracing is Linux only for now; on a Mac, warnings and clean mode say so instead of staying silent.k2 app clean-mode on runs that App the 0.46.1 way: a clean environment, the system PATH, its own home folder, and on Linux any owner-token call from it is refused. Turning it on is always allowed (an App's agent can do it); turning it back off is the owner's call.k2 app key mint --scopes users,rooms,fetch makes a key that works for that one App only: it can manage the App's own users and their Thread rooms (only the rooms you allow), send password-reset links to people who use only this App, and call outside services through K2 with a secret by name, so the App never holds the secret. Minting asks you to confirm in person; K2 puts the key in the vault and the App reads it from $K2_SECRETS_DIR/K2_APP_KEY at its next start. Agents never see a key. Every App now also gets K2_APP_NAME and K2_GATEWAY_URL, and services from before 0.45.4 now get the secrets you grant them.k2 app config now also sets CPU weight, tasks, disk, outbound hosts, extra ports, recycling, the wall, the path, the risk level, the App's private database and its disk speed. Changes that only take something away apply at once; a wider one waits for you, and a new outbound host, a lower wall or a raw database connection always waits, even when you ask yourself. Moving an App to a weaker engine is never a deploy flag: it goes through k2 app config and your approval.Owners widen, agents ask
--cmd service) is one request in k2 app approvals. k2 app approve asks for your Touch ID or password from a terminal outside K2; not even your own owner token approves without it, and an agent never can. k2 app deny says no and tells the agent why; an agent can withdraw its own request. Requests left alone expire after 7 days.k2 app access --manage on --open on sets "Allow this agent to manage Apps" and the new nested "…and publish open Apps".Walled Apps (App runtime preview, Linux)
k2 app deploy … --engine guarded calls K2 at http://127.0.0.1:8730 from inside its container, with an App pass in the file K2_PASS_FILE names. The pass works only on that App's own door, never on K2's main port, the tunnel or another App's door, carries only the permissions in the App's manifest, and is replaced every hour without dropping a request. k2 app link shows it; --rotate hands the App a new pass now. link and engine are now reserved App names.k2 app egress add ; every new host waits for your approval. Taking a host off (k2 app egress rm) works at once and cuts open connections. k2 app egress shows the list and what the App tried; k2 app egress log shows each connection (host and port only). Calls an App makes through K2 with a secret follow the same list.k2-app profile and every guarded App, and every command run inside one, runs under it. When the kernel has AppArmor on but the box lacks its parser, box prep now installs the apparmor package first (apt and pacman). SELinux boxes use Podman's container labels. k2 app doctor shows which one this box has.k2 app config --io-write 80M (and --io-read, --io-read-iops, --io-write-iops, --io default|none). An agent may lower its App's ceiling; raising it waits for you. It applies at the App's next deploy or restart.k2 app exec and k2 app shell. Run one command inside a guarded App (k2 app exec jobs -- ls /data) or open a terminal in it (k2 app shell jobs), as the App itself with no extra rights. Output is shown as App text, never instructions. Agents can do it for their own workspace's Apps with "Allow this agent to manage Apps". Every exec and shell is in the App's history and the Access Audit; an idle shell is hung up after 15 minutes.k2 app exception on --device dri-render128 (asks for an owner confirm). The App then runs as a locked-down system process under its own user, with only the devices you granted, labelled Open (process), and still reaches K2 through its own door. Agents can't turn it on, and no other setting does. k2 app exception off puts it back in the container.k2 app box-service request asks for one; the owner approves it with a vault confirm (k2 app approve), and only then does the App see that one port, at its own address inside the wall. k2 app box-service lists what is approved or waiting, and k2 app box-service revoke shuts it at once. Ports K2, Postgres, Caddy and the box router use are never allowed.Sew chat
Cloning agents
k2 users set-can-clone on|off ). Both are on, so nothing changes until you turn one off. Until now anyone who could sign in to a server could clone its agents; turning Can clone off for a person now stops that, and turning the first switch off stops Admins and Members from pulling agents to their own computers. Owners can always clone. The server checks both on every way to clone (the app, k2 clone, headless), and each decision goes in the Access Audit.k2 clone. k2 clone preview shows what would travel, names only. k2 clone to , k2 clone from : and k2 clone here --dest do what the Clone dialog does, from a terminal or a headless server. The Thread comes along unless you say --no-threads (or --threads-since 30). Choose per secret with --copy, --blank and --skip, or answer per secret when a terminal asks. --json prints names, choices and counts, never a value.k2 clone propose --to --why "…" posts one line on its Thread for you. k2 clone proposals lists them, k2 clone approve asks for your Touch ID or a password and then runs the clone as you, and k2 clone deny says no. The agent is told either way; proposals left alone expire after 7 days.sales on rosson.k2.dev" line, with other people's messages shown by name. Imported lines are read-only and Chatter never travels. k2 thread export , k2 thread import --to and k2 thread imports move Threads outside a clone (owners and admins)..env files ask first. "Include secrets" in the Clone dialog is now Send .env files as files. It sends them as plain files inside the clone, so it now asks for Touch ID or your password first (an owner or admin), and offers to move them into the vault instead (k2 vault import .env). Members with Can clone can clone, but can't send .env files or copy secrets. A .env.k2 that holds only k2v:// references now travels with the clone.k2 vault carry is stricter. It never carries K2 logins, App passes or engine credentials, and k2 vault carry import now puts secrets into the workspace with the right id instead of any workspace with the same name.Grok Bots
k2 thread gb:. Agents and App guests still can't.Gardens
k2 zen garden put, k2 zen widget put), with every act in Access Audit. Without the switch, an agent's Garden or widget change becomes a proposal you approve or reject (k2 zen proposals). K2's built-in widgets are never written.k2 sources approve a b c --secret NAME binds one secret to every source in one go, with a single confirm. It binds all or none.sources.* was always refused as "not bound"; it now reads and subscribes to the sources its placement names.Security
k2 users audit. The local wiki site only answers requests addressed to itself or its own published subdomain, sends no CORS headers, and no longer shows your folder path or dot-folder notes. Serve and Public chat are hidden in the app for now; agents can still use k2 wiki serve|publish|unpublish, and k2 wiki chat on stops with exit 3.Changes tab
k2 changes (diff, stage, unstage, discard, commit), on their own workspace only.k2 changes notes). Notes follow their lines as the file changes and say when those lines have changed. Open in editor opens the file, k2 changes open brings up the tab, and a folder that isn't a git repo yet gets Initialize repository (k2 changes init), with the first commit working too. Untracked folders stage in one click.Design mode
k2 workspace design-mode set off ). Agents and scripts can file the same note with k2 browser note.Status marks
Thread
Tabs
Usage
k2 usage. k2 usage tokens, k2 usage turns and k2 usage limits [--refresh] from a terminal. An agent sees its own workspace. Owners and admins see the whole server; members can't.Publishing
k2 publish run --probe-timeout 10m gives a service up to 15 minutes to open its port (the default is still 15 seconds), and restarts and reboots use it too. While it waits, k2 publish ps and status say "starting (waiting for port 3047, 4m12s left)", and a tunnelled service's public address goes live once the port answers. A local service that binds late turns running instead of staying unhealthy. Only when the time runs out is the run rolled back, and it then shows no public address.Browser
A new look
k2 and k2-node command and k2 study page, with search (Cmd/Ctrl+K). When Home shows an agent on another server, the title reads server / agent / branch.k2 users list shows it, but messages are always sent and assigned by username. On the computer K2 runs on, K2 asks once which Admin Access user is you (or helps you create one), replacing the old "This is me" checkbox and "Your name"; your messages to agents then read [from z3thon]. Settings → General → Your account changes it later.Fixes
k2 tunnel status no longer stops with a Python SyntaxError (broken in 0.45.7).k2 workspace create makes missing parent folders instead of failing.vault_confirm_required (a 0.45.x server's confirm_required is still understood).k2 msg who can look up who sent it.k2 mail sending off|approval|on , or Email sending in the workspace's settings, which shows what is in effect. k2 mail inboxes shows each inbox's real send state, and the hint when sending is off now names the right command.After updating
k2 app warnings to see what each of your Apps still needs.--cmd service needs both App switches on its workspace; until then k2 publish run only warns, and says so.k2 app engine install (a deploy on the old engine stops and says so).~/.k2/hooks/statusline.sh) to ~/.claude/settings.json, only when you have no status line set. Yours is never replaced.confirm_required should also accept vault_confirm_required.v0.45.7
0.45.7 — Grok Bots at home
[from ] , so the bot knows who wrote it: your display name from Settings, or your login if you signed in to this server. In K2 the chat shows your name on the message instead of the tag. K2 limits how fast you can send, and never passes messages between K2 agents and Grok Bots on its own. If a bot's conversation now runs somewhere other than this computer (another box, or Grok's cloud), its chat in K2 says so and keeps the older history from this computer. You can still message that bot from K2: your message reaches its live conversation, and K2 shows its new replies under a "Live since" line as they arrive. K2 only sees the bot's latest message at each check, so when a bot writes several in a row, K2 shows the last one and says earlier ones may be missing; open Grok Bot to read them all.k2 tunnel status shows which relay you're on and where the list came from.tunnel.json. If the settings can't be read right after a wake, the running tunnel stays up instead of going dark. Every tunnel stop and every tunnel change now goes in the daemon log with the reason and who asked: the owner, a Connect user, an agent, or a client over the tunnel.k2 publish and other Connect commands work on desktops again. Since 0.45.4 the tunnel token lives in the K2 vault, so k2 publish status and k2 publish subdomain list/create/point/rm said "no K2 Connect tunnel token". The K2 server now makes those calls for the CLI with the token it holds; the token never leaves the server. k2 connect status reports the vault token too.k2 vault grant --to ws: --as env --env-name MY_VAR ), the agent now gets it as MY_VAR. Before, the workspace's own default delivery won, and a secret with a dash in its name (my-api-key) couldn't be delivered as an env var at all; now it becomes MY_API_KEY. k2 vault delivery … --env-name used to say OK and do nothing; it now refuses and points you to k2 vault grant.k2 publish, no Settings needed. From its K2 terminal an agent can run k2 publish run, k2 publish subdomain create , change where it points with k2 publish subdomain target (same as point), and k2 publish subdomain rm . A label an agent creates belongs to its workspace, and an agent can only change or remove its own workspace's labels: never your main subdomain, the reserved skin, meet, chat and mail, or another workspace's. An agent can create or remove up to 20 subdomains an hour per workspace. address, enter where it points (like localhost:3000) and, if you want, pick the workspace that owns it. Each row has Change target and Remove (Remove asks first). The new address shows up right away. Only the owner or an admin of this server sees these controls, and not while you're viewing another server. Nested subdomains still need the Pro plan; Settings says so if you don't have it. Before, this was only k2 publish subdomain create in a terminal.After updating
v0.45.6
0.45.6 — Live cards and hired hands
k2 sources propose; you approve it in Settings → K2 Server → Data Sources, with a vault confirm when it uses a secret. Built-in Garden cards show it (fleet grid, version spread, relays and DNS, deploys, money alerts), and custom widgets can read it too. A trigger can wake an agent when something really changes, never on a brief blip. Keys stay in the vault and are bound to one exact site. You can also choose to store only states and never the values.k2 store, but only with the grants you give them in Settings → Gardens → Widget data. Big edits land all at once, changes appear live in every open window, and K2 keeps 7 daily and 4 weekly snapshots you can export or restore (k2 zen data …). An agent signs each widget version it makes. A version nobody has signed gets no data until you click It's mine.k2 agent hire now uses the same engine, and k2 msg who shows K2's own record of who really sent a message, so agents don't have to trust text that only looks like a sender tag.k2 hooks emit..k2) by default. If an App really needs it, add the files:agentconfig permission to that App's role. App login lockouts now count per person, not per typed name, and App pages serve WebAssembly, modules, fonts and modern images correctly.k2 agent restart restarts an agent's pinned chat. Removing a workspace now stops its agent sessions. K2 starts on macOS 14 again. Connect only remembers your password when the Keychain actually saved it. k2 root-helper status works inside K2 terminals. A compute job that asks for network = none is refused until K2 can enforce it. The names mail, meet and chat are reserved for K2's own web pages on your server. Data sources can now read sites that require a browser-like identity (such as the GitHub API). On Linux, Settings → General points deb and rpm installs to the new package instead of showing an update error, dark-theme dropdowns are readable, and shortcuts show the real keys instead of Mac symbols. One Esc in a Settings dialog now closes just the dialog.After updating
.k2 folder on purpose, add files:agentconfig to that App's role.v0.45.5
0.45.5 — Who's who
k2 app grant copy-host), or k2 app user add --app for someone who should see only that App. Custom (--cmd) Apps get K2_APP_ID, K2_HOST and K2_PORT, and can name themselves when they sign people in; without that, login works exactly as before. App logins also accept an email, and a locked login says how long to wait.k2 thread ask --expires 3d or --no-expiry), show "expires in…", and close on their own at the deadline. The agent is now told who really answered (an App user's or Connect user's name, not the owner's), and the card shows "answered by". Agents close cards that no longer apply with k2 thread void.k2.actor_kind() tells a person (guest) from an agent (agent), and k2.actor_info() says which. Only you can mark an App login as an agent's (k2 app user agent ). App-user writes through the database door now work like regular queries (including RETURNING), errors read plainly, K2's own tables are closed to App users, and one write is capped at 5,000 rows.k2 compute node admin … does the same from the CLI. Node updates are now signed with K2's root key and the Mac node is notarized. A job that asks for a tool the node can't install is refused before it starts, and nodes can now install cmake, ninja and protoc. Per agent, Allow this agent to operate compute nodes sits next to Allow compute nodes.After updating
k2 compute node update if it already runs remote admin); after that, updates arrive signed.v0.45.4
0.45.4 — Vault, root door and mail that delivers
.env files keep working as before. Set up the vault's recovery key in Settings → Vault: confirm with Touch ID or your Mac password, write down the 24 words, and type three of them back. See also k2 vault.k2 publish services no longer inherit K2's own environment. Services from before this update keep it for now and show that this ends in 0.46.0: switch each with k2 publish env clean and grant only the secrets it needs (k2 publish secret add).k2-root-helper replaces the separate mail and database helpers. It accepts only updates signed with its own key, and installing it removes the old helpers (backed up first). Your hosting provider rolls it out box by box.k2 hostmail upgrade moves a box up (after the root helper is installed), checks the result and rolls back on its own if Stalwart doesn't come back healthy. An upgrade interrupted by a restart now finishes or rolls back at the next start, so mail is never left stopped.k2 tickets settings but can't change them. The Tickets page now opens on Waiting on me (or All, or your last tab), and says "Nothing is waiting on you" when that's true (GitHub #75).k2 compute run on every machine you switched on, including ones you add later, with sensible limits you can change (k2 compute grant). Switching a machine off lets its running jobs finish, then removes it. Your other servers with "Make this computer a node" on will list here for one-click joining once K2 Connect is updated; until then add them with an enroll code.--transfer, and every move is logged.v0.45.3
0.45.3 — Quiet keychain, your own compute
k2 llm tokens) shows the one command to run in Terminal. Thanks to Appa (Baden) for the report.k2 compute preview on, then k2 compute node add prints a one-line installer for the machine you're adding; confirm the 6-digit code it shows, grant it to a workspace, and agents can k2 compute run -- . Output streams back and the command's exit code comes with it. The machine's owner can pause or drain it at any time. This is a preview: CLI only, off by default, and it may change. Read k2 study compute first.k2.canvas.setHitRegions) and make any of its own elements drag the window (k2.window.startDrag). K2's menu, Garden switcher and Zen toggle always stay on top, so you can never lose your way out. See k2 study zen.v0.45.2
0.45.2 — A haunted Diary
counts (subagents, tools and commands this turn), numbers only. Custom widgets and Apps can show them; the SDK types include the field.After updating
v0.45.1
0.45.1 — Gardens you build
k2 zen widget new gets an agent started.k2 calendar lists, reads and drafts events on hosted inboxes (never sends invites on its own). Owners and IT agents can create groups and shared team calendars with k2 hostmail group and k2 hostmail calendar share. An assistant agent with access to a person's inbox sees that person's shared calendars.k2 hostmail status shows the real certificate names and the last certificate error, domain add lists the A records you need, and spam rules that newer rule downloads broke are repaired. New: k2 hostmail outbound. k2 hostmail backup plan measures how much space a backup would need.k2 domain refresh.k2 msg works with a workspace's handle and its agent name. k2 agent hire --name keeps the name you give it.k2 workspace swap-canonical moves a workspace's main chat to another AI tool and hands over the recent conversation. Thanks to Sterling Long (Luzzotica) for this one.Security
k2 publish frame --allow https://your.site (owner only). Apps published with --cmd run their own server: k2 publish ps warns when one sends no frame protection.Fixes
After updating
agent.md::, add it again with the agent's name.v0.45.0
0.45.0 — See your agents work
k2 llm tokens.k2 hostmail profile) and an explicit Stalwart upgrade to 0.16.20. Certificates K2 issues now renew themselves before they expire.k2 mail send --bcc, and an owner "always BCC" setting per workspace that the agent can't remove. Agents send only through K2, so your rules always apply. An agent allowed to manage mail can now do what you can for other mailboxes, except loosen the rules on its own mail.k2 sidecar. Agents can start, list and stop side chats for Claude, Codex, Grok, Gemini, Cursor, Pi and Hermes. Each can be resumed later. Turn it on per workspace with k2 sidecar access on.Fixes
k2 commands act as that chat. Messages you send before Codex's first reply no longer disappear. If Codex was already open, restart it once after updating.(eval) errors when the login shell prints extra output at startup.localhost load even when the server lists IPv6 first. An app that isn't running shows "Service not reachable" (502) instead of a 404.Server owners: to use the calendar features, re-run the mail helper installer once with --version 0.45.0 (sudo bash install-mail-helper.sh --version 0.45.0). New servers we set up get it automatically.
v0.44.4
0.44.4 — Security update
v0.44.3
0.44.3 — Gardens your way
slot = "top" puts My Home, Agents, Projects and Tickets as a row of icons next to the Garden switcher.k2 zen guide. A user guide in the CLI with 10 topics and copy-paste examples (bottom bar, both buttons in a menu, the rail on top…). It works even when K2 isn't running. k2 study zen points to it, and validate errors name the page to read.v0.44.2
0.44.2 — IMAP repair works without the mail helper
v0.44.1
0.44.1 — Hosted mail installs again, and air-gap fixes
k2 hostmail enable stops before downloading anything and prints that exact command instead of "Permission denied". k2 hostmail status shows helper: installed, missing, or not allowed by sudoers.k2 hostmail ptr set judges "aligned" by what k2.dev actually published. If this machine's DNS cache still has the old name, you get a note saying it clears on its own, instead of "not aligned".v0.44.0
0.44.0 — Zen Gardens
k2 zen garden list|new|rename|reorder|delete|template and the k2-zen skill let your agents arrange and restyle Gardens for you. Settings → Gardens manages them too.v0.43.3
0.43.3 — Tickets go live for apps
k2 study app-tickets documents the events and the ticket calls.v0.43.2
0.43.2 — Agents from other servers open right on Home, and tickets you can read
v0.43.1
0.43.1 — No more "Something went wrong" after 0.43.0
v0.43.0
0.43.0 — Home, heartbeats that fire on their own, and apps
heartbeats:read and heartbeats:write. App developers can read k2 study app-heartbeats. Apps can hear "agent working" again.~/.k2/client-event-faults.log. Mac stoplights stay centered after moving between displays, waking, or switching light and dark.v0.41.6
0.41.6 — Notes you can page, and a lock you can clear
k2 app user unlock clears an app guest's lock and leaves the password alone. k2 users unlock does the same for a box login. A name with no lock still succeeds. Changing an app user's password leaves the lock in place. Changing a box user's password still clears that lock.activity:read on its own. files:read and files:write do not include it. A new file name is one name, not a path.k2 db grant can name the tables or views another workspace may use. Repeating --relation replaces that list. Leaving --relation off restores the whole public schema. A later migrate keeps the same list.v0.41.5
0.41.5 — Nested workspaces, and menus that stay put
v0.41.4
0.41.4 — User access, apps, and shortcuts in the front window
k2 command that is already on the machine, including an Arch install. It no longer offers a Mac-only install button when that command is missing from the Mac path.v0.41.3
0.41.3 — Window chrome, and a crash after a long run
v0.41.2
0.41.2 — Arch download, and quieter stoplights
k2--x86_64.pkg.tar.zst ). The app does not install it. The same version stays quiet.v0.41.1
0.41.1 — Server switch no longer quits the app
setEditedFlag:, setTemporarilyDisabled:), and the app quit. Those calls now go to the system button. The square paint stays.v0.41.0
0.41.0 — Usage, chat continuation, and a desktop that stays put
Everything since 0.40.150. The window, the browser, usage, and how a chat continues.
k2 workspace resources. list, add, and remove for a workspace’s resource files.Not in this build: Gemini’s subscription meter, and Home.
v0.40.150
0.40.150 — People, grants, and mail an agent can stand up
A skin user can have a full name, and Settings shows that list as People. Who may open an app is a grant. An agent on the box can bring hosted mail up with the CLI.
k2 app user full-name sets or clears it.k2 app grant list|add|rm is owner-only. There is no separate people table.k2 app. The human-facing command is k2 app. k2 skin still runs and points at it.k2 can run k2 hostmail enable from zero. A root helper does the system steps, so enable does not need a second admin at the keyboard. A partial enable resumes instead of stopping because this box is already listening on port 25.k2--x86_64.pkg.tar.zst on the Arch runner and attaches it to the GitHub release. One package for both. pacman -R k2 leaves ~/.k2 in place.Not in this build: a Windows runner, a grant required per app address, mailbox and database grants applied to mail or Postgres.
v0.40.150a
Arch and Omarchy package for 0.40.150. The Mac release is v0.40.150. The package file is k2-0.40.150-x86_64.pkg.tar.zst.
v0.40.149
0.40.149 — Agents can attach hostnames; doctor refreshes; certs over CNAME
Mail-manage / DNS-manage agents can add mail. themselves once the apex is on the box. Thread posts from k2 thread remind agents the overlay paints markdown.
k2 domain name add [--role mail|publish|direct|other] and name remove use the same grant as k2 dns / k2 cert issue. Apex k2 domain add|remove stays owner (exit 3). e2e on lztek: idempotent add of mail.discover-nocode.com, scratch add+remove, apex still owner_only.k2 thread write (not --json), a stderr hint on the first post and every 10th: Thread renders markdown (bold, lists, code, fences, links). Help and AGENTS.md Tooling say the same.k2 hostmail doctor POSTs /cli/mail/doctor (runs probes now). It no longer GETs the last stored run, which stayed stale after PTR/DNS already moved.dns_write, k2 cert issue uses DNS-01 on _acme-challenge. (not the mail CNAME). It waits until ns1 and ns2 both have the TXT, then 8.8.8.8 and 1.1.1.1, before telling Let's Encrypt (querying public DNS too early caches NXDOMAIN from a lagging NS). Finalize accepts an already-Valid order. Issue JSON reports inventory PEM SANs, not live TLS through a CNAME. e2e: scratch-le4.discover-nocode.com issued YE2. If the hostname is a CNAME and the zone is not dns_write, it fails loud instead of HTTP-01 following the CNAME onto a closed :80.Not in this build: People hub, hide XOAUTH2 when no IdP, Omarchy pacman package.