zerogterm 0.7.0-alpha2 → 0.8.0-alpha
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/LICENSE +21 -21
- package/README.md +244 -21
- package/bin/zerogterm.cjs +23 -23
- package/dist/main/main/ai-protocol.js +225 -0
- package/dist/main/main/ai-service.js +148 -0
- package/dist/main/main/command-history-store.js +231 -0
- package/dist/main/main/main.js +228 -9
- package/dist/main/main/port-forward-protocol.js +161 -0
- package/dist/main/main/port-forward-service.js +230 -0
- package/dist/main/main/port-forward-store.js +133 -0
- package/dist/main/main/preload.cjs +30 -1
- package/dist/main/main/secret-store.js +156 -0
- package/dist/main/main/session-service.js +22 -4
- package/dist/main/main/shell-catalog.js +63 -2
- package/dist/main/main/ssh-inventory.js +11 -0
- package/dist/main/main/workspace-store.js +213 -0
- package/dist/main/main/wsl-home.js +62 -0
- package/dist/main/shared/endpoints.js +73 -0
- package/dist/main/shared/version.js +32 -0
- package/dist/renderer/assets/index-BPS6JAQV.js +142 -0
- package/dist/renderer/assets/index-p0gJDyuE.css +1 -0
- package/dist/renderer/index.html +7 -4
- package/package.json +32 -2
- package/dist/renderer/assets/index-BjXtNztF.css +0 -1
- package/dist/renderer/assets/index-Ogyjvi0e.js +0 -19
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Stephen Phillips
|
|
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.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Stephen Phillips
|
|
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.
|
package/README.md
CHANGED
|
@@ -7,24 +7,27 @@ ZeroG Terminal is an alpha project, but it is already useful as a multi-session
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
- Multi-pane workspaces with stack, vertical split, horizontal split, and four-pane grid layouts.
|
|
10
|
-
- Draggable dividers between panes and beside the sidebar, so a split does not have to be an even one. Sizes are remembered between launches.
|
|
11
|
-
- A compact navigation rail for sessions, overview, settings, SSH connections, and opening a new local terminal, while keeping the sessions sidebar collapsible.
|
|
12
|
-
- Layout controls that restore a split, even up its pane sizes, and maximize or restore a pane in a predictable sequence.
|
|
10
|
+
- Draggable dividers between panes and beside the sidebar, so a split does not have to be an even one. Sizes are remembered between launches.
|
|
11
|
+
- A compact navigation rail for sessions, overview, settings, SSH connections, and opening a new local terminal, while keeping the sessions sidebar collapsible.
|
|
12
|
+
- Layout controls that restore a split, even up its pane sizes, and maximize or restore a pane in a predictable sequence.
|
|
13
13
|
- Maximize a focused pane and cycle between sessions without losing the other panes.
|
|
14
|
-
- Local sessions powered by Bash, PowerShell, WSL, and other supported shell backends; persistent sessions use `screen` where available, with a process-only fallback when it is unavailable.
|
|
14
|
+
- Local sessions powered by Bash, PowerShell, WSL, and other supported shell backends; persistent sessions use `screen` where available, with a process-only fallback when it is unavailable. A WSL pane starts in the distribution's own home directory rather than the Windows one seen through `/mnt/c`.
|
|
15
15
|
- SSH sessions for hosts, `user@host`, and `user@host:port` targets.
|
|
16
|
-
- SSH configuration discovery from known connections, including remote `screen` session discovery.
|
|
16
|
+
- SSH configuration discovery from known connections, including remote `screen` session discovery. In the sidebar's Connections tab, clicking a saved connection opens the connect dialog with the host filled in, and double-clicking it skips the dialog and opens the host in a new pane.
|
|
17
17
|
- Reconnect to existing local or remote `screen` sessions from the Screens view.
|
|
18
18
|
- Remote screen attachment that waits for SSH readiness before sending commands, including host and port-aware matching.
|
|
19
|
+
- Shared ports over SSH, in a Ports view opened from the rail: forward a port on a remote host so it answers on this machine, or a port here so it answers on the remote. Each tunnel is its own SSH connection, so a host needs no terminal open first. Ports bind to loopback unless you widen them, and are remembered between launches.
|
|
20
|
+
- A directory browser inside a pane, opened from the folder button in its title bar: the pane splits, terminal on one side and the directories on the other, with a draggable divider. Double-click a folder to take the shell there. It works on SSH panes and on local ones, WSL included, follows a `cd` you type by hand, and is remembered per pane when you switch workspaces or relaunch.
|
|
19
21
|
- An SFTP transfer panel, opened from the ⇅ button above the panes: local files on the left, the active SSH session's host on the right, with upload, download, new folder, rename, and delete. It connects to the host that session is already using and opens at the directory its shell is standing in, so a file can go straight to the project being worked on.
|
|
20
22
|
- Session history for reconnecting to sessions after a relaunch, with bounded structured history and no stored secrets.
|
|
21
|
-
-
|
|
23
|
+
- A ranked command palette on `Ctrl+Shift+R`, in the spirit of [McFly](https://github.com/cantino/mcfly): commands you have run, ranked by directory, host, recency, frequency, whether they worked, and whether you picked them before. Off by default — it is the one feature that stores what you typed — and it refuses anything that looks like it carries a credential.
|
|
24
|
+
- Workspaces for grouping sessions and quickly switching between projects or tasks. Drag the tabs beside the wordmark to put them in the order you want; `Ctrl+Shift+1` … `9` follow that order, and it is remembered between launches. Right-click a tab to rename it, duplicate it, move it, or close it. Each workspace keeps its own panes, layout, focused terminal, and maximized pane, so switching to one restores the arrangement you left it in. Workspaces survive a relaunch: local `screen` terminals reattach on their own, and SSH panes come back as ghost rows that reconnect when clicked, rather than dialling out to a host on startup.
|
|
22
25
|
- Session overview, collapsible sidebar, keyboard shortcuts, and light/dark themes.
|
|
23
26
|
- xterm.js terminal rendering with scrollback preservation while changing layouts.
|
|
24
|
-
-
|
|
27
|
+
- Voice input, either with Whisper ONNX inside the app through Transformers.js or through an OpenAI-compatible transcription server you point it at — on this machine, on the LAN, or hosted; transcribed text is typed into the selected terminal without automatic execution.
|
|
25
28
|
- A per-pane proceed button that sends a configurable phrase — `OK, proceed` by default — for waving an agent on without typing the same reply again.
|
|
26
29
|
- A settings panel for appearance, terminal behaviour, session defaults, and speech recognition, including a built-in recognition test.
|
|
27
|
-
- AI command
|
|
30
|
+
- AI command suggestions from any OpenAI-compatible endpoint — Ollama, LM Studio, llama.cpp, vLLM, OpenRouter, or OpenAI itself — configured with a base URL, a model and an optional key in Settings. Ask what you want, get one command with an explanation, and approve it before it runs.
|
|
28
31
|
- Sandboxed Electron renderer, context isolation, disabled Node integration, and a narrow typed preload API.
|
|
29
32
|
- Safe argument-array handling and validation around SSH and `screen` session operations.
|
|
30
33
|
|
|
@@ -34,9 +37,9 @@ See the project walkthrough on [YouTube](https://youtu.be/4aJZCxLHD14).
|
|
|
34
37
|
|
|
35
38
|
## Release status
|
|
36
39
|
|
|
37
|
-
ZeroG Terminal is currently a public alpha. The current release is `0.
|
|
40
|
+
ZeroG Terminal is currently a public alpha. The current release is `0.8.0-alpha`; the version history is tracked in [versions.txt](versions.txt). The running version is shown beside the wordmark in the title bar, read from the app itself rather than written into the interface, so it is accurate in a packaged build too.
|
|
38
41
|
|
|
39
|
-
The
|
|
42
|
+
The GitHub Releases page provides a Windows x64 installer and portable executable for each desktop release. These alpha builds are intended for early adopters and testing rather than production use. The npm package remains available for developers who prefer to launch ZeroG from Node.js.
|
|
40
43
|
|
|
41
44
|
## Terminal shortcuts
|
|
42
45
|
|
|
@@ -44,12 +47,42 @@ The npm package contains the built Electron application and project documentatio
|
|
|
44
47
|
- `Ctrl+Shift+V` — paste into the active terminal
|
|
45
48
|
- `Ctrl+C` remains the interrupt signal (not copy)
|
|
46
49
|
- `Ctrl+Shift+N` — new workspace
|
|
50
|
+
- `Ctrl+Shift+1` … `Ctrl+Shift+9` — switch to a workspace by position
|
|
47
51
|
- `Ctrl+Shift+T` — new local terminal in the current workspace
|
|
52
|
+
- `Ctrl+Shift+R` — ranked command history palette
|
|
53
|
+
- `Ctrl+Shift+A` — ask the AI endpoint for a command
|
|
54
|
+
- `Ctrl+Shift+L` — fold to a single pane, or back to the last split
|
|
48
55
|
- `Ctrl+Shift+O` — session overview
|
|
49
56
|
- `Ctrl+Shift+B` — toggle sessions sidebar
|
|
50
57
|
- `Ctrl+Shift+,` — settings
|
|
58
|
+
- `Ctrl+Shift+/` — the help panel: what is here, and this list
|
|
51
59
|
- `Esc` — close overview / dialogs, cancel voice recording
|
|
52
60
|
|
|
61
|
+
Every one of these can be moved: **Settings → Shortcuts** lists them, and
|
|
62
|
+
pressing a new chord in a row rebinds it. A shortcut needs Ctrl and at least one
|
|
63
|
+
of Shift or Alt, so a shell keeps its own bindings — `Ctrl+C` interrupts,
|
|
64
|
+
`Ctrl+R` is still readline's reverse search, `Ctrl+L` still clears the screen,
|
|
65
|
+
and `Ctrl+A` still reaches `screen` or `tmux`. None of these shortcuts reaches
|
|
66
|
+
the shell in the pane that has focus, which was verified by asking bash to report
|
|
67
|
+
the control characters it receives.
|
|
68
|
+
|
|
69
|
+
Rebinding exists because nothing in the app can outrank the machine it runs on.
|
|
70
|
+
`Ctrl+Shift+T` was reported already taken on Windows 11; Windows itself uses Ctrl
|
|
71
|
+
and Shift together to switch keyboard layout when more than one is installed; and
|
|
72
|
+
some applications — Teams, for one — register chords globally while they are
|
|
73
|
+
running. `Ctrl+Alt` is usually clear, though on some layouts it behaves as AltGr,
|
|
74
|
+
so a chord you would type in a terminal is worth avoiding. `Ctrl+Shift+1` … `9`
|
|
75
|
+
and the clipboard pair cannot be moved.
|
|
76
|
+
|
|
77
|
+
The `?` in the title bar opens the same help panel, which lists the shortcuts as
|
|
78
|
+
they are currently bound rather than as they shipped.
|
|
79
|
+
|
|
80
|
+
The Ports view, the SFTP transfer panel and a pane's directory browser have no
|
|
81
|
+
shortcut of their own; they open from the rail, the ⇅ button above the panes, and
|
|
82
|
+
the folder button in a pane's title bar. `Esc` deliberately does not close the
|
|
83
|
+
directory browser: it is part of the pane rather than an overlay, and `Esc` has
|
|
84
|
+
to keep reaching the shell for `vi` to be usable.
|
|
85
|
+
|
|
53
86
|
Clicking a link in a pane opens it in your own browser rather than in a window
|
|
54
87
|
of ZeroG. Hovering one first shows where it actually goes in the status bar,
|
|
55
88
|
which matters because a terminal hyperlink can be labelled with anything. Only
|
|
@@ -63,6 +96,61 @@ sequence — this is how TUI tools such as CLI coding agents, tmux and Neovim pu
|
|
|
63
96
|
text on the clipboard, including over SSH. Reading the clipboard through OSC 52
|
|
64
97
|
is refused, so a program on a remote host cannot see what you last copied.
|
|
65
98
|
|
|
99
|
+
## The command history palette
|
|
100
|
+
|
|
101
|
+
`Ctrl+Shift+R` opens a search over the commands you have actually run, ranked so
|
|
102
|
+
the one you want is usually first: same directory beats same host, recent beats
|
|
103
|
+
frequent, something that worked beats something that failed, and something you
|
|
104
|
+
picked from this palette before beats something you merely ran. Typing matches a
|
|
105
|
+
subsequence, so `gcm` finds `git commit -m`, and the matched characters are
|
|
106
|
+
highlighted so it is clear why a row is there.
|
|
107
|
+
|
|
108
|
+
Enter puts the command on the prompt **without running it**. The command came out
|
|
109
|
+
of a store rather than from your hands a moment ago, so pressing Enter is your
|
|
110
|
+
decision — and it leaves room to change an argument, which is most of why anyone
|
|
111
|
+
reaches for history.
|
|
112
|
+
|
|
113
|
+
`Ctrl+R` is untouched. Your shell keeps its own reverse search; McFly can rebind
|
|
114
|
+
that key because it *is* the shell, and ZeroG taking it would remove
|
|
115
|
+
reverse-search from every pane including remote ones this feature cannot see.
|
|
116
|
+
|
|
117
|
+
### Turning it on
|
|
118
|
+
|
|
119
|
+
Recording is off until you switch it on in Settings under "AI & voice". It is the
|
|
120
|
+
only part of ZeroG that stores what you typed, so it is opt-in rather than a
|
|
121
|
+
default you have to find and disable.
|
|
122
|
+
|
|
123
|
+
Commands are read from the standard OSC 133 prompt marks a shell emits — the same
|
|
124
|
+
marks VS Code, kitty, WezTerm and Windows Terminal use. If you already have shell
|
|
125
|
+
integration from any of those, or from an oh-my-zsh plugin, ZeroG reads what is
|
|
126
|
+
already there and you need to add nothing. Otherwise Settings offers a snippet
|
|
127
|
+
per shell to paste into your rc file, and the panel says how many of your open
|
|
128
|
+
panes are actually reporting marks, so "did that work" has an answer.
|
|
129
|
+
|
|
130
|
+
A remote host needs the snippet installed on the remote host: the marks come from
|
|
131
|
+
the shell, and over SSH that shell is on the far side. A pane whose shell reports
|
|
132
|
+
no marks records nothing, rather than guessing from the screen and recording
|
|
133
|
+
something wrong.
|
|
134
|
+
|
|
135
|
+
### What is stored, and what is refused
|
|
136
|
+
|
|
137
|
+
Each entry holds the command, the directory and host it ran in, its exit status,
|
|
138
|
+
when it last ran, how many times, and how often you picked it. It lives in
|
|
139
|
+
`command-history.json` in ZeroG's profile directory, written with owner-only
|
|
140
|
+
permissions. "Forget all remembered commands" empties it and deletes the file.
|
|
141
|
+
|
|
142
|
+
A command that looks like it carries a credential is refused outright rather than
|
|
143
|
+
stored with the value masked — a masked entry still records that you set a
|
|
144
|
+
particular secret in a particular directory at a particular time. Refused shapes
|
|
145
|
+
include assignments to anything named like a token, key, secret or password;
|
|
146
|
+
`--password`, `--token` and `--api-key` flags; credentials inside a URL;
|
|
147
|
+
`Authorization` headers; `curl -u user:pass`; vendor-shaped tokens; and long
|
|
148
|
+
high-entropy words.
|
|
149
|
+
|
|
150
|
+
This is not a complete defence and is not claimed to be. A secret typed as a bare
|
|
151
|
+
argument to an unusual program, or piped in from `echo`, looks like ordinary text.
|
|
152
|
+
See [SECURITY.md](SECURITY.md).
|
|
153
|
+
|
|
66
154
|
## Resizing panes and the sidebar
|
|
67
155
|
|
|
68
156
|
Drag the line between two panes, or the sidebar's right edge, to change how the
|
|
@@ -74,6 +162,65 @@ a time, and Enter or a double-click puts it back in the middle. One divider
|
|
|
74
162
|
position is shared by every layout, so a split you set up in the vertical split
|
|
75
163
|
is the same split you get in the four-pane grid.
|
|
76
164
|
|
|
165
|
+
## Sharing ports over SSH
|
|
166
|
+
|
|
167
|
+
The Ports button in the rail opens a list of shared ports, grouped by the host
|
|
168
|
+
each one runs through. "Share port" asks for a host and a port, and the port is
|
|
169
|
+
then reachable as though the service were running here.
|
|
170
|
+
|
|
171
|
+
Two directions are available under "More options". The default sends a port on
|
|
172
|
+
the remote to this machine, which is what a remote dev server, database, or
|
|
173
|
+
debugger needs. The other sends a port here to the remote, for a webhook or an
|
|
174
|
+
agent on that host calling back. A row always names the side that listens first,
|
|
175
|
+
so which way a tunnel runs is never left to be inferred.
|
|
176
|
+
|
|
177
|
+
A shared port answers only on the machine that binds it, unless you tick "Share
|
|
178
|
+
on my network" — which re-exports the service to whatever network that machine is
|
|
179
|
+
attached to, and is marked `LAN` on the row so it cannot be forgotten about. A
|
|
180
|
+
port sent to the remote is bound on loopback there by default; widening it also
|
|
181
|
+
needs `GatewayPorts` enabled in that host's `sshd_config`, and the row says so
|
|
182
|
+
when the server refuses.
|
|
183
|
+
|
|
184
|
+
Each tunnel is a separate `ssh` process, which is what makes closing one exact:
|
|
185
|
+
the cross stops that tunnel and nothing else. It also means a host that
|
|
186
|
+
authenticates with a password asks once per tunnel, in the panel, and nothing
|
|
187
|
+
typed there is stored. Hosts using a key or an agent are not asked at all.
|
|
188
|
+
|
|
189
|
+
Shared ports are remembered between launches and come back listed but not
|
|
190
|
+
connected. Clicking one reconnects it — the app never opens a connection to a
|
|
191
|
+
host on its own at startup.
|
|
192
|
+
|
|
193
|
+
## AI command suggestions
|
|
194
|
+
|
|
195
|
+
Set an endpoint in Settings under "AI & voice": a base URL ending in `/v1`, a
|
|
196
|
+
model, and a key if the endpoint wants one. One field serves every provider,
|
|
197
|
+
because `chat/completions` is the request shape they all implement — a local
|
|
198
|
+
Ollama at `http://127.0.0.1:11434/v1` needs no key at all. "Test connection"
|
|
199
|
+
asks the model for a token and reports what came back, and "Refresh" lists the
|
|
200
|
+
models the endpoint says it has. A key is stored encrypted by the operating
|
|
201
|
+
system, never in the settings file, and is only ever read in the main process:
|
|
202
|
+
it is not held in the window.
|
|
203
|
+
|
|
204
|
+
Suggest asks what you want, then returns a single command with an explanation.
|
|
205
|
+
Only one command, ever — a reply naming several, or answering in prose rather
|
|
206
|
+
than the structure asked for, produces no command to run and says so. The
|
|
207
|
+
command is written to the pane you asked from, not to whichever pane is focused
|
|
208
|
+
when the answer arrives.
|
|
209
|
+
|
|
210
|
+
By default the model is told only your shell, directory and host. Turning on
|
|
211
|
+
"Send recent terminal output" also sends the tail of the focused pane, which is
|
|
212
|
+
what lets a suggestion read the error you are actually looking at — and means
|
|
213
|
+
terminal content goes to whatever endpoint you configured. The panel says which
|
|
214
|
+
of those is happening.
|
|
215
|
+
|
|
216
|
+
While output is being sent, approval cannot be turned off. Terminal output can
|
|
217
|
+
come from a remote host, and a host can print text shaped like an instruction;
|
|
218
|
+
a command chosen downstream of that must be read before it runs. The output is
|
|
219
|
+
sent as clearly delimited data with the delimiter stripped out of it, and the
|
|
220
|
+
answer is only believed if it arrives in the exact structure requested — but
|
|
221
|
+
neither of those is trusted to hold on its own, which is why the approval step
|
|
222
|
+
is not optional in that configuration.
|
|
223
|
+
|
|
77
224
|
## Transferring files over SFTP
|
|
78
225
|
|
|
79
226
|
The ⇅ button above the panes opens a two-pane transfer panel: this computer on
|
|
@@ -92,12 +239,12 @@ OSC 7 — the sequence a shell emits to report its directory — and otherwise f
|
|
|
92
239
|
the path in the prompt; it never types `pwd` into your session to find out. When
|
|
93
240
|
neither is available the panel opens at the login directory.
|
|
94
241
|
|
|
95
|
-
Select files with a click, or several with Ctrl-click or Shift-click, then Upload or Download.
|
|
242
|
+
Select files with a click, or several with Ctrl-click or Shift-click, then Upload or Download.
|
|
96
243
|
Double-click a folder to open it, or type a path into the folder box. New folder,
|
|
97
244
|
rename, and delete act on one selected item; deleting asks first, and a folder
|
|
98
|
-
must be empty, so a single click can never remove a tree. Remote folders can be
|
|
99
|
-
downloaded recursively with the system `sftp` client; uploads remain file-only,
|
|
100
|
-
so a local folder is never copied accidentally as a different job.
|
|
245
|
+
must be empty, so a single click can never remove a tree. Remote folders can be
|
|
246
|
+
downloaded recursively with the system `sftp` client; uploads remain file-only,
|
|
247
|
+
so a local folder is never copied accidentally as a different job.
|
|
101
248
|
|
|
102
249
|
Filenames containing quotes, backslashes, or the wildcard characters `* ? [ ]`
|
|
103
250
|
are refused with a message rather than acted on. The `sftp` client re-reads its
|
|
@@ -105,6 +252,67 @@ own arguments through a glob pass, and there is no encoding of those characters
|
|
|
105
252
|
that is provably correct for every command — being approximately right about
|
|
106
253
|
which file to delete is not good enough.
|
|
107
254
|
|
|
255
|
+
### Duplicating a workspace
|
|
256
|
+
|
|
257
|
+
Right-clicking a tab offers **Duplicate**, which copies the arrangement rather
|
|
258
|
+
than the sessions: the layout comes across, and each SSH pane comes across as a
|
|
259
|
+
pane waiting to be reconnected, so clicking it opens a *new* session to the same
|
|
260
|
+
host. A local pane is not copied — its shell is a process on this machine, so a
|
|
261
|
+
copy would be a different terminal rather than a duplicate of anything, and the
|
|
262
|
+
status line says how many were left behind rather than letting you notice a pane
|
|
263
|
+
missing.
|
|
264
|
+
|
|
265
|
+
## Browsing directories inside a pane
|
|
266
|
+
|
|
267
|
+
The folder button in a pane's title bar splits that pane: the terminal on one
|
|
268
|
+
side, the directories where its shell is standing on the other. Drag the divider
|
|
269
|
+
to change the balance, double-click it to centre it, or use the arrow keys when
|
|
270
|
+
it has focus. A pane remembers whether its browser was open and where the divider
|
|
271
|
+
was, per workspace and between launches.
|
|
272
|
+
|
|
273
|
+
Single-click a folder to look inside it without moving the shell.
|
|
274
|
+
**Double-click** it to take the shell there — ZeroG types the `cd` into the pane,
|
|
275
|
+
which is deliberately visible: you asked for it, and seeing the command is how
|
|
276
|
+
you know what happened. The button in the bottom-right corner does the same for
|
|
277
|
+
the directory already on screen, which is how you retry after a `cd` that was
|
|
278
|
+
refused because the pane was busy, or catch the shell up after browsing around.
|
|
279
|
+
`..` is always the first row, except at a root the shell cannot go above.
|
|
280
|
+
|
|
281
|
+
A single click waits a moment before it acts, because it has to find out whether
|
|
282
|
+
it is the first half of a double-click: browsing immediately would replace the
|
|
283
|
+
row under the pointer and the second press would land on a different one.
|
|
284
|
+
|
|
285
|
+
The browser opens on the directory the pane's shell reports, and on the login
|
|
286
|
+
directory before it has reported anything — a pane that has just connected has
|
|
287
|
+
run nothing, so there is nothing to read yet. That login directory comes from the
|
|
288
|
+
connection itself, never from a command typed into your session.
|
|
289
|
+
|
|
290
|
+
Where it lists from depends on the pane. An SSH pane lists over an SFTP
|
|
291
|
+
connection to its host, opening one if there is not already one open — the same
|
|
292
|
+
client, `~/.ssh/config`, agent and `known_hosts` the transfer panel uses, and the
|
|
293
|
+
same connection when both are looking at the same host. If the host asks for a
|
|
294
|
+
password, a key passphrase, or a decision about its host key, the browser says
|
|
295
|
+
so and the transfer panel (⇅) is where you answer: it shows the question with
|
|
296
|
+
the key fingerprint beside it, and ZeroG never answers one on your behalf. The
|
|
297
|
+
login directory that connection reports is also how a `~` in the pane's prompt
|
|
298
|
+
becomes a path. A native local pane lists the filesystem directly. A WSL pane lists the distribution through the `\\wsl.localhost\` share
|
|
299
|
+
Windows serves it on, so what you see is the distribution's own filesystem and
|
|
300
|
+
not the Windows one — and `~` is resolved by asking the distribution once, never
|
|
301
|
+
by typing `pwd` into your pane.
|
|
302
|
+
|
|
303
|
+
Two things it will refuse, with a sentence rather than in silence:
|
|
304
|
+
|
|
305
|
+
- **A pane that is not at a prompt.** A `cd` sent while `vi`, `less`, or an agent
|
|
306
|
+
has the terminal goes to that program instead. Where a shell reports the OSC 133
|
|
307
|
+
prompt marks — the same integration the command history uses — this is known
|
|
308
|
+
exactly; otherwise the shape of the last line is the best available answer.
|
|
309
|
+
- **A directory name it cannot quote for that shell.** A name containing a line
|
|
310
|
+
break, or a double quote in a Command Prompt pane, is not typed at all rather
|
|
311
|
+
than approximated.
|
|
312
|
+
|
|
313
|
+
The browser navigates; it does not move files. The SFTP panel is the surface for
|
|
314
|
+
that.
|
|
315
|
+
|
|
108
316
|
## Settings
|
|
109
317
|
|
|
110
318
|
Settings open from the gear at the bottom of the left rail, the avatar in the
|
|
@@ -148,13 +356,23 @@ about 968 MB for small at full precision; models are cached after first use.
|
|
|
148
356
|
Multilingual models add language and transcribe/translate options, which
|
|
149
357
|
English-only checkpoints reject and so do not show.
|
|
150
358
|
|
|
151
|
-
**
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
359
|
+
**Server** posts the recorded audio as a WAV file to a transcription server,
|
|
360
|
+
using the OpenAI `/v1/audio/transcriptions` shape that whisper.cpp's server, LM
|
|
361
|
+
Studio, faster-whisper-server and similar tools speak. This is the way to use a
|
|
362
|
+
model the built-in engine cannot load — a GGUF build such as
|
|
363
|
+
`unslothai/Qwen3-ASR-0.6B-GGUF` needs a llama.cpp-family runtime, so something
|
|
364
|
+
else has to host it. Any `http://` or `https://` address works: loopback, a
|
|
365
|
+
machine on the LAN such as `http://10.0.10.46:8888/v1/audio/transcriptions`, or
|
|
366
|
+
a hosted service. The field says whether the address it holds is on this machine
|
|
367
|
+
or not, because a remote one means recorded speech leaves it.
|
|
368
|
+
|
|
369
|
+
Servers that want authentication take an API key in the same panel, sent as an
|
|
370
|
+
`Authorization: Bearer` header. The key is not kept in the settings file: the
|
|
371
|
+
main process stores it encrypted through the operating system's own secret store
|
|
372
|
+
— DPAPI on Windows, Keychain on macOS, libsecret or kwallet on Linux — and hands
|
|
373
|
+
it to the renderer only for the request being made. On a system with no keyring
|
|
374
|
+
available, saving is refused rather than written in the clear, and the key can be
|
|
375
|
+
held for the session instead. Leave it empty for a local server that wants none.
|
|
158
376
|
|
|
159
377
|
Both engines share the maximum utterance length and the silence threshold, and
|
|
160
378
|
the **Try it** button on that page records a phrase and shows the transcript,
|
|
@@ -195,6 +413,11 @@ required whichever shell you start them from.
|
|
|
195
413
|
for Windows and macOS, so a C/C++ toolchain is a Linux requirement rather than a
|
|
196
414
|
general one — there, `npm install` compiles it.
|
|
197
415
|
|
|
416
|
+
### Windows desktop release
|
|
417
|
+
|
|
418
|
+
Download the latest Windows x64 installer from [GitHub Releases](https://github.com/HappyMonkeyAI/ZeroGTerm/releases). The installer adds ZeroG Terminal to the current user's applications. The portable `.exe` can be run without installation.
|
|
419
|
+
|
|
420
|
+
These binaries are unsigned alpha builds, so Windows SmartScreen may show a warning on first launch. If you downloaded the release from the official repository, choose **More info → Run anyway**. Review the release notes before installing; SSH, WSL, PowerShell, Git Bash, and any remote `screen` sessions are provided by the host system rather than bundled with the app.
|
|
198
421
|
### Linux
|
|
199
422
|
|
|
200
423
|
```bash
|
package/bin/zerogterm.cjs
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const { spawn } = require('node:child_process');
|
|
4
|
-
const path = require('node:path');
|
|
5
|
-
const electron = require('electron');
|
|
6
|
-
|
|
7
|
-
const packageRoot = path.resolve(__dirname, '..');
|
|
8
|
-
const child = spawn(electron, [packageRoot, ...process.argv.slice(2)], {
|
|
9
|
-
stdio: 'inherit'
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
child.on('error', (error) => {
|
|
13
|
-
console.error(`Failed to start ZeroG Terminal: ${error.message}`);
|
|
14
|
-
process.exitCode = 1;
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
child.on('close', (code, signal) => {
|
|
18
|
-
if (signal) {
|
|
19
|
-
process.kill(process.pid, signal);
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
process.exitCode = code ?? 1;
|
|
23
|
-
});
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require('node:child_process');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const electron = require('electron');
|
|
6
|
+
|
|
7
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
8
|
+
const child = spawn(electron, [packageRoot, ...process.argv.slice(2)], {
|
|
9
|
+
stdio: 'inherit'
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
child.on('error', (error) => {
|
|
13
|
+
console.error(`Failed to start ZeroG Terminal: ${error.message}`);
|
|
14
|
+
process.exitCode = 1;
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
child.on('close', (code, signal) => {
|
|
18
|
+
if (signal) {
|
|
19
|
+
process.kill(process.pid, signal);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
process.exitCode = code ?? 1;
|
|
23
|
+
});
|