Set the limits
In Settings → Agents → Resource limits, turn on the switch. Then enter a CPU limit in cores (fractions such as2.5 work) and a Memory limit in GiB. An empty field means no limit. The value saves when you leave the field.
The line under the fields shows the result:
- Active: agent commands share the limits. The line names the cgroup they run in.
- Not applied: the line gives the reason. Fix the cause (see Status messages), then click Try again.
What the limit covers
The limit covers the commands of local and worktree workspaces: bash tool commands in the foreground and background, tool hooks, init and lifecycle hooks, MCP servers that run as local commands, and the other commands Xum runs in the workspace for the agent. It does not cover:- Terminals that you open.
- The desktop that desktop tools start, and the programs that the desktop starts.
- Xum itself, including the git commands it runs to create and remove worktrees, and repository hooks such as
post-checkoutthat those commands run. - Docker, dev container, SSH, and Coder workspaces. Their commands run in the container or on the remote machine.
xum run and xum workflow apply the saved limits to their commands too. Their commands share one limit with the agents of a running Xum only when both use the same base cgroup (see How Xum sets up the cgroup), for example when you start them from a shell in xum-app.
Things to know about the limits:
- The CPU limit is a quota: with
2.5, agent commands together get 250 ms of CPU time in each 100 ms period, on any number of CPUs. Programs built with Go 1.25 or later set their defaultGOMAXPROCSfrom it, unless theirgo.modnames an earlier Go version. - The memory limit covers RAM, not swap. If the machine has swap, agent commands can still use it.
- If you lower the memory limit below what agent commands use now, the kernel reclaims memory and can stop agent processes with the out-of-memory killer.
How Xum sets up the cgroup
A user can move a process into a cgroup only inside a cgroup tree that is delegated to that user. Xum therefore uses the cgroup it runs in, which this page calls the base cgroup. When you set a limit, Xum:- Enables the
cpuandmemorycontrollers for the base cgroup’s children. A cgroup that does this cannot hold processes itself, so Xum first moves the processes of the base cgroup into a child namedxum-app. - Creates the child
xum-agentsand writes the limits to itscpu.maxandmemory.max. - Moves each new agent command into
xum-agentsbefore the command runs.
max to both files. It does not move processes back or delete the cgroups. After the first setup, start other processes in xum-app, not in the base cgroup. A Xum that you restart from a shell in xum-app uses the same base cgroup again.
Start Xum in a delegated cgroup
If the status says that Xum cannot manage its cgroup, start Xum in a cgroup that your user owns.With systemd
Start Xum in a scope with delegation:cpu controller is not available, the systemd user manager does not have it. To delegate it, create /etc/systemd/system/user@.service.d/delegate.conf with:
sudo systemctl daemon-reload and log in again.
With sudo (containers and Coder workspaces)
Without a systemd user manager, create the cgroup as root, give it to the user that runs Xum, and start Xum from a shell that root moved into it. Replacecoder with that user:
cgroup.procs of the closest cgroup that contains both the old and the new cgroup, and here that is the root cgroup. /sys/fs/cgroup/xum/cgroup.controllers must list cpu and memory. If it does not, enable them in the parent’s cgroup.subtree_control as root. In a Coder workspace, put these steps in the startup script before Xum starts.
The user controls only this cgroup and its children. Limits on its parents still apply.
Status messages
If a command prints
xum: could not apply the agent resource limit to this command, the command ran without the limit, for example because the xum-agents cgroup was removed. Click Try again in Settings, or restart Xum.