agent-leash 0.3.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.
- agent_leash-0.3.0/.github/workflows/ci.yml +21 -0
- agent_leash-0.3.0/.github/workflows/release.yml +75 -0
- agent_leash-0.3.0/.gitignore +5 -0
- agent_leash-0.3.0/.pre-commit-config.yaml +55 -0
- agent_leash-0.3.0/CONTRIBUTING.md +120 -0
- agent_leash-0.3.0/LICENSE +21 -0
- agent_leash-0.3.0/Makefile +11 -0
- agent_leash-0.3.0/PKG-INFO +18 -0
- agent_leash-0.3.0/README.md +85 -0
- agent_leash-0.3.0/RELEASE.md +37 -0
- agent_leash-0.3.0/docs/demo.gif +0 -0
- agent_leash-0.3.0/frontend/eslint.config.js +36 -0
- agent_leash-0.3.0/frontend/index.html +12 -0
- agent_leash-0.3.0/frontend/package-lock.json +3046 -0
- agent_leash-0.3.0/frontend/package.json +30 -0
- agent_leash-0.3.0/frontend/src/App.vue +168 -0
- agent_leash-0.3.0/frontend/src/components/DomainApproval.vue +38 -0
- agent_leash-0.3.0/frontend/src/components/DomainsPane.vue +67 -0
- agent_leash-0.3.0/frontend/src/components/FilesystemPane.vue +242 -0
- agent_leash-0.3.0/frontend/src/components/SandboxDetail.vue +56 -0
- agent_leash-0.3.0/frontend/src/components/ServicesPane.vue +174 -0
- agent_leash-0.3.0/frontend/src/components/TerminalPane.vue +159 -0
- agent_leash-0.3.0/frontend/src/main.ts +6 -0
- agent_leash-0.3.0/frontend/src/style.css +190 -0
- agent_leash-0.3.0/frontend/tsconfig.json +13 -0
- agent_leash-0.3.0/frontend/vite.config.ts +16 -0
- agent_leash-0.3.0/hatch_build.py +12 -0
- agent_leash-0.3.0/pyproject.toml +50 -0
- agent_leash-0.3.0/src/aleash/__init__.py +0 -0
- agent_leash-0.3.0/src/aleash/bwrap.py +218 -0
- agent_leash-0.3.0/src/aleash/cli.py +209 -0
- agent_leash-0.3.0/src/aleash/db.py +223 -0
- agent_leash-0.3.0/src/aleash/profiles.py +70 -0
- agent_leash-0.3.0/src/aleash/proxy_addon.py +50 -0
- agent_leash-0.3.0/src/aleash/runner.py +556 -0
- agent_leash-0.3.0/src/aleash/server.py +657 -0
- agent_leash-0.3.0/src/aleash/services.py +126 -0
- agent_leash-0.3.0/src/aleash/static/assets/index-DZWOxijS.css +32 -0
- agent_leash-0.3.0/src/aleash/static/assets/index-gPIKKcCv.js +25 -0
- agent_leash-0.3.0/src/aleash/static/index.html +13 -0
- agent_leash-0.3.0/uv.lock +2295 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
lint:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v6
|
|
16
|
+
- uses: astral-sh/setup-uv@v8.1.0
|
|
17
|
+
- name: Install frontend deps
|
|
18
|
+
run: npm --prefix frontend ci
|
|
19
|
+
- uses: pre-commit/action@v3.0.1
|
|
20
|
+
with:
|
|
21
|
+
extra_args: --all-files
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v[0-9]+.[0-9]+.[0-9]+'
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
validate:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: astral-sh/setup-uv@v4
|
|
18
|
+
- name: Check tag matches pyproject.toml version
|
|
19
|
+
run: |
|
|
20
|
+
TAG_VERSION="${GITHUB_REF_NAME#v}"
|
|
21
|
+
PKG_VERSION=$(uv version --short)
|
|
22
|
+
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
|
|
23
|
+
echo "Tag $GITHUB_REF_NAME does not match pyproject.toml version $PKG_VERSION"
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
lint:
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v6
|
|
30
|
+
- uses: astral-sh/setup-uv@v8.1.0
|
|
31
|
+
- uses: pre-commit/action@v3.0.1
|
|
32
|
+
with:
|
|
33
|
+
extra_args: --all-files
|
|
34
|
+
build:
|
|
35
|
+
needs: [validate, lint]
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v4
|
|
39
|
+
- uses: astral-sh/setup-uv@v4
|
|
40
|
+
- name: Install frontend deps
|
|
41
|
+
run: npm --prefix frontend ci
|
|
42
|
+
- name: Build distribution
|
|
43
|
+
run: uv build
|
|
44
|
+
- uses: actions/upload-artifact@v4
|
|
45
|
+
with:
|
|
46
|
+
name: dist
|
|
47
|
+
path: dist/
|
|
48
|
+
|
|
49
|
+
publish-pypi:
|
|
50
|
+
needs: [build]
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
environment: pypi
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/download-artifact@v4
|
|
55
|
+
with:
|
|
56
|
+
name: dist
|
|
57
|
+
path: dist/
|
|
58
|
+
- name: Publish to PyPI
|
|
59
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
github-release:
|
|
63
|
+
needs: [publish-pypi]
|
|
64
|
+
runs-on: ubuntu-latest
|
|
65
|
+
steps:
|
|
66
|
+
- uses: actions/download-artifact@v4
|
|
67
|
+
with:
|
|
68
|
+
name: dist
|
|
69
|
+
path: dist/
|
|
70
|
+
- name: Create GitHub Release
|
|
71
|
+
uses: softprops/action-gh-release@v2
|
|
72
|
+
with:
|
|
73
|
+
files: |
|
|
74
|
+
dist/*
|
|
75
|
+
generate_release_notes: true
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
+
rev: v6.0.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: trailing-whitespace
|
|
6
|
+
- id: end-of-file-fixer
|
|
7
|
+
- id: check-yaml
|
|
8
|
+
- id: check-toml
|
|
9
|
+
- id: check-merge-conflict
|
|
10
|
+
- id: check-added-large-files
|
|
11
|
+
args: [--maxkb=1000]
|
|
12
|
+
- id: debug-statements
|
|
13
|
+
- repo: https://github.com/codespell-project/codespell
|
|
14
|
+
rev: v2.4.2
|
|
15
|
+
hooks:
|
|
16
|
+
- id: codespell
|
|
17
|
+
name: Spell check source files
|
|
18
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
19
|
+
rev: v0.15.14
|
|
20
|
+
hooks:
|
|
21
|
+
- id: ruff
|
|
22
|
+
args: [--fix]
|
|
23
|
+
- id: ruff-format
|
|
24
|
+
- repo: local
|
|
25
|
+
hooks:
|
|
26
|
+
- id: pyright
|
|
27
|
+
name: Type checking for python
|
|
28
|
+
entry: uv run --frozen pyright
|
|
29
|
+
language: system
|
|
30
|
+
types: [python]
|
|
31
|
+
pass_filenames: false
|
|
32
|
+
- id: vue-tsc
|
|
33
|
+
name: TypeScript type check (frontend)
|
|
34
|
+
entry: npm --prefix frontend run typecheck
|
|
35
|
+
language: system
|
|
36
|
+
files: ^frontend/src/.*\.(ts|vue)$
|
|
37
|
+
pass_filenames: false
|
|
38
|
+
- id: eslint-frontend
|
|
39
|
+
name: ESLint (frontend)
|
|
40
|
+
entry: npm --prefix frontend run lint
|
|
41
|
+
language: system
|
|
42
|
+
files: ^frontend/src/.*\.(ts|vue)$
|
|
43
|
+
pass_filenames: false
|
|
44
|
+
- id: licensecheck
|
|
45
|
+
name: License compatibility
|
|
46
|
+
entry: uv run --frozen licensecheck
|
|
47
|
+
language: system
|
|
48
|
+
pass_filenames: false
|
|
49
|
+
stages: [pre-push]
|
|
50
|
+
- id: uv-audit
|
|
51
|
+
name: Vulnerability scan (uv audit)
|
|
52
|
+
entry: uv audit
|
|
53
|
+
language: system
|
|
54
|
+
pass_filenames: false
|
|
55
|
+
stages: [pre-push]
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
## System requirements
|
|
4
|
+
|
|
5
|
+
| Tool | Purpose | Install |
|
|
6
|
+
|------|---------|---------|
|
|
7
|
+
| `bwrap` | filesystem isolation | `dnf install bubblewrap` / `apt install bubblewrap` |
|
|
8
|
+
| `xdg-dbus-proxy` | portal socket for xdg-open | `dnf install xdg-dbus-proxy` / `apt install xdg-dbus-proxy` |
|
|
9
|
+
| Python ≥ 3.11 | backend | system or pyenv |
|
|
10
|
+
| Node ≥ 18 + npm | frontend build | system or nvm |
|
|
11
|
+
|
|
12
|
+
`mitmproxy` is a Python dependency — no separate install needed.
|
|
13
|
+
|
|
14
|
+
## First-time setup
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
git clone <repo> aleash
|
|
18
|
+
cd aleash
|
|
19
|
+
|
|
20
|
+
# Python env — uv creates .venv, downloads Python 3.12 (pinned in .python-version),
|
|
21
|
+
# and installs all deps. The frontend build is skipped for editable installs.
|
|
22
|
+
uv sync
|
|
23
|
+
|
|
24
|
+
# Frontend deps + initial build (one-time)
|
|
25
|
+
cd frontend
|
|
26
|
+
npm install # generates package-lock.json if missing
|
|
27
|
+
npm run build # outputs to src/aleash/static/
|
|
28
|
+
cd ..
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Running in dev mode
|
|
32
|
+
|
|
33
|
+
Two terminals needed.
|
|
34
|
+
|
|
35
|
+
**Terminal 1 — daemon (foreground so you see logs):**
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
uv run aleash start --foreground
|
|
39
|
+
# → Sandbox UI available on http://localhost:7612/
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Terminal 2 — run an agent:**
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
cd /some/project
|
|
46
|
+
uv run --project /path/to/aleash aleash claude
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Open http://localhost:7612/ to see the UI.
|
|
50
|
+
|
|
51
|
+
## Frontend iteration
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
make frontend
|
|
55
|
+
# → http://localhost:5173/
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Vite serves the UI with hot-reload. Edits to `frontend/src/` reflect instantly in the browser.
|
|
59
|
+
Proxies `/api` and `/ws` to the daemon — requires `uv run aleash start --foreground` running first.
|
|
60
|
+
|
|
61
|
+
## Project layout
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
src/aleash/
|
|
65
|
+
cli.py # Click commands: start / stop / list / claude / opencode / run
|
|
66
|
+
server.py # FastAPI daemon (REST + WebSocket)
|
|
67
|
+
runner.py # PTY capture, bwrap + mitmproxy orchestration
|
|
68
|
+
proxy_addon.py # mitmproxy addon (domain gating)
|
|
69
|
+
bwrap.py # bubblewrap argv builder
|
|
70
|
+
profiles.py # per-agent bind-mount profiles
|
|
71
|
+
db.py # aiosqlite schema + queries (~/.aleash/data.db)
|
|
72
|
+
notifications.py# notify-send wrapper
|
|
73
|
+
|
|
74
|
+
frontend/src/
|
|
75
|
+
App.vue # root: sidebar + main panel + approval modal
|
|
76
|
+
components/SandboxList.vue # sidebar sandbox list
|
|
77
|
+
components/SandboxDetail.vue # tabs: Terminal | Domains
|
|
78
|
+
components/TerminalPane.vue # xterm.js over WebSocket
|
|
79
|
+
components/DomainsPane.vue # domain decision table
|
|
80
|
+
components/DomainApproval.vue # approval modal
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Adding an agent profile
|
|
84
|
+
|
|
85
|
+
Edit `src/aleash/profiles.py`:
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
_register(Profile(
|
|
89
|
+
name="myagent",
|
|
90
|
+
binary_names=["myagent"], # binary names on PATH to auto-detect
|
|
91
|
+
extra_binds=[
|
|
92
|
+
(_home(".config/myagent"), _home(".config/myagent")),
|
|
93
|
+
],
|
|
94
|
+
ensure_home_dirs=[".cache/myagent"],
|
|
95
|
+
))
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Then add a Click command in `cli.py` (copy the `claude` command, change the name).
|
|
99
|
+
|
|
100
|
+
## Building a wheel
|
|
101
|
+
|
|
102
|
+
Requires npm on PATH — the build hook runs `npm ci && npm run build` automatically for wheel builds (skipped for editable installs).
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
uv build
|
|
106
|
+
# outputs dist/aleash-*.whl
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Data
|
|
110
|
+
|
|
111
|
+
All state lives in `~/.aleash/`:
|
|
112
|
+
|
|
113
|
+
| Path | Content |
|
|
114
|
+
|------|---------|
|
|
115
|
+
| `~/.aleash/data.db` | SQLite: sandboxes, terminal logs, domain decisions |
|
|
116
|
+
| `~/.aleash/server.pid` | daemon PID |
|
|
117
|
+
| `~/.aleash/server.log` | daemon stdout/stderr when daemonized |
|
|
118
|
+
| `~/.mitmproxy/` | mitmproxy CA cert (auto-generated on first run) |
|
|
119
|
+
|
|
120
|
+
Delete `~/.aleash/data.db` to reset all history.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mathieu Lacage
|
|
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.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-leash
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Isolated sandbox for AI coding agents
|
|
5
|
+
Project-URL: Repository, https://github.com/mathieu-lacage/agent-leash.git
|
|
6
|
+
Project-URL: Issues, https://github.com/mathieu-lacage/agent-leash/issues
|
|
7
|
+
Author-email: Mathieu Lacage <mathieu.lacage@cutebugs.net>
|
|
8
|
+
Maintainer-email: Mathieu Lacage <mathieu.lacage@cutebugs.net>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Python: >=3.11
|
|
12
|
+
Requires-Dist: aiosqlite>=0.20
|
|
13
|
+
Requires-Dist: click>=8.1
|
|
14
|
+
Requires-Dist: fastapi>=0.111
|
|
15
|
+
Requires-Dist: httpx>=0.27
|
|
16
|
+
Requires-Dist: mitmproxy>=10.3
|
|
17
|
+
Requires-Dist: uvicorn[standard]>=0.29
|
|
18
|
+
Provides-Extra: dev
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# agent-leash
|
|
2
|
+
|
|
3
|
+
Sandbox runner for AI coding agents:
|
|
4
|
+
|
|
5
|
+
- Restricts filesystem access to the current directory
|
|
6
|
+
- Custom allow-list to expose more directories as read-only or read-write
|
|
7
|
+
- Intercepts all network traffic with interactive per-domain approval
|
|
8
|
+
- Controls access to host services (podman, docker, ssh-agent, etc.)
|
|
9
|
+
|
|
10
|
+
```console
|
|
11
|
+
$ pipx install agent-leash
|
|
12
|
+
$ aleash claude
|
|
13
|
+
Sandbox UI available on http://localhost:7612/
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+

|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
## How it works
|
|
20
|
+
|
|
21
|
+
- **Filesystem** — [bubblewrap](https://github.com/containers/bubblewrap) restricts the agent to the current working directory. The rest of the filesystem is read-only or hidden.
|
|
22
|
+
- **Network** — [mitmproxy](https://mitmproxy.org/) intercepts all outbound HTTPS. Each new domain triggers a browser popup (and desktop notification). You choose: always allow, allow once, always block, or block once.
|
|
23
|
+
- **Web UI** — Vue 3 + xterm.js frontend served on `localhost:7612`. Shows live terminal output, domain decisions
|
|
24
|
+
|
|
25
|
+
## Requirements
|
|
26
|
+
|
|
27
|
+
| Tool | Install |
|
|
28
|
+
|------|---------|
|
|
29
|
+
| `bwrap` (bubblewrap) | `dnf install bubblewrap` / `apt install bubblewrap` |
|
|
30
|
+
| `xdg-dbus-proxy` | `dnf install xdg-dbus-proxy` / `apt install xdg-dbus-proxy` |
|
|
31
|
+
| Python ≥ 3.11 | system or [pyenv](https://github.com/pyenv/pyenv) |
|
|
32
|
+
|
|
33
|
+
`mitmproxy` is installed automatically as a Python dependency.
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
### Pass arguments
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
aleash claude -- --dangerously-skip-permissions
|
|
41
|
+
aleash run python script.py --some-flag
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Terminal size
|
|
45
|
+
|
|
46
|
+
By default the local terminal controls the PTY size. The browser shows the fixed-size terminal with scrollbars. Use `--browser-master` to invert this (browser FitAddon resizes the PTY):
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
aleash --browser-master claude
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Profile override
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
aleash --profile generic claude # run claude with the generic profile
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Profiles
|
|
59
|
+
|
|
60
|
+
| Profile | What it binds |
|
|
61
|
+
|---------|--------------|
|
|
62
|
+
| `claude` | `~/.claude`, `~/.claude.json`, `~/.gitconfig`, `~/.local/share/claude` |
|
|
63
|
+
| `opencode` | `~/.opencode`, `~/.gitconfig`, and opencode config/cache dirs |
|
|
64
|
+
| `generic` | nothing extra |
|
|
65
|
+
|
|
66
|
+
`claude` and `opencode` are auto-detected by binary name. Use `--profile` to override.
|
|
67
|
+
|
|
68
|
+
## Data
|
|
69
|
+
|
|
70
|
+
All state lives in `CWD/.aleash/`:
|
|
71
|
+
|
|
72
|
+
| Path | Content |
|
|
73
|
+
|------|---------|
|
|
74
|
+
| `CWD/.aleash/data.db` | SQLite: sessions, terminal logs, domain decisions |
|
|
75
|
+
| `~/.mitmproxy/` | mitmproxy CA cert (auto-generated on first run) |
|
|
76
|
+
|
|
77
|
+
Delete `CWD/.aleash/data.db` to reset all history.
|
|
78
|
+
|
|
79
|
+
## Contributing
|
|
80
|
+
|
|
81
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
82
|
+
|
|
83
|
+
## License
|
|
84
|
+
|
|
85
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Release process
|
|
2
|
+
|
|
3
|
+
## How to create a new release
|
|
4
|
+
|
|
5
|
+
The release process is fully automated via GitHub Actions. The workflow is triggered by tagging a commit with a version tag (`v*`).
|
|
6
|
+
|
|
7
|
+
### Manual steps
|
|
8
|
+
|
|
9
|
+
1. Bump the version in `pyproject.toml`:
|
|
10
|
+
```console
|
|
11
|
+
$ uv version --bump minor
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
2. Commit the version bump:
|
|
15
|
+
```console
|
|
16
|
+
$ git add pyproject.toml
|
|
17
|
+
$ git commit -m "release: $(uv version --short)"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
3. Create a version tag (must match the version in `pyproject.toml`):
|
|
21
|
+
```console
|
|
22
|
+
$ git tag v$(uv version --short)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
4. Push to GitHub (triggers the release workflow):
|
|
26
|
+
```console
|
|
27
|
+
$ git push github main --tags
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### What happens next (automated)
|
|
31
|
+
|
|
32
|
+
The `.github/workflows/release.yml` workflow automatically:
|
|
33
|
+
|
|
34
|
+
1. **Validates** the tag matches the version in `pyproject.toml`
|
|
35
|
+
5. **Builds** the Python distribution (wheel + sdist)
|
|
36
|
+
6. **Publishes to PyPI** (via OIDC Trusted Publisher, no token needed)
|
|
37
|
+
8. **Creates a GitHub Release** with both the Python dist and the squashfs artifact
|
|
Binary file
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import js from '@eslint/js'
|
|
2
|
+
import tseslint from 'typescript-eslint'
|
|
3
|
+
import pluginVue from 'eslint-plugin-vue'
|
|
4
|
+
import globals from 'globals'
|
|
5
|
+
|
|
6
|
+
export default tseslint.config(
|
|
7
|
+
js.configs.recommended,
|
|
8
|
+
...tseslint.configs.recommended,
|
|
9
|
+
...pluginVue.configs['flat/recommended'],
|
|
10
|
+
{
|
|
11
|
+
files: ['**/*.vue', '**/*.ts'],
|
|
12
|
+
languageOptions: {
|
|
13
|
+
globals: {
|
|
14
|
+
...globals.browser,
|
|
15
|
+
},
|
|
16
|
+
parserOptions: {
|
|
17
|
+
parser: tseslint.parser,
|
|
18
|
+
project: './tsconfig.json',
|
|
19
|
+
extraFileExtensions: ['.vue'],
|
|
20
|
+
sourceType: 'module',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
rules: {
|
|
24
|
+
'vue/multi-word-component-names': 'off',
|
|
25
|
+
'@typescript-eslint/no-explicit-any': 'warn',
|
|
26
|
+
// Template formatting rules conflict with existing compact style
|
|
27
|
+
'vue/max-attributes-per-line': 'off',
|
|
28
|
+
'vue/singleline-html-element-content-newline': 'off',
|
|
29
|
+
'vue/multiline-html-element-content-newline': 'off',
|
|
30
|
+
'vue/attributes-order': 'off',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
ignores: ['dist/**', 'node_modules/**'],
|
|
35
|
+
},
|
|
36
|
+
)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Sandbox</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="app"></div>
|
|
10
|
+
<script type="module" src="/src/main.ts"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|