@buzzni/saycode-cli 0.8.2 → 0.9.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 CHANGED
@@ -285,6 +285,107 @@ emoji의 표시 폭도 반영합니다. 링크는 파이프 출력에서도 목
285
285
  표시되는 인자는 허용 목록(`command`, `file_path`, `pattern`, `query` 등)만 거칩니다 — 도구 인자에
286
286
  섞여 들어온 비밀 값이 터미널에 찍히지 않도록 하기 위해서입니다.
287
287
 
288
+ ## 셀프호스트 서버 (`saycode server`)
289
+
290
+ GUI 없는 머신(Debian/Ubuntu, macOS — Windows는 `run`만)에서 Saycode 서버와 중계를 직접 운영합니다. 소유자 1명용이며,
291
+ 서버 머신 자신도 작업 머신이 됩니다. 휴대폰·Desktop·이 CLI와 다른 작업 머신이 이 서버에 붙습니다.
292
+
293
+ **준비물**: Node 20 이상. Linux는 `sudo apt install openssl python3 make g++`가 필요합니다. openssl이 없으면 서버가 시작
294
+ 직후 멈춥니다. 빌드 도구는 아키텍처와 관계없이(x64·arm64) `happy-cli`의 `node-pty`를 소스에서 빌드하는 데 씁니다. 서버 머신도
295
+ 자기 daemon을 위해 `happy-cli`를 설치하므로 함께 필요합니다. 에이전트를 쓰려면 각 머신에서 Claude Code·Codex 로그인이 필요합니다.
296
+
297
+ **일반 사용자로 실행하세요.** daemon은 에이전트를 권한 확인 없이 실행하는데, Claude Code는 root에서 이 모드를 거절합니다.
298
+ 그래서 root로 띄운 머신에서는 대화가 시작되지 않습니다(`init`·`run`·`status`가 경고합니다). root로만 운영해야 하는 서버는
299
+ `saycode server run --no-daemon`으로 중계만 맡기고, 대화는 일반 사용자로 붙인 작업 머신에서 실행하세요.
300
+
301
+ ```bash
302
+ saycode server init # 고정된 @buzzni/happy-server 릴리스 설치. 다른 버전·.tgz는 --runtime <spec>
303
+ saycode server run # 포그라운드. 기본 127.0.0.1:3005, Ctrl+C로 전부 정리
304
+ saycode server install # 상시 서비스: Linux systemd user unit, macOS LaunchAgent
305
+ sudo loginctl enable-linger $USER # Linux: 로그인 없이 부팅 때 시작 (install이 필요할 때 안내)
306
+ saycode server status # 상태·공개 주소·이 머신 온라인 여부
307
+ saycode server logs --follow # stop | start | uninstall 도 있습니다
308
+ ```
309
+
310
+ 데이터는 `~/.saycode/server`(`--data-dir`로 변경, 절대경로)에 있습니다. 비밀은 `secrets.v1.json`(권한 600),
311
+ 서비스 로그는 `logs/server.out.log`입니다. `install`은 실행한 셸의 PATH를 저장하므로 node·claude·codex 위치를 바꾸면 다시 실행하세요.
312
+ `install`은 systemd user 세션에 접근할 수 있어야 합니다. `su`·`sudo`로 바꾼 셸이나 systemd가 없는 컨테이너에서는 설치하지 않고
313
+ 이유를 알려 줍니다. 그때는 `run`을 tmux·컨테이너·시스템 서비스로 직접 감독하세요.
314
+
315
+ ### 외부에 공개하기
316
+
317
+ 서버는 외부 포트를 하나(front door)만 엽니다. TLS는 앞단 프록시나 터널이 맡습니다. 외부 인터페이스에 바인드하려면
318
+ `--public-url`(클라이언트가 접속할 origin)이 필요하고, 사설망이 아닌 `http://` 주소는 `--allow-insecure-http` 없이는 거부됩니다.
319
+
320
+ 아래 앞단 설정은 예시입니다. 도메인·터널 주소는 환경에 맞게 바꾸세요.
321
+
322
+ | 방식 | 서버 | 앞단 |
323
+ |---|---|---|
324
+ | Caddy (도메인·자동 TLS) | `saycode server install --public-url https://saycode.example.org --trust-proxy` | `saycode.example.org { reverse_proxy 127.0.0.1:3005 }` |
325
+ | Cloudflare Tunnel | `saycode server install --public-url https://<터널 주소> --trust-proxy` | `cloudflared tunnel --url http://127.0.0.1:3005` |
326
+ | zrok | `saycode server install --public-url https://<share 주소> --trust-proxy` | `zrok share public http://127.0.0.1:3005` (고정 주소는 reserved share) |
327
+ | Tailscale·사내망 | `saycode server install --host 0.0.0.0 --public-url http://<사설 IP>:3005` | 없음 |
328
+
329
+ `--trust-proxy`는 앞단이 넣은 `X-Forwarded-For`를 믿고 요청 상한을 실제 접속 주소별로 적용합니다. 이 헤더는 같은 머신
330
+ (127.0.0.1·::1)에서 들어온 연결에서만 믿습니다. 다른 머신에서 직접 들어온 요청의 헤더는 이 옵션을 켜도 덮어씁니다. 그래서
331
+ 앞단 프록시는 서버와 같은 머신에 두세요.
332
+
333
+ ### 작업 머신 붙이기
334
+
335
+ ```bash
336
+ # 새 머신 (SSH·스크립트처럼 터미널이 없어도 연결 코드를 출력하고 기다립니다)
337
+ npm i -g @buzzni/happy-cli
338
+ happy auth login --server https://saycode.example.org
339
+
340
+ # 서버에서 승인 (또는 self-host 로그인이 된 다른 기기에서 `saycode machines approve '<코드>'`)
341
+ saycode server approve 'happy://terminal?…'
342
+
343
+ # 새 머신
344
+ happy daemon start
345
+ saycode server machines # 서버에서 전체 머신 확인
346
+ ```
347
+
348
+ 계정 비밀은 그 머신의 1회용 키로 봉인돼 전달되며 셸 명령·히스토리에 남지 않습니다. 연결 코드는 한 번만 쓰이고
349
+ 승인하지 않으면 10분 뒤 만료됩니다.
350
+
351
+ ### 휴대폰·Desktop·다른 컴퓨터의 CLI
352
+
353
+ ```bash
354
+ saycode server connect # QR + 연결 코드 출력
355
+ ```
356
+
357
+ - 휴대폰: Saycode 앱으로 QR을 스캔합니다.
358
+ - Desktop: 시작 화면 `개인 사용` 아래 `셀프호스트 서버에 연결`에 코드를 붙여넣습니다.
359
+ - CLI: `saycode login --connect '<코드>'` — 이후 명령은 `SAYCODE_SERVER_URL` 없이 그 서버를 씁니다.
360
+
361
+ 연결 코드는 **계정 전체 권한**입니다. 내 기기에만 보여 주세요.
362
+
363
+ ### 보안과 회수
364
+
365
+ - 서버는 소유자 키로만 로그인을 받고, 인증 전 요청에 주소·키별 상한을 둡니다.
366
+ - `saycode server rotate-tokens`(서버를 멈춘 뒤)는 발급된 모든 토큰을 무효로 합니다. 다시 시작하면 서버 머신은 스스로 붙고,
367
+ 다른 머신은 `happy auth login --server … --force` 후 다시 승인, 휴대폰·Desktop은 새 연결 코드로 다시 연결합니다.
368
+ - 한계: 승인된 작업 머신은 계정 키를 받으므로 머신 하나만 골라 회수할 수는 없습니다. 기기를 잃으면 `rotate-tokens`로
369
+ 토큰을 끊고, 계정 키 자체가 새었다고 판단되면 데이터 폴더를 새로 만들어(새 계정) 다시 시작해야 합니다.
370
+
371
+ ### 업그레이드
372
+
373
+ ```bash
374
+ saycode server stop # 서비스로 운영 중이면 (포그라운드 run이면 Ctrl+C)
375
+ npm i -g @buzzni/saycode-cli # 새 CLI
376
+ saycode server init # 새 CLI가 고정한 서버·happy-cli로 교체합니다. 비밀·데이터·머신 ID는 그대로입니다
377
+ saycode server start # 또는 saycode server run
378
+ ```
379
+
380
+ 새 CLI만 설치하면 서버가 쓰는 런타임은 바뀌지 않습니다. `init`을 다시 실행해야 교체됩니다. 작업 머신은 각자
381
+ `npm i -g @buzzni/happy-cli` 후 `happy daemon start`로 올립니다.
382
+
383
+ ### 오래 방치된 세션 정리
384
+
385
+ 24시간 동안 사용자 활동·실행 중인 작업·답변 대기·백그라운드 작업이 없는 대화는 그 머신의 daemon이 다시 확인한 뒤 멈춥니다.
386
+ 대화 기록은 남고 다시 보내면 이어집니다. 서버 전체에서 끄려면 `SAYCODE_SERVER_IDLE_REAPER=off`로 서버를 실행하고,
387
+ 머신 하나만 끄려면 그 머신 daemon에 `HAPPY_DAEMON_SESSION_IDLE_REAPER_DISABLED=1`을 줍니다.
388
+
288
389
  ## 아직 안 되는 것
289
390
 
290
391
  프로젝트 생성·기존 worktree 목록 관리/삭제·코드리뷰·배포·커넥터 커맨드, 원격 터미널(PTY), 마우스 클릭.
@@ -3,7 +3,7 @@
3
3
  The `saycode` binary is distributed as a single bundled file. The packages
4
4
  below are compiled into it and remain under their own licenses.
5
5
 
6
- 28 package(s).
6
+ 31 package(s).
7
7
 
8
8
  ## @noble/hashes@2.2.0
9
9
 
@@ -144,6 +144,32 @@ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
144
144
  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
145
145
  ```
146
146
 
147
+ ## dijkstrajs@1.0.3
148
+
149
+ License: MIT
150
+
151
+ ```
152
+ ```
153
+ Dijkstra path-finding functions. Adapted from the Dijkstar Python project.
154
+
155
+ Copyright (C) 2008
156
+ Wyatt Baldwin <self@wyattbaldwin.com>
157
+ All rights reserved
158
+
159
+ Licensed under the MIT license.
160
+
161
+ http://www.opensource.org/licenses/mit-license.php
162
+
163
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
164
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
165
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
166
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
167
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
168
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
169
+ THE SOFTWARE.
170
+ ```
171
+ ```
172
+
147
173
  ## engine.io-client@6.6.6
148
174
 
149
175
  License: MIT
@@ -1001,6 +1027,33 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1001
1027
  THE SOFTWARE.
1002
1028
  ```
1003
1029
 
1030
+ ## pngjs@5.0.0
1031
+
1032
+ License: MIT
1033
+
1034
+ ```
1035
+ pngjs2 original work Copyright (c) 2015 Luke Page & Original Contributors
1036
+ pngjs derived work Copyright (c) 2012 Kuba Niegowski
1037
+
1038
+ Permission is hereby granted, free of charge, to any person obtaining a copy
1039
+ of this software and associated documentation files (the "Software"), to deal
1040
+ in the Software without restriction, including without limitation the rights
1041
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1042
+ copies of the Software, and to permit persons to whom the Software is
1043
+ furnished to do so, subject to the following conditions:
1044
+
1045
+ The above copyright notice and this permission notice shall be included in
1046
+ all copies or substantial portions of the Software.
1047
+
1048
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1049
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1050
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1051
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1052
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1053
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1054
+ THE SOFTWARE.
1055
+ ```
1056
+
1004
1057
  ## process-nextick-args@2.0.1
1005
1058
 
1006
1059
  License: MIT
@@ -1027,6 +1080,22 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1027
1080
  SOFTWARE.**
1028
1081
  ```
1029
1082
 
1083
+ ## qrcode@1.5.4
1084
+
1085
+ License: MIT
1086
+
1087
+ ```
1088
+ The MIT License (MIT)
1089
+
1090
+ Copyright (c) 2012 Ryan Day
1091
+
1092
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
1093
+
1094
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
1095
+
1096
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1097
+ ```
1098
+
1030
1099
  ## readable-stream@2.3.8
1031
1100
 
1032
1101
  License: MIT