create-opentray 0.19.0 → 0.20.0
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.
- package/README.md +136 -133
- package/assets/create-opentray-logo.png +0 -0
- package/dist/bin-sZB5nWq0.mjs +2142 -0
- package/dist/bin-sZB5nWq0.mjs.map +1 -0
- package/dist/bin.d.mts +15 -2
- package/dist/bin.d.mts.map +1 -0
- package/dist/bin.mjs +1 -1
- package/dist/index.d.mts +62 -351
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -1
- package/dist/shell/assets/browse.js +1 -1
- package/dist/shell/assets/index.css +1 -1
- package/dist/shell/assets/index.js +7 -7
- package/dist/shell/assets/input.js +1 -1
- package/dist/shell/assets/main.js +21 -43
- package/dist/shell/assets/terminal-pane.js +1 -1
- package/dist/shell/browse.html +3 -0
- package/dist/shell/favicon-16.png +0 -0
- package/dist/shell/favicon-32.png +0 -0
- package/dist/shell/favicon-64.png +0 -0
- package/dist/shell/index.html +3 -0
- package/dist/shell/logo.png +0 -0
- package/dist/shell/terminal.html +3 -0
- package/dist/skill/SKILL.md +156 -0
- package/dist/skill/references/cli-reference.md +77 -0
- package/dist/skill/references/how-it-works.md +49 -0
- package/dist/webui/assets/browse.js +1 -1
- package/dist/webui/assets/index.css +1 -1
- package/dist/webui/assets/index.js +7 -7
- package/dist/webui/assets/input.js +1 -1
- package/dist/webui/assets/main.js +21 -43
- package/dist/webui/assets/terminal-pane.js +1 -1
- package/dist/webui/browse.html +3 -0
- package/dist/webui/favicon-16.png +0 -0
- package/dist/webui/favicon-32.png +0 -0
- package/dist/webui/favicon-64.png +0 -0
- package/dist/webui/index.html +3 -0
- package/dist/webui/logo.png +0 -0
- package/dist/webui/terminal.html +3 -0
- package/package.json +12 -6
- package/skill/SKILL.md +156 -0
- package/skill/references/cli-reference.md +77 -0
- package/skill/references/how-it-works.md +49 -0
- package/dist/bin-BT_kcLuP.mjs +0 -3823
- package/dist/bin-BT_kcLuP.mjs.map +0 -1
- package/dist/bin-CeFW1wxR.d.mts +0 -15
- package/dist/bin-CeFW1wxR.d.mts.map +0 -1
- package/dist/icon-codec-BQ3cGV1n.mjs +0 -13
- package/dist/icon-codec-BQ3cGV1n.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
<p align="center"><img src="./assets/create-opentray-logo.png" alt="create-opentray logo" width="180"></p>
|
|
2
|
+
|
|
1
3
|
# create-opentray
|
|
2
4
|
|
|
3
5
|
Turn any start command that serves HTTP locally into an OpenTray-hosted
|
|
4
|
-
desktop app — through a browser wizard
|
|
6
|
+
desktop app — through a browser wizard or fully non-interactively, without
|
|
7
|
+
writing OpenTray code.
|
|
5
8
|
|
|
6
9
|
```bash
|
|
7
10
|
npx create-opentray
|
|
@@ -9,149 +12,148 @@ npx create-opentray
|
|
|
9
12
|
|
|
10
13
|
Requires Node >= 20 (native `sharp` icon pipeline).
|
|
11
14
|
|
|
12
|
-
##
|
|
13
|
-
|
|
14
|
-
1. Starts a token-guarded WebUI (React + shadcn/ui) on `127.0.0.1` and opens
|
|
15
|
-
your browser.
|
|
16
|
-
2. You paste a start command (e.g. `npx somecommand start --xx`). It runs
|
|
17
|
-
immediately in a **real interactive terminal** inside a Chrome-style tabs
|
|
18
|
-
panel: prompts, TUI output, and keystrokes all work.
|
|
19
|
-
3. Confirmed HTTP services (TCP listener owned by the command's process tree
|
|
20
|
-
**and** answering an HTTP probe) each open an iframe tab automatically —
|
|
21
|
-
newly sniffed tabs take focus — and stay alive across switches. The tab
|
|
22
|
-
strip sits above the context toolbar; on service tabs it shows an editable
|
|
23
|
-
URL with back/forward/reload backed by a per-tab history. The terminal tab's status bar shows cursor position,
|
|
24
|
-
selection range, and clickable service entries that jump to the matching
|
|
25
|
-
iframe tab by hostname.
|
|
26
|
-
4. Auto-derived defaults (scraped title, derived appId) are shown as
|
|
27
|
-
**input placeholders** — an empty field means "use the default"; edits win
|
|
28
|
-
over later scrapes. The icon row is a square file picker plus scraped
|
|
29
|
-
candidates: every icon the page declares (SVG, apple-touch-icon, sized
|
|
30
|
-
PNG sets, /favicon.ico) is collected, measured by true pixel clarity,
|
|
31
|
-
deduplicated perceptually, and ranked; clicking a candidate (or uploading
|
|
32
|
-
a local image) selects it, and the clearest candidate is the default.
|
|
33
|
-
5. 高级选项 — the settings button beside the command bar opens an accordion:
|
|
34
|
-
- 命令选项: 参数输入模式 (string vs 数组/argv — array mode commits ONE argv
|
|
35
|
-
element per tag, verbatim, never splitting strings), 工作目录 (cwd;
|
|
36
|
-
default is the USER_HOME directory, displayed in full — relative paths
|
|
37
|
-
resolve from there), and 环境变量 (env overlay; also persisted into the
|
|
38
|
-
generated app).
|
|
39
|
-
- 应用选项: the tray-icon picker (defaults to the app icon choice; solid
|
|
40
|
-
black/white silhouettes derived from every candidate) and the two
|
|
41
|
-
generated-app window options 显示启动终端 / 显示地址栏 (both default off).
|
|
42
|
-
Service ports are NEVER hard-bound: the form has no manual port input, and
|
|
43
|
-
the generated app resolves its address exclusively by sniffing the
|
|
44
|
-
command's owned listening ports (HTTP-verified) at runtime.
|
|
45
|
-
6. 确定创建 freezes the resolved identity, shows a confirmation dialog, then
|
|
46
|
-
确认生成 runs the pipeline with live logs: scaffold → icon generation →
|
|
47
|
-
dependency install → first launch → (macOS) stable bundle verification.
|
|
48
|
-
7. Success offers 打开应用 plus a platform pinning hint (Windows taskbar /
|
|
49
|
-
macOS Dock).
|
|
50
|
-
|
|
51
|
-
## CLI
|
|
15
|
+
## Command tree
|
|
52
16
|
|
|
53
|
-
```
|
|
54
|
-
create-opentray
|
|
55
|
-
|
|
17
|
+
```text
|
|
18
|
+
create-opentray # WebUI wizard (compatibility default)
|
|
19
|
+
create-opentray web [--port <n>] [--no-open]
|
|
20
|
+
create-opentray create [options] # non-interactive creation
|
|
21
|
+
create-opentray app list|edit|copy|export|uninstall
|
|
22
|
+
create-opentray skill [list|read] # packaged English AI skill
|
|
56
23
|
```
|
|
57
24
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
- `--skip-install` — scaffold without installing dependencies.
|
|
61
|
-
- `--force` — allow materializing into a non-empty directory.
|
|
25
|
+
Every command accepts `--json` for a machine-readable typed result on stdout
|
|
26
|
+
(progress and diagnostics then use stderr only).
|
|
62
27
|
|
|
63
|
-
##
|
|
28
|
+
## Non-interactive create
|
|
64
29
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
30
|
+
```bash
|
|
31
|
+
npx create-opentray create \
|
|
32
|
+
--app-id app.local.mytool \
|
|
33
|
+
--app-name "My Tool" \
|
|
34
|
+
--exec npm --arg run --arg dev \
|
|
35
|
+
--cwd /path/to/project \
|
|
36
|
+
--app-icon https://example.com/logo.png \
|
|
37
|
+
--tray-icon ./tray.png \
|
|
38
|
+
--pm npm
|
|
39
|
+
```
|
|
72
40
|
|
|
41
|
+
- `--arg` is repeatable; each value is ONE exact argv element — never a shell
|
|
42
|
+
string (`&&` stays a literal argument).
|
|
43
|
+
- Icon sources: local files, `http(s)` URLs, or `data:` URLs. The CLI never
|
|
44
|
+
scrapes names or favicons.
|
|
45
|
+
- `--config <file>` loads a complete v1 document; explicit flags override
|
|
46
|
+
only their named fields.
|
|
47
|
+
- `--dry-run` prints the plan without mutating anything.
|
|
48
|
+
- `--force` replaces only a VERIFIED create-opentray payload — it never
|
|
49
|
+
adopts or clears a user directory.
|
|
50
|
+
- `--no-image-smoothing` renders icons with nearest-neighbor sampling
|
|
51
|
+
(pixel-art safe: enlarged app/tray icons keep hard edges).
|
|
52
|
+
- `--developer-mode` admits WebView DevTools in the generated app (default
|
|
53
|
+
off; it means nothing else).
|
|
54
|
+
- `--window <WxH>` sets the window size (default 1200x800).
|
|
55
|
+
|
|
56
|
+
## The v1 registry layout
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
~/.opentray/create/<encoded-app-id>/
|
|
60
|
+
create-opentray.json # the SOLE editable authority (schemaVersion 1)
|
|
61
|
+
app/ # generated payload (managed dir, or a link)
|
|
62
|
+
app-icon.<ext> # committed icon snapshots (hash-verified)
|
|
63
|
+
tray-icon.<ext>
|
|
73
64
|
```
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
65
|
+
|
|
66
|
+
`create-opentray.json` is the only file you edit: identity/name, exact
|
|
67
|
+
command vector (executable/args/cwd/env), package manager, icon resource
|
|
68
|
+
references with content hashes and provenance, icon-rendering options
|
|
69
|
+
(including `imageSmoothingEnabled`), window options, and `developerMode`.
|
|
70
|
+
Generated files are derived output and are regenerated on every apply.
|
|
71
|
+
|
|
72
|
+
Key rules:
|
|
73
|
+
|
|
74
|
+
- **appId is immutable** — a new identity is `app copy`, never an edit.
|
|
75
|
+
- **The registry root is fixed** at `~/.opentray/create/`.
|
|
76
|
+
- **Snapshots are stable** — URL-fetched icons are committed locally; later
|
|
77
|
+
URL drift never changes an existing registration.
|
|
78
|
+
- **Breaking boundary**: projects identified only by the older
|
|
79
|
+
`opentray.app.json` marker are not discovered, listed, or migrated.
|
|
80
|
+
|
|
81
|
+
## Managing applications
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npx create-opentray app list
|
|
85
|
+
npx create-opentray app edit app.local.mytool --app-name "Renamed" --force
|
|
86
|
+
npx create-opentray app copy app.local.mytool --new-app-id app.local.tool2
|
|
87
|
+
npx create-opentray app export app.local.mytool --format sh -o make.sh
|
|
88
|
+
npx create-opentray app uninstall app.local.mytool
|
|
98
89
|
```
|
|
99
90
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
-
|
|
121
|
-
|
|
91
|
+
- `app list` reports health: `healthy`, `invalid-config`,
|
|
92
|
+
`incompatible-version`, `missing-payload`, `broken-link`, or `running`,
|
|
93
|
+
with registration and payload paths.
|
|
94
|
+
- A running instance blocks edits/uninstalls with a typed `app_running`
|
|
95
|
+
result until `--stop-running` is passed. Processes are terminated only
|
|
96
|
+
when the recorded PID, ownership token, and start fingerprint still match;
|
|
97
|
+
a reused PID is refused, never killed.
|
|
98
|
+
- `app uninstall` retains a linked external target unless `--purge-target`
|
|
99
|
+
explicitly authorizes deletion after revalidation. macOS Dock pins and
|
|
100
|
+
Windows taskbar pins are user-managed.
|
|
101
|
+
|
|
102
|
+
## Export
|
|
103
|
+
|
|
104
|
+
`app export` produces a complete recreation artifact:
|
|
105
|
+
|
|
106
|
+
- `--format command` — exact argv command line (uploads embed as data URLs
|
|
107
|
+
only with `--force-copy`).
|
|
108
|
+
- `--format sh` / `--format ps1` — self-contained scripts (LF / CRLF);
|
|
109
|
+
uploaded icon bytes are embedded and reconstructed into a temp file before
|
|
110
|
+
invocation.
|
|
111
|
+
- Any environment entry makes complete export require `--acknowledge-env`.
|
|
112
|
+
create-opentray never guesses which values are sensitive — it always asks
|
|
113
|
+
once, and never echoes env values in ordinary output.
|
|
114
|
+
|
|
115
|
+
## WebUI wizard
|
|
116
|
+
|
|
117
|
+
`create-opentray` (or `create-opentray web`) starts a token-guarded WebUI on
|
|
118
|
+
`127.0.0.1` and opens your browser: paste a start command, watch it run in a
|
|
119
|
+
real interactive terminal, confirmed HTTP services open as tabs, and
|
|
120
|
+
identity/icon defaults are suggested from the served page (every suggestion
|
|
121
|
+
is a placeholder you can override). The wizard speaks the same Core as the
|
|
122
|
+
CLI, so both produce identical plans.
|
|
123
|
+
|
|
124
|
+
## Generated project
|
|
125
|
+
|
|
126
|
+
The entry (`main.mjs`) spawns the recorded command (output → `app.log`),
|
|
127
|
+
continuously discovers the command's OWNED HTTP listening ports (foreign
|
|
128
|
+
listeners such as browser DevTools sockets are never adopted), hosts each
|
|
129
|
+
verified port in an application-mode WebView window, and owns the tray
|
|
130
|
+
session (Quit lives in the tray menu). Optional startup-terminal and
|
|
131
|
+
address-bar shells are available through the wizard's advanced options.
|
|
122
132
|
|
|
123
133
|
## Platform notes
|
|
124
134
|
|
|
125
|
-
- **Objective terminal transport**: the preview runs through
|
|
126
|
-
[@lydell/node-pty](https://github.com/lydell/node-pty) (prebuilt per-platform
|
|
127
|
-
binaries; no compiler needed) and is rendered by
|
|
128
|
-
[ghostty-web](https://github.com/coder/ghostty-web). The backend forwards the
|
|
129
|
-
PTY binding's chunks verbatim — no re-decoding, no analysis; the renderer
|
|
130
|
-
owns every escape sequence. Invalid bytes are replaced with U+FFFD *inside
|
|
131
|
-
the PTY binding* (its documented text-channel contract, shared with every
|
|
132
|
-
node-pty consumer); the wizard adds no interpretation on top.
|
|
133
|
-
- The optional PTY dependency degrades to a read-only pipe mode with a visible
|
|
134
|
-
notice when it cannot load; the wizard itself keeps working.
|
|
135
|
-
- **Runtime-native PTY backends**: under Bun the terminal attaches through
|
|
136
|
-
the built-in `Bun.Terminal` + `Bun.spawn({ terminal })` (no native npm
|
|
137
|
-
dependency, fully interactive — verified output, stdin echo, resize, and
|
|
138
|
-
exit codes on Bun 1.3.14). Under Node it uses prebuilt `@lydell/node-pty`.
|
|
139
|
-
Both transport the PTY's chunks verbatim. Only when neither backend exists
|
|
140
|
-
(Node without the optional dependency, or a Bun older than 1.2.19) does the
|
|
141
|
-
preview degrade to read-only pipes with a visible notice.
|
|
142
|
-
- The Run button becomes an Interrupt button while the preview process is
|
|
143
|
-
alive and returns to Run when the process exits — including when it is
|
|
144
|
-
killed outside the wizard.
|
|
145
|
-
- The generated app runs the command supervised but headless (output goes to
|
|
146
|
-
`app.log`); commands that require an interactive TTY at runtime are not
|
|
147
|
-
supported inside the generated app.
|
|
148
135
|
- macOS: the stable `.app` bundle is materialized by the OpenTray runtime on
|
|
149
|
-
first launch;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
the taskbar.
|
|
153
|
-
-
|
|
154
|
-
|
|
136
|
+
first launch; pin it to the Dock (removing a pin is manual).
|
|
137
|
+
- Windows: directory links use junctions (or symlinks when permitted);
|
|
138
|
+
failure is a typed error, never a silent copy. The appMode window joins
|
|
139
|
+
the taskbar/Alt-Tab. Native acceptance runs on Windows agents —
|
|
140
|
+
non-Windows fixtures are preparatory evidence only.
|
|
141
|
+
- Linux: taskbar pinning depends on the desktop environment.
|
|
142
|
+
|
|
143
|
+
## AI skill
|
|
144
|
+
|
|
145
|
+
The package ships an English AI skill (`skill/`) readable without any
|
|
146
|
+
network access:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
npx create-opentray skill # read SKILL.md
|
|
150
|
+
npx create-opentray skill list references # list one directory
|
|
151
|
+
npx create-opentray skill read SKILL.md # read any packaged file
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Skill access is read-only and contained: absolute paths, `..` traversal, NUL
|
|
155
|
+
bytes, and symlink escapes are rejected before any filesystem read, and the
|
|
156
|
+
output is always the canonical English tree regardless of host locale.
|
|
155
157
|
|
|
156
158
|
## Programmatic use
|
|
157
159
|
|
|
@@ -159,5 +161,6 @@ URL. Quit lives in the tray menu.
|
|
|
159
161
|
import { createWizardSession, deriveDefaultAppId } from "create-opentray";
|
|
160
162
|
```
|
|
161
163
|
|
|
162
|
-
See the package's TypeScript definitions (dist/index.d.mts) for the full
|
|
163
|
-
discovery, scraping, launch-vector
|
|
164
|
+
See the package's TypeScript definitions (dist/index.d.mts) for the full
|
|
165
|
+
surface (wizard session, server, discovery, scraping, launch-vector
|
|
166
|
+
resolution, scaffold, materialize).
|
|
Binary file
|