helm-server 0.1.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.
- helm_server-0.1.0/PKG-INFO +200 -0
- helm_server-0.1.0/README.md +181 -0
- helm_server-0.1.0/helm_server/__init__.py +3 -0
- helm_server-0.1.0/helm_server/__main__.py +3 -0
- helm_server-0.1.0/helm_server/acp.py +722 -0
- helm_server-0.1.0/helm_server/address.py +59 -0
- helm_server-0.1.0/helm_server/cli.py +214 -0
- helm_server-0.1.0/helm_server/config.py +86 -0
- helm_server-0.1.0/helm_server/console/404.html +8 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/201-ecef95b81469223d.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/293-ee592ff59e8ce2e6.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/363-70a53ad0283ce855.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/375-f62175e49eb5d9aa.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/43eb9ba4-7e1c5d21763d9eb8.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/532-00835d842d7c0210.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/69-04f480fc82519544.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/844-98a3ec041e7a2b76.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/979-2f5c557872f40a47.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/999-0b892a6060ef8678.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/(auth)/(routes)/sign-in/[[...sign-in]]/page-066d4a1245c3cc2e.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/(auth)/(routes)/sign-up/[[...sign-up]]/page-066d4a1245c3cc2e.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/(auth)/error-1ec1ad7a2df557bc.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/(auth)/layout-066d4a1245c3cc2e.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/(dashboard)/(routes)/code/page-2914efccccf68c98.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/(dashboard)/(routes)/console/page-6c8479514527e739.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/(dashboard)/(routes)/conversation/page-066d4a1245c3cc2e.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/(dashboard)/(routes)/dashboard/page-066d4a1245c3cc2e.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/(dashboard)/(routes)/help/page-961567c37010d8ff.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/(dashboard)/(routes)/image/page-0227eb0066cf598e.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/(dashboard)/(routes)/settings/page-b9089adef92bf8eb.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/(dashboard)/error-2d6064d8b73a7b86.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/(dashboard)/layout-33c767365bd2906e.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/(landing)/error-0965ae952e9ae6cd.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/(landing)/layout-066d4a1245c3cc2e.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/(landing)/page-066d4a1245c3cc2e.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/(landing)/welcome/page-4e62bb12cb334014.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/_not-found/page-9b07e72d48d76ed2.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/app/layout-579b5da72eaf488a.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/framework-3d0dca36a4a33ef1.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/main-app-bbb707078d4589bd.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/main-f89f759535b7c220.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/pages/_app-0d261f2eefdc8a6e.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/pages/_error-572f2f4b0ed26a49.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/chunks/webpack-f680f37e1455f20a.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/css/b4948be5aeab3586.css +3 -0
- helm_server-0.1.0/helm_server/console/_next/static/vcbjpFWgBdBoqGwcUZPuZ/_buildManifest.js +1 -0
- helm_server-0.1.0/helm_server/console/_next/static/vcbjpFWgBdBoqGwcUZPuZ/_ssgManifest.js +1 -0
- helm_server-0.1.0/helm_server/console/apple-touch-icon.png +0 -0
- helm_server-0.1.0/helm_server/console/code.html +8 -0
- helm_server-0.1.0/helm_server/console/code.txt +30 -0
- helm_server-0.1.0/helm_server/console/console.html +8 -0
- helm_server-0.1.0/helm_server/console/console.txt +30 -0
- helm_server-0.1.0/helm_server/console/conversation.html +1 -0
- helm_server-0.1.0/helm_server/console/conversation.txt +27 -0
- helm_server-0.1.0/helm_server/console/dashboard.html +1 -0
- helm_server-0.1.0/helm_server/console/dashboard.txt +27 -0
- helm_server-0.1.0/helm_server/console/favicon.ico +0 -0
- helm_server-0.1.0/helm_server/console/help.html +8 -0
- helm_server-0.1.0/helm_server/console/help.txt +27 -0
- helm_server-0.1.0/helm_server/console/image.html +8 -0
- helm_server-0.1.0/helm_server/console/image.txt +30 -0
- helm_server-0.1.0/helm_server/console/index.html +1 -0
- helm_server-0.1.0/helm_server/console/index.txt +25 -0
- helm_server-0.1.0/helm_server/console/next.svg +1 -0
- helm_server-0.1.0/helm_server/console/scribbl-192.png +0 -0
- helm_server-0.1.0/helm_server/console/scribbl-512-maskable.png +0 -0
- helm_server-0.1.0/helm_server/console/scribbl-512.png +0 -0
- helm_server-0.1.0/helm_server/console/settings.html +8 -0
- helm_server-0.1.0/helm_server/console/settings.txt +30 -0
- helm_server-0.1.0/helm_server/console/sign-in.html +1 -0
- helm_server-0.1.0/helm_server/console/sign-in.txt +25 -0
- helm_server-0.1.0/helm_server/console/sign-up.html +1 -0
- helm_server-0.1.0/helm_server/console/sign-up.txt +25 -0
- helm_server-0.1.0/helm_server/console/welcome.html +8 -0
- helm_server-0.1.0/helm_server/console/welcome.txt +26 -0
- helm_server-0.1.0/helm_server/console.py +102 -0
- helm_server-0.1.0/helm_server/doctor.py +123 -0
- helm_server-0.1.0/helm_server/events.py +171 -0
- helm_server-0.1.0/helm_server/fleet.py +101 -0
- helm_server-0.1.0/helm_server/main.py +242 -0
- helm_server-0.1.0/helm_server/pair.py +238 -0
- helm_server-0.1.0/helm_server/paths.py +76 -0
- helm_server-0.1.0/helm_server/push.py +277 -0
- helm_server-0.1.0/helm_server/runners.py +99 -0
- helm_server-0.1.0/helm_server/server.py +754 -0
- helm_server-0.1.0/helm_server/service.py +230 -0
- helm_server-0.1.0/helm_server/session.py +1487 -0
- helm_server-0.1.0/helm_server/skill/pair-helm/SKILL.md +198 -0
- helm_server-0.1.0/helm_server/skill_notice.py +120 -0
- helm_server-0.1.0/helm_server/spaces.py +532 -0
- helm_server-0.1.0/helm_server/ticket.py +96 -0
- helm_server-0.1.0/helm_server/uploads.py +81 -0
- helm_server-0.1.0/helm_server.egg-info/PKG-INFO +200 -0
- helm_server-0.1.0/helm_server.egg-info/SOURCES.txt +112 -0
- helm_server-0.1.0/helm_server.egg-info/dependency_links.txt +1 -0
- helm_server-0.1.0/helm_server.egg-info/entry_points.txt +2 -0
- helm_server-0.1.0/helm_server.egg-info/requires.txt +1 -0
- helm_server-0.1.0/helm_server.egg-info/top_level.txt +1 -0
- helm_server-0.1.0/pyproject.toml +44 -0
- helm_server-0.1.0/setup.cfg +4 -0
- helm_server-0.1.0/tests/test_acp.py +339 -0
- helm_server-0.1.0/tests/test_address.py +50 -0
- helm_server-0.1.0/tests/test_cli.py +69 -0
- helm_server-0.1.0/tests/test_config.py +87 -0
- helm_server-0.1.0/tests/test_console.py +83 -0
- helm_server-0.1.0/tests/test_doctor.py +95 -0
- helm_server-0.1.0/tests/test_events.py +83 -0
- helm_server-0.1.0/tests/test_main.py +59 -0
- helm_server-0.1.0/tests/test_paths.py +53 -0
- helm_server-0.1.0/tests/test_runners.py +83 -0
- helm_server-0.1.0/tests/test_service.py +100 -0
- helm_server-0.1.0/tests/test_session.py +1385 -0
- helm_server-0.1.0/tests/test_skill_notice.py +75 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: helm-server
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Pairs the Helm iPhone app with the Cursor CLI on your Linux or macOS server.
|
|
5
|
+
License: Proprietary
|
|
6
|
+
Keywords: helm,cursor,cursor-agent,iphone,remote
|
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
|
8
|
+
Classifier: Environment :: Console
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: Other/Proprietary License
|
|
11
|
+
Classifier: Operating System :: MacOS
|
|
12
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Topic :: Software Development
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: cryptography>=41
|
|
19
|
+
|
|
20
|
+
# helm-server
|
|
21
|
+
|
|
22
|
+
Run your Cursor agent from your iPhone. helm-server runs on your own Linux or
|
|
23
|
+
macOS server, next to your code, and drives the Cursor CLI with your own Cursor
|
|
24
|
+
account. The Helm iPhone app pairs with it and talks only to your server.
|
|
25
|
+
|
|
26
|
+
## Before you install: what this does
|
|
27
|
+
|
|
28
|
+
- **Installs** one Python package (`helm-server`) for your user. No root.
|
|
29
|
+
- **Runs** one small HTTP server on `127.0.0.1:7788`, as your user, under
|
|
30
|
+
systemd (Linux) or launchd (macOS). It only listens on loopback.
|
|
31
|
+
- **Reaches the phone** through an https front you choose and control:
|
|
32
|
+
Tailscale Funnel, a Cloudflare tunnel on your account, or your own domain
|
|
33
|
+
with a reverse proxy. helm-server never opens a public port itself.
|
|
34
|
+
- **Grants a paired phone** the same power as running Cursor's agent yourself,
|
|
35
|
+
in the checkouts you allow: it can read and edit files and run shell commands
|
|
36
|
+
as your user there. Pairing needs a one-time code you mint on the server.
|
|
37
|
+
Codes expire after 10 minutes and work once.
|
|
38
|
+
- **Keeps secrets on the server.** The phone holds a pairing ticket, not your
|
|
39
|
+
Cursor login or the server's tokens.
|
|
40
|
+
|
|
41
|
+
## Requirements
|
|
42
|
+
|
|
43
|
+
- Linux or macOS, Python 3.10 or newer
|
|
44
|
+
- The Cursor CLI, logged in (`curl https://cursor.com/install -fsS | bash`,
|
|
45
|
+
then `cursor-agent login`)
|
|
46
|
+
- An https address your phone can reach (see step 5)
|
|
47
|
+
- The Helm app on your iPhone
|
|
48
|
+
|
|
49
|
+
## Let your coding agent set it up
|
|
50
|
+
|
|
51
|
+
Paste this to Cursor's agent (or any CLI agent) on the server:
|
|
52
|
+
|
|
53
|
+
> Install helm-server from PyPI with `uv tool install helm-server` (or
|
|
54
|
+
> `pipx install helm-server`), run `helm-server skill install`, then follow the
|
|
55
|
+
> `pair-helm` skill to set it up and pair my phone. Explain each step before
|
|
56
|
+
> you run it.
|
|
57
|
+
|
|
58
|
+
The `pair-helm` skill explains everything first, installs nothing without your
|
|
59
|
+
yes, never runs `sudo` for you, and ends with a pairing code for the app.
|
|
60
|
+
`helm-server skill show` prints it.
|
|
61
|
+
|
|
62
|
+
## Set it up yourself
|
|
63
|
+
|
|
64
|
+
1. Install:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
uv tool install helm-server # or: pipx install helm-server
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
2. Allow the checkouts Helm may work in, and group them into a Space:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
helm-server repos add /path/to/my-app
|
|
74
|
+
helm-server spaces add main my-app --label "My app"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
3. Start the service:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
helm-server service install
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
On Linux, run the `loginctl enable-linger` command it prints if you want
|
|
84
|
+
the service to keep running after you log out.
|
|
85
|
+
|
|
86
|
+
4. Check:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
helm-server doctor
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
5. Put an https front in front of `http://127.0.0.1:7788`. Any one of:
|
|
93
|
+
|
|
94
|
+
- Tailscale Funnel: `tailscale funnel --bg 7788`
|
|
95
|
+
- A Cloudflare named tunnel pointed at `http://127.0.0.1:7788`
|
|
96
|
+
- Caddy on a domain pointing at this server:
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
helm.example.com {
|
|
100
|
+
reverse_proxy 127.0.0.1:7788
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Then save that address. Only a public `https://` origin with no path is
|
|
105
|
+
accepted:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
helm-server url set https://helm.example.com
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`helm-server doctor` should now show every line `ok`, including `reachable`.
|
|
112
|
+
|
|
113
|
+
6. Pair:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
helm-server pair
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
In Helm on the iPhone: Settings → Your server, paste the https address, then
|
|
120
|
+
paste the code.
|
|
121
|
+
|
|
122
|
+
## Commands
|
|
123
|
+
|
|
124
|
+
| Command | What it does |
|
|
125
|
+
|---|---|
|
|
126
|
+
| `helm-server doctor [--json]` | Checks the Cursor CLI, checkouts, service, address, and reachability |
|
|
127
|
+
| `helm-server pair [SPACE]` | Mints a one-time pairing code |
|
|
128
|
+
| `helm-server repos add PATH \| list \| remove NAME` | Checkouts Helm may use |
|
|
129
|
+
| `helm-server spaces add ID REPO... \| list` | Group checkouts into Spaces |
|
|
130
|
+
| `helm-server url set ORIGIN \| show \| clear` | The https address the app connects to |
|
|
131
|
+
| `helm-server service install \| start \| stop \| restart \| status \| logs \| uninstall` | The background service |
|
|
132
|
+
| `helm-server skill install \| show` | The `pair-helm` skill for coding agents |
|
|
133
|
+
| `helm-server run` | Run the server in the foreground |
|
|
134
|
+
|
|
135
|
+
## Upgrade, sign out, remove
|
|
136
|
+
|
|
137
|
+
- Upgrade: `uv tool upgrade helm-server`, then `helm-server service restart`.
|
|
138
|
+
- Sign out every phone: delete `ticket.secret` (below), then
|
|
139
|
+
`helm-server service restart`. Pair again with `helm-server pair`.
|
|
140
|
+
- Remove: `helm-server service uninstall`, then `uv tool uninstall helm-server`.
|
|
141
|
+
Delete the config and state folders below to remove all data.
|
|
142
|
+
|
|
143
|
+
## Where it keeps things
|
|
144
|
+
|
|
145
|
+
| | Linux | macOS |
|
|
146
|
+
|---|---|---|
|
|
147
|
+
| Config and secrets | `~/.config/helm` | `~/Library/Application Support/Helm` |
|
|
148
|
+
| State | `~/.local/state/helm` | `~/Library/Application Support/Helm/state` |
|
|
149
|
+
| Logs | `~/.local/state/helm/logs` | `~/Library/Logs/Helm` |
|
|
150
|
+
|
|
151
|
+
Config holds `repos.json`, `spaces.json`, `public-url`, `session.token`,
|
|
152
|
+
`ticket.secret`, and `vapid.json`. Every path can be moved with an environment
|
|
153
|
+
variable (`HELM_CONFIG_DIR`, `HELM_STATE_DIR`, `HELM_LOG_DIR`, or
|
|
154
|
+
`HELM_SPACES_FILE`, `HELM_REPOS_FILE`, `HELM_TOKEN_FILE`,
|
|
155
|
+
`HELM_TICKET_SECRET_FILE`, `HELM_VAPID_FILE`, `HELM_ORIGIN_FILE`).
|
|
156
|
+
|
|
157
|
+
## Agent
|
|
158
|
+
|
|
159
|
+
Cursor is the only agent at launch (`HELM_AGENT=cursor`, the default).
|
|
160
|
+
helm-server finds the Cursor CLI in `~/.local/bin` or on `PATH`; point at another
|
|
161
|
+
copy with `HELM_CURSOR_AGENT_BIN` (print runs and host commands) or
|
|
162
|
+
`HELM_CURSOR_ACP_BIN` (`agent acp`, used by the app). `/health` reports the agent
|
|
163
|
+
and version.
|
|
164
|
+
|
|
165
|
+
## Releases
|
|
166
|
+
|
|
167
|
+
Releases are published to PyPI from the `zai-core/helm-server` release workflow
|
|
168
|
+
with PyPI trusted publishing. No upload token exists, and each file carries a
|
|
169
|
+
signed provenance attestation naming the workflow and tag that built it.
|
|
170
|
+
|
|
171
|
+
## Operator settings
|
|
172
|
+
|
|
173
|
+
Off by default. An operator running several hosts or the Telegram bridge sets:
|
|
174
|
+
|
|
175
|
+
| Variable | Purpose |
|
|
176
|
+
|---|---|
|
|
177
|
+
| `HELM_FLEET_FILE` | Fleet map, so each host advertises only its own Spaces |
|
|
178
|
+
| `HELM_TELEGRAM_BOTS_FILE` | Bot list used to find this host in the fleet |
|
|
179
|
+
| `HELM_TELEGRAM_STATE_DIR` | Bridge state, so Telegram-owned chats stay on Telegram |
|
|
180
|
+
| `HELM_GITHUB_PAT_DIR` | Per-owner `github_pat.<owner>` files injected into runs |
|
|
181
|
+
| `HELM_CORS_ORIGINS` | Browser origins allowed to call the API |
|
|
182
|
+
| `HELM_PUSH_CONTACT` | VAPID contact (`mailto:` or https) for web push |
|
|
183
|
+
| `HELM_CONSOLE_DIR` | Serve the web console from another folder |
|
|
184
|
+
|
|
185
|
+
## Development
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
. scripts/ci-tools.sh # pinned uv on PATH
|
|
189
|
+
make lint build test-unit test-functional
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Jenkins runs the same four targets and posts `Jenkins / Lint`, `Build`,
|
|
193
|
+
`Unit tests`, and `Functional tests`. Functional tests install the built wheel
|
|
194
|
+
into a clean venv, start the real server with a stub `cursor-agent`, and pair
|
|
195
|
+
and run over HTTP. See `.github/MERGE_GATE.md`.
|
|
196
|
+
|
|
197
|
+
To release: merge the console change to scribblr-agent main, put that commit's
|
|
198
|
+
SHA in `console.ref`, bump `helm_server.__version__`, merge, then push the tag
|
|
199
|
+
`v<version>` on main. `.github/workflows/release.yml` builds the console at
|
|
200
|
+
`console.ref`, bundles it, tests the wheel, and publishes.
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# helm-server
|
|
2
|
+
|
|
3
|
+
Run your Cursor agent from your iPhone. helm-server runs on your own Linux or
|
|
4
|
+
macOS server, next to your code, and drives the Cursor CLI with your own Cursor
|
|
5
|
+
account. The Helm iPhone app pairs with it and talks only to your server.
|
|
6
|
+
|
|
7
|
+
## Before you install: what this does
|
|
8
|
+
|
|
9
|
+
- **Installs** one Python package (`helm-server`) for your user. No root.
|
|
10
|
+
- **Runs** one small HTTP server on `127.0.0.1:7788`, as your user, under
|
|
11
|
+
systemd (Linux) or launchd (macOS). It only listens on loopback.
|
|
12
|
+
- **Reaches the phone** through an https front you choose and control:
|
|
13
|
+
Tailscale Funnel, a Cloudflare tunnel on your account, or your own domain
|
|
14
|
+
with a reverse proxy. helm-server never opens a public port itself.
|
|
15
|
+
- **Grants a paired phone** the same power as running Cursor's agent yourself,
|
|
16
|
+
in the checkouts you allow: it can read and edit files and run shell commands
|
|
17
|
+
as your user there. Pairing needs a one-time code you mint on the server.
|
|
18
|
+
Codes expire after 10 minutes and work once.
|
|
19
|
+
- **Keeps secrets on the server.** The phone holds a pairing ticket, not your
|
|
20
|
+
Cursor login or the server's tokens.
|
|
21
|
+
|
|
22
|
+
## Requirements
|
|
23
|
+
|
|
24
|
+
- Linux or macOS, Python 3.10 or newer
|
|
25
|
+
- The Cursor CLI, logged in (`curl https://cursor.com/install -fsS | bash`,
|
|
26
|
+
then `cursor-agent login`)
|
|
27
|
+
- An https address your phone can reach (see step 5)
|
|
28
|
+
- The Helm app on your iPhone
|
|
29
|
+
|
|
30
|
+
## Let your coding agent set it up
|
|
31
|
+
|
|
32
|
+
Paste this to Cursor's agent (or any CLI agent) on the server:
|
|
33
|
+
|
|
34
|
+
> Install helm-server from PyPI with `uv tool install helm-server` (or
|
|
35
|
+
> `pipx install helm-server`), run `helm-server skill install`, then follow the
|
|
36
|
+
> `pair-helm` skill to set it up and pair my phone. Explain each step before
|
|
37
|
+
> you run it.
|
|
38
|
+
|
|
39
|
+
The `pair-helm` skill explains everything first, installs nothing without your
|
|
40
|
+
yes, never runs `sudo` for you, and ends with a pairing code for the app.
|
|
41
|
+
`helm-server skill show` prints it.
|
|
42
|
+
|
|
43
|
+
## Set it up yourself
|
|
44
|
+
|
|
45
|
+
1. Install:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
uv tool install helm-server # or: pipx install helm-server
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
2. Allow the checkouts Helm may work in, and group them into a Space:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
helm-server repos add /path/to/my-app
|
|
55
|
+
helm-server spaces add main my-app --label "My app"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
3. Start the service:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
helm-server service install
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
On Linux, run the `loginctl enable-linger` command it prints if you want
|
|
65
|
+
the service to keep running after you log out.
|
|
66
|
+
|
|
67
|
+
4. Check:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
helm-server doctor
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
5. Put an https front in front of `http://127.0.0.1:7788`. Any one of:
|
|
74
|
+
|
|
75
|
+
- Tailscale Funnel: `tailscale funnel --bg 7788`
|
|
76
|
+
- A Cloudflare named tunnel pointed at `http://127.0.0.1:7788`
|
|
77
|
+
- Caddy on a domain pointing at this server:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
helm.example.com {
|
|
81
|
+
reverse_proxy 127.0.0.1:7788
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Then save that address. Only a public `https://` origin with no path is
|
|
86
|
+
accepted:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
helm-server url set https://helm.example.com
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`helm-server doctor` should now show every line `ok`, including `reachable`.
|
|
93
|
+
|
|
94
|
+
6. Pair:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
helm-server pair
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
In Helm on the iPhone: Settings → Your server, paste the https address, then
|
|
101
|
+
paste the code.
|
|
102
|
+
|
|
103
|
+
## Commands
|
|
104
|
+
|
|
105
|
+
| Command | What it does |
|
|
106
|
+
|---|---|
|
|
107
|
+
| `helm-server doctor [--json]` | Checks the Cursor CLI, checkouts, service, address, and reachability |
|
|
108
|
+
| `helm-server pair [SPACE]` | Mints a one-time pairing code |
|
|
109
|
+
| `helm-server repos add PATH \| list \| remove NAME` | Checkouts Helm may use |
|
|
110
|
+
| `helm-server spaces add ID REPO... \| list` | Group checkouts into Spaces |
|
|
111
|
+
| `helm-server url set ORIGIN \| show \| clear` | The https address the app connects to |
|
|
112
|
+
| `helm-server service install \| start \| stop \| restart \| status \| logs \| uninstall` | The background service |
|
|
113
|
+
| `helm-server skill install \| show` | The `pair-helm` skill for coding agents |
|
|
114
|
+
| `helm-server run` | Run the server in the foreground |
|
|
115
|
+
|
|
116
|
+
## Upgrade, sign out, remove
|
|
117
|
+
|
|
118
|
+
- Upgrade: `uv tool upgrade helm-server`, then `helm-server service restart`.
|
|
119
|
+
- Sign out every phone: delete `ticket.secret` (below), then
|
|
120
|
+
`helm-server service restart`. Pair again with `helm-server pair`.
|
|
121
|
+
- Remove: `helm-server service uninstall`, then `uv tool uninstall helm-server`.
|
|
122
|
+
Delete the config and state folders below to remove all data.
|
|
123
|
+
|
|
124
|
+
## Where it keeps things
|
|
125
|
+
|
|
126
|
+
| | Linux | macOS |
|
|
127
|
+
|---|---|---|
|
|
128
|
+
| Config and secrets | `~/.config/helm` | `~/Library/Application Support/Helm` |
|
|
129
|
+
| State | `~/.local/state/helm` | `~/Library/Application Support/Helm/state` |
|
|
130
|
+
| Logs | `~/.local/state/helm/logs` | `~/Library/Logs/Helm` |
|
|
131
|
+
|
|
132
|
+
Config holds `repos.json`, `spaces.json`, `public-url`, `session.token`,
|
|
133
|
+
`ticket.secret`, and `vapid.json`. Every path can be moved with an environment
|
|
134
|
+
variable (`HELM_CONFIG_DIR`, `HELM_STATE_DIR`, `HELM_LOG_DIR`, or
|
|
135
|
+
`HELM_SPACES_FILE`, `HELM_REPOS_FILE`, `HELM_TOKEN_FILE`,
|
|
136
|
+
`HELM_TICKET_SECRET_FILE`, `HELM_VAPID_FILE`, `HELM_ORIGIN_FILE`).
|
|
137
|
+
|
|
138
|
+
## Agent
|
|
139
|
+
|
|
140
|
+
Cursor is the only agent at launch (`HELM_AGENT=cursor`, the default).
|
|
141
|
+
helm-server finds the Cursor CLI in `~/.local/bin` or on `PATH`; point at another
|
|
142
|
+
copy with `HELM_CURSOR_AGENT_BIN` (print runs and host commands) or
|
|
143
|
+
`HELM_CURSOR_ACP_BIN` (`agent acp`, used by the app). `/health` reports the agent
|
|
144
|
+
and version.
|
|
145
|
+
|
|
146
|
+
## Releases
|
|
147
|
+
|
|
148
|
+
Releases are published to PyPI from the `zai-core/helm-server` release workflow
|
|
149
|
+
with PyPI trusted publishing. No upload token exists, and each file carries a
|
|
150
|
+
signed provenance attestation naming the workflow and tag that built it.
|
|
151
|
+
|
|
152
|
+
## Operator settings
|
|
153
|
+
|
|
154
|
+
Off by default. An operator running several hosts or the Telegram bridge sets:
|
|
155
|
+
|
|
156
|
+
| Variable | Purpose |
|
|
157
|
+
|---|---|
|
|
158
|
+
| `HELM_FLEET_FILE` | Fleet map, so each host advertises only its own Spaces |
|
|
159
|
+
| `HELM_TELEGRAM_BOTS_FILE` | Bot list used to find this host in the fleet |
|
|
160
|
+
| `HELM_TELEGRAM_STATE_DIR` | Bridge state, so Telegram-owned chats stay on Telegram |
|
|
161
|
+
| `HELM_GITHUB_PAT_DIR` | Per-owner `github_pat.<owner>` files injected into runs |
|
|
162
|
+
| `HELM_CORS_ORIGINS` | Browser origins allowed to call the API |
|
|
163
|
+
| `HELM_PUSH_CONTACT` | VAPID contact (`mailto:` or https) for web push |
|
|
164
|
+
| `HELM_CONSOLE_DIR` | Serve the web console from another folder |
|
|
165
|
+
|
|
166
|
+
## Development
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
. scripts/ci-tools.sh # pinned uv on PATH
|
|
170
|
+
make lint build test-unit test-functional
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Jenkins runs the same four targets and posts `Jenkins / Lint`, `Build`,
|
|
174
|
+
`Unit tests`, and `Functional tests`. Functional tests install the built wheel
|
|
175
|
+
into a clean venv, start the real server with a stub `cursor-agent`, and pair
|
|
176
|
+
and run over HTTP. See `.github/MERGE_GATE.md`.
|
|
177
|
+
|
|
178
|
+
To release: merge the console change to scribblr-agent main, put that commit's
|
|
179
|
+
SHA in `console.ref`, bump `helm_server.__version__`, merge, then push the tag
|
|
180
|
+
`v<version>` on main. `.github/workflows/release.yml` builds the console at
|
|
181
|
+
`console.ref`, bundles it, tests the wheel, and publishes.
|