uxon 3.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- uxon-3.0.0/.gitignore +30 -0
- uxon-3.0.0/CHANGELOG.md +55 -0
- uxon-3.0.0/CONTRIBUTING.md +137 -0
- uxon-3.0.0/LICENSE +21 -0
- uxon-3.0.0/PKG-INFO +373 -0
- uxon-3.0.0/README.md +337 -0
- uxon-3.0.0/SECURITY.md +66 -0
- uxon-3.0.0/config/config.example.toml +45 -0
- uxon-3.0.0/docs/architecture.md +170 -0
- uxon-3.0.0/docs/cli.md +224 -0
- uxon-3.0.0/docs/configuration.md +266 -0
- uxon-3.0.0/docs/deployment.md +162 -0
- uxon-3.0.0/examples/uxon-config.json +20 -0
- uxon-3.0.0/install/install_uxon.py +138 -0
- uxon-3.0.0/install/render_uxon_config.py +182 -0
- uxon-3.0.0/pyproject.toml +128 -0
- uxon-3.0.0/src/uxon/__init__.py +8 -0
- uxon-3.0.0/src/uxon/__main__.py +12 -0
- uxon-3.0.0/src/uxon/agents.py +154 -0
- uxon-3.0.0/src/uxon/cli.py +2858 -0
- uxon-3.0.0/src/uxon/git_backend_gh.py +152 -0
- uxon-3.0.0/src/uxon/git_backend_token.py +269 -0
- uxon-3.0.0/src/uxon/git_create.py +307 -0
- uxon-3.0.0/src/uxon/git_profiles.py +171 -0
- uxon-3.0.0/src/uxon/settings.py +424 -0
- uxon-3.0.0/src/uxon/tui/__init__.py +64 -0
- uxon-3.0.0/src/uxon/tui/app.py +407 -0
- uxon-3.0.0/src/uxon/tui/context.py +366 -0
- uxon-3.0.0/src/uxon/tui/events.py +115 -0
- uxon-3.0.0/src/uxon/tui/hints.py +14 -0
- uxon-3.0.0/src/uxon/tui/launch.py +70 -0
- uxon-3.0.0/src/uxon/tui/screens/__init__.py +5 -0
- uxon-3.0.0/src/uxon/tui/screens/agents_unavailable.py +76 -0
- uxon-3.0.0/src/uxon/tui/screens/confirm.py +125 -0
- uxon-3.0.0/src/uxon/tui/screens/existing.py +117 -0
- uxon-3.0.0/src/uxon/tui/screens/git_profile.py +105 -0
- uxon-3.0.0/src/uxon/tui/screens/git_remotes.py +52 -0
- uxon-3.0.0/src/uxon/tui/screens/launch_options.py +239 -0
- uxon-3.0.0/src/uxon/tui/screens/main.py +699 -0
- uxon-3.0.0/src/uxon/tui/screens/new_project.py +114 -0
- uxon-3.0.0/src/uxon/tui/screens/settings.py +479 -0
- uxon-3.0.0/src/uxon/tui/state.py +373 -0
- uxon-3.0.0/src/uxon/tui/styles.tcss +149 -0
- uxon-3.0.0/src/uxon/tui/widgets/__init__.py +13 -0
- uxon-3.0.0/src/uxon/tui/widgets/action_row.py +132 -0
- uxon-3.0.0/src/uxon/tui/widgets/session_table.py +177 -0
- uxon-3.0.0/tests/harness/__init__.py +0 -0
- uxon-3.0.0/tests/harness/pty_tui.py +236 -0
- uxon-3.0.0/tests/harness/textual_scenarios.py +81 -0
- uxon-3.0.0/tests/test_tui_integration.py +280 -0
- uxon-3.0.0/tests/test_uxon.py +1320 -0
- uxon-3.0.0/tests/test_uxon_agents.py +130 -0
- uxon-3.0.0/tests/test_uxon_git_backend_gh.py +128 -0
- uxon-3.0.0/tests/test_uxon_git_backend_token.py +282 -0
- uxon-3.0.0/tests/test_uxon_git_create.py +264 -0
- uxon-3.0.0/tests/test_uxon_git_profiles.py +140 -0
- uxon-3.0.0/tests/test_uxon_settings.py +300 -0
- uxon-3.0.0/tests/test_uxon_tui.py +553 -0
- uxon-3.0.0/tests/test_uxon_tui_agents_unavailable.py +96 -0
- uxon-3.0.0/tests/test_uxon_tui_bindings.py +130 -0
- uxon-3.0.0/tests/test_uxon_tui_logging.py +62 -0
- uxon-3.0.0/tests/test_uxon_tui_screens.py +473 -0
- uxon-3.0.0/tests/test_uxon_tui_widgets_textual.py +190 -0
uxon-3.0.0/.gitignore
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.pyc
|
|
3
|
+
.pytest_cache/
|
|
4
|
+
|
|
5
|
+
# Build artefacts (hatchling / python -m build)
|
|
6
|
+
dist/
|
|
7
|
+
build/
|
|
8
|
+
*.egg-info/
|
|
9
|
+
|
|
10
|
+
# Local config (gitignored except the example)
|
|
11
|
+
config/*
|
|
12
|
+
!config/config.example.toml
|
|
13
|
+
|
|
14
|
+
# Agent-only material — kept on local disk, never tracked in git
|
|
15
|
+
.claude/
|
|
16
|
+
AGENTS.md
|
|
17
|
+
CLAUDE.md
|
|
18
|
+
docs/agents/
|
|
19
|
+
|
|
20
|
+
# Misc
|
|
21
|
+
_external_sources/
|
|
22
|
+
|
|
23
|
+
# Local environments and editor / OS junk
|
|
24
|
+
.venv/
|
|
25
|
+
.env
|
|
26
|
+
.envrc
|
|
27
|
+
.DS_Store
|
|
28
|
+
*.swp
|
|
29
|
+
.idea/
|
|
30
|
+
.vscode/
|
uxon-3.0.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format
|
|
4
|
+
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
|
|
5
|
+
this project adheres to [Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [3.0.0] — 2026-05-01
|
|
10
|
+
|
|
11
|
+
First PyPI release.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- Released on PyPI as [`uxon`](https://pypi.org/project/uxon/).
|
|
16
|
+
Install with `uv tool install uxon`, `pipx install uxon`, or
|
|
17
|
+
`pip install --user uxon`.
|
|
18
|
+
- `python -m uxon` works alongside the generated `uxon` console
|
|
19
|
+
script — same entrypoint, useful for in-tree development.
|
|
20
|
+
- PyPI release pipeline at `.github/workflows/release.yml`: pushing
|
|
21
|
+
a `v*` tag builds sdist + wheel, publishes via OIDC trusted
|
|
22
|
+
publisher (no API token in GitHub Secrets), and creates a GitHub
|
|
23
|
+
Release with auto-generated notes. PEP 740 attestations are
|
|
24
|
+
generated automatically.
|
|
25
|
+
- `legacy_session_prefixes` config key — array of additional `tmux`
|
|
26
|
+
prefixes that `uxon list` / `attach` / `kill` recognise alongside
|
|
27
|
+
`session_prefix`. Useful when migrating from a previous prefix.
|
|
28
|
+
New sessions are always created under `session_prefix`.
|
|
29
|
+
- `docs/cli.md` — full CLI reference (every flag, exit code,
|
|
30
|
+
identifier resolution, repeat behaviour).
|
|
31
|
+
- `docs/configuration.md` — use-case-driven configuration guide
|
|
32
|
+
(single-user laptop, multi-user host, sandboxed agent user,
|
|
33
|
+
pinning agents to directories, GitHub repo creation).
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- **`uxon` ships as a `src/uxon/` Python package** built with
|
|
38
|
+
`hatchling`. Out-of-tree consumers import from `uxon.*` (e.g.
|
|
39
|
+
`from uxon.settings import ...`, `from uxon.tui.app import ...`).
|
|
40
|
+
- **`install/install_uxon.py`** now creates a dedicated venv at
|
|
41
|
+
`--venv-dir` (default `/opt/uxon/venv`), installs the package
|
|
42
|
+
into it, and symlinks the venv's console script to
|
|
43
|
+
`--install-path`. Used for the shared-host / multi-user VPS
|
|
44
|
+
scenario only — solo laptops use `uv tool install` /
|
|
45
|
+
`pipx install`. Adds `--dry-run` and `--reinstall` flags.
|
|
46
|
+
- README rewritten around the TUI as the primary interface, with a
|
|
47
|
+
compact CLI summary linking to `docs/cli.md`. Install section
|
|
48
|
+
leads with `uv tool install uxon` and `pipx install uxon`.
|
|
49
|
+
|
|
50
|
+
### Dependencies
|
|
51
|
+
|
|
52
|
+
- `textual >=0.80,<9` and `tomlkit` are hard runtime dependencies,
|
|
53
|
+
pulled in automatically by `pip install` / `pipx install` /
|
|
54
|
+
`uv tool install`. The optional `dev` extra ships `pytest`,
|
|
55
|
+
`pytest-xdist`, `ruff`, and `pyright`.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Contributing to uxon
|
|
2
|
+
|
|
3
|
+
Thanks for taking the time. This guide covers everything you need
|
|
4
|
+
to make and ship a change.
|
|
5
|
+
|
|
6
|
+
## Local setup
|
|
7
|
+
|
|
8
|
+
`uxon` is a regular Python package (`pyproject.toml`, hatchling backend).
|
|
9
|
+
For development, install editable into a venv. Two equivalent paths:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
git clone https://github.com/vzd3v/uxon.git
|
|
13
|
+
cd uxon
|
|
14
|
+
|
|
15
|
+
# A) uv (recommended; faster, shared dep cache)
|
|
16
|
+
uv venv
|
|
17
|
+
uv pip install -e ".[dev]"
|
|
18
|
+
source .venv/bin/activate
|
|
19
|
+
|
|
20
|
+
# B) plain venv + pip
|
|
21
|
+
python3 -m venv .venv
|
|
22
|
+
source .venv/bin/activate
|
|
23
|
+
python3 -m pip install -e ".[dev]"
|
|
24
|
+
|
|
25
|
+
uxon --version
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Both pull `ruff`, `pyright`, `pytest`, `textual`, `tomlkit`
|
|
29
|
+
automatically.
|
|
30
|
+
|
|
31
|
+
`uxon` requires Python 3.11+. The TUI uses `textual >=0.80,<9`; config
|
|
32
|
+
writes use `tomlkit`. Both are hard runtime dependencies (pulled in by
|
|
33
|
+
`pip install` / `pipx install` / `uv tool install`).
|
|
34
|
+
|
|
35
|
+
## Local checks
|
|
36
|
+
|
|
37
|
+
Before opening a PR, run:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
python3 -m py_compile $(git ls-files '*.py')
|
|
41
|
+
python3 -m pytest tests/ -n auto
|
|
42
|
+
ruff check .
|
|
43
|
+
ruff format --check .
|
|
44
|
+
pyright
|
|
45
|
+
python -m build # smoke-test the wheel/sdist
|
|
46
|
+
twine check dist/* # README rendering on PyPI
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
CI runs the same. If something passes locally but breaks CI, please
|
|
50
|
+
add a test that catches it.
|
|
51
|
+
|
|
52
|
+
## Branching and commits
|
|
53
|
+
|
|
54
|
+
- Branch off `main`. Open PRs against `main`.
|
|
55
|
+
- One logical unit per commit. No drive-by refactors mixed in with a
|
|
56
|
+
bug fix; split them into separate commits.
|
|
57
|
+
- Commit-message subject in imperative mood ("add", "fix",
|
|
58
|
+
"rewrite") with a short body explaining *why*. Conventional Commits
|
|
59
|
+
(`feat:`, `fix:`, `docs:`, `chore:`, `refactor:`) is the existing
|
|
60
|
+
style — match it.
|
|
61
|
+
- Never bypass git hooks (`--no-verify`) and never amend a published
|
|
62
|
+
commit.
|
|
63
|
+
|
|
64
|
+
## When to bump `__version__`
|
|
65
|
+
|
|
66
|
+
Bump `__version__` in [`src/uxon/__init__.py`](src/uxon/__init__.py)
|
|
67
|
+
in the same commit as any user-visible behaviour change. Hatch reads
|
|
68
|
+
the same string at build time, so wheels and the in-tree CLI always
|
|
69
|
+
agree. Semver:
|
|
70
|
+
- **Major** for breaking changes to the CLI surface, the config
|
|
71
|
+
schema, or the on-disk session-naming scheme.
|
|
72
|
+
- **Minor** for new features that don't break existing config or
|
|
73
|
+
session names.
|
|
74
|
+
- **Patch** for bug fixes and doc-only changes that affect users.
|
|
75
|
+
|
|
76
|
+
Then add a matching entry to [`CHANGELOG.md`](CHANGELOG.md) under
|
|
77
|
+
`## [Unreleased]`.
|
|
78
|
+
|
|
79
|
+
## Architectural rules a contributor will hit
|
|
80
|
+
|
|
81
|
+
These are non-negotiable — see [`docs/architecture.md`](docs/architecture.md)
|
|
82
|
+
for the full picture. Quick list:
|
|
83
|
+
|
|
84
|
+
- **`textual` is imported lazily inside `do_interactive`.** Non-TUI
|
|
85
|
+
subcommands (`uxon list`, `uxon doctor`, `uxon version`) must run
|
|
86
|
+
without `textual` installed.
|
|
87
|
+
- **All key handling goes through `BINDINGS`.** No `on_key` overrides
|
|
88
|
+
on screen classes; a drift guard test refuses the PR otherwise.
|
|
89
|
+
- **Config writes use `tomlkit`** — round-trip preserves comments and
|
|
90
|
+
formatting. CLI read paths stay on stdlib `tomllib`.
|
|
91
|
+
- **One launch builder.** `uxon` is the single place that builds agent
|
|
92
|
+
command lines (`_build_tmux_launch_request` in `src/uxon/cli.py`).
|
|
93
|
+
Don't add direct agent exec calls anywhere else.
|
|
94
|
+
- **Module boundaries.** `src/uxon/cli.py` may import from sibling
|
|
95
|
+
modules in `src/uxon/*`; those modules never import from `cli`. UI
|
|
96
|
+
files under `src/uxon/tui/` must not import `subprocess`/`pwd` or
|
|
97
|
+
touch the filesystem directly — push that through callbacks on
|
|
98
|
+
`TuiContext`.
|
|
99
|
+
|
|
100
|
+
## Tests
|
|
101
|
+
|
|
102
|
+
- Prefer pure tests in `src/uxon/tui/state.py` for branchy UI logic.
|
|
103
|
+
Pilot/pty tests are reserved for Textual wiring (mounting, key
|
|
104
|
+
routing, `ListView`/`DataTable` events, async workers,
|
|
105
|
+
`call_later`).
|
|
106
|
+
- Don't add a new `App.run_test()` case when a pure state helper can
|
|
107
|
+
cover the behaviour and a smoke test already proves the wiring.
|
|
108
|
+
- Batch compatible Pilot scenarios via
|
|
109
|
+
`tests/harness/textual_scenarios.py::run_screen_scenarios` —
|
|
110
|
+
amortise the Textual lifecycle.
|
|
111
|
+
- Run the minimum sufficient subset while iterating
|
|
112
|
+
(`pytest tests/test_specific.py -k name`); always run the full
|
|
113
|
+
suite (`-n auto`) before pushing.
|
|
114
|
+
|
|
115
|
+
## Adding a config key
|
|
116
|
+
|
|
117
|
+
1. Extend `DEFAULT_CONFIG`, `Config`, and `load_config` in
|
|
118
|
+
`src/uxon/cli.py`.
|
|
119
|
+
2. Add validation if the value space is constrained.
|
|
120
|
+
3. Add a matching `SettingSpec` in
|
|
121
|
+
`src/uxon/settings.py::SETTINGS_SPECS` so the TUI Settings screen
|
|
122
|
+
exposes it.
|
|
123
|
+
4. Document it in the README config table.
|
|
124
|
+
5. Add a `load_config` test in `tests/test_uxon.py` and a
|
|
125
|
+
round-trip test in `tests/test_uxon_settings.py` if the value
|
|
126
|
+
has non-trivial encoding.
|
|
127
|
+
|
|
128
|
+
## Reporting bugs and proposing features
|
|
129
|
+
|
|
130
|
+
Please use the issue templates (bug reports include `uxon doctor`
|
|
131
|
+
output and the exact command). For security issues, see
|
|
132
|
+
[`SECURITY.md`](SECURITY.md).
|
|
133
|
+
|
|
134
|
+
## License
|
|
135
|
+
|
|
136
|
+
By contributing, you agree that your contributions are licensed
|
|
137
|
+
under the [MIT License](LICENSE).
|
uxon-3.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vasily Zakharov <vz@vz.team>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
uxon-3.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: uxon
|
|
3
|
+
Version: 3.0.0
|
|
4
|
+
Summary: Multi-user wrapper for managing terminal AI coding agent sessions (claude, codex, cursor)
|
|
5
|
+
Project-URL: Homepage, https://github.com/vzd3v/uxon
|
|
6
|
+
Project-URL: Issues, https://github.com/vzd3v/uxon/issues
|
|
7
|
+
Project-URL: Source, https://github.com/vzd3v/uxon
|
|
8
|
+
Project-URL: Changelog, https://github.com/vzd3v/uxon/blob/main/CHANGELOG.md
|
|
9
|
+
Author-email: Vasily Zakharov <vz@vz.team>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: ai-agents,claude,cli,codex,cursor,tmux
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Environment :: Console :: Curses
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Intended Audience :: System Administrators
|
|
18
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
19
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
20
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Software Development
|
|
25
|
+
Classifier: Topic :: System :: Systems Administration
|
|
26
|
+
Classifier: Topic :: Terminals
|
|
27
|
+
Requires-Python: >=3.11
|
|
28
|
+
Requires-Dist: textual<9,>=0.80
|
|
29
|
+
Requires-Dist: tomlkit
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pyright; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest-xdist; extra == 'dev'
|
|
34
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# uxon
|
|
38
|
+
|
|
39
|
+
[](https://pypi.org/project/uxon/)
|
|
40
|
+
[](https://github.com/vzd3v/uxon/actions/workflows/ci.yml)
|
|
41
|
+
[](LICENSE)
|
|
42
|
+

|
|
43
|
+

|
|
44
|
+
|
|
45
|
+
**Run terminal AI coding agents (Claude Code, Codex, Cursor) on a shared
|
|
46
|
+
server — safely, persistently, and visibly to the operator.**
|
|
47
|
+
|
|
48
|
+
`uxon` is a small `tmux` wrapper with a full-screen TUI session picker.
|
|
49
|
+
It standardises session names, isolates each user on a dedicated `tmux`
|
|
50
|
+
socket, and lets you start, attach, monitor, and kill agent sessions
|
|
51
|
+
from one screen — your laptop, your phone over SSH, or a sysadmin's
|
|
52
|
+
shell with `sudo`.
|
|
53
|
+
|
|
54
|
+
<!-- screenshot goes here -->
|
|
55
|
+
|
|
56
|
+
## What it solves
|
|
57
|
+
|
|
58
|
+
- **Sandboxed agent runs.** Drop the agent into a low-privilege OS
|
|
59
|
+
account with a restricted filesystem view via `sudo -iu`, while you
|
|
60
|
+
keep operating from your own login. The agent can't reach what its
|
|
61
|
+
user can't reach.
|
|
62
|
+
- **Many users on one box.** Each developer logs into their own OS
|
|
63
|
+
user, runs their own authenticated `claude` / `codex` / `cursor`
|
|
64
|
+
with their own keys and quotas, and never sees another user's tmux
|
|
65
|
+
sessions by accident — every launch user gets a dedicated socket
|
|
66
|
+
at `/tmp/uxon-<user>.sock`.
|
|
67
|
+
- **Operator visibility.** Anyone with passwordless `sudo` opens
|
|
68
|
+
`uxon` and immediately sees every agent session on the host:
|
|
69
|
+
CPU, RAM, age, last attach, attached-or-not. Attach to any of
|
|
70
|
+
them with `Enter`, kill a runaway with `d`, nuke the lot with
|
|
71
|
+
a confirmed `kill-all-global`. No more "who's that 38 GB python
|
|
72
|
+
on the dashboard?".
|
|
73
|
+
- **Attach from anywhere.** Sessions live in `tmux`, so they survive
|
|
74
|
+
every disconnect. Start at your desk, reattach from your phone over
|
|
75
|
+
SSH on the train, switch to a tablet later — same session, same
|
|
76
|
+
state. The TUI is keyboard-only and fits a small screen.
|
|
77
|
+
- **Predictable session names.** `uxon-<project>@<agent>` (`-2`,
|
|
78
|
+
`-3` for parallels). No more hand-rolled `tmux new -s` strings or
|
|
79
|
+
guessing what you called it yesterday.
|
|
80
|
+
- **Permissive by default, lockable for ops.** Out of the box you
|
|
81
|
+
can launch an agent in any folder where the launch user has write
|
|
82
|
+
access. On a shared host, set `allowed_roots` in the config to
|
|
83
|
+
pin agents to specific directories. See
|
|
84
|
+
[`docs/configuration.md`](docs/configuration.md).
|
|
85
|
+
- **One tool, every agent.** Flip a config switch to enable Claude
|
|
86
|
+
Code, Codex, Cursor — together or any subset. Built-in `--auto`
|
|
87
|
+
and `--dsp` (skip-permissions / "yolo") flags translate to whatever
|
|
88
|
+
the underlying agent uses today.
|
|
89
|
+
- **Optional niceties.** Git worktrees, GitHub repo creation on a new
|
|
90
|
+
project (with a strict whitelist), per-project config overrides.
|
|
91
|
+
All off by default.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Install
|
|
96
|
+
|
|
97
|
+
Requires **Python 3.11+**, `tmux`, and Linux. Dependencies (`textual`,
|
|
98
|
+
`tomlkit`) are pulled in automatically.
|
|
99
|
+
|
|
100
|
+
### Single-user laptop (recommended)
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# uv tool — recommended. uv is the 2026 default Python toolchain;
|
|
104
|
+
# fast, uses uv-managed Python and a shared dep cache.
|
|
105
|
+
uv tool install uxon
|
|
106
|
+
|
|
107
|
+
# pipx — equivalent. Same console-script entrypoint.
|
|
108
|
+
pipx install uxon
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Either creates an isolated venv and puts `uxon` on your `PATH`.
|
|
112
|
+
Update with `uv tool upgrade uxon` / `pipx upgrade uxon`.
|
|
113
|
+
|
|
114
|
+
For the bleeding edge from `main` (before a release lands on PyPI):
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
uv tool install git+https://github.com/vzd3v/uxon.git
|
|
118
|
+
# or: pipx install git+https://github.com/vzd3v/uxon.git
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
If you maintain your own Python (pyenv, asdf, uv-managed) and prefer
|
|
122
|
+
no isolation, `pip install --user uxon` works too — `uxon` lands in
|
|
123
|
+
`~/.local/bin/`. On Debian/Ubuntu/Fedora system Python, PEP 668 blocks
|
|
124
|
+
plain `pip install`; use `pipx` (recommended) or know-what-you-do
|
|
125
|
+
`pip install --user --break-system-packages uxon`.
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
uxon doctor # verify the install
|
|
129
|
+
# Optional: bootstrap an example config (uxon runs in $HOME with defaults).
|
|
130
|
+
curl -fsSL https://raw.githubusercontent.com/vzd3v/uxon/main/config/config.example.toml -o ./config.toml
|
|
131
|
+
$EDITOR ./config.toml # set allowed_roots, session_users, agents
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
You'll also need at least one of the agent CLIs installed for the
|
|
135
|
+
launch user — see [Supported agents](#supported-agents).
|
|
136
|
+
|
|
137
|
+
### Shared host / multi-user VPS
|
|
138
|
+
|
|
139
|
+
For a host where several Linux users need a single shared `uxon` on
|
|
140
|
+
`PATH`, install into a dedicated venv and symlink the console script:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
git clone https://github.com/vzd3v/uxon.git
|
|
144
|
+
cd uxon
|
|
145
|
+
sudo python3 install/install_uxon.py \
|
|
146
|
+
--repo-dir "$(pwd)" \
|
|
147
|
+
--install-path /usr/local/bin/uxon
|
|
148
|
+
# (uses /opt/uxon/venv by default; override with --venv-dir)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The installer creates a venv at `--venv-dir`, installs the package
|
|
152
|
+
into it, and symlinks `/opt/uxon/venv/bin/uxon` to `/usr/local/bin/uxon`.
|
|
153
|
+
|
|
154
|
+
For multi-host rollout, generated config from a JSON payload, and
|
|
155
|
+
deployment topology, see [`docs/deployment.md`](docs/deployment.md).
|
|
156
|
+
|
|
157
|
+
## Quick start
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
uxon # full-screen TUI picker (recommended; needs a TTY)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
That's the intended entry point. Everything below — creating
|
|
164
|
+
projects, attaching, killing, switching agents — happens inside the
|
|
165
|
+
TUI. Read on.
|
|
166
|
+
|
|
167
|
+
For non-interactive use (scripts, CI, SSH one-liners), the same
|
|
168
|
+
operations are available as subcommands; see [CLI](#cli) at the end.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## The TUI
|
|
173
|
+
|
|
174
|
+
`uxon` with no arguments on a TTY opens a full-screen `textual`
|
|
175
|
+
picker. One screen, three blocks:
|
|
176
|
+
|
|
177
|
+
### 1. Actions (top)
|
|
178
|
+
|
|
179
|
+
1. **New session in current folder** — start the default agent in
|
|
180
|
+
`$PWD` (gated on the allowed-roots check).
|
|
181
|
+
2. **Create new project** — prompt for a name, create
|
|
182
|
+
`<new_project_root>/<name>`, optionally create a GitHub remote
|
|
183
|
+
(if [git-remote profiles](docs/configuration.md#use-case-github-repo-creation-on-new-project)
|
|
184
|
+
are configured), launch the agent.
|
|
185
|
+
3. **Open existing project** — pick a directory under
|
|
186
|
+
`new_project_root` and launch.
|
|
187
|
+
|
|
188
|
+
Before every launch, a permissions modal asks whether to start the
|
|
189
|
+
agent in normal mode or with `--dangerously-skip-permissions`
|
|
190
|
+
("yolo"). No accidental yolos.
|
|
191
|
+
|
|
192
|
+
### 2. Your sessions
|
|
193
|
+
|
|
194
|
+
Live list of `uxon-*` sessions for the current user with:
|
|
195
|
+
|
|
196
|
+
- session name, agent, working directory;
|
|
197
|
+
- live CPU / RAM (refreshed every `tui_refresh_interval_seconds`);
|
|
198
|
+
- attached-or-not marker;
|
|
199
|
+
- creation time and last-attach time.
|
|
200
|
+
|
|
201
|
+
`Enter` attaches. `d` kills (with confirmation). `D` kills *all your
|
|
202
|
+
own* sessions after typing `kill-all`.
|
|
203
|
+
|
|
204
|
+
### 3. Server status (bottom)
|
|
205
|
+
|
|
206
|
+
Load average, normalised CPU load, RAM, disk, uptime. When you're
|
|
207
|
+
inside an SSH session, an async `ssh-link` probe shows RTT, jitter,
|
|
208
|
+
and retransmits — quick read on whether the lag you're feeling is
|
|
209
|
+
the agent or the network.
|
|
210
|
+
|
|
211
|
+
### ⚡ Superuser block (only when passwordless `sudo` is detected)
|
|
212
|
+
|
|
213
|
+
Appears below your own sessions whenever the host trusts you with
|
|
214
|
+
`sudo`:
|
|
215
|
+
|
|
216
|
+
- **Other users' sessions** with a yellow `USER` column. `Enter`
|
|
217
|
+
attaches via `sudo -iu <user>` (read-only-ish — you're a guest in
|
|
218
|
+
their tmux); `d` kills the highlighted one.
|
|
219
|
+
- **⚙ Settings** — repo-level `config.toml` editor. Bool keys
|
|
220
|
+
toggle, enums cycle, strings open an input, arrays use
|
|
221
|
+
comma-separated input. Saves rewrite the file via a `tomlkit`
|
|
222
|
+
round-trip (using `sudo tee` automatically when needed) and
|
|
223
|
+
preserve untouched comments and formatting. Project-level
|
|
224
|
+
`.uxon.toml` keys are read-only here — edit them in the project.
|
|
225
|
+
- **Kill ALL uxon sessions (all users)** — appears when at least
|
|
226
|
+
one session exists anywhere; requires typing `kill-all-global`
|
|
227
|
+
to confirm. The "fire alarm" button.
|
|
228
|
+
|
|
229
|
+
### Keys
|
|
230
|
+
|
|
231
|
+
| Key | Action |
|
|
232
|
+
|--------------------|--------|
|
|
233
|
+
| `↑` `↓` / `j` `k` | Navigate |
|
|
234
|
+
| `1`–`9` | Jump to item by number |
|
|
235
|
+
| `Enter` | Activate (launch / attach) |
|
|
236
|
+
| `d` | Kill highlighted session (with confirmation) |
|
|
237
|
+
| `D` | Kill all *own* sessions (`kill-all` to confirm) |
|
|
238
|
+
| `r` | Refresh |
|
|
239
|
+
| `g` / `G` | Jump to first / last |
|
|
240
|
+
| `q` / `Esc` | Quit (or back, in sub-screens) |
|
|
241
|
+
|
|
242
|
+
### Detach and re-enter
|
|
243
|
+
|
|
244
|
+
When the launched session exits — or you `Ctrl-b d` to detach —
|
|
245
|
+
`uxon` returns to the main screen with a refreshed list. The same
|
|
246
|
+
binary you launched is the same binary you come back to. `q` / `Esc`
|
|
247
|
+
on the main screen exits to the shell.
|
|
248
|
+
|
|
249
|
+
If a launch fails, the failure output stays on the physical
|
|
250
|
+
terminal with a banner before the TUI re-enters fullscreen, so you
|
|
251
|
+
can read whatever stderr the agent printed.
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Supported agents
|
|
256
|
+
|
|
257
|
+
| Agent id | Binary | `--auto` mode | `--dsp` (yolo) | Install |
|
|
258
|
+
|----------|--------|---------------|----------------|---------|
|
|
259
|
+
| `claude` | `claude` | `--permission-mode auto` | `--dangerously-skip-permissions` | [Anthropic docs](https://docs.claude.com/claude-code) |
|
|
260
|
+
| `codex` | `codex` | `--full-auto` | `--dangerously-bypass-approvals-and-sandbox` | `npm i -g @openai/codex` |
|
|
261
|
+
| `cursor` | `cursor-agent` | (not supported) | `--yolo` | `curl https://cursor.com/install -fsSL \| bash` |
|
|
262
|
+
|
|
263
|
+
Enable agents in `config/config.toml`:
|
|
264
|
+
|
|
265
|
+
```toml
|
|
266
|
+
[agents]
|
|
267
|
+
enabled = ["claude", "codex"]
|
|
268
|
+
default = "claude"
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
`uxon doctor` probes each enabled agent and prints its path, version,
|
|
272
|
+
and status. If none of the enabled agents are installed for the
|
|
273
|
+
launch user, the TUI shows a modal with install hints.
|
|
274
|
+
|
|
275
|
+
`-w <branch>` (worktree mode) is currently claude-only.
|
|
276
|
+
`--auto` is unavailable for cursor.
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Configuration
|
|
281
|
+
|
|
282
|
+
`uxon` works out of the box with no configuration — the launch user
|
|
283
|
+
can run an agent anywhere they have write access, and `uxon new`
|
|
284
|
+
creates projects under `~/projects`.
|
|
285
|
+
|
|
286
|
+
Configuration becomes useful once you're hosting more than one user,
|
|
287
|
+
or want to restrict where agents may run, or want one-shot GitHub
|
|
288
|
+
repo creation, or want to switch the default agent. All keys, with
|
|
289
|
+
the **use case** for each, live in
|
|
290
|
+
**[`docs/configuration.md`](docs/configuration.md)**.
|
|
291
|
+
|
|
292
|
+
Two config layers (later wins):
|
|
293
|
+
|
|
294
|
+
1. **Repo config** — `<repo>/config/config.toml`, host-wide.
|
|
295
|
+
`config/config.example.toml` is the tracked starting point.
|
|
296
|
+
2. **Project config** — the nearest `.uxon.toml` in `cwd` or a
|
|
297
|
+
parent inside an `allowed_roots` entry. Per-project overrides.
|
|
298
|
+
The TUI never writes `.uxon.toml`.
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## CLI
|
|
303
|
+
|
|
304
|
+
The TUI is the recommended entry point. The CLI exposes the same
|
|
305
|
+
operations for scripting, SSH one-liners, and CI. Brief summary:
|
|
306
|
+
|
|
307
|
+
| Command | What it does |
|
|
308
|
+
|---------|--------------|
|
|
309
|
+
| `uxon` | Open the interactive TUI (needs a TTY). |
|
|
310
|
+
| `uxon run [-w <branch>] [agent-flags...]` | Start an agent in `$PWD`. |
|
|
311
|
+
| `uxon new <name> [-w <branch>] [...]` | Create / reuse a project under `new_project_root` and start an agent. |
|
|
312
|
+
| `uxon list [--all-users]` | List `uxon-*` sessions for this user (or all configured users). |
|
|
313
|
+
| `uxon attach <id>` | Re-attach to a session. Accepts full name, short name, bare stem, or active-pane PID. |
|
|
314
|
+
| `uxon kill <id>` | Kill one session. |
|
|
315
|
+
| `uxon kill-all [--force]` | Kill every `uxon-*` session for the current launch user. |
|
|
316
|
+
| `uxon doctor` | Read-only diagnostics: caller / launch user, config, allowed_roots, agents, sockets, sessions, detected issues. Run this first when something looks wrong. |
|
|
317
|
+
| `uxon version` | Print version + git commit. |
|
|
318
|
+
|
|
319
|
+
Short forms: `-l` / `-a` / `-k` / `-n` / `-V` / `--killall`.
|
|
320
|
+
|
|
321
|
+
Full reference with every flag, exit code, identifier-resolution
|
|
322
|
+
rules, repeat-behaviour, worktree details, and legacy-session notes
|
|
323
|
+
is in **[`docs/cli.md`](docs/cli.md)**.
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Troubleshooting
|
|
328
|
+
|
|
329
|
+
- **`uxon` started inside an existing `tmux`?** Handled
|
|
330
|
+
transparently when `$TMUX` names the same socket as `uxon`. If
|
|
331
|
+
it's a different (foreign) `tmux`, `uxon` prints an actionable
|
|
332
|
+
error — `Ctrl-b d` first.
|
|
333
|
+
- **`textual` not installed?** The TUI prints an install hint and
|
|
334
|
+
exits. The whole CLI keeps working.
|
|
335
|
+
- **TUI errors render as a red toast.** Tmux-gone, permission
|
|
336
|
+
denied, allowed-roots mismatch, git remote failure, config-write
|
|
337
|
+
conflict — all caught and shown in-place rather than crashing.
|
|
338
|
+
- **Always run `uxon doctor` first.** It prints the resolved caller /
|
|
339
|
+
launch user, active config paths, allowed roots, agent paths,
|
|
340
|
+
socket details, current sessions, and any detected configuration
|
|
341
|
+
issues.
|
|
342
|
+
|
|
343
|
+
More edge cases (legacy session prefixes, failed-launch banner, the
|
|
344
|
+
`--dsp` flag and its legacy aliases) are documented in
|
|
345
|
+
[`docs/cli.md`](docs/cli.md).
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## Documentation
|
|
350
|
+
|
|
351
|
+
- [`docs/configuration.md`](docs/configuration.md) — all config keys
|
|
352
|
+
organised by use case (single-user laptop, shared multi-user host,
|
|
353
|
+
restricted launch directories, GitHub repo on new project, …).
|
|
354
|
+
- [`docs/cli.md`](docs/cli.md) — full CLI reference (every flag,
|
|
355
|
+
exit code, identifier resolution, repeat behaviour).
|
|
356
|
+
- [`docs/deployment.md`](docs/deployment.md) — multi-host rollout,
|
|
357
|
+
config rendering from JSON, runtime dependencies.
|
|
358
|
+
- [`docs/architecture.md`](docs/architecture.md) — module map, TUI
|
|
359
|
+
internals, code boundaries.
|
|
360
|
+
- [`CONTRIBUTING.md`](CONTRIBUTING.md) — local checks, branch
|
|
361
|
+
policy, release process.
|
|
362
|
+
- [`SECURITY.md`](SECURITY.md) — threat model, disclosure policy.
|
|
363
|
+
- [`CHANGELOG.md`](CHANGELOG.md) — version history.
|
|
364
|
+
|
|
365
|
+
## Versioning
|
|
366
|
+
|
|
367
|
+
`uxon` follows [SemVer](https://semver.org/). `uxon --version`
|
|
368
|
+
prints the version and short git commit (with `-dirty` when the
|
|
369
|
+
checkout is dirty).
|
|
370
|
+
|
|
371
|
+
## License
|
|
372
|
+
|
|
373
|
+
[MIT](LICENSE) © 2026 Vasily Zakharov.
|