pi-deck 0.1.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 +122 -0
- package/bin/pi-deck.js +86 -0
- package/dist/server.js +7295 -0
- package/dist/server.js.map +7 -0
- package/package.json +76 -0
- package/packages/client/dist/assets/MarkdownContent-BP8uvTu3.js +2 -0
- package/packages/client/dist/assets/index-1WD5ZoeL.css +1 -0
- package/packages/client/dist/assets/index-BIGMLGdI.js +422 -0
- package/packages/client/dist/index.html +17 -0
- package/packages/client/dist/pi.svg +4 -0
package/README.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Pi-Deck
|
|
2
|
+
|
|
3
|
+
A web interface for [Pi](https://github.com/badlogic/pi-mono), the terminal coding agent. This is a personal project I built for my own workflow — it lets me use Pi from a browser instead of the terminal, with multi-workspace support so I can manage several projects at once.
|
|
4
|
+
|
|
5
|
+
> **Note:** This is personal tooling, not a general-purpose product. It works for my setup and I make no guarantees about stability, compatibility, or support. Feel free to fork or take ideas from it.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Multi-workspace tabs** — open multiple project directories side by side
|
|
10
|
+
- **Real-time streaming** — chat with Pi via WebSocket, see responses as they arrive
|
|
11
|
+
- **Tool visualization** — watch tool calls execute with live output
|
|
12
|
+
- **Thinking blocks** — collapsible display for reasoning model internals
|
|
13
|
+
- **Session management** — switch between sessions, pick models per workspace
|
|
14
|
+
- **Image support** — paste or drag images into prompts
|
|
15
|
+
- **Persistent state** — open workspaces, theme, and drafts sync across devices via SQLite
|
|
16
|
+
- **Directory allowlist** — control which directories are accessible from the UI
|
|
17
|
+
|
|
18
|
+
## Stack
|
|
19
|
+
|
|
20
|
+
- **Frontend:** React 19, Vite, TailwindCSS
|
|
21
|
+
- **Backend:** Express, WebSocket, Pi SDK
|
|
22
|
+
- **Storage:** SQLite for UI state
|
|
23
|
+
|
|
24
|
+
## Install from npm
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install -g pi-deck
|
|
28
|
+
pi-deck
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or run without installing:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx pi-deck
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Requires Node.js 20+ and an API key configured (e.g. `ANTHROPIC_API_KEY`).
|
|
38
|
+
|
|
39
|
+
Open `http://localhost:9741` in your browser.
|
|
40
|
+
|
|
41
|
+
### CLI options
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
pi-deck # start the server on port 9741
|
|
45
|
+
pi-deck --port 8080 # use a custom port
|
|
46
|
+
pi-deck --build # rebuild before starting (for local dev)
|
|
47
|
+
pi-deck --help # show all options
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Development setup
|
|
51
|
+
|
|
52
|
+
Clone the repo and install dependencies:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
git clone https://github.com/user/pi-deck.git
|
|
56
|
+
cd pi-deck
|
|
57
|
+
npm install
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Dev mode (hot-reload)
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm run dev # frontend on :9740, backend on :9741
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Production mode (no hot-reload)
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npm run build # build everything
|
|
70
|
+
npm start # start the server on :9741
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Local CLI
|
|
74
|
+
|
|
75
|
+
To use the `pi-deck` command from your local checkout:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npm run build
|
|
79
|
+
npm link # creates a global 'pi-deck' symlink
|
|
80
|
+
pi-deck # works from any directory
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
To remove: `npm unlink -g pi-deck`
|
|
84
|
+
|
|
85
|
+
## Publishing to npm
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npm run build # builds shared → server → client → bundles server with esbuild
|
|
89
|
+
npm pack # creates a .tgz to inspect before publishing
|
|
90
|
+
npm publish # publish to the npm registry
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The published package includes a bundled server (`dist/server.js`) and the pre-built client SPA (`packages/client/dist/`). Workspace dependencies are inlined by esbuild; only runtime dependencies (`express`, `better-sqlite3`, etc.) are installed by npm.
|
|
94
|
+
|
|
95
|
+
## Configuration
|
|
96
|
+
|
|
97
|
+
Create a config file at `~/.config/pi-deck/config.json`:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"port": 9741,
|
|
102
|
+
"host": "0.0.0.0",
|
|
103
|
+
"allowedDirectories": ["~/projects", "~/code"]
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Or use environment variables: `PORT`, `HOST`, `PI_ALLOWED_DIRS` (colon-separated).
|
|
108
|
+
|
|
109
|
+
## Running as a service
|
|
110
|
+
|
|
111
|
+
I run this on a Mac mini with Tailscale for always-on access from any device.
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
npm run service:install # install as launchd service (starts on login)
|
|
115
|
+
npm run service:uninstall # remove it
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Logs go to `~/Library/Logs/pi-deck/`.
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
MIT
|
package/bin/pi-deck.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { dirname, join, resolve } from 'path';
|
|
5
|
+
import { existsSync } from 'fs';
|
|
6
|
+
import { execSync, fork } from 'child_process';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
10
|
+
const ROOT = resolve(__dirname, '..');
|
|
11
|
+
|
|
12
|
+
const bundledServer = join(ROOT, 'dist/server.js');
|
|
13
|
+
const clientDist = join(ROOT, 'packages/client/dist');
|
|
14
|
+
|
|
15
|
+
// Parse CLI flags
|
|
16
|
+
const args = process.argv.slice(2);
|
|
17
|
+
const helpFlag = args.includes('--help') || args.includes('-h');
|
|
18
|
+
const buildFlag = args.includes('--build');
|
|
19
|
+
const portFlag = args.indexOf('--port');
|
|
20
|
+
const portValue = portFlag !== -1 ? args[portFlag + 1] : undefined;
|
|
21
|
+
|
|
22
|
+
if (helpFlag) {
|
|
23
|
+
console.log(`
|
|
24
|
+
pi-deck - Start the Pi-Deck server
|
|
25
|
+
|
|
26
|
+
Usage:
|
|
27
|
+
pi-deck [options]
|
|
28
|
+
|
|
29
|
+
Options:
|
|
30
|
+
--build Build before starting (if not already built)
|
|
31
|
+
--port <n> Override server port (default: 9741)
|
|
32
|
+
-h, --help Show this help message
|
|
33
|
+
|
|
34
|
+
The server will serve the built client UI and expose the WebSocket API.
|
|
35
|
+
Run 'npm run build' in the project root first, or use --build.
|
|
36
|
+
`);
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Check if build exists, offer to build if not
|
|
41
|
+
const serverBuilt = existsSync(bundledServer);
|
|
42
|
+
const clientBuilt = existsSync(clientDist);
|
|
43
|
+
|
|
44
|
+
if (!serverBuilt || !clientBuilt) {
|
|
45
|
+
if (buildFlag) {
|
|
46
|
+
console.log('[pi-deck] Building project...');
|
|
47
|
+
try {
|
|
48
|
+
execSync('npm run build', { cwd: ROOT, stdio: 'inherit' });
|
|
49
|
+
} catch {
|
|
50
|
+
console.error('[pi-deck] Build failed. Fix errors and retry.');
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
if (!serverBuilt) console.error(`[pi-deck] Server not built. Missing: ${bundledServer}`);
|
|
55
|
+
if (!clientBuilt) console.error(`[pi-deck] Client not built. Missing: ${clientDist}`);
|
|
56
|
+
console.error('[pi-deck] Run "npm run build" first, or use "pi-deck --build".');
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Set port via env if provided
|
|
62
|
+
if (portValue) {
|
|
63
|
+
process.env.PORT = portValue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Tell the bundled server where the client dist lives
|
|
67
|
+
process.env.PI_DECK_CLIENT_DIST = clientDist;
|
|
68
|
+
|
|
69
|
+
// Start the server
|
|
70
|
+
console.log('[pi-deck] Starting Pi-Deck server...');
|
|
71
|
+
const child = fork(bundledServer, [], {
|
|
72
|
+
cwd: ROOT,
|
|
73
|
+
stdio: 'inherit',
|
|
74
|
+
env: { ...process.env },
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
child.on('exit', (code) => {
|
|
78
|
+
process.exit(code ?? 0);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Forward signals for clean shutdown
|
|
82
|
+
for (const sig of ['SIGINT', 'SIGTERM']) {
|
|
83
|
+
process.on(sig, () => {
|
|
84
|
+
child.kill(sig);
|
|
85
|
+
});
|
|
86
|
+
}
|