vivream 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 +87 -0
- package/bin/cli.js +123 -0
- package/package.json +30 -0
- package/vivream-server.tar.gz +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Vivream
|
|
2
|
+
|
|
3
|
+
**Brain-dump in. Blueprint out.**
|
|
4
|
+
|
|
5
|
+
A local AI workbench that turns your raw ideas into structured plans — powered by your own Claude Code, Codex, or Agy CLI. No cloud account needed. Completely free.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/vivream)
|
|
8
|
+
[](https://github.com/sponsors/AppSoApp)
|
|
9
|
+
[](https://ko-fi.com/appsoapplication)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx vivream
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Opens automatically at `http://localhost:3001`.
|
|
20
|
+
|
|
21
|
+
## Requirements
|
|
22
|
+
|
|
23
|
+
- **Node.js ≥ 20**
|
|
24
|
+
- One of the following AI runtimes:
|
|
25
|
+
- [Claude Code](https://claude.ai/code) (recommended)
|
|
26
|
+
- [OpenAI Codex CLI](https://github.com/openai/codex)
|
|
27
|
+
- [Agy](https://github.com/antigravityai/agy)
|
|
28
|
+
- **Or** enter a BYOK API key inside the app under Settings
|
|
29
|
+
|
|
30
|
+
## How It Works
|
|
31
|
+
|
|
32
|
+
1. Brain-dump your thoughts into the entry box
|
|
33
|
+
2. Let the AI organize them into a structured plan
|
|
34
|
+
3. Save sessions, compare ideas, and generate pitch decks
|
|
35
|
+
|
|
36
|
+
All processing happens on your machine using your own AI credentials. No data leaves your device.
|
|
37
|
+
|
|
38
|
+
## Support Development
|
|
39
|
+
|
|
40
|
+
Vivream is free and open to use. If it saves you time, consider sponsoring:
|
|
41
|
+
|
|
42
|
+
- [GitHub Sponsors](https://github.com/sponsors/AppSoApp)
|
|
43
|
+
- [Ko-fi](https://ko-fi.com/appsoapplication)
|
|
44
|
+
|
|
45
|
+
## Contact
|
|
46
|
+
|
|
47
|
+
appsoapplication@gmail.com · [Issues](https://github.com/AppSoApp/Vivream/issues)
|
|
48
|
+
|
|
49
|
+
## License
|
|
50
|
+
|
|
51
|
+
MIT
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 한국어
|
|
56
|
+
|
|
57
|
+
**두뇌 덤프 → 블루프린트 완성.**
|
|
58
|
+
|
|
59
|
+
내 Claude Code / Codex / Agy CLI 로 구동되는 로컬 AI 워크벤치. 클라우드 계정 불필요. 완전 무료.
|
|
60
|
+
|
|
61
|
+
### 시작하기
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npx vivream
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`http://localhost:3001` 이 자동으로 열립니다.
|
|
68
|
+
|
|
69
|
+
### 필요 사항
|
|
70
|
+
|
|
71
|
+
- **Node.js ≥ 20**
|
|
72
|
+
- 아래 중 하나의 AI 런타임:
|
|
73
|
+
- [Claude Code](https://claude.ai/code) (권장)
|
|
74
|
+
- [OpenAI Codex CLI](https://github.com/openai/codex)
|
|
75
|
+
- [Agy](https://github.com/antigravityai/agy)
|
|
76
|
+
- 또는 앱 내 설정에서 BYOK API 키 입력
|
|
77
|
+
|
|
78
|
+
### 후원
|
|
79
|
+
|
|
80
|
+
Vivream 은 무료입니다. 도움이 됐다면 후원을 고려해 주세요:
|
|
81
|
+
|
|
82
|
+
- [GitHub Sponsors](https://github.com/sponsors/AppSoApp)
|
|
83
|
+
- [Ko-fi](https://ko-fi.com/appsoapplication)
|
|
84
|
+
|
|
85
|
+
### 문의
|
|
86
|
+
|
|
87
|
+
appsoapplication@gmail.com · [이슈](https://github.com/AppSoApp/Vivream/issues)
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const { spawn, spawnSync } = require('child_process');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const net = require('net');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
|
|
10
|
+
const PKG_ROOT = path.join(__dirname, '..');
|
|
11
|
+
const PKG_JSON = require(path.join(PKG_ROOT, 'package.json'));
|
|
12
|
+
const VERSION = PKG_JSON.version;
|
|
13
|
+
|
|
14
|
+
// npm excludes node_modules/ from published packages unconditionally,
|
|
15
|
+
// so the standalone server is shipped as a tarball and extracted here on first run.
|
|
16
|
+
const BUNDLE_PATH = path.join(PKG_ROOT, 'vivream-server.tar.gz');
|
|
17
|
+
const CACHE_DIR = path.join(os.homedir(), '.vivream', 'cache', VERSION);
|
|
18
|
+
const SERVER_PATH = path.join(CACHE_DIR, 'server.js');
|
|
19
|
+
|
|
20
|
+
const DEFAULT_PORT = 3001;
|
|
21
|
+
|
|
22
|
+
const isKo = /^ko/.test(process.env.LANG || process.env.LC_ALL || process.env.VIVREAM_LANG || '');
|
|
23
|
+
|
|
24
|
+
const MSG = {
|
|
25
|
+
extracting: isKo ? ' 번들 추출 중 (최초 1회)...' : ' Extracting bundle (first run only)...',
|
|
26
|
+
starting: isKo ? ' Vivream 시작 중...' : ' Starting Vivream...',
|
|
27
|
+
ready: (port) => isKo
|
|
28
|
+
? `\n ✓ 준비 완료 → http://localhost:${port}\n\n 종료: Ctrl+C\n 문의: appsoapplication@gmail.com\n`
|
|
29
|
+
: `\n ✓ Ready → http://localhost:${port}\n\n Quit: Ctrl+C\n Contact: appsoapplication@gmail.com\n`,
|
|
30
|
+
noCli: isKo
|
|
31
|
+
? '\n ⚠ 로컬 AI CLI 미감지 (Claude Code / Codex / Agy).\n 설치 후 재실행하거나, 앱 설정에서 BYOK API 키를 입력하세요.\n'
|
|
32
|
+
: '\n ⚠ No local AI CLI detected (Claude Code / Codex / Agy).\n Install one and restart, or enter a BYOK API key inside the app.\n',
|
|
33
|
+
portBusy: (p) => isKo ? ` 포트 ${p} 사용 중 — 다음 포트 시도...` : ` Port ${p} in use — trying next...`,
|
|
34
|
+
error: isKo
|
|
35
|
+
? ' 서버 시작 실패. Node.js ≥20 이 설치되어 있는지 확인하세요.'
|
|
36
|
+
: ' Failed to start server. Ensure Node.js ≥20 is installed.',
|
|
37
|
+
extractError: isKo
|
|
38
|
+
? ' 번들 추출 실패. 재설치를 시도하세요: npm install -g vivream'
|
|
39
|
+
: ' Failed to extract bundle. Try reinstalling: npm install -g vivream',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
function ensureExtracted() {
|
|
43
|
+
if (fs.existsSync(SERVER_PATH)) return;
|
|
44
|
+
if (!fs.existsSync(BUNDLE_PATH)) {
|
|
45
|
+
process.stderr.write(MSG.extractError + '\n');
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
process.stdout.write(MSG.extracting + '\n');
|
|
49
|
+
fs.mkdirSync(CACHE_DIR, { recursive: true });
|
|
50
|
+
const result = spawnSync('tar', ['-xzf', BUNDLE_PATH, '-C', CACHE_DIR], { stdio: 'inherit' });
|
|
51
|
+
if (result.status !== 0) {
|
|
52
|
+
process.stderr.write(MSG.extractError + '\n');
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function findFreePort(start) {
|
|
58
|
+
return new Promise((resolve) => {
|
|
59
|
+
const srv = net.createServer();
|
|
60
|
+
srv.listen(start, '127.0.0.1', () => {
|
|
61
|
+
const { port } = srv.address();
|
|
62
|
+
srv.close(() => resolve(port));
|
|
63
|
+
});
|
|
64
|
+
srv.on('error', () => resolve(findFreePort(start + 1)));
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function openBrowser(port) {
|
|
69
|
+
const url = `http://localhost:${port}`;
|
|
70
|
+
const args =
|
|
71
|
+
process.platform === 'darwin' ? ['open', [url]] :
|
|
72
|
+
process.platform === 'win32' ? ['cmd', ['/c', 'start', '', url]] :
|
|
73
|
+
['xdg-open', [url]];
|
|
74
|
+
try { spawnSync(args[0], args[1], { stdio: 'ignore' }); } catch { /* ignore */ }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function cliExists(name) {
|
|
78
|
+
const r = spawnSync(name, ['--version'], { stdio: 'ignore', shell: false });
|
|
79
|
+
return r.status === 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function main() {
|
|
83
|
+
ensureExtracted();
|
|
84
|
+
|
|
85
|
+
if (!['claude', 'codex', 'agy'].some(cliExists)) {
|
|
86
|
+
process.stderr.write(MSG.noCli);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const port = await findFreePort(DEFAULT_PORT);
|
|
90
|
+
if (port !== DEFAULT_PORT) process.stdout.write(MSG.portBusy(DEFAULT_PORT) + '\n');
|
|
91
|
+
process.stdout.write(MSG.starting + '\n');
|
|
92
|
+
|
|
93
|
+
const server = spawn(process.execPath, [SERVER_PATH], {
|
|
94
|
+
cwd: CACHE_DIR,
|
|
95
|
+
env: { ...process.env, PORT: String(port), HOSTNAME: '127.0.0.1', NODE_ENV: 'production' },
|
|
96
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
let ready = false;
|
|
100
|
+
|
|
101
|
+
const handleReady = () => {
|
|
102
|
+
if (ready) return;
|
|
103
|
+
ready = true;
|
|
104
|
+
process.stdout.write(MSG.ready(port));
|
|
105
|
+
setTimeout(() => openBrowser(port), 400);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
server.stdout.on('data', (d) => {
|
|
109
|
+
if (/ready|started|listening/i.test(d.toString())) handleReady();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Fallback: open browser after 3s regardless
|
|
113
|
+
setTimeout(handleReady, 3000);
|
|
114
|
+
|
|
115
|
+
server.on('error', () => { process.stderr.write(MSG.error + '\n'); process.exit(1); });
|
|
116
|
+
server.on('exit', (code) => { if (code && code !== 0) process.exit(code); });
|
|
117
|
+
|
|
118
|
+
const shutdown = () => { server.kill('SIGTERM'); setTimeout(() => process.exit(0), 500); };
|
|
119
|
+
process.on('SIGINT', shutdown);
|
|
120
|
+
process.on('SIGTERM', shutdown);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
main().catch((e) => { process.stderr.write(String(e) + '\n'); process.exit(1); });
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vivream",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Brain-dump in. Blueprint out. — Local AI workbench powered by your own Claude / Codex / Agy CLI",
|
|
5
|
+
"keywords": ["ai", "claude", "brain-dump", "workbench", "local-first", "mindmap", "prompt"],
|
|
6
|
+
"homepage": "https://github.com/AppSoApp/Vivream",
|
|
7
|
+
"bugs": {
|
|
8
|
+
"url": "https://github.com/AppSoApp/Vivream/issues",
|
|
9
|
+
"email": "appsoapplication@gmail.com"
|
|
10
|
+
},
|
|
11
|
+
"author": {
|
|
12
|
+
"name": "AppSoApp",
|
|
13
|
+
"email": "appsoapplication@gmail.com"
|
|
14
|
+
},
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"bin": {
|
|
17
|
+
"vivream": "./bin/cli.js"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"bin/",
|
|
21
|
+
"vivream-server.tar.gz"
|
|
22
|
+
],
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=20.0.0"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/AppSoApp/Vivream.git"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
Binary file
|