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. Anyone with passwordless
sudoopensuxonand immediately sees every agent session on the host: CPU, RAM, age, last attach, attached-or-not. Attach to any of them withEnter, kill a runaway withd, nuke the lot with a confirmedkill-all-global. 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 by default, lockable for ops. Out of the box you
can launch an agent in any folder where the launch user has write
access. On a shared host, set
allowed_rootsin the config to pin agents to specific directories. Seedocs/configuration.md. - One tool, every agent. Flip a config switch to enable Claude
Code, Codex, Cursor — together or any subset. Built-in
--autoand--dsp(skip-permissions / "yolo") flags translate to whatever the underlying agent uses today. - Optional niceties. Git worktrees, GitHub repo creation on a new project (with a strict whitelist), per-project config overrides. All off by default.
Install
Requires Python 3.11+, tmux, and Linux. Dependencies (textual,
tomlkit) are pulled in automatically.
Single-user laptop (recommended)
# 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
Either creates an isolated venv and puts uxon on your PATH.
Update with uv tool upgrade uxon / pipx upgrade uxon.
For the bleeding edge from main (before a release lands on PyPI):
uv tool install git+https://github.com/vzd3v/uxon.git
# or: pipx install git+https://github.com/vzd3v/uxon.git
If you maintain your own Python (pyenv, asdf, uv-managed) and prefer
no isolation, pip install --user uxon works too — uxon lands in
~/.local/bin/. On Debian/Ubuntu/Fedora system Python, PEP 668 blocks
plain pip install; use pipx (recommended) or know-what-you-do
pip install --user --break-system-packages uxon.
uxon doctor # verify the install
# Optional: bootstrap an example config (uxon runs in $HOME 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
You'll also need at least one of the agent CLIs installed for the launch user — see Supported agents.
Shared host / multi-user VPS
For a host where several Linux users need a single shared uxon on
PATH, install into a dedicated venv and symlink the console script:
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)
The installer creates a venv at --venv-dir, installs the package
into it, and symlinks /opt/uxon/venv/bin/uxon to /usr/local/bin/uxon.
For multi-host rollout, generated config from a JSON payload, and
deployment topology, see docs/deployment.md.
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 works out of the box with no configuration — the launch user
can run an agent anywhere they have write access, and uxon new
creates projects under ~/projects.
Configuration becomes useful once you're hosting more than one user,
or want to restrict where agents may run, 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.
- Always run
uxon doctorfirst. It prints the resolved caller / launch user, active config paths, allowed roots, agent paths, socket details, current sessions, and any detected configuration issues.
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.0.0.tar.gz.
File metadata
- Download URL: uxon-3.0.0.tar.gz
- Upload date:
- Size: 135.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db41845620eba7cdec918dca99d21aedfbee67fee6e0e70da5f12db54800d0a1
|
|
| MD5 |
f83473a0f2dafa0ed7b62c583cbf1b00
|
|
| BLAKE2b-256 |
1939f29abd8842fbbb7f86ad627bcf94fb5e064d2a057171b7168cceb9265d8e
|
Provenance
The following attestation bundles were made for uxon-3.0.0.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.0.0.tar.gz -
Subject digest:
db41845620eba7cdec918dca99d21aedfbee67fee6e0e70da5f12db54800d0a1 - Sigstore transparency entry: 1421880518
- Sigstore integration time:
-
Permalink:
vzd3v/uxon@a80374be47c477b17569bada2061cc9615e1452c -
Branch / Tag:
refs/tags/v3.0.0 - Owner: https://github.com/vzd3v
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a80374be47c477b17569bada2061cc9615e1452c -
Trigger Event:
push
-
Statement type:
File details
Details for the file uxon-3.0.0-py3-none-any.whl.
File metadata
- Download URL: uxon-3.0.0-py3-none-any.whl
- Upload date:
- Size: 96.8 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 |
87ff44c3fc5c6a73789c2b1751cb781bcca988f46de8071072c7657a32945031
|
|
| MD5 |
1cced9f3923aa4472b6411cfa01af229
|
|
| BLAKE2b-256 |
fe14e446922ff9b0fc4efd74d646b24e80b85c8a147fa9c8443580dca810a54c
|
Provenance
The following attestation bundles were made for uxon-3.0.0-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.0.0-py3-none-any.whl -
Subject digest:
87ff44c3fc5c6a73789c2b1751cb781bcca988f46de8071072c7657a32945031 - Sigstore transparency entry: 1421880594
- Sigstore integration time:
-
Permalink:
vzd3v/uxon@a80374be47c477b17569bada2061cc9615e1452c -
Branch / Tag:
refs/tags/v3.0.0 - Owner: https://github.com/vzd3v
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a80374be47c477b17569bada2061cc9615e1452c -
Trigger Event:
push
-
Statement type: