sing-box-cli 0.1.1__tar.gz → 0.1.3__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.
- sing_box_cli-0.1.3/PKG-INFO +186 -0
- sing_box_cli-0.1.3/README.md +137 -0
- sing_box_cli-0.1.3/docs/config-serve.md +49 -0
- sing_box_cli-0.1.3/docs/traefik-config-serve.yml +19 -0
- sing_box_cli-0.1.3/hatch_build.py +47 -0
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/pyproject.toml +7 -1
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/src/sing_box_cli/__init__.py +1 -1
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/src/sing_box_cli/api/__init__.py +27 -17
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/src/sing_box_cli/api/client.py +14 -6
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/src/sing_box_cli/api/connections.py +22 -21
- sing_box_cli-0.1.3/src/sing_box_cli/api/logs.py +93 -0
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/src/sing_box_cli/api/monitor.py +45 -56
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/src/sing_box_cli/api/policy.py +18 -16
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/src/sing_box_cli/config/__init__.py +12 -1
- sing_box_cli-0.1.3/src/sing_box_cli/config/_serve_worker.py +56 -0
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/src/sing_box_cli/config/config.py +12 -0
- sing_box_cli-0.1.3/src/sing_box_cli/config/serve.py +282 -0
- sing_box_cli-0.1.3/src/sing_box_cli/config/serve_backend.py +340 -0
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/src/sing_box_cli/config/utils.py +3 -1
- sing_box_cli-0.1.3/src/sing_box_cli/installation.py +67 -0
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/src/sing_box_cli/main.py +17 -2
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/src/sing_box_cli/service/manager.py +54 -110
- sing_box_cli-0.1.3/windows-service/common.go +121 -0
- sing_box_cli-0.1.3/windows-service/common_test.go +66 -0
- sing_box_cli-0.1.3/windows-service/go.mod +5 -0
- sing_box_cli-0.1.3/windows-service/go.sum +2 -0
- sing_box_cli-0.1.3/windows-service/integration_windows_test.go +141 -0
- sing_box_cli-0.1.3/windows-service/main_other.go +13 -0
- sing_box_cli-0.1.3/windows-service/main_windows.go +385 -0
- sing_box_cli-0.1.3/windows-service/testdata/core.go +30 -0
- sing_box_cli-0.1.1/.github/dependabot.yml +0 -16
- sing_box_cli-0.1.1/.github/workflows/main.yml +0 -99
- sing_box_cli-0.1.1/.pre-commit-config.yaml +0 -50
- sing_box_cli-0.1.1/CHANGELOG.md +0 -551
- sing_box_cli-0.1.1/PKG-INFO +0 -99
- sing_box_cli-0.1.1/README.md +0 -50
- sing_box_cli-0.1.1/assets/image.png +0 -0
- sing_box_cli-0.1.1/scripts/bump.sh +0 -8
- sing_box_cli-0.1.1/scripts/format.sh +0 -5
- sing_box_cli-0.1.1/scripts/lint.sh +0 -8
- sing_box_cli-0.1.1/scripts/pre-commit.sh +0 -9
- sing_box_cli-0.1.1/scripts/test.sh +0 -8
- sing_box_cli-0.1.1/src/sing_box_cli/api/logs.py +0 -93
- sing_box_cli-0.1.1/src/sing_box_cli/bin/nssm.exe +0 -0
- sing_box_cli-0.1.1/tests/config/test_utils.py +0 -177
- sing_box_cli-0.1.1/tests/conftest.py +0 -11
- sing_box_cli-0.1.1/tests/data/config.json +0 -243
- sing_box_cli-0.1.1/uv.lock +0 -1036
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/.gitignore +0 -0
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/LICENSE +0 -0
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/src/sing_box_cli/api/widget.py +0 -0
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/src/sing_box_cli/common.py +0 -0
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/src/sing_box_cli/py.typed +0 -0
- {sing_box_cli-0.1.1 → sing_box_cli-0.1.3}/src/sing_box_cli/service/__init__.py +0 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: sing-box-cli
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: cross-platform sing-box manager.
|
|
5
|
+
Project-URL: Homepage, https://github.com/aittcuszz/sing-box-service
|
|
6
|
+
Project-URL: Issues, https://github.com/atticuszz/sing-box-service/issues
|
|
7
|
+
Project-URL: documentation, https://atticuszz.github.io/sing-box-service/
|
|
8
|
+
Project-URL: Changelog, https://github.com/atticuszz/sing-box-service/blob/main/CHANGELOG.md
|
|
9
|
+
Author-email: "A.J.Zeller" <hello@atticux.me>
|
|
10
|
+
Maintainer-email: "A.J.Zeller" <hello@atticux.me>
|
|
11
|
+
License: MIT License
|
|
12
|
+
|
|
13
|
+
Copyright (c) 2024 A.J.Zeller
|
|
14
|
+
|
|
15
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
16
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
17
|
+
in the Software without restriction, including without limitation the rights
|
|
18
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
19
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
20
|
+
furnished to do so, subject to the following conditions:
|
|
21
|
+
|
|
22
|
+
The above copyright notice and this permission notice shall be included in all
|
|
23
|
+
copies or substantial portions of the Software.
|
|
24
|
+
|
|
25
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
26
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
27
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
28
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
29
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
30
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
31
|
+
SOFTWARE.
|
|
32
|
+
License-File: LICENSE
|
|
33
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
34
|
+
Classifier: Programming Language :: Python
|
|
35
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
40
|
+
Requires-Python: <3.15,>=3.11
|
|
41
|
+
Requires-Dist: httpx>=0.28.1
|
|
42
|
+
Requires-Dist: plotext>=5.3.2
|
|
43
|
+
Requires-Dist: prompt-toolkit>=3.0.50
|
|
44
|
+
Requires-Dist: psutil>=6.1.1
|
|
45
|
+
Requires-Dist: pydantic>=2.10.6
|
|
46
|
+
Requires-Dist: sing-box-bin>=1.12.12
|
|
47
|
+
Requires-Dist: typer>=0.15.1
|
|
48
|
+
Description-Content-Type: text/markdown
|
|
49
|
+
|
|
50
|
+
# Sing-Box CLI
|
|
51
|
+
|
|
52
|
+
🎤 Cross-platform sing-box service manager.
|
|
53
|
+
|
|
54
|
+

|
|
55
|
+
|
|
56
|
+
## Install
|
|
57
|
+
|
|
58
|
+
### uv
|
|
59
|
+
|
|
60
|
+
Windows
|
|
61
|
+
|
|
62
|
+
```powershell
|
|
63
|
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Linux
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### sing-box-cli
|
|
73
|
+
|
|
74
|
+
Install
|
|
75
|
+
```powershell
|
|
76
|
+
# windows
|
|
77
|
+
uv tool install sing-box-cli
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# linux
|
|
82
|
+
uv tool install sing-box-cli
|
|
83
|
+
sbc install
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
On Linux, `sbc install` installs both `sbc` and `sing-box-cli` into
|
|
87
|
+
`/usr/local/bin`, requesting sudo only to write those system launchers. It replaces
|
|
88
|
+
the old manual symlinks and can be run again safely. Use `--bin-dir PATH` to select
|
|
89
|
+
another existing executable directory. Unrelated files are preserved.
|
|
90
|
+
|
|
91
|
+
The system launchers use Python `-B`, so commands such as `sudo sbc service enable`
|
|
92
|
+
do not create root-owned `__pycache__` files in your uv environment. Run the install
|
|
93
|
+
command as your normal user after installing the tool. Do not run `uv tool install`,
|
|
94
|
+
`uv tool upgrade`, or `uv run` with sudo.
|
|
95
|
+
|
|
96
|
+
Install with specific sing-box version
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
uv tool install sing-box-cli --with sing-box-bin==x.y.z
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Upgrade
|
|
103
|
+
```bash
|
|
104
|
+
uv tool upgrade sing-box-cli
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Linux launchers continue to use the same environment after a normal uv upgrade.
|
|
108
|
+
Run `sbc install` again if you move or change the installation environment.
|
|
109
|
+
|
|
110
|
+
After upgrading on Windows, run the following in an administrator PowerShell:
|
|
111
|
+
|
|
112
|
+
```powershell
|
|
113
|
+
sbc service enable
|
|
114
|
+
sbc service status
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
This refreshes the installed service paths and migrates existing NSSM installations
|
|
118
|
+
to the native Go service host, keeping the same `sing-box-service` name and account.
|
|
119
|
+
An existing running service is stopped and restarted when its executable paths change.
|
|
120
|
+
If that update fails, the old service target is restored and the error is reported.
|
|
121
|
+
|
|
122
|
+
The native host and core are copied into versioned directories under
|
|
123
|
+
`%ProgramFiles%/sing-box-cli/sing-box-service`. The running service does not depend
|
|
124
|
+
on uv's environment, so future uv upgrades do not overwrite its running executables.
|
|
125
|
+
Configuration files stay in their existing location. Windows services run at boot;
|
|
126
|
+
closing the terminal does not stop them. Linux continues to use the existing systemd service.
|
|
127
|
+
|
|
128
|
+
No Go installation is required when installing a published wheel. Go is needed
|
|
129
|
+
only to build a wheel from source; the required version is in `windows-service/go.mod`.
|
|
130
|
+
Architecture support follows `sing-box-bin`: Windows distributes the amd64 core
|
|
131
|
+
and service helper; Linux distributes amd64 and arm64 cores. No additional CPU
|
|
132
|
+
architectures are introduced by the service helper.
|
|
133
|
+
|
|
134
|
+
### Logs
|
|
135
|
+
|
|
136
|
+
The service uses the user's sing-box configuration without changing its log level.
|
|
137
|
+
Set `log.level` to `info` or `warn` in that configuration to reduce generated logs.
|
|
138
|
+
`sbc logs --log-level debug` selects the logs to view; it cannot recover debug entries
|
|
139
|
+
that the core did not generate. For diagnostics, explicitly change the core's log level
|
|
140
|
+
and restart, then restore it when finished.
|
|
141
|
+
|
|
142
|
+
The native Windows host writes only warnings/errors to the Windows Application event
|
|
143
|
+
log (source `sing-box-service-native`). Core stdout/stderr is kept as a bounded diagnostic
|
|
144
|
+
tail for failures, without an additional debug log file. To persist core logs, use
|
|
145
|
+
sing-box's `log.output` configuration; streaming `sbc logs` continues to use the core API.
|
|
146
|
+
Old versioned executables are retained for rollback. After disabling the service,
|
|
147
|
+
its directory under Program Files may be removed manually; user configuration is separate.
|
|
148
|
+
|
|
149
|
+
## Run
|
|
150
|
+
|
|
151
|
+
Windows in Admin powershell
|
|
152
|
+
|
|
153
|
+
```powershell
|
|
154
|
+
sbc --help
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Linux
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
sudo sbc --help
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Serve private GitHub configurations
|
|
164
|
+
|
|
165
|
+
Set `GH_TOKEN` (or `GITHUB_TOKEN`) with **Contents: read** access to your private
|
|
166
|
+
repository, then run as your normal user:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
sbc config serve add https://github.com/owner/private-configs --domain sub.example.com
|
|
170
|
+
sbc config serve list
|
|
171
|
+
sbc config serve start
|
|
172
|
+
sbc config serve stop
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
`list` prints URLs for valid root `.json` configurations. The server reads GitHub
|
|
176
|
+
through its API without cloning; `start` runs in the background at `127.0.0.1:8080`
|
|
177
|
+
by default. Use `--host` and `--port` for another listening address.
|
|
178
|
+
|
|
179
|
+
Point Traefik at the server using [this example](docs/traefik-config-serve.yml).
|
|
180
|
+
Clients continue to use the existing update command:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
sbc config update https://sub.example.com/alice.json --restart
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
See [configuration server details](docs/config-serve.md) for settings, logs and limits.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Sing-Box CLI
|
|
2
|
+
|
|
3
|
+
🎤 Cross-platform sing-box service manager.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
### uv
|
|
10
|
+
|
|
11
|
+
Windows
|
|
12
|
+
|
|
13
|
+
```powershell
|
|
14
|
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Linux
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### sing-box-cli
|
|
24
|
+
|
|
25
|
+
Install
|
|
26
|
+
```powershell
|
|
27
|
+
# windows
|
|
28
|
+
uv tool install sing-box-cli
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# linux
|
|
33
|
+
uv tool install sing-box-cli
|
|
34
|
+
sbc install
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
On Linux, `sbc install` installs both `sbc` and `sing-box-cli` into
|
|
38
|
+
`/usr/local/bin`, requesting sudo only to write those system launchers. It replaces
|
|
39
|
+
the old manual symlinks and can be run again safely. Use `--bin-dir PATH` to select
|
|
40
|
+
another existing executable directory. Unrelated files are preserved.
|
|
41
|
+
|
|
42
|
+
The system launchers use Python `-B`, so commands such as `sudo sbc service enable`
|
|
43
|
+
do not create root-owned `__pycache__` files in your uv environment. Run the install
|
|
44
|
+
command as your normal user after installing the tool. Do not run `uv tool install`,
|
|
45
|
+
`uv tool upgrade`, or `uv run` with sudo.
|
|
46
|
+
|
|
47
|
+
Install with specific sing-box version
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
uv tool install sing-box-cli --with sing-box-bin==x.y.z
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Upgrade
|
|
54
|
+
```bash
|
|
55
|
+
uv tool upgrade sing-box-cli
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Linux launchers continue to use the same environment after a normal uv upgrade.
|
|
59
|
+
Run `sbc install` again if you move or change the installation environment.
|
|
60
|
+
|
|
61
|
+
After upgrading on Windows, run the following in an administrator PowerShell:
|
|
62
|
+
|
|
63
|
+
```powershell
|
|
64
|
+
sbc service enable
|
|
65
|
+
sbc service status
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This refreshes the installed service paths and migrates existing NSSM installations
|
|
69
|
+
to the native Go service host, keeping the same `sing-box-service` name and account.
|
|
70
|
+
An existing running service is stopped and restarted when its executable paths change.
|
|
71
|
+
If that update fails, the old service target is restored and the error is reported.
|
|
72
|
+
|
|
73
|
+
The native host and core are copied into versioned directories under
|
|
74
|
+
`%ProgramFiles%/sing-box-cli/sing-box-service`. The running service does not depend
|
|
75
|
+
on uv's environment, so future uv upgrades do not overwrite its running executables.
|
|
76
|
+
Configuration files stay in their existing location. Windows services run at boot;
|
|
77
|
+
closing the terminal does not stop them. Linux continues to use the existing systemd service.
|
|
78
|
+
|
|
79
|
+
No Go installation is required when installing a published wheel. Go is needed
|
|
80
|
+
only to build a wheel from source; the required version is in `windows-service/go.mod`.
|
|
81
|
+
Architecture support follows `sing-box-bin`: Windows distributes the amd64 core
|
|
82
|
+
and service helper; Linux distributes amd64 and arm64 cores. No additional CPU
|
|
83
|
+
architectures are introduced by the service helper.
|
|
84
|
+
|
|
85
|
+
### Logs
|
|
86
|
+
|
|
87
|
+
The service uses the user's sing-box configuration without changing its log level.
|
|
88
|
+
Set `log.level` to `info` or `warn` in that configuration to reduce generated logs.
|
|
89
|
+
`sbc logs --log-level debug` selects the logs to view; it cannot recover debug entries
|
|
90
|
+
that the core did not generate. For diagnostics, explicitly change the core's log level
|
|
91
|
+
and restart, then restore it when finished.
|
|
92
|
+
|
|
93
|
+
The native Windows host writes only warnings/errors to the Windows Application event
|
|
94
|
+
log (source `sing-box-service-native`). Core stdout/stderr is kept as a bounded diagnostic
|
|
95
|
+
tail for failures, without an additional debug log file. To persist core logs, use
|
|
96
|
+
sing-box's `log.output` configuration; streaming `sbc logs` continues to use the core API.
|
|
97
|
+
Old versioned executables are retained for rollback. After disabling the service,
|
|
98
|
+
its directory under Program Files may be removed manually; user configuration is separate.
|
|
99
|
+
|
|
100
|
+
## Run
|
|
101
|
+
|
|
102
|
+
Windows in Admin powershell
|
|
103
|
+
|
|
104
|
+
```powershell
|
|
105
|
+
sbc --help
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Linux
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
sudo sbc --help
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Serve private GitHub configurations
|
|
115
|
+
|
|
116
|
+
Set `GH_TOKEN` (or `GITHUB_TOKEN`) with **Contents: read** access to your private
|
|
117
|
+
repository, then run as your normal user:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
sbc config serve add https://github.com/owner/private-configs --domain sub.example.com
|
|
121
|
+
sbc config serve list
|
|
122
|
+
sbc config serve start
|
|
123
|
+
sbc config serve stop
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`list` prints URLs for valid root `.json` configurations. The server reads GitHub
|
|
127
|
+
through its API without cloning; `start` runs in the background at `127.0.0.1:8080`
|
|
128
|
+
by default. Use `--host` and `--port` for another listening address.
|
|
129
|
+
|
|
130
|
+
Point Traefik at the server using [this example](docs/traefik-config-serve.yml).
|
|
131
|
+
Clients continue to use the existing update command:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
sbc config update https://sub.example.com/alice.json --restart
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
See [configuration server details](docs/config-serve.md) for settings, logs and limits.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Configuration server
|
|
2
|
+
|
|
3
|
+
The server maps one domain to one private GitHub repository. Multiple domains can
|
|
4
|
+
share a server. Set `GH_TOKEN` or `GITHUB_TOKEN` to a fine-grained token with
|
|
5
|
+
**Contents: read** access to all registered repositories.
|
|
6
|
+
|
|
7
|
+
`config serve add` checks GitHub access and saves the binding; registering the same
|
|
8
|
+
binding again is safe. `config serve list` validates root `.json` files with the
|
|
9
|
+
sing-box core bundled with this package, prints valid URLs, and reports invalid
|
|
10
|
+
configurations on stderr.
|
|
11
|
+
|
|
12
|
+
## Background process
|
|
13
|
+
|
|
14
|
+
`config serve start` waits until the socket is listening, then prints the PID,
|
|
15
|
+
address and log path. Closing the terminal leaves the server running. Repeated
|
|
16
|
+
starts use the existing process, and repeated stops are safe. Run `stop` as the
|
|
17
|
+
same user with the same state directory. Restart after changing the GitHub token
|
|
18
|
+
or upgrading the package. Boot-time startup is managed separately by deployment.
|
|
19
|
+
|
|
20
|
+
Settings, process identity and `serve.log` are stored in the platform's
|
|
21
|
+
`sing-box-cli/serve` application directory (`~/.config/sing-box-cli/serve` on Linux).
|
|
22
|
+
Set `SBC_SERVE_DIR` to use another directory for all commands. Tokens and client
|
|
23
|
+
configuration are not stored there. New registrations take effect while running.
|
|
24
|
+
|
|
25
|
+
## GitHub reads and validation
|
|
26
|
+
|
|
27
|
+
Requests read the repository's default branch through the GitHub Contents API.
|
|
28
|
+
No Git installation, clone/pull, background synchronization or persistent config
|
|
29
|
+
cache is needed. File updates and deletions take effect on subsequent requests.
|
|
30
|
+
|
|
31
|
+
Each response is validated and preserves the original content. Missing files,
|
|
32
|
+
invalid configurations and GitHub errors return HTTP errors. Configurations are
|
|
33
|
+
limited to 5 MiB and must be compatible with the bundled core. Referenced sibling
|
|
34
|
+
files are not downloaded. Existing client `--token` subscriptions and saved
|
|
35
|
+
settings remain supported; server URLs need no client token.
|
|
36
|
+
|
|
37
|
+
## Traefik
|
|
38
|
+
|
|
39
|
+
Merge [the example router and service](traefik-config-serve.yml) into the existing
|
|
40
|
+
`http.routers` and `http.services` sections. Traefik must preserve the `Host` header.
|
|
41
|
+
The example uses `websecure` and the host gateway from `digitalocean-public`'s
|
|
42
|
+
`~/devspace/traefik.yml`. Bind to that gateway for this deployment:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
sbc config serve start --host 172.18.0.1 --port 8080
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Replace `sub.example.com` with your domain and configure DNS and the TLS
|
|
49
|
+
certificate through your deployment. `--domain` only registers the binding.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Merge these entries into the existing http.routers and http.services sections.
|
|
2
|
+
# Set the domain to match config serve add --domain.
|
|
3
|
+
http:
|
|
4
|
+
routers:
|
|
5
|
+
config-serve:
|
|
6
|
+
rule: "Host(`sub.example.com`)"
|
|
7
|
+
entryPoints:
|
|
8
|
+
- websecure
|
|
9
|
+
service: config-serve
|
|
10
|
+
tls: {}
|
|
11
|
+
|
|
12
|
+
services:
|
|
13
|
+
config-serve:
|
|
14
|
+
loadBalancer:
|
|
15
|
+
passHostHeader: true
|
|
16
|
+
servers:
|
|
17
|
+
# Host gateway used by the existing digitalocean-public Traefik config.
|
|
18
|
+
# Bind sbc config serve start --host 172.18.0.1 --port 8080 on the host.
|
|
19
|
+
- url: "http://172.18.0.1:8080"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Bundle the small Windows SCM helper; the CLI remains Python."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import shutil
|
|
5
|
+
import subprocess
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class CustomBuildHook(BuildHookInterface):
|
|
13
|
+
def initialize(self, version: str, build_data: dict[str, Any]) -> None:
|
|
14
|
+
if self.target_name != "wheel" or version == "editable":
|
|
15
|
+
return
|
|
16
|
+
go = shutil.which("go")
|
|
17
|
+
if go is None:
|
|
18
|
+
raise RuntimeError(
|
|
19
|
+
"Building a wheel requires Go (see windows-service/go.mod). Installing a published wheel does not require Go."
|
|
20
|
+
)
|
|
21
|
+
root = Path(self.root)
|
|
22
|
+
output = root / "build" / "windows-service"
|
|
23
|
+
output.mkdir(parents=True, exist_ok=True)
|
|
24
|
+
# Match sing-box-bin's single Windows amd64 resource.
|
|
25
|
+
filename = "sbc-service-windows-amd64.exe"
|
|
26
|
+
destination = output / filename
|
|
27
|
+
subprocess.run(
|
|
28
|
+
[
|
|
29
|
+
go,
|
|
30
|
+
"build",
|
|
31
|
+
"-mod=readonly",
|
|
32
|
+
"-trimpath",
|
|
33
|
+
"-ldflags=-s -w",
|
|
34
|
+
"-o",
|
|
35
|
+
str(destination),
|
|
36
|
+
".",
|
|
37
|
+
],
|
|
38
|
+
cwd=root / "windows-service",
|
|
39
|
+
env={
|
|
40
|
+
**os.environ,
|
|
41
|
+
"GOOS": "windows",
|
|
42
|
+
"GOARCH": "amd64",
|
|
43
|
+
"CGO_ENABLED": "0",
|
|
44
|
+
},
|
|
45
|
+
check=True,
|
|
46
|
+
)
|
|
47
|
+
build_data["force_include"][str(destination)] = f"sing_box_cli/bin/{filename}"
|
|
@@ -71,6 +71,12 @@ path = "src/sing_box_cli/__init__.py"
|
|
|
71
71
|
packages = ["src/sing_box_cli"]
|
|
72
72
|
# FROM: https://hatch.pypa.io/latest/build/
|
|
73
73
|
|
|
74
|
+
[tool.hatch.build.hooks.custom]
|
|
75
|
+
path = "hatch_build.py"
|
|
76
|
+
|
|
77
|
+
[tool.hatch.build.targets.sdist]
|
|
78
|
+
include = ["/src", "/windows-service", "/docs", "/hatch_build.py", "/pyproject.toml", "/README.md", "/LICENSE"]
|
|
79
|
+
|
|
74
80
|
## Test
|
|
75
81
|
[tool.mypy]
|
|
76
82
|
strict = true
|
|
@@ -209,7 +215,7 @@ topo_order = false
|
|
|
209
215
|
sort_commits = "oldest"
|
|
210
216
|
|
|
211
217
|
[tool.bumpversion]
|
|
212
|
-
current_version = "0.1.
|
|
218
|
+
current_version = "0.1.3"
|
|
213
219
|
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
|
214
220
|
serialize = ["{major}.{minor}.{patch}"]
|
|
215
221
|
search = "{current_version}"
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
from
|
|
2
|
+
from collections.abc import Callable, Coroutine
|
|
3
|
+
from typing import Annotated, Any
|
|
3
4
|
|
|
4
5
|
import typer
|
|
5
6
|
|
|
@@ -53,16 +54,33 @@ def create_client(
|
|
|
53
54
|
return SingBoxAPIClient(base_url, token)
|
|
54
55
|
|
|
55
56
|
|
|
57
|
+
def _run_tui(
|
|
58
|
+
ctx: typer.Context,
|
|
59
|
+
command: Callable[[SingBoxAPIClient], Coroutine[Any, Any, None]],
|
|
60
|
+
base_url: StrOrNone,
|
|
61
|
+
token: StrOrNone,
|
|
62
|
+
) -> None:
|
|
63
|
+
"""Run an interactive command and handle user-requested exits consistently."""
|
|
64
|
+
try:
|
|
65
|
+
ctx_obj = get_context_obj(ctx)
|
|
66
|
+
api_client = create_client(ctx_obj.config, base_url, token)
|
|
67
|
+
asyncio.run(command(api_client))
|
|
68
|
+
except (KeyboardInterrupt, EOFError):
|
|
69
|
+
pass
|
|
70
|
+
print("Exited.")
|
|
71
|
+
|
|
72
|
+
|
|
56
73
|
@api.command()
|
|
57
74
|
def stats(
|
|
58
75
|
ctx: typer.Context, base_url: ApiUrlOption = None, token: ApiTokenOption = None
|
|
59
76
|
) -> None:
|
|
60
77
|
"""Show sing-box traffic, memory statistics and connections, requires API token(Optional)"""
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
78
|
+
_run_tui(
|
|
79
|
+
ctx,
|
|
80
|
+
lambda client: ResourceMonitor(client, ResourceVisualizer()).start(),
|
|
81
|
+
base_url,
|
|
82
|
+
token,
|
|
83
|
+
)
|
|
66
84
|
|
|
67
85
|
|
|
68
86
|
@api.command()
|
|
@@ -70,10 +88,7 @@ def conns(
|
|
|
70
88
|
ctx: typer.Context, base_url: ApiUrlOption = None, token: ApiTokenOption = None
|
|
71
89
|
) -> None:
|
|
72
90
|
"""Manage sing-box connections, requires API token(Optional)"""
|
|
73
|
-
|
|
74
|
-
api_client = create_client(ctx_obj.config, base_url, token)
|
|
75
|
-
manager = ConnectionsManager(api_client)
|
|
76
|
-
asyncio.run(manager.run())
|
|
91
|
+
_run_tui(ctx, lambda client: ConnectionsManager(client).run(), base_url, token)
|
|
77
92
|
|
|
78
93
|
|
|
79
94
|
@api.command()
|
|
@@ -81,10 +96,7 @@ def proxy(
|
|
|
81
96
|
ctx: typer.Context, base_url: ApiUrlOption = None, token: ApiTokenOption = None
|
|
82
97
|
) -> None:
|
|
83
98
|
"""Manage sing-box policy groups, requires API token(Optional)"""
|
|
84
|
-
|
|
85
|
-
api_client = create_client(ctx_obj.config, base_url, token)
|
|
86
|
-
manager = PolicyGroupManager(api_client)
|
|
87
|
-
asyncio.run(manager.run())
|
|
99
|
+
_run_tui(ctx, lambda client: PolicyGroupManager(client).run(), base_url, token)
|
|
88
100
|
|
|
89
101
|
|
|
90
102
|
@api.command()
|
|
@@ -95,7 +107,5 @@ def logs(
|
|
|
95
107
|
token: ApiTokenOption = None,
|
|
96
108
|
) -> None:
|
|
97
109
|
"""Show sing-box logs, requires API token(Optional)"""
|
|
98
|
-
ctx_obj = get_context_obj(ctx)
|
|
99
|
-
api_client = create_client(ctx_obj.config, base_url, token)
|
|
100
110
|
print("⌛ Showing real-time logs (Press Ctrl+C to exit)")
|
|
101
|
-
|
|
111
|
+
_run_tui(ctx, lambda client: get_logs(client, log_level), base_url, token)
|
|
@@ -5,6 +5,7 @@ Provides an async client for interacting with Sing-Box HTTP API.
|
|
|
5
5
|
|
|
6
6
|
import json
|
|
7
7
|
from collections.abc import AsyncGenerator
|
|
8
|
+
from contextlib import aclosing
|
|
8
9
|
from typing import Any, TypeVar
|
|
9
10
|
|
|
10
11
|
import httpx
|
|
@@ -224,8 +225,11 @@ class SingBoxAPIClient:
|
|
|
224
225
|
Yields:
|
|
225
226
|
TrafficData object containing traffic data (up/down in B/s)
|
|
226
227
|
"""
|
|
227
|
-
async
|
|
228
|
-
|
|
228
|
+
async with aclosing(
|
|
229
|
+
self._make_stream_request("/traffic", TrafficData)
|
|
230
|
+
) as stream:
|
|
231
|
+
async for data in stream:
|
|
232
|
+
yield data
|
|
229
233
|
|
|
230
234
|
async def memory_stream(self) -> AsyncGenerator[MemoryData, None]:
|
|
231
235
|
"""
|
|
@@ -234,8 +238,9 @@ class SingBoxAPIClient:
|
|
|
234
238
|
Yields:
|
|
235
239
|
MemoryData object containing memory data (inuse/total in bytes)
|
|
236
240
|
"""
|
|
237
|
-
async
|
|
238
|
-
|
|
241
|
+
async with aclosing(self._make_stream_request("/memory", MemoryData)) as stream:
|
|
242
|
+
async for data in stream:
|
|
243
|
+
yield data
|
|
239
244
|
|
|
240
245
|
async def log_stream(
|
|
241
246
|
self, level: str | None = None
|
|
@@ -247,8 +252,11 @@ class SingBoxAPIClient:
|
|
|
247
252
|
LogEntry object containing log data (type/payload)
|
|
248
253
|
"""
|
|
249
254
|
params = {"level": level} if level else None
|
|
250
|
-
async
|
|
251
|
-
|
|
255
|
+
async with aclosing(
|
|
256
|
+
self._make_stream_request("/logs", LogEntry, params=params)
|
|
257
|
+
) as stream:
|
|
258
|
+
async for data in stream:
|
|
259
|
+
yield data
|
|
252
260
|
|
|
253
261
|
async def get_connections(self) -> ConnectionData:
|
|
254
262
|
"""
|