Multi-user wrapper for managing terminal AI coding agent sessions (claude, codex, cursor)
Project description
uxon
Run terminal AI coding agents (Claude Code, Codex, Cursor) on a shared server — safely, persistently, and visibly to the operator.
uxon is a small tmux wrapper with a full-screen TUI session picker.
It standardises session names, isolates each user on a dedicated tmux
socket, and lets you start, attach, monitor, and kill agent sessions
from one screen — your laptop, your phone over SSH, or a sysadmin's
shell with sudo.
What it solves
- Sandboxed agent runs. Drop the agent into a low-privilege OS
account with a restricted filesystem view via
sudo -iu, while you keep operating from your own login. The agent can't reach what its user can't reach. - Many users on one box. Each developer logs into their own OS
user, runs their own authenticated
claude/codex/cursorwith their own keys and quotas, and never sees another user's tmux sessions by accident — every launch user gets a dedicated socket at/tmp/uxon-<user>.sock. - Operator visibility and control. With passwordless
sudoto the launch users listed insession_users, the operator opensuxonand sees every agent session of those users — their own and others' — with CPU, RAM, age, last attach, attached-or-not.Enterattaches to any of those sessions (you join theirtmuxas a guest viasudo -iu),dkills a runaway, andkill-all-globalreaps every session of every listedsession_userafter explicit confirmation. No more "who's that 38 GB python on the dashboard?". - Attach from anywhere. Sessions live in
tmux, so they survive every disconnect. Start at your desk, reattach from your phone over SSH on the train, switch to a tablet later — same session, same state. The TUI is keyboard-only and fits a small screen. - Predictable session names.
uxon-<project>@<agent>(-2,-3for parallels). No more hand-rolledtmux new -sstrings or guessing what you called it yesterday. - Permissive defaults, strict-whitelist for ops. With
allowed_roots = [](default), the TUI's "new session in current folder" anduxon run(CLI) both launch anywhere the launch user can write. Withallowed_roots = [...]set, both switch to strict whitelist — only those paths are accepted, with no$HOME-implicit or any other side allowance.allowed_rootsalso boundsuxon new(creating a new project directory). To restrict what the agent can reach on disk regardless of whereuxonis invoked, sandbox launches under a low-privilege OS user viaruntime_user. Seedocs/configuration.md. - One tool, every agent. Flip a config switch to enable Claude
Code, Codex, Cursor — together or any subset. Built-in
--dsp(skip-permissions / "yolo") flag maps to each agent's native equivalent across all three;--autodoes the same forclaudeandcodex(cursor has no auto mode and errors out). - Optional niceties. Git worktrees (currently
claude-only —codexandcursorerror if you pass-w), GitHub repo creation on a new project (with a strict whitelist of named profiles), per-project config overrides. All off by default.
Install
Requires Python 3.11+, tmux, and Linux. Dependencies (textual,
tomlkit) are pulled in automatically.
uxon is built for persistent Linux servers where one or several OS
users run agent sessions that need to survive disconnects. Two install
flavours, depending on whether each user installs their own copy or
the host has one shared uxon on PATH for everyone.
Per-user install (recommended)
Use this when each OS user manages their own copy of uxon —
independently versioned, no sudo needed, easy uninstall. The
common case for solo developers and small teams where everyone
prefers full control over their tooling.
Each OS user runs one of these in their own account:
# uv tool — recommended. uv is the 2026 default Python toolchain;
# fast, uses uv-managed Python and a shared dep cache.
uv tool install uxon
# pipx — equivalent. Same console-script entrypoint.
pipx install uxon
# pip --user — no isolation. See PEP 668 caveat below.
pip install --user uxon
uv/pipx isolate uxon and its deps in a per-user venv; pip --user
puts them under ~/.local/ shared with anything else installed that
way. All three put a uxon console script on the user's PATH.
Updates: uv tool upgrade uxon / pipx upgrade uxon /
pip install --user --upgrade uxon.
On Debian/Ubuntu/Fedora system Python, PEP 668 blocks
pip install --user; use pipx (recommended) or
pip install --user --break-system-packages uxon if you know what
you're doing. With your own Python (pyenv/asdf/uv-managed) PEP 668
doesn't apply.
For unreleased changes from main:
uv tool install git+https://github.com/vzd3v/uxon.git
# or: pipx install git+https://github.com/vzd3v/uxon.git
Host-wide install (one uxon for all users on the host)
Use this when you administer a server where several OS users
launch agent sessions and you want them on a single shared uxon
in /usr/local/bin/uxon — one version, one update path, one place
to audit. With (a) passwordless sudo to other launch users and
(b) those users listed in session_users in config.toml, the
operator additionally sees and can attach to those users'
sessions from the same TUI (the Superuser block, described under
The TUI below). Missing either piece — no sudo, or
empty session_users — and every OS user is sandboxed to their
own sessions only. Each OS user keeps their own tmux socket and
their own uxon-* sessions; only the binary is shared.
# Simple: pipx as a system installer (pipx 1.5+).
sudo pipx install --global uxon
# Updates: sudo pipx upgrade --global uxon
# Explicit: bundled installer. Useful for fleet rollout (Ansible /
# Puppet) and when ops conventions pin paths like /opt/uxon/venv.
git clone https://github.com/vzd3v/uxon.git
cd uxon
sudo python3 install/install_uxon.py \
--repo-dir "$(pwd)" \
--install-path /usr/local/bin/uxon
# (uses /opt/uxon/venv by default; override with --venv-dir)
# Updates: re-run with --reinstall
Both isolate uxon's Python deps in a dedicated venv and put the
console script on PATH via a /usr/local/bin/uxon shim. Don't use
sudo pip install uxon — it dumps textual / rich / tomlkit /
etc. into the system Python site-packages and conflicts with the
distro's package manager (this is what PEP 668 protects against).
For multi-host rollout, generated config from a JSON payload, and
deployment topology, see docs/deployment.md.
After install
uxon # launch the TUI; it self-diagnoses
# Optional: bootstrap an example config (uxon also runs with defaults).
curl -fsSL https://raw.githubusercontent.com/vzd3v/uxon/main/config/config.example.toml -o ./config.toml
$EDITOR ./config.toml # set allowed_roots, session_users, agents
For deeper, scriptable host inspection see
docs/cli.md.
You'll also need at least one of the agent CLIs installed for the launch user — see Supported agents.
Quick start
uxon # full-screen TUI picker (recommended; needs a TTY)
That's the intended entry point. Everything below — creating projects, attaching, killing, switching agents — happens inside the TUI. Read on.
For non-interactive use (scripts, CI, SSH one-liners), the same operations are available as subcommands; see CLI at the end.
The TUI
uxon with no arguments on a TTY opens a full-screen textual
picker. One screen, three blocks:
1. Actions (top)
- New session in current folder — start the default agent in
$PWD(gated on the allowed-roots check). - Create new project — prompt for a name, create
<new_project_root>/<name>, optionally create a GitHub remote (if git-remote profiles are configured), launch the agent. - Open existing project — pick a directory under
new_project_rootand launch.
Before every launch, a permissions modal asks whether to start the
agent in normal mode or with --dangerously-skip-permissions
("yolo"). No accidental yolos.
2. Your sessions
Live list of uxon-* sessions for the current user with:
- session name, agent, working directory;
- live CPU / RAM (refreshed every
tui_refresh_interval_seconds); - attached-or-not marker;
- creation time and last-attach time.
Enter attaches. d kills (with confirmation). D kills all your
own sessions after typing kill-all.
3. Server status (bottom)
Load average, normalised CPU load, RAM, disk, uptime. When you're
inside an SSH session, an async ssh-link probe shows RTT, jitter,
and retransmits — quick read on whether the lag you're feeling is
the agent or the network.
⚡ Superuser block (only when passwordless sudo is detected)
Appears below your own sessions whenever the host trusts you with
sudo:
- Other users' sessions with a yellow
USERcolumn.Enterattaches viasudo -iu <user>(read-only-ish — you're a guest in their tmux);dkills the highlighted one. - ⚙ Settings — repo-level
config.tomleditor. Bool keys toggle, enums cycle, strings open an input, arrays use comma-separated input. Saves rewrite the file via atomlkitround-trip (usingsudo teeautomatically when needed) and preserve untouched comments and formatting. Project-level.uxon.tomlkeys are read-only here — edit them in the project. - Kill ALL uxon sessions (all users) — appears when at least
one session exists anywhere; requires typing
kill-all-globalto confirm. The "fire alarm" button.
Keys
| Key | Action |
|---|---|
↑ ↓ / j k |
Navigate |
1–9 |
Jump to item by number |
Enter |
Activate (launch / attach) |
d |
Kill highlighted session (with confirmation) |
D |
Kill all own sessions (kill-all to confirm) |
r |
Refresh |
g / G |
Jump to first / last |
q / Esc |
Quit (or back, in sub-screens) |
Detach and re-enter
When the launched session exits — or you Ctrl-b d to detach —
uxon returns to the main screen with a refreshed list. The same
binary you launched is the same binary you come back to. q / Esc
on the main screen exits to the shell.
If a launch fails, the failure output stays on the physical terminal with a banner before the TUI re-enters fullscreen, so you can read whatever stderr the agent printed.
Supported agents
| Agent id | Binary | --auto mode |
--dsp (yolo) |
Install |
|---|---|---|---|---|
claude |
claude |
--permission-mode auto |
--dangerously-skip-permissions |
Anthropic docs |
codex |
codex |
--full-auto |
--dangerously-bypass-approvals-and-sandbox |
npm i -g @openai/codex |
cursor |
cursor-agent |
(not supported) | --yolo |
curl https://cursor.com/install -fsSL | bash |
Enable agents in config/config.toml:
[agents]
enabled = ["claude", "codex"]
default = "claude"
uxon doctor probes each enabled agent and prints its path, version,
and status. If none of the enabled agents are installed for the
launch user, the TUI shows a modal with install hints.
-w <branch> (worktree mode) is currently claude-only.
--auto is unavailable for cursor.
Configuration
uxon run and the TUI's "New session in current folder" work out of
the box with no configuration — the launch user can run an agent
anywhere they have write access. uxon new <name> (creating a
project) requires allowed_roots to be non-empty and to cover
new_project_root.
Configuration becomes useful once you're hosting more than one user,
or want to restrict where agents may run, or want uxon new to
scaffold projects, or want one-shot GitHub repo creation, or want to
switch the default agent. All keys, with the use case for each,
live in docs/configuration.md.
Two config layers (later wins):
- Repo config —
<repo>/config/config.toml, host-wide.config/config.example.tomlis the tracked starting point. - Project config — the nearest
.uxon.tomlincwdor a parent inside anallowed_rootsentry. Per-project overrides. The TUI never writes.uxon.toml.
CLI
The TUI is the recommended entry point. The CLI exposes the same operations for scripting, SSH one-liners, and CI. Brief summary:
| Command | What it does |
|---|---|
uxon |
Open the interactive TUI (needs a TTY). |
uxon run [-w <branch>] [agent-flags...] |
Start an agent in $PWD. |
uxon new <name> [-w <branch>] [...] |
Create / reuse a project under new_project_root and start an agent. |
uxon list [--all-users] |
List uxon-* sessions for this user (or all configured users). |
uxon attach <id> |
Re-attach to a session. Accepts full name, short name, bare stem, or active-pane PID. |
uxon kill <id> |
Kill one session. |
uxon kill-all [--force] |
Kill every uxon-* session for the current launch user. |
uxon doctor |
Read-only diagnostics: caller / launch user, config, allowed_roots, agents, sockets, sessions, detected issues. Run this first when something looks wrong. |
uxon version |
Print version + git commit. |
Short forms: -l / -a / -k / -n / -V / --killall.
Full reference with every flag, exit code, identifier-resolution
rules, repeat-behaviour, worktree details, and legacy-session notes
is in docs/cli.md.
Troubleshooting
uxonstarted inside an existingtmux? Handled transparently when$TMUXnames the same socket asuxon. If it's a different (foreign)tmux,uxonprints an actionable error —Ctrl-b dfirst.textualnot installed? The TUI prints an install hint and exits. The whole CLI keeps working.- TUI errors render as a red toast. Tmux-gone, permission denied, allowed-roots mismatch, git remote failure, config-write conflict — all caught and shown in-place rather than crashing.
- TUI surfaces tmux/agent issues in line. Missing
tmuxor missing agent binaries trigger a friendly preflight error from the CLI and an in-line hint in the TUI; freshly-installed agents are auto-detected and offered for one-keypress enabling. For deeper diagnostics seedocs/cli.md.
More edge cases (legacy session prefixes, failed-launch banner, the
--dsp flag and its legacy aliases) are documented in
docs/cli.md.
Documentation
docs/configuration.md— all config keys organised by use case (single-user laptop, shared multi-user host, restricted launch directories, GitHub repo on new project, …).docs/cli.md— full CLI reference (every flag, exit code, identifier resolution, repeat behaviour).docs/deployment.md— multi-host rollout, config rendering from JSON, runtime dependencies.docs/architecture.md— module map, TUI internals, code boundaries.CONTRIBUTING.md— local checks, branch policy, release process.SECURITY.md— threat model, disclosure policy.CHANGELOG.md— version history.
Versioning
uxon follows SemVer. uxon --version
prints the version and short git commit (with -dirty when the
checkout is dirty).
License
MIT © 2026 Vasily Zakharov.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file uxon-3.2.1.tar.gz.
File metadata
- Download URL: uxon-3.2.1.tar.gz
- Upload date:
- Size: 153.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0fa581c493f9951f338fea530eef5ea4445f94479499e36dbd4360dc495ca4cb
|
|
| MD5 |
6f74f3b03091ede497f3aee313819980
|
|
| BLAKE2b-256 |
09fd39e5a6c71c8100f20118cb387b0f6ec38f37920b58a88328d039a20ee181
|
Provenance
The following attestation bundles were made for uxon-3.2.1.tar.gz:
Publisher:
release.yml on vzd3v/uxon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
uxon-3.2.1.tar.gz -
Subject digest:
0fa581c493f9951f338fea530eef5ea4445f94479499e36dbd4360dc495ca4cb - Sigstore transparency entry: 1429423434
- Sigstore integration time:
-
Permalink:
vzd3v/uxon@80bbaf62aa75d1d7415402513f07b42b11d4e890 -
Branch / Tag:
refs/tags/v3.2.1 - Owner: https://github.com/vzd3v
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@80bbaf62aa75d1d7415402513f07b42b11d4e890 -
Trigger Event:
push
-
Statement type:
File details
Details for the file uxon-3.2.1-py3-none-any.whl.
File metadata
- Download URL: uxon-3.2.1-py3-none-any.whl
- Upload date:
- Size: 108.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b8f72f515f0ece25fe6636749086f24dfa4ba537ff9bd82882d13ab1e5696bb7
|
|
| MD5 |
437cebc5d0207be4d4e154309f87737f
|
|
| BLAKE2b-256 |
cdba2e9048d8e09be39e28ac32440e7c1455e270bd2efbbe3ca8f575e70a3de2
|
Provenance
The following attestation bundles were made for uxon-3.2.1-py3-none-any.whl:
Publisher:
release.yml on vzd3v/uxon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
uxon-3.2.1-py3-none-any.whl -
Subject digest:
b8f72f515f0ece25fe6636749086f24dfa4ba537ff9bd82882d13ab1e5696bb7 - Sigstore transparency entry: 1429423445
- Sigstore integration time:
-
Permalink:
vzd3v/uxon@80bbaf62aa75d1d7415402513f07b42b11d4e890 -
Branch / Tag:
refs/tags/v3.2.1 - Owner: https://github.com/vzd3v
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@80bbaf62aa75d1d7415402513f07b42b11d4e890 -
Trigger Event:
push
-
Statement type: