Changelog
October 2026
-
UI stacks: in some cases the auto completion of available stacks did not work.
-
UI improvements: to port forwarding.
-
Apple Containers: fixed an issue where it wasn’t possible to delete the container.
September 2026
-
The spaces page broke for users with only the share permission: it requested the user list without being allowed it, and the resulting error stopped the page loading anything. The share permission now grants the user list read the share dialog needs, and the page keeps working if that request fails.
-
UI improvements: the Clients page command block is readable in dark mode, and share/transfer dropdown avatars load only when opened instead of on every page view.
-
Outbound network restrictions for server-side scripts: a new
server.script_net_policysetting points MCP tool and event sink scripts at a network policy file — the network equivalent ofserver.script_fs_allowed_paths. See Network Policy. -
MCP over stdio (
knot mcp): run knot as a local MCP server — the command proxies the remote server’s/mcpendpoint over stdio, authenticating from the stored connection (--alias) or--server/--token, never from the host’s config. Also built into the agent binary, so inside a spaceknot mcpconnects through the agent socket with no configuration. Seeknot mcp. -
MCP Apps in the AI chat: a tool call linked to a
ui://resource (the MCP Apps extension) now renders its app view inline in the conversation instead of staying buried in the tool-call disclosure. Remote MCP servers’ tools and resources are exposed to the chat too, and the MCP servers management page badges app tools and shows their icons. -
Skills served over the MCP skills extension: knot’s skills are now exposed the standard way on
/mcp:skills/listandskills/get, with eachSKILL.mdreadable as askill://resource, scoped to the requesting user’s access. The web assistant and the OpenAI-compatible endpoints list available skills in the system prompt — including skills from attached remote MCP servers — and pull the full content on demand. See Skills. -
Exclusive pool member leases:
knot pool acquirechecks out one healthy pool member for a caller’s exclusive use — shared routing skips it while held, and the holder works with it by its space name, the same way they would ssh to it. The default is the simple allocate → use → release with no timeout; optional lease limits and extension caps cover shared pools and CI, andrelease --destroyswaps the member for a fresh one so the next acquire starts clean. See Space Pools. -
Scriptling:
knot.poolleases:acquire(name, time=None, wait=None),extend(space, time=None),release(space, destroy=False),leases(name)and aleased()context manager; extend and release take the member’s space name or id, durations accept"5m"-style strings or"none". See knot.pool. -
Idle auto-stop for spaces: a new template idle timeout stops a running space after it has had no user activity, an open terminal, SSH or web-port session (even idle), method calls, sustained CPU, and on Pro filesystem writes — for the configured time. Held pool leases are exempt. Set it next to Maximum Uptime in the template form, the API (
idle_timeout,idle_timeout_unit), template export/import, andknot.template.create/update. See Managing Templates. -
Shared ports and cross-user forwarding: template ports gain a shared type (alongside http, https and tcp), not published anywhere but reachable by every user in the same zone through port forwards, addressed as
user--space.knot space port forward client 5432 paul--shared-pg 5432. Forward targets resolve as your own space, your own pool (round-robin across healthy members, leased members excluded), or another user’s space/pool on shared ports; access is re-checked on every connection. Templates, pool membership and users are now cached in memory on each node, invalidated on every write. See Space Forwarding. -
Template port forward wiring Pro : templates can carry port forwards seeded into every new space. Client spaces connect to their services (or a pool) automatically on start. Edited in the Pro template form; available through the API, export/import and
knot.templateeverywhere.
-
The
/mcpendpoint serves knot’s own tools only: remote MCP servers are no longer federated through the public endpoint, so its tool list describes knot alone and doesn’t churn when a remote server is added, removed or changes. The web chat, the OpenAI-compatible endpoints andknot.mcpin scripts still list and call remote tools under their namespace prefix; external MCP clients that want a remote server’s tools should connect to that server directly. See Remote MCP Servers. -
The
get_skillMCP tool is removed: skills are no longer exposed as a tool on any surface. External MCP clients use the skills extension instead (skills/list,skills/get,resources/readon theskill://URI). The CLI, theknot.skillscripting library and the skills API are unchanged.
-
knot.mcpworks again: the scriptling library’slist_tools(),call_tool(),tool_search()andexecute_tool()called API routes that were removed when chat moved to the OpenAI endpoints in February, so every call failed. The routes are back, resolving tools exactly like the web chat: knot’s own tools plus remote MCP servers under their namespace prefix. See knot.mcp. -
CSI volume deletes survive an in-flight operation: Nomad rejects a concurrent delete with
Aborted — an operation with the given Volume ID already exists; knot now retries for up to five minutes until the earlier operation clears, and if it stays wedged says so — with the remedy — instead of failing with the raw error. -
The template form could never enable Maximum Uptime: the unit was submitted as
disabledfor every platform, so the setting silently did nothing regardless of what was chosen. -
Persistent forwards created on a stopped space never came up: they stored the target as a space ID, which the proxy rejected, so the forward sat dead after the space started. Targets are now stored by name (
user--spacefor other users’ targets) and the proxy accepts names, qualified names and IDs. -
Non-admins got an empty space list from the CLI:
knot space listand every other client that calls the spaces API without auser_idfilter received nothing back, because the endpoint only allowed admins an unfiltered list. An omitteduser_idnow means the requester’s own spaces; asking for another user’s id still returns nothing without the manage-spaces permission.
- KVM virtual machines: a new template platform that runs spaces as full VMs on KVM-capable nodes — their own kernel and systemd, booted from a cloud-init image, with everything interactive (terminal, VS Code, SSH, scripts, jobs) working as with containers. Bridged or NAT networking per template, persistent stop/start, device passthrough, serial and graphical consoles in the browser, and full spec-wizard support. Nodes advertise the
kvmruntime automatically. See KVM Nodes and the VM Specification.
- Scriptling:
knot.spacegains KVM IP support —create()andupdate()acceptip_address, newget_ip_address()/set_ip_address()helpers, and every space dict carriesip_address;knot.templateresponses expose the KVM network fields.
- Tunnel domain everywhere the wildcard domain is: new
server.tunnel_domainspec/stack variable with editor autocomplete; the server-info API andknot.server.info()now returntunnel_domainalongsidewildcard_domain.
- Spaces list: the log window action is hidden for KVM spaces — a VM has no container runtime to stream logs from.
- Tunnels now survive a knot server restart: instead of giving up after a few seconds, tunnel clients (daemon-mode web tunnels especially) retry with backoff indefinitely and reform the tunnel, same URL, once the server is back.