Changelog

October 2026

v0.40.0
Changed
  • Show a space’s CPU in cores as well as its share of what the space may use, and treat a space as busy for idle shutdown from a quarter of a core
Added
  • Add space restrictions: a space can keep only chosen buckets, make file storage read-only, switch off personal secrets or lock its processes out of everything else, until lifted from outside, with knot restrict (docs)
Fixed
  • Fix a space’s logs going missing when written before its agent connects to the server, or while it reconnects

  • Fix space CPU, memory and disk usage, and CPU history, showing the host’s figures rather than the space’s own

  • Fix knot secret get failing with an i/o timeout when 1Password takes more than a few seconds to answer, as it does for a mistyped reference Pro

  • Fix the usage history chart showing disk at 0% for spaces without a disk limit: it now shows the space used, on its own axis


v0.39.0
Changed
  • Keep each space’s agent forwarding setting in knot ssh-config update, including changes made by hand; add --reset to apply the defaults again (docs)
  • Turn off agent forwarding for spaces shared with you in knot ssh-config update
Added
  • Add personal secrets: users store their own 1Password token and read their secrets in their spaces Pro (docs)
  • Add 1Password service account support to secret providers Pro (docs)
  • Add a template option to disable file storage in its spaces (docs)
Fixed
  • Fix scripts that check knot.permission.USE_LOG_SINKS failing on Knot Core

v0.38.2
Changed
  • Tell MCP clients what knot is and how to find its on-demand tools, including through knot mcp
Fixed
  • Fix knot mcp not connecting when the server address ends in /mcp

v0.38.1
Added
  • Add knot to Claude as a custom connector, signing in with OAuth2 (docs)

v0.38.0
Changed
  • Breaking: reject pool custom fields that are unknown, leave a required field without a value or template default, or give a select field a value outside its options (docs)
  • Breaking: pass each argument of knot space run, the run_command MCP tool and knot.space.run() to the command unchanged, without shell splitting or expansion; give pipes and redirection as one quoted command (docs)
  • Breaking: pass everything after the command in knot space run to it, flags included; give knot’s own flags before the space name (docs)
  • Report a failed command: knot space run exits with its exit code (124 on timeout) and writes its stderr to stderr, and run_command returns success, exit_code, error and the output
  • Start new pool members in the background, so creating or starting a pool returns straight away
  • Make the pool MCP tools discoverable; knot mcp --show-all lists them (docs)
  • Show template names in knot pool list and hide Masked values in knot pool update
Added
  • Add knot pool create, with --lease-time and --lease-extensions for member leases (docs)
  • Add pool custom fields, given to each member when it is created or started; set them in the pool form, knot pool create --custom-field, knot pool update, the API, knot.pool and the create_pool MCP tool (docs)
  • Add the MCP tools list_pools, acquire_pool_member, extend_pool_lease, release_pool_member and list_pool_leases (docs)
  • Add lease settings to the create_pool MCP tool and to knot.pool.create() and update() (docs)
  • Serve the server’s skills through knot mcp (docs)
Fixed
  • Fix knot mcp not finding or running discoverable tools, and showing no tools instead of an error when the server’s MCP endpoint is off
  • Fix a command’s own short flag being read as a global one, such as -t on knot space run as --token
  • Fix knot space mirror succeeding when files failed to upload
  • Fix importing a template YAML without a maximum uptime

v0.37.0
Changed
  • Breaking: back up through the API into a folder, and restore into a running new server; backup files made by earlier versions can’t be restored (docs)
  • Template export and import now require the Manage Templates permission and moved to knot admin template export|import; knot template list remains available to all users (docs)
  • Start API tokens with tk_, so none can begin with -; existing tokens keep working
  • Limit usernames of new users to 30 characters ending in a letter or digit
  • Use the chat provider setting on its own, with base_url defaulting to the provider’s API; type with base_url is for other OpenAI-compatible servers, and takes precedence (docs)
  • Match custom field values case-insensitively, ignoring decoration around a pasted reference such as #1234 or [1234]
  • Improve accessibility and usability across the web interface, and tidy the login page
  • Warn before the web session expires, with the option to stay signed in
Added
  • Add file storage Experimental : buckets replicated across the cluster, with sharing, quotas, the Files page, knot file commands, the knot.files library and an API (docs)

  • Add S3 access to file storage at <server>/s3 Pro Experimental (docs)

  • Add the Backup Server permission and a backup API token scope; a new server creates a Backup User role and gives it, with Admin, to its first user

  • Improve usage visualization for the Usage and Users pages

  • Add the buckets each user can reach to the Users access overview Pro

  • Add Grok (xAI) support: set the chat provider to grok, or use provider=ai.GROK with scriptling.ai in scripts (docs)

  • Add PostgreSQL as a database; it stores sessions too, so they survive a restart without Redis / Valkey, which still takes the sessions when enabled (docs)

  • Add two-way and continual sync between a directory and a bucket with knot file sync --two-way and --watch (docs)

  • Add knot file move (alias mv), and move files on the Files page by dragging them onto a folder

  • Add the template custom field option Always Show When Creating a Space (docs)

  • Cache API tokens and groups to cut database reads

  • Suggest the closest commands, with their aliases, when the CLI is given an unknown command

Fixed
  • Fix new installations failing to create their tables on MySQL 8 and later

  • Fix tunnel clients reconnecting after a tunnel was deleted on a busy server

  • Fix knot admin ignoring server.redis.hosts

  • Fix creating templates through the API without an idle timeout unit

  • Fix the Users page showing no users when one was created without roles or groups

  • Fix the chat ignoring provider and never sending reasoning_effort to the model

  • Fix a slow direct connection blocking a port forward from accepting further connections

  • Fix syslog lines without a priority, such as web access logs, being logged as errors

  • Fix space health checks ignoring the template’s timeout and skip SSL verification settings

  • Fix knot.template.update() turning off VNC on KVM templates

  • Fix knot.role.get() leaving out plugin permissions, so knot.role.update() cleared them

  • Fix knot.stack.list() reporting every space as not running

  • Fix the OAuth provider scopes setting being ignored Pro

  • Fix listing sessions through the API failing when authenticated with an API token

  • Fix the chat temperature and max_tokens settings never reaching the model; with temperature unset, the provider’s default now applies

  • Fix the AI assistant refusing on-demand tools: every approved execute_tool or tool_search call failed with “not callable from this context”

  • Fix a mistyped CLI subcommand running a different command, such as knot file buket list running knot file list


v0.36.2
Fixed
  • UI stacks: stack name auto completion on the space form offered no suggestions to users without permission to set space dependencies.

  • UI port forwarding: the target picker lists other users’ spaces that share a port, narrowed to those sharing the remote port entered Pro .

  • Apple Containers: fixed an issue where it wasn’t possible to delete the container.


September 2026

v0.36.1
Fixed
  • 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.


v0.36.0
Added
  • Outbound network restrictions for server-side scripts: a new server.script_net_policy setting points MCP tool and event sink scripts at a network policy file — the network equivalent of server.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 /mcp endpoint 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 space knot mcp connects through the agent socket with no configuration. See knot 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/list and skills/get, with each SKILL.md readable as a skill:// 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 acquire checks 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, and release --destroy swaps the member for a fresh one so the next acquire starts clean. See Space Pools.

  • Scriptling: knot.pool leases: acquire(name, time=None, wait=None), extend(space, time=None), release(space, destroy=False), leases(name) and a leased() 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, and knot.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.template everywhere.

Changed
  • The /mcp endpoint 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 and knot.mcp in 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_skill MCP 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/read on the skill:// URI). The CLI, the knot.skill scripting library and the skills API are unchanged.

Fixed
  • knot.mcp works again: the scriptling library’s list_tools(), call_tool(), tool_search() and execute_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 disabled for 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--space for other users’ targets) and the proxy accepts names, qualified names and IDs.

  • Non-admins got an empty space list from the CLI: knot space list and every other client that calls the spaces API without a user_id filter received nothing back, because the endpoint only allowed admins an unfiltered list. An omitted user_id now means the requester’s own spaces; asking for another user’s id still returns nothing without the manage-spaces permission.


v0.35.0
Added
  • 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 kvm runtime automatically. See KVM Nodes and the VM Specification.
Added
  • Scriptling: knot.space gains KVM IP support — create() and update() accept ip_address, new get_ip_address()/set_ip_address() helpers, and every space dict carries ip_address; knot.template responses expose the KVM network fields.
Added
  • Tunnel domain everywhere the wildcard domain is: new server.tunnel_domain spec/stack variable with editor autocomplete; the server-info API and knot.server.info() now return tunnel_domain alongside wildcard_domain.
Changed
  • Spaces list: the log window action is hidden for KVM spaces — a VM has no container runtime to stream logs from.
Fixed
  • 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.