@jhizzard/termdeck 0.2.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/LICENSE +21 -0
- package/README.md +242 -0
- package/config/config.example.yaml +58 -0
- package/config/secrets.env.example +17 -0
- package/package.json +65 -0
- package/packages/cli/src/index.js +101 -0
- package/packages/client/public/index.html +3444 -0
- package/packages/server/src/config.js +308 -0
- package/packages/server/src/database.js +130 -0
- package/packages/server/src/engram-bridge/index.js +232 -0
- package/packages/server/src/index.js +581 -0
- package/packages/server/src/rag.js +216 -0
- package/packages/server/src/session-logger.js +166 -0
- package/packages/server/src/session.js +421 -0
- package/packages/server/src/themes.js +250 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Joshua Izzard
|
|
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
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# TermDeck
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
Web-based terminal multiplexer with AI-aware session management, rich metadata overlays, and cross-project RAG integration.
|
|
6
|
+
|
|
7
|
+
Think of it as tmux in your browser — but each terminal panel shows you what project it belongs to, what the AI is doing, and pipes everything into your memory system.
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx @jhizzard/termdeck
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
That's it — the published package ships prebuilt binaries for `node-pty` and `better-sqlite3`, so you don't need a C++ toolchain for the common path (Node 20/22/24 on macOS, Linux, Windows).
|
|
18
|
+
|
|
19
|
+
### From source
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
git clone https://github.com/jhizzard/termdeck.git
|
|
23
|
+
cd termdeck
|
|
24
|
+
npm install
|
|
25
|
+
npm run dev
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Prerequisites for source builds only
|
|
29
|
+
|
|
30
|
+
If prebuilt binaries are unavailable for your platform (rare), TermDeck falls back to compiling [node-pty](https://github.com/microsoft/node-pty) locally. In that case you'll need:
|
|
31
|
+
|
|
32
|
+
- **macOS**: `xcode-select --install` (installs Xcode Command Line Tools)
|
|
33
|
+
- **Windows**: Install [Visual Studio Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) with the "Desktop development with C++" workload
|
|
34
|
+
- **Linux (Debian/Ubuntu)**: `sudo apt install build-essential python3`
|
|
35
|
+
- **Linux (Fedora)**: `sudo dnf groupinstall "Development Tools"`
|
|
36
|
+
|
|
37
|
+
If `npm install` fails with errors mentioning `node-gyp`, `gyp`, or `node-pty`, you're missing the compiler.
|
|
38
|
+
|
|
39
|
+
### macOS
|
|
40
|
+
```bash
|
|
41
|
+
npm run install:app
|
|
42
|
+
# Creates ~/Applications/TermDeck.app — double-click to launch, drag to Dock
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Windows
|
|
46
|
+
```cmd
|
|
47
|
+
install.bat
|
|
48
|
+
# Creates Start Menu + Desktop shortcuts
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Linux
|
|
52
|
+
```bash
|
|
53
|
+
npm run dev
|
|
54
|
+
# Or: node packages/cli/src/index.js
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
No terminal needed after installation — TermDeck opens your browser automatically.
|
|
58
|
+
|
|
59
|
+
## What it does
|
|
60
|
+
|
|
61
|
+
TermDeck gives you a single browser window with multiple embedded terminal panels. Each panel is a real PTY — full ANSI/VT100 support, so Claude Code, Gemini CLI, vim, htop, and any other terminal app works exactly as it would in a native terminal.
|
|
62
|
+
|
|
63
|
+
Each terminal panel has:
|
|
64
|
+
|
|
65
|
+
- **Status indicator** — green (active), purple (thinking), amber (idle), red (errored)
|
|
66
|
+
- **Type detection** — automatically identifies Claude Code, Gemini CLI, Python servers, or plain shells
|
|
67
|
+
- **Project tag** — color-coded project association
|
|
68
|
+
- **Metadata strip** — when opened, why, last commands, detected ports, request counts
|
|
69
|
+
- **Individual controls** — theme selector, focus/half/close, AI question input
|
|
70
|
+
- **Per-terminal theming** — Tokyo Night, Rose Pine Dawn, Catppuccin, Dracula, Nord, and more
|
|
71
|
+
|
|
72
|
+
## Layout modes
|
|
73
|
+
|
|
74
|
+
Designed for iMac-scale screens. Layout modes let you see the right amount of detail:
|
|
75
|
+
|
|
76
|
+
| Mode | Grid | Use case |
|
|
77
|
+
|------|------|----------|
|
|
78
|
+
| 1x1 | Single terminal | Deep work with one AI agent |
|
|
79
|
+
| 2x1 | Two columns | Half-screen split |
|
|
80
|
+
| 2x2 | 2x2 grid | Four terminals at comfortable size |
|
|
81
|
+
| 3x2 | 3x2 grid | Six terminals, monitoring mode |
|
|
82
|
+
| 2x4 | 2x4 grid | Eight terminals, tall vertical pairs |
|
|
83
|
+
| 4x2 | 4x2 grid | Eight terminals, control room |
|
|
84
|
+
| Focus | One expanded | Temporarily expand any panel |
|
|
85
|
+
| Half | One large + stack | One primary + secondary panels |
|
|
86
|
+
|
|
87
|
+
## Prompt bar
|
|
88
|
+
|
|
89
|
+
The bottom prompt bar launches new terminals:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
> bash # Plain shell
|
|
93
|
+
> claude code ~/my-project # Claude Code in a directory
|
|
94
|
+
> python3 manage.py runserver # Django dev server
|
|
95
|
+
> cc my-project # Shorthand: Claude Code + project
|
|
96
|
+
> gemini # Gemini CLI
|
|
97
|
+
> npx vitest run # One-shot command
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Select a project from the dropdown to auto-tag and auto-`cd` into the project directory.
|
|
101
|
+
|
|
102
|
+
## Configuration
|
|
103
|
+
|
|
104
|
+
The installer creates `~/.termdeck/config.yaml`. Edit it to define your projects:
|
|
105
|
+
|
|
106
|
+
```yaml
|
|
107
|
+
port: 3000
|
|
108
|
+
shell: /bin/zsh
|
|
109
|
+
defaultTheme: tokyo-night
|
|
110
|
+
|
|
111
|
+
projects:
|
|
112
|
+
my-project:
|
|
113
|
+
path: ~/code/my-project
|
|
114
|
+
defaultTheme: catppuccin-mocha
|
|
115
|
+
defaultCommand: claude
|
|
116
|
+
|
|
117
|
+
rag:
|
|
118
|
+
enabled: false
|
|
119
|
+
supabaseUrl: https://your-project.supabase.co
|
|
120
|
+
supabaseKey: your-anon-key
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## RAG integration
|
|
124
|
+
|
|
125
|
+
TermDeck has a three-layer memory system:
|
|
126
|
+
|
|
127
|
+
1. **Session memory** — what happened in each terminal session
|
|
128
|
+
2. **Project memory** — commands, file edits, and patterns shared across sessions within a project
|
|
129
|
+
3. **Developer memory** — cross-project patterns (your habits, common workflows, error resolutions)
|
|
130
|
+
|
|
131
|
+
Events are always recorded to local SQLite (`~/.termdeck/termdeck.db`). Enable Supabase sync by adding your credentials to the config file and running `config/supabase-migration.sql` in your Supabase SQL editor.
|
|
132
|
+
|
|
133
|
+
## Keyboard shortcuts
|
|
134
|
+
|
|
135
|
+
| Shortcut | Action |
|
|
136
|
+
|----------|--------|
|
|
137
|
+
| Ctrl+Shift+N | Focus prompt bar |
|
|
138
|
+
| Ctrl+Shift+1 | Layout: 1x1 |
|
|
139
|
+
| Ctrl+Shift+2 | Layout: 2x1 |
|
|
140
|
+
| Ctrl+Shift+3 | Layout: 2x2 |
|
|
141
|
+
| Ctrl+Shift+4 | Layout: 3x2 |
|
|
142
|
+
| Ctrl+Shift+5 | Layout: 2x4 |
|
|
143
|
+
| Ctrl+Shift+6 | Layout: 4x2 |
|
|
144
|
+
| Ctrl+Shift+] | Next terminal |
|
|
145
|
+
| Ctrl+Shift+[ | Previous terminal |
|
|
146
|
+
| Escape | Exit focus/half mode |
|
|
147
|
+
|
|
148
|
+
## Architecture
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
Browser (xterm.js panels)
|
|
152
|
+
| WebSocket (1 per terminal)
|
|
153
|
+
Node.js server
|
|
154
|
+
|-- Session manager (create, destroy, metadata)
|
|
155
|
+
|-- WebSocket hub (mux terminal I/O)
|
|
156
|
+
|-- REST API (CRUD, resize, themes)
|
|
157
|
+
|-- Output analyzer (status detection)
|
|
158
|
+
|-- RAG event recorder (SQLite + Supabase sync)
|
|
159
|
+
| node-pty
|
|
160
|
+
OS pseudo-terminals
|
|
161
|
+
|-- bash/zsh
|
|
162
|
+
|-- Claude Code
|
|
163
|
+
|-- python3 servers
|
|
164
|
+
|-- Gemini CLI
|
|
165
|
+
|-- any CLI tool
|
|
166
|
+
|
|
|
167
|
+
SQLite (local) --sync--> Supabase (RAG)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Security
|
|
171
|
+
|
|
172
|
+
TermDeck gives each terminal panel full shell access on your machine. It binds to `127.0.0.1` (localhost only) by default.
|
|
173
|
+
|
|
174
|
+
**Do NOT expose TermDeck to the network without authentication.** There is no built-in auth in v0.1. If you need remote access, put it behind a VPN or SSH tunnel.
|
|
175
|
+
|
|
176
|
+
## Tech stack
|
|
177
|
+
|
|
178
|
+
- **Server**: Node.js, Express, node-pty, ws, better-sqlite3
|
|
179
|
+
- **Client**: xterm.js, xterm-addon-fit, vanilla JS (no build step)
|
|
180
|
+
- **Storage**: SQLite (local), Supabase/PostgreSQL (RAG)
|
|
181
|
+
- **Themes**: 8 curated terminal color schemes
|
|
182
|
+
- **Launch**: macOS .app bundle (no terminal needed)
|
|
183
|
+
|
|
184
|
+
## How to test
|
|
185
|
+
|
|
186
|
+
After installing, verify each feature works:
|
|
187
|
+
|
|
188
|
+
1. **Launch** — Double-click TermDeck.app or run `npm run dev`. Browser should open automatically.
|
|
189
|
+
2. **Create terminals** — Type `bash` in the prompt bar and click Launch. Verify the terminal is interactive (`ls`, `pwd`, `echo hello`).
|
|
190
|
+
3. **Multiple terminals** — Open 4+ terminals. Verify they're independent.
|
|
191
|
+
4. **Layouts** — Click each layout button (1x1 through 4x2). Try Ctrl+Shift+1-6.
|
|
192
|
+
5. **Focus/Half** — Click the focus (square) and half (rectangle) buttons on a panel. Press Escape to exit.
|
|
193
|
+
6. **Keyboard nav** — Use Ctrl+Shift+] and [ to cycle between terminals.
|
|
194
|
+
7. **Metadata** — Run commands and verify "last command" updates in the metadata strip.
|
|
195
|
+
8. **Port detection** — Run `python3 -m http.server 8888`. Verify port shows in metadata and type changes to "Python Server".
|
|
196
|
+
9. **Themes** — Change themes on two terminals independently via the dropdown.
|
|
197
|
+
10. **Projects** — Select a project from the dropdown, launch a terminal. Verify it cd's to the right directory.
|
|
198
|
+
11. **Terminal exit** — Type `exit` in a terminal. Panel should dim with "Exited (0)".
|
|
199
|
+
12. **Persistence** — Restart the server. Old sessions should be marked as exited in the DB.
|
|
200
|
+
13. **Command history** — Check `GET http://localhost:3000/api/sessions/:id/history`.
|
|
201
|
+
14. **RAG events** — Check `GET http://localhost:3000/api/rag/events` to see recorded events.
|
|
202
|
+
|
|
203
|
+
## Development
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# Install dependencies
|
|
207
|
+
npm install
|
|
208
|
+
|
|
209
|
+
# Run server directly
|
|
210
|
+
npm run server
|
|
211
|
+
|
|
212
|
+
# Run via CLI (opens browser)
|
|
213
|
+
npm run dev
|
|
214
|
+
|
|
215
|
+
# The client is served as static files from packages/client/public/
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Troubleshooting
|
|
219
|
+
|
|
220
|
+
### `npm install` fails with node-gyp errors
|
|
221
|
+
|
|
222
|
+
Install the C++ compiler for your platform (see Prerequisites above), then:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
npm cache clean --force
|
|
226
|
+
rm -rf node_modules package-lock.json
|
|
227
|
+
npm install
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Terminal panels don't respond to input
|
|
231
|
+
|
|
232
|
+
Check that node-pty compiled correctly:
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
node -e "require('node-pty')"
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
If this throws an error, reinstall with: `npm rebuild node-pty`
|
|
239
|
+
|
|
240
|
+
## License
|
|
241
|
+
|
|
242
|
+
MIT
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# TermDeck Configuration
|
|
2
|
+
# Copy to ~/.termdeck/config.yaml and customize
|
|
3
|
+
|
|
4
|
+
port: 3000
|
|
5
|
+
host: 127.0.0.1
|
|
6
|
+
shell: /bin/zsh # or /bin/bash
|
|
7
|
+
|
|
8
|
+
defaultTheme: tokyo-night
|
|
9
|
+
|
|
10
|
+
# Project definitions
|
|
11
|
+
# Each project maps a name to a directory + defaults
|
|
12
|
+
# These appear in the prompt bar dropdown and enable auto-cd + default themes
|
|
13
|
+
projects:
|
|
14
|
+
# my-project:
|
|
15
|
+
# path: ~/code/my-project
|
|
16
|
+
# defaultTheme: catppuccin-mocha
|
|
17
|
+
# defaultCommand: claude # or bash, gemini, etc.
|
|
18
|
+
# another-project:
|
|
19
|
+
# path: ~/code/another-project
|
|
20
|
+
# defaultTheme: dracula
|
|
21
|
+
# defaultCommand: bash
|
|
22
|
+
|
|
23
|
+
# RAG Integration (Supabase)
|
|
24
|
+
# Multi-layer memory: session -> project -> developer
|
|
25
|
+
# Events are always recorded to local SQLite.
|
|
26
|
+
#
|
|
27
|
+
# Secrets live in ~/.termdeck/secrets.env (see config/secrets.env.example).
|
|
28
|
+
# Values below use ${VAR} substitution so this file stays free of secrets.
|
|
29
|
+
rag:
|
|
30
|
+
enabled: false
|
|
31
|
+
supabaseUrl: ${SUPABASE_URL}
|
|
32
|
+
supabaseKey: ${SUPABASE_SERVICE_ROLE_KEY}
|
|
33
|
+
openaiApiKey: ${OPENAI_API_KEY}
|
|
34
|
+
anthropicApiKey: ${ANTHROPIC_API_KEY}
|
|
35
|
+
# developerId: your-username (defaults to OS username)
|
|
36
|
+
syncIntervalMs: 10000
|
|
37
|
+
|
|
38
|
+
# Engram bridge — how /api/ai/query talks to @jhizzard/engram.
|
|
39
|
+
# direct — server embeds + queries Supabase itself (default, preserves v0.1 behavior)
|
|
40
|
+
# webhook — POST to a running `engram serve` HTTP webhook (see engramWebhookUrl)
|
|
41
|
+
# mcp — spawn the local `engram` binary and talk JSON-RPC over stdio
|
|
42
|
+
engramMode: direct
|
|
43
|
+
engramWebhookUrl: http://localhost:37778/engram
|
|
44
|
+
# engramBinary: engram # override path to the @jhizzard/engram CLI for mcp mode
|
|
45
|
+
|
|
46
|
+
# Supabase table names (created by config/supabase-migration.sql)
|
|
47
|
+
tables:
|
|
48
|
+
session: engram_session_memory
|
|
49
|
+
project: engram_project_memory
|
|
50
|
+
developer: engram_developer_memory
|
|
51
|
+
commands: engram_commands
|
|
52
|
+
|
|
53
|
+
# Per-session markdown logs written to ~/.termdeck/sessions/ on session exit.
|
|
54
|
+
# Zero-config: works without Supabase / OpenAI. Optional LLM summary requires
|
|
55
|
+
# ANTHROPIC_API_KEY (env or rag.anthropicApiKey). CLI flag: `termdeck --session-logs`.
|
|
56
|
+
sessionLogs:
|
|
57
|
+
enabled: false
|
|
58
|
+
summaryModel: claude-haiku-4-5
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# TermDeck secrets (F2.2)
|
|
2
|
+
# Copy this file to ~/.termdeck/secrets.env and fill in the values.
|
|
3
|
+
# ~/.termdeck/secrets.env should NEVER be committed — it lives outside the repo.
|
|
4
|
+
#
|
|
5
|
+
# These keys are referenced from ~/.termdeck/config.yaml via ${VAR} substitution,
|
|
6
|
+
# so you can edit yaml freely without accidentally leaking a secret.
|
|
7
|
+
|
|
8
|
+
# Supabase project that backs the RAG / Engram memory tables.
|
|
9
|
+
SUPABASE_URL=
|
|
10
|
+
SUPABASE_SERVICE_ROLE_KEY=
|
|
11
|
+
|
|
12
|
+
# OpenAI embeddings — only needed when rag.engramMode is `direct`.
|
|
13
|
+
OPENAI_API_KEY=
|
|
14
|
+
|
|
15
|
+
# Anthropic — powers the session-log summarizer (T2.5) and any future
|
|
16
|
+
# LLM-backed features that run server-side.
|
|
17
|
+
ANTHROPIC_API_KEY=
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jhizzard/termdeck",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Browser-based terminal multiplexer with metadata overlays, panel flashback memory recall, and AI-aware session management",
|
|
5
|
+
"bin": {
|
|
6
|
+
"termdeck": "./packages/cli/src/index.js"
|
|
7
|
+
},
|
|
8
|
+
"main": "packages/cli/src/index.js",
|
|
9
|
+
"files": [
|
|
10
|
+
"packages/cli/src/**",
|
|
11
|
+
"packages/server/src/**",
|
|
12
|
+
"packages/client/public/**",
|
|
13
|
+
"config/config.example.yaml",
|
|
14
|
+
"config/secrets.env.example",
|
|
15
|
+
"LICENSE",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"workspaces": [
|
|
19
|
+
"packages/server",
|
|
20
|
+
"packages/client",
|
|
21
|
+
"packages/cli"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"dev": "node packages/server/src/index.js",
|
|
25
|
+
"server": "node packages/server/src/index.js",
|
|
26
|
+
"start": "NODE_ENV=production node packages/cli/src/index.js",
|
|
27
|
+
"install:app": "bash install.sh"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"express": "^4.18.2",
|
|
31
|
+
"ws": "^8.16.0",
|
|
32
|
+
"@homebridge/node-pty-prebuilt-multiarch": "^0.13.1",
|
|
33
|
+
"better-sqlite3": "^12.9.0",
|
|
34
|
+
"uuid": "^9.0.0",
|
|
35
|
+
"yaml": "^2.3.4",
|
|
36
|
+
"chalk": "^5.3.0",
|
|
37
|
+
"open": "^10.0.0"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"terminal",
|
|
41
|
+
"multiplexer",
|
|
42
|
+
"xterm",
|
|
43
|
+
"pty",
|
|
44
|
+
"web-terminal",
|
|
45
|
+
"tmux-alternative",
|
|
46
|
+
"claude-code",
|
|
47
|
+
"memory",
|
|
48
|
+
"flashback",
|
|
49
|
+
"rag",
|
|
50
|
+
"devtools"
|
|
51
|
+
],
|
|
52
|
+
"repository": {
|
|
53
|
+
"type": "git",
|
|
54
|
+
"url": "git+https://github.com/jhizzard/termdeck.git"
|
|
55
|
+
},
|
|
56
|
+
"homepage": "https://github.com/jhizzard/termdeck#readme",
|
|
57
|
+
"bugs": {
|
|
58
|
+
"url": "https://github.com/jhizzard/termdeck/issues"
|
|
59
|
+
},
|
|
60
|
+
"author": "Joshua Izzard",
|
|
61
|
+
"license": "MIT",
|
|
62
|
+
"engines": {
|
|
63
|
+
"node": ">=18.0.0"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// TermDeck CLI launcher
|
|
4
|
+
// Usage: termdeck [--port 3000] [--no-open]
|
|
5
|
+
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const { execSync } = require('child_process');
|
|
8
|
+
|
|
9
|
+
// Parse CLI args
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
const flags = {};
|
|
12
|
+
for (let i = 0; i < args.length; i++) {
|
|
13
|
+
if (args[i] === '--port' && args[i + 1]) {
|
|
14
|
+
flags.port = parseInt(args[i + 1], 10);
|
|
15
|
+
i++;
|
|
16
|
+
} else if (args[i] === '--no-open') {
|
|
17
|
+
flags.noOpen = true;
|
|
18
|
+
} else if (args[i] === '--session-logs') {
|
|
19
|
+
flags.sessionLogs = true;
|
|
20
|
+
} else if (args[i] === '--help' || args[i] === '-h') {
|
|
21
|
+
console.log(`
|
|
22
|
+
TermDeck - Web-based terminal multiplexer
|
|
23
|
+
|
|
24
|
+
Usage:
|
|
25
|
+
termdeck Start with defaults (port 3000)
|
|
26
|
+
termdeck --port 8080 Start on custom port
|
|
27
|
+
termdeck --no-open Don't auto-open browser
|
|
28
|
+
termdeck --session-logs Write per-session markdown logs to ~/.termdeck/sessions/
|
|
29
|
+
|
|
30
|
+
Keyboard shortcuts (in browser):
|
|
31
|
+
Ctrl+Shift+N Focus prompt bar
|
|
32
|
+
Ctrl+Shift+1-6 Switch layout (1x1 → 4x2)
|
|
33
|
+
Ctrl+Shift+] / [ Next / previous terminal
|
|
34
|
+
Escape Exit focus/half mode
|
|
35
|
+
|
|
36
|
+
Config:
|
|
37
|
+
~/.termdeck/config.yaml Server + project + RAG configuration
|
|
38
|
+
~/.termdeck/termdeck.db Session history (SQLite)
|
|
39
|
+
`);
|
|
40
|
+
process.exit(0);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Load and start server
|
|
45
|
+
const { createServer, loadConfig } = require(path.join(__dirname, '..', '..', 'server', 'src', 'index.js'));
|
|
46
|
+
|
|
47
|
+
// Flag-driven env vars must be set BEFORE loadConfig() so any module that
|
|
48
|
+
// reads process.env at require-time sees them.
|
|
49
|
+
if (flags.sessionLogs) {
|
|
50
|
+
process.env.TERMDECK_SESSION_LOGS = '1';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const config = loadConfig();
|
|
54
|
+
if (flags.port) config.port = flags.port;
|
|
55
|
+
if (flags.sessionLogs) {
|
|
56
|
+
config.sessionLogs = { ...(config.sessionLogs || {}), enabled: true };
|
|
57
|
+
console.log('[cli] session logs enabled — writing to ~/.termdeck/sessions/ on panel exit');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const { server } = createServer(config);
|
|
61
|
+
const port = config.port || 3000;
|
|
62
|
+
const host = config.host || '127.0.0.1';
|
|
63
|
+
const url = `http://${host}:${port}`;
|
|
64
|
+
|
|
65
|
+
server.listen(port, host, async () => {
|
|
66
|
+
console.log(`
|
|
67
|
+
╔══════════════════════════════════════╗
|
|
68
|
+
║ TermDeck v0.2.0 ║
|
|
69
|
+
╠══════════════════════════════════════╣
|
|
70
|
+
║ ${url.padEnd(34)} ║
|
|
71
|
+
║ ║
|
|
72
|
+
║ Ctrl+C to stop ║
|
|
73
|
+
╚══════════════════════════════════════╝
|
|
74
|
+
`);
|
|
75
|
+
|
|
76
|
+
// Skip auto-open in Codespaces/CI (port forwarding handles it)
|
|
77
|
+
const isCodespaces = !!process.env.CODESPACES || !!process.env.GITHUB_CODESPACE_TOKEN;
|
|
78
|
+
const isCI = !!process.env.CI;
|
|
79
|
+
|
|
80
|
+
if (!flags.noOpen && !isCodespaces && !isCI) {
|
|
81
|
+
try {
|
|
82
|
+
const { platform } = require('os');
|
|
83
|
+
const cmd = platform() === 'darwin' ? 'open'
|
|
84
|
+
: platform() === 'win32' ? 'start'
|
|
85
|
+
: 'xdg-open';
|
|
86
|
+
execSync(`${cmd} ${url}`, { stdio: 'ignore' });
|
|
87
|
+
} catch (err) {
|
|
88
|
+
console.error('[cli] auto-open browser failed:', err.message);
|
|
89
|
+
console.log(` Open ${url} in your browser\n`);
|
|
90
|
+
}
|
|
91
|
+
} else if (isCodespaces) {
|
|
92
|
+
console.log(` Codespaces detected — use the Ports tab to open the browser\n`);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Graceful shutdown
|
|
97
|
+
process.on('SIGINT', () => {
|
|
98
|
+
console.log('\n Shutting down TermDeck...');
|
|
99
|
+
server.close(() => process.exit(0));
|
|
100
|
+
setTimeout(() => process.exit(1), 3000);
|
|
101
|
+
});
|