What's New
Release notes for K2. Updates are published to GitHub.
v0.40.62
Latest0.40.62 — Settings that scale: Connect, LLMs, General
K2 Connect is easier to navigate
Settings → K2 Connect is no longer a permanent side-by-side Host /
Servers wall. You get clear tabs:
Pair two cloud servers while you’re signed into one
The saved-servers list (this Mac’s address book) stays visible when
you’re connected to a remote. That unlocks Pair as federated peer
between two K2 Cloud boxes without bouncing back to Local first. The
top-bar server switcher still always shows *your* list — not the remote
machine’s.
Agentic systems are just on
No more Agentic Systems beta toggle. Canonical Agent Flow, Heartbeats,
workspace Skills, and agent polling are always available. Older
“turn agentic off” flags no longer hide the product.
Editors and LLMs are separate
column for the big seven (Claude live auto-refresh; Codex, Grok, Gemini,
Cursor Agent, Hermes, Pi coming soon)
Nav: LLMs sits under Styles. Workspace settings are labeled
Workspaces / Agents.
General has real tabs
Settings → General:
| Tab | What’s there |
|---|---|
| General | Version, CLI, What’s new, your name, reset |
| Workspaces | Active-bar hours, completion sound, Canonical Agent Flow help |
| Server | K2 Server + keep running when the window closes |
| Local LLM beta | Workspace assistant / model |
Canonical Agent Flow is no longer its own top-level page — it lives under
General → Workspaces, with room for the diagram and a shorter intro.
Agent presets & CLI guide
Built-in order puts Grok before Gemini. CLI Tools Setup matches that
list and includes Hermes. Existing installs get the Grok/Gemini swap
on the next daemon start (or use Reset Built-ins).
---
v0.40.61
0.40.61 — Linux servers actually update (and stay reachable)
Update from the app installs the new daemon
On a remote Linux host (Settings → Connections → Update to …),
K2 now finishes the full install path: download → verify → **install &
restart**. Before this release, that button could download and stage a
build without ever swapping the binary, so the box looked like it
“updated,” came back on the same version, and left you thinking
nothing changed.
After install, the app only treats the update as successful when the
host’s /boot-status reports the expected new version — not merely
“online again.”
(Settings → General → remote host Download / Install & restart
was already the complete flow; Connections is now aligned.)
Tunnel stays in sync after restart
Restarting a Linux daemon (including for an update) could leave the
public *.k2.dev tunnel pointing at a dead local port while the
daemon listened elsewhere — external HTTP 000 until an operator
SSHed in and ran systemctl restart.
0.40.61 keeps the live HTTPS listener port as the source of truth for
frpc, hardens tunnel stop/reap so orphan frpc is less likely, and
self-heals when frpc’s local port is unreachable but a live listener
exists (rewrite frpc only — agent sessions are not killed for that
heal).
Ops note for already-provisioned boxes: new install scripts use
KillMode=control-group so orphan tunnel helpers die with the unit.
Existing units may still say KillMode=process until you redeploy the
unit or:
`bash
sudo sed -i 's/KillMode=process/KillMode=control-group/' /etc/systemd/system/k2-daemon.service
sudo systemctl daemon-reload && sudo systemctl restart k2-daemon
`
Update both the thin client and the daemon on the host so the
new Connections flow and the tunnel self-heal land together.
---
v0.40.60
0.40.60 — Tickets, and chat text you can actually select
Feedback is now Tickets
The Feedback surface is Tickets end to end — page label, agent CLI
(k2 tickets …), and wording. Existing ticket data and routes keep
working; this is a product rename, not a wipe.
Ticket polish
resizes with the detail panel
Highlight and copy chat text
You can drag-select and copy message bodies in Tickets threads
and Project chat — not only the composer.
A global “return focus to the terminal” path was treating those
message divs as dead space and clearing the highlight almost instantly.
That reclaim now leaves a live selection alone (and skips full-page
Tickets / Projects / Wiki overlays).
---
v0.40.59
0.40.59 — Files tree no longer bounces on busy hosts
On remote (and busy local) machines, the Files drawer could flash
Loading... over and over, making the tree jump while agents or other
tools wrote under the workspace.
Live refresh still updates when real project files change. High-churn
paths (agent/runtime state, .git, build caches, logs) no longer thrash
the list, and a directory you already have open refreshes quietly in the
background instead of re-showing the loading row.
Update both the thin client and the daemon on the host (e.g. NSI)
so the quieter watcher and the calmer UI land together.
---
v0.40.58
0.40.58 — Files that keep up, and previews that actually work
The Files drawer is a real workspace browser again — not a list that
lags behind agents or only shows plain text when you open something.
Live refresh when others change the tree
When an agent, another client, or a process on the host adds, renames, or
deletes files, the Files tree updates without a full window reload. That
covers local workspaces and remote hosts the same way.
Dropping files no longer multiplies copies
Dragging from Finder (or another app) into Files used to sometimes create
several copies of the same drop — especially with multiple panes open.
Drops are routed once and uploads single-flight, so one drag means one
landing.
Open more than code
Click a file and K2 picks a preview when it can:
files on remote hosts
remote server’s speakers; bytes stream from the host daemon
.mmd / .mermaid) rendered in the viewertext tab
Spreadsheets and slide decks (xlsx / pptx) are still out of scope for this
release.
Polished tree
Folders sort first, icons follow light/dark (Seti-style), and **Reveal in
Finder** / the OS equivalent is labeled correctly.
---
v0.40.57
0.40.57 — Live agent terminals stay alive across brief disconnects
The Active reaper no longer kills a live agent terminal just because the
app or control plane briefly disconnects. If the PTY is still running, the
session is left alone — only truly idle/orphaned sessions are aged out.
Explicit dismiss still closes chats the way you expect. Closing or
dismissing a session yourself is unchanged.
Daemon stderr is quieter too: terminal poll performance histogram lines no
longer spam the log during normal use.
---
v0.40.56
0.40.56 — Agent passports no longer die overnight
Long-running agents were losing the ability to use the K2 CLI
(k2 msg, inbox, peers, and other in-cell tools) after about a day, with
errors that looked like an expired auth token — even though the agent
session itself was still alive.
What was wrong
Each agent cell gets a scoped passport (K2_HOOK_TOKEN) at spawn so it
can call the daemon without holding the full owner secret. That passport
had a hard 24-hour wall-clock expiry, and there was no way to refresh
it while the process was running. After 24 hours the daemon rejected the
token; messaging and other CLI verbs failed until you restarted the cell.
What we fixed
Passports now last for the life of the agent cell. They still stop
when the session is torn down (or on a global revoke) — that is intentional
security. They no longer suddenly expire just because the clock advanced.
If an agent already hit the old expiry, restart that session once after
updating so it mints a fresh passport under the new rules.
---
v0.40.55
0.40.55 — Clone To: full chat history + your pin comes with you
Clone To is a real workspace migration again — not “files only, then
figure out /resume.”
Chats show up after clone (no awkward first resume)
Past conversations appear in Chat History and the agent chat dropdown as
soon as the workspace lands on the destination. You no longer need a
mystery /resume just to make the list wake up.
Pinned Chat stays pinned to the same conversation
If the workspace had a Pinned Chat tied to a specific session, that
session id travels with the clone (when the transcript is present). Stars
and custom chat names for those sessions come along too.
More than Claude — the agents you actually use
Clone To can now carry session history for the major harnesses K2 already
knows how to resume:
Paths and project slugs are rewritten for the destination machine so
resume keeps working when the home path changes (Mac → Linux, etc.).
What we deliberately do *not* copy
Provider logins and subscriptions stay put. The destination server is
expected to use its own Claude / Grok / Codex / … accounts. Clone To
moves workspace + chat history, not credentials, auth tokens, or
Keychain blobs. Sign in on the other box if you haven’t already.
Also unchanged: tunnel identity, connect-users, and machine-local K2
state stay on each host.
---
v0.40.54
0.40.54 — Tunnel resilience + hosted web (beta)
Two Connect upgrades: tunnels that actually stop, and a beta browser
client for your machine at https://.
Hosted web client — beta, available now
Open your K2 server in a normal browser while the desktop app (or headless
daemon) is online with Connect running:
https://.app.k2.dev (example: https://z3thon.app.k2.dev).user, sessions and terminals over the tunnel.
web_client_enabled / owner settings if you do not want browser access.
expect rough edges, rapid fixes, and desktop remaining the primary client.
edge, cookie session on your daemon). Desktop Connect to
stays the true end-to-end tunnel path.
Bookmark your .app.k2.dev URL once the tunnel is up. If the machine is
asleep or the tunnel is down, the page will say so until it comes back.
Tunnel resilience (Stop means stopped)
Connect tunnels that used to leave a live frpc behind after Stop,
daemon restart, or self-update — and that could desync from the live
listener on older builds — now tear down cleanly and keep serving after a
transient frpc drop without a full daemon restart.
#### Stop actually kills the tunnel
frpc for thisdaemon's config, including the default single-relay (solo) path.
local frpc after update or restart.
#### Self-heal on frpc drop (no agent kill)
E2E listener port — it does not invent a new localPort while sockets
are still bound.
worked). Prefer this build on any box that saw silent external outages
while systemctl still showed active (fleet boxes on pre-fix builds
should upgrade).
#### Identity for multi-device tunnels
device_id when the daemon has one,so the relay can tell same-token machines apart (groundwork for
cross-machine eviction on the control plane).
#### Connect tunnel picker — apex only
tunnel only shows purchased apex** names (you.k2.dev). Nested
routes (api.you.k2.dev, staging.you.k2.dev, …) no longer appear as
tunnel targets — those are routing under an apex tunnel, not separate
tunnels.
Upgrade any Connect server that flapped after tunnel restart or left
orphan frpc after systemctl stop / self-update — and try the beta web
client at https:// once the tunnel is up.
v0.40.53
0.40.53 — Remote Session (safer-than-SSH help over Connect)
Consent-gated, time-boxed shell drive on a K2 device — for migrations and
remote help without handing out root SSH or permanent keys.
Turn it on (owner)
k2 remote-session enable / disable. Master wall; disable kills everyremote shell immediately.
k2 remote-session grant --ttl 45m --label "…". Mints a one-time k2rs_… drive token (shown once). Revoke with
k2 remote-session revoke .
Drive (helper / agent)
k2 remote-session shell --token k2rs_… opens a daemon-user login shell (never root). Works locally or via Connect with --host.
write / read drive that session. Wrong token, expired grant, orwall OFF → clear teaching errors (not a silent failure).
k2 remote-session status so you always know someone tried.
What this is for
root SSH. Full automated runbooks come later; this release is the safe
hands + grant layer so real migrations can teach the runbook.
See docs/remote-session.md for the full cookbook.
v0.40.52
0.40.52 — Headless Connect CLI + wiki session revive
Provision a Linux box from the shell, and public-wiki chat sessions recover
cleanly after idle reaping.
Headless K2 Connect onboarding
k2 users add. Create the first owner (or more Connect users) on a headless daemon: hidden password prompt or --password-stdin, then
--role owner|admin|member|viewer. Uses the daemon owner token on the
box (external setup works without a session passport); in-cell agents
stay on their scoped passport and cannot elevate.
k2 connect login. Pair a purchased k2.dev subdomain from the CLI: account email/password (or --token access JWT) → pick a subdomain →
write tunnel config → start tunnel → print the live URL. Session stored
in ~/.k2/connect-account.json (0600); password is never written.
k2 connect status / k2 connect logout for check and re-auth.
Manual K2_TUNNEL_TOKEN remains the automation fallback.
Public wiki session lifecycle
a dead terminal open in the app.
session (stored session id) surfaces a fresh tab so the inject is visible
again.
k2 msg --wake. Host-session firstmessage uses settle + readiness + screen quiescence so Grok (and peers)
don’t lose the paste during first paint.
v0.40.51
0.40.51 — Public wiki chat + agents control heartbeats
Wiki visitors can talk to a workspace agent in the site itself, and agents
can manage their own heartbeat schedules without fake “invalid token”
errors.
Public wiki chat
wiki (default off). Visitors get a third-column chat panel on the live
site; messages run through the same host-session API as external keys,
with the chat key held only on the daemon (never in HTML or browser
responses).
workspace into skip-permissions for host sessions so the visitor’s
first message isn’t stuck on a human approval prompt. First-message
inject also waits for screen quiescence so the paste isn’t wiped by
the agent’s startup repaint.
(read-only preference + k2 respond), same as other API host sessions.
Agents own heartbeat schedules
k2 heartbeat works from agent sessions. Agents can list, add,edit, enable/disable, and fire workspace schedules with their session
passport (UDS when in-cell, TCP dual-auth otherwise). The daemon stamps
the caller’s workspace so one agent can’t schedule into another’s
project.
similar owner surfaces no longer say “Invalid or missing auth token”
when an agent passport is presented — they return owner_only with a
hint to ask the human. Agents stop chasing a “broken token” that was
really a scope boundary.
v0.40.50
0.40.50 — CLI stays current on Linux servers
Server updates no longer leave the k2 command stuck on an old version
while the daemon moves ahead.
Server updates
k2 CLI can no longer fall behind the daemon. On Linux servers, the daemon refreshes the k2 command alongside itself on
every update. If the system-wide install at /usr/local/bin/k2 isn't
writable by the daemon's user (a common setup/migration artifact), the
daemon now stages the current CLI at ~/.local/bin/k2 instead of
silently leaving the old version in place. Server provisioning also
installs the CLI daemon-writable from the start.
v0.40.49
0.40.49 — Pair as federated peer
Cross-server agents needed one more obvious step: trust. Turning on
federation and signing into a server was never enough by itself — the two
daemons still had to pin each other as peers. That step is now a button.
Federated peer pairing
server tile has a Pair as federated peer button. One click establishes
mutual trust between this Mac and that server (owner on both sides). When
it works, the tile shows Peer: trusted.
you to pick a federated server before any peer existed — and there was no
UI path to create the first one. Pair from Connections first; then the
server shows up in Federated Connections so you can link agents.
lists now point you at the Pair button instead of a vague "pair first"
hint.
v0.40.48
0.40.48 — Resilient reconnect
Server reboots and updates are now a non-event. When a host you're
connected to restarts, K2 notices, waits politely, and reconnects on its
own — no more infinite "Reconnecting…", no more restarting your app to
recover.
Reconnect that actually recovers
detects the fresh server instance and quietly reconnects and resyncs.
The recovery pill (now square, matching the rest of K2) tells you
what's happening and gets out of the way when it's done.
keep reusing a dead connection after a server restart (the "works in
curl, broken in the app" wedge). K2 now detects this with an
out-of-app probe, clears it automatically where possible, and — in the
rare case only a restart cures it — says so plainly with a
Restart K2 button instead of spinning forever.
it: requests fail fast, retries are spread out, and reconnection happens
the moment the host is genuinely back.
Remote updates you can trust
longer freezes on "Installing & restarting…" — K2 watches the host come
back and confirms the version it actually returned with. If an update
rolled back, it tells you that instead of pretending it worked.
gracefully on restarts and self-updates (including supervisor stops),
releasing their tunnel registration immediately — so the offline window
during an update is seconds, not minutes.
Heartbeats
the heartbeats of the server you're connected to — not your local
machine's. Live/resumable/scheduled states come straight from the host.
Heartbeats page (roster, fire history, session picker, delivery
target) now manages the connected host's heartbeats too — everything
you see and change lands on the server you're looking at.
Heartbeats page (every workspace's heartbeats + the fires audit log +
wake-scheduler apply) now shows and manages the host you're connected
to. Requires the host to also run 0.40.48+ for the cross-workspace
lists; older hosts show an honest error instead of silently showing
the wrong machine.
actual error instead of an eternal "Loading…".
Layout
columns now saves immediately and survives connection blips — no more
splits quietly reverting when you're connected to a server.
Agent messaging
agent with k2 msg/k2 talk used to report success while the message
silently vanished — the injection raced the resumed session's redraw.
Delivery now waits for the woken terminal to settle before typing, so
the message lands every time.
guess fired on healthy agent-to-agent messaging (and could quietly
spawn duplicate sessions via its auto-retry). It's gone; the daemon
owns spawn health.
Active area
exactly when it has a live terminal session (or is pinned). An agent
woken by a message pops back in the moment its session exists — on
every connected client.
from the Active area immediately; its session is put to sleep a few
seconds later.
v0.40.47
0.40.47 — Workspace wiki brain map
Your notes become a living map. Open View Wiki on a workspace to explore
[[wikilinks]] as a force graph, read articles side-by-side, and zoom out to
every brain on the machine.
Workspace knowledge base
.k2/wiki/ Markdown notes. Click a node to read it; wikilinks in the
article jump to other notes. Hide article collapses the reader so
the graph uses the full width.
Articles shows how many real notes match the current scope and
search (not phantom missing links).
the neighborhood of the selected note (depth 1–2). Home stays lightly
blue when not selected so you can always find it.
.k2/wiki/.Serve a read-only localhost site when you want to share or browse in a
browser. CLI: k2 wiki status|index|note|seed|serve.
K2 fleet map
(~/.k2/wiki). Workspace hubs connect into each brain without polluting
per-workspace notes.
- Projects — project squares link to member workspace hubs. Filter
with the same workspace/project dropdown used on Feedback.
- Groups — focus-group squares link to hubs when focus groups are
on. Filter with a focus-group menu (All / Ungrouped / each group).
focus group). Solid edges inside a brain are real [[wikilinks]].
Cleanup
surface area are removed so the model stays simpler: workspaces,
projects, and agents.
v0.40.46
0.40.46 — Cross-server agents + WebGL terminal you can tune
Two big tracks since 0.40.45: **federated agent messaging that actually
pairs and talks, and Kessel WebGL** spacing, weight, scroll, and
recovery after workspace switches.
Cross-server agents
Connections**, pick a paired server and an agent it exposes. K2
auto-pairs both daemons (mutual trust, no codes) and records the link
both ways, so either side can message the other. X removes that
agent link (and the reverse when it can). Peer pickers only — no
free-typed hostnames.
agent::host, not mail. Federated addresses use double-colon (cortana::rosson.k2.dev). Inbound chat shows [from agent::host], so
agents use k2 msg instead of k2 mail. Legacy agent@host
still works on the way in.
same-version AirDrop used to leave the *old* launchd daemon running
(version matched, binary on disk was new). The app now detects a
replaced k2-daemon and kickstarts it. Open the app once after install
so federation fixes load.
k2 fed peers lists pinned servers and trust. Failed k2 msg agent::host names known peers and hints when a
reply path isn’t paired yet. Error copy says k2, not the old k2so
name.
Remote Access / contact permission so you don’t pick agents that won’t
accept federated messages.
their scoped credential when the connection and trust gates pass —
without elevating to disk-owner for every hop.
Terminal (WebGL painter)
thinner. Override under **Settings → Styles → Terminal text weight
(WebGL) — saved per style and scheme**, live on open tabs. Switching
styles restores that style’s weight.
Settings → Terminal (WebGL only): line height (default 1.2× font
size) and character spacing/tracking. Same values across themes; open
tabs update live. DOM painter is unchanged.
force an atlas clear; wheel paint and scrollbar drag use live geometry;
resync after a big backlog no longer yanks the view when you’re
scrolled up (content seam-match re-anchoring).
Settings used to lose the GL context for good. The painter remounts when
the surface is shown again instead of permanently falling back to DOM.
little more ink after smoothing.
v0.40.45
0.40.45 — Safer agent mail, cleaner terminals, smoother painting
Agents get clearer boundaries on mail and messaging — and the terminal
looks and scrolls the way you expect, whether you stick with the classic
painter or try the new WebGL one.
grants and levels you already set, but catalog and send paths are
tighter: the inboxes list is dual-auth with a real session passport,
linked/BYO send follows the same agent-send gate as hosted mail, and
listing every hosted address stays owner-only. Agents can also
schedule outbound mail with --at / --in and track it in the
outbox. Owner-only hostmail and access verbs now answer with a clear
owner-only teaching error (exit 3) instead of a misleading
“invalid token.”
msg, read, andinbox compose from an agent require a local connection first — no more
silent surprise paths. Creating those connections stays **off by
default** until you enable “Allow agents to create connections” in
Settings (or per workspace). Compose and inbox targets also stay put
under stamp (no more writing the wrong inbox after identity stamp).
UTF-8 locale, so box-drawing and typography copied from TUI tools
(Claude Code, etc.) land on the pasteboard cleanly instead of as
mojibake.
synthetic box/block glyphs, steadier scroll (no hop or jump-back while
scrolled up), fuller TUI wheel forwarding, weight/smoothing fixes for
“chonky” text, and emoji that keep their width and a bit more presence.
Flip Settings → Terminal → Terminal Painter when you want WebGL;
DOM remains the default.
knew how to notify; a gateway URL normalization fix means those
notifications reach registered devices instead of dying on a bad path.
v0.40.44
0.40.44 — DNS your agents can manage
Point a domain at K2 and let an agent run its DNS — safely, because every
agent now carries its own identity.
agents can now view and change its records with k2 dns — `k2 dns
access to see what they're allowed to touch, list / records` to
read, and record add|remove for A / AAAA / CNAME / TXT / MX / SRV /
CAA. It's off by default: nothing happens until you grant it, per
server or per workspace, in Settings → K2 Connect. Creating or deleting
whole zones stays a human-only action.
session now carries an unforgeable credential that K2 issues the moment
the session starts — so a capability you grant one agent can't be
borrowed by another, even on the same machine. This is what makes
handing an agent real power like DNS safe, and it's the foundation the
rest of the permission system now builds on. Nothing to configure; it
just works.
k2 publish now speaks --json like k2 dns, k2 mail, and k2 tunnel do, and help text, error
format, and exit codes are consistent across all of them — so agents
scripting against K2 get predictable, machine-readable output
everywhere.
v0.40.43
0.40.43 — Resilient Edge
Your tunnel now survives infrastructure failures — and you get real control
over its lifecycle.
*list* of relay servers instead of one. If your relay becomes
unreachable — mid-session or at connect time — the tunnel automatically
re-homes to a backup relay within seconds and fails back once the
primary has proven stable. New K2 Cloud servers get the two-relay
configuration out of the box; existing tunnels keep working exactly as
before and gain failover as their configuration updates. Nothing to set
up, nothing changes about your you.k2.dev address.
the tunnel and stays paused across daemon restarts, reboots, and even a
forgotten background daemon — no more zombie processes reclaiming your
subdomain. *Release* goes further: it permanently retires this device's
claim on the subdomain (with a confirmation step), so a stale backup or
an old machine can never contest the name again. `k2 tunnel
disable|enable|release` from the CLI, or Settings → K2 Connect in the
app. k2 migrate now releases the old machine's claim automatically as
its final step.
/v1 HTTP API can now be switched on per server by the owner in Settings (or k2 api on|off) —
it takes effect immediately, no restart, and the K2_API=1 environment
variable still works as a force-on for headless deployments.
deployments, "Download & install" would verify and stage the new
version, restart — and come back running the *old* one, with no error.
(The helper process that swapped the binary was being killed by systemd
before it could do its job.) The daemon now installs the update itself
before restarting, so it works on any Linux box regardless of how its
service was set up — and if an update ever fails to boot, it rolls back
to the previous version automatically.
v0.40.42
0.40.42 — K2 gets email
The big one: agents can now run and use real email. Three pieces, tied together by one CLI.
k2 mail). The layer that brings itall together: a workspace's agent can mint addresses, list and read
incoming mail, block on k2 mail wait for a verification code, and
send / reply / draft — all under your governance (off by default,
approval, or on, with an outbox and audit trail). Every message body
arrives wrapped in BEGIN/END EXTERNAL EMAIL markers so the agent treats
it as data, never instructions. Whether an address is hosted by K2 or a
linked account you own, it's the same verbs.
deployment, Settings → Email Hosting stands up a real mail server: add a
domain and K2 shows the exact MX / SPF / DKIM / DMARC / rDNS records
to set, verifies them, then you mint unlimited addresses on that
domain (cPanel-style, with catch-all and plus-addressing). A built-in
deliverability doctor probes port 25, reverse DNS, blocklists, TLS,
and open-relay safety and grades your send readiness; send **direct from
the box or via a relay** (SMTP / SES / Mailgun / Resend). (On Mac the
page shows with a "Linux deployments only" banner.)
account as a read + draft (and, when you allow it, send) assistant
inbox, bound to one workspace. Two ways in: an app-password over
IMAP (Gmail, Fastmail, company IMAP), or Gmail over OAuth — sign
in through Google in your browser, no app-password to generate. Reply
drafts land in the account's real Drafts folder for you to review.
Microsoft (Outlook / 365) is coming soon.
k2 mail send/reply take --attach (repeatable), and k2 mail outbox lists what you
attached. And Settings → Email Link → OAuth apps (advanced) points
K2 at your *own* registered Google/Microsoft OAuth client — your quota,
your consent screen — instead of the built-in default; the client secret
is write-only, vaulted and never shown back.
folders on any inbox — plus a batch of help-text, status, routing, and
wording fixes from real agent testing.
v0.40.41
0.40.41 — The heartbeat CLI you were promised
Workspace Settings and the Heartbeat Settings page) now has a delivery
drop-down: Pinned chat, Own session (fresh on next fire), or
any saved session in the workspace — Claude, Codex, Gemini, whichever.
Train a session once, then let the heartbeat wake *that exact session*
on schedule; a one-line wakeup is enough because the session already
knows the flow. The open button beside it jumps straight to wherever
the heartbeat delivers. Agents get the same lever via
]k2 heartbeat session .
k2 connect is now k2 publish (breaking). Putting a subdomainon the internet is *publishing*, so the CLI verb finally says so:
k2 publish status and `k2 publish subdomain
create/list/point/rm/claim/unclaim. There is no alias — k2 connect`
now fails with a one-line pointer to the new verb. (Only the CLI verb
changed; the K2 Connect product and Settings page keep their name.)
k2 heartbeat --help is finally just help. Asking any heartbeatcommand for help used to get parsed as a schedule and *written* —
routine discovery corrupted your schedule state. Help now prints usage
and exits, everywhere, guaranteed. (GH#22, #23, #24)
add/list/remove/edit/rename/enable/disable and k2 heartbeat signal
fire/wakeup/wake` — the surface the docs and skills always described —
are wired to the real named-heartbeat system. Bare k2 heartbeat
lists your schedules instead of erroring. Unknown subcommands and
misspelled flags are loud usage errors instead of silent writes or
silently-ignored options. (GH#10, #24)
--instructions "..." (or --instructions-file
WAKEUP.md at create time — no more schedules that fire with no defined
work, and no $EDITOR required for headless agents. (GH#23, #24)
warns loudly if the schedule transport (launchd/cron) isn't installed
or has stopped ticking. The daemon also rejects junk schedule writes
from older CLIs and cleans up any junk they already left behind.
(GH#22, #23)
v0.40.40
# K2 0.40.40
Hotfix on hotfix/chat-styles-shortcuts (from main). Five focused fixes.
Fixes
Project chat permissions + attribution
Viewer read-only) — no longer blocked by presence window-mode.
POST /cli/project-group/msg requires ≥ Member; Viewers get 403. "owner".
Styles are per-client
storage events.Cmd+N single-fire
useTerminalShortcuts chords(N / T / Shift+T / D / O / W) removed; webview is the keyboard owner.
Projects wake → Active
activateProject for the member workspace before ensure-pinned-chat, so Active reaper
spares the session (~15s grace no longer fires while watching).
Commits
v0.40.39
0.40.39 — The agent status you can trust
tab used to die a second after you switched away — the app lost sight
of hidden panes. Activity detection now lives in the daemon, which
watches every session whether or not anyone's looking, so spinners
stay accurate across tab switches, across windows, and across remote
connections.
root cause: switching away used to fire the chime ~5 seconds later
regardless of whether the agent was done. Now it rings at the real
moment of completion — and only for work you weren't watching.
completes while you're elsewhere, its tab now shows an amber square in
the spinner slot (matching the Active bar's amber dot) until you visit
it. Lots of tabs, one chime — now you know where to look. Hover still
gives you the ✕ if you just want to close it.
Some agent CLIs quietly remove session transcripts after ~30 days. K2
now sweeps daily and copies aging sessions into
.k2/session-archive/ inside each project (originals untouched —
resume keeps working). Default is 14 days; configurable via the
session_archive_days setting, 0 disables.
chat history now update instantly for everyone connected to a server —
no more reloading to see a teammate's changes.
commands shown in tab tooltips) no longer vanish when you log out of a
server and back in.
v0.40.38
# K2 0.40.38 — "Make K2 yours: Styles"
The modular Style System: K2's entire visual language — colors, radii, borders/rings,
shadows, glass materials, spacing, motion, terminal colors — is now schema-validated
data, switchable at runtime.
Styles
swatches (including terminal ANSI-16 strips), Light/Dark/Auto scheme control
(Auto follows the OS appearance live), density presets, style dials, and a live
mini-K2 preview. Hover to preview, click to commit, Esc-safe.
- Square — the classic look, rebuilt on the contract (pixel-parity verified by a
zero-threshold screenshot harness). Palettes: Charcoal, Paper (warm paper-and-ink
light). Density: Compact/Regular/Spacious (floating tiles with draggable seams).
- Liquid Glass *(experimental preview)* — frosted translucent chrome over an
ambient canvas; terminals stay opaque; reduced-transparency and no-backdrop-filter
fallbacks. Palettes: Obsidian, Veil. Includes a Frost dial (blur 0–30px).
- Bezel *(experimental preview)* — the layered-ring aesthetic: hairline → bright
gap → outer line, keycap controls. Palettes: Graphite, Porcelain (the light
original of the ring technique).
ANSI-16; live terminals repaint on switch (KesselConfigProvider bridge).
buttons with the UI (new set_traffic_light_inset command; re-asserted on resize).
AppSettings.style, new typed struct) with a localStorage mirror for flash-free first paint; cross-window sync via sync:settings.
Under the hood
styles// packages (manifest + tokens + palettes + bounded overrides.css) compiled by scripts/build-styles.mjs into generated CSS + a typed
registry. Every slot required; missing slots fail the build loudly.
components/ui/): Surface/Button/Input/Toggle/Callout/Dialog —the only layer that spells out shape slots. ~600 hardcoded colors migrated to
contract slots across parity-gated waves.
bun run styles:lint): per-file raw-color budgets that canonly shrink; CI-enforced.
CONTRIBUTING-STYLES.md + a styles CI workflow (schemavalidation, policy lint, per-style screenshot matrix attached to PRs). Live authoring
via bun run styles:watch + vite HMR.
screens (Playwright WebKit harness, threshold 0); Settings screens differ only by the
new nav item.
Docs
CONTRIBUTING-STYLES.md, styles/README.md, README "Styles" section.v0.40.37
0.40.37 — Spring cleaning, part one
.k2so era is ending — safely. Every internal path now uses ~/.k2 directly, and on first launch K2 quietly rewrites any
agent CLI configs (Claude/Cursor/Gemini) that still pointed at the old
location. Nothing changes for you; the compatibility link stays in
place as a safety net while the transition completes over the next
releases. A new build-time guard makes sure the old paths can never
sneak back in.
showed the old ~/.k2so/... paths for models and logs; they now show
where the files actually live.
v0.40.36
0.40.36 — Copy that
time.** Selecting text in a TUI on a remote server now lands on YOUR
clipboard. The 0.40.34 plumbing was right, but the final OS-clipboard
write was silently rejected by the webview; it now goes through a
native path that can't be. Copies go only to the person who made the
selection.
domains like example.com work), hit Enter — a browser tab opens.
Previously only intercepted links could create one.
or project icon while connected to a remote host now browses the
HOST's files in K2's own picker instead of your local Finder.
bug could spawn 2–4 agents per press. One press, one terminal.
fix (no app update needed) cures a class of "Server unreachable" /
silent connect failures where the app's requests could bypass tunnel
routing entirely. If relaunching K2 used to fix your connection —
this was why.
v0.40.35
0.40.35 — Fresh-install pairing fix
creating a compatibility link the app relies on to find its daemon, so
brand-new installs on 0.40.33/0.40.34 couldn't connect on first launch.
Fixed — and if you already installed one of those versions, K2 repairs
the link automatically the next time it starts on this version.
v0.40.34
0.40.34 — The web comes to K2
pane — a new tab type alongside terminals and files, with an address
bar. It's the foundation for agents that browse.
in a session opens a URL (xdg-open, $BROWSER, or clicking a link in
the terminal), it now opens as a K2 browser tab on your screen — even
when the session runs on a headless server an ocean away, where
"opening a browser" used to mean nothing happening on a machine with no
display.
feedback used to update in real time only on your local machine — on a
hosted server you had to leave the page and come back. All of it now
streams live over the same channel that follows your connection.
copies your selection (OSC 52), the text now lands on the clipboard of
the person who selected it — and only theirs — whether the session is
local or on a remote host.
k2 api-key create gained --workspaces ('*' or a list) — keys minted without a grant authorize
nothing on the /v1 API by design, and the CLI previously had no way to
say otherwise (it now warns loudly when you mint an ungranted key).
v0.40.33
0.40.33 — Your files, where you left them
file from Finder into the file tree used to silently relocate the
original, which could look like losing it entirely if you thought it
was headed to a remote server. External drops are copies, full stop;
reorganizing files within the tree still moves them like before.
behind anything your .gitignore listed — which usually meant your
agent's entire .k2/ folder (persona, skills, heartbeats) and your
.env files, even with "Include secrets" checked. Agent state now
always travels, and the Include-secrets toggle genuinely decides
whether your .env/.auth files come along.
.k2so folder. Thecompatibility symlink now only appears on machines that actually
migrated from the pre-0.40 layout.