npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

shellbase

v0.16.0

Published

내 컴퓨터 터미널(특히 Claude Code 세션)을 폰 브라우저로 실시간 접속하게 해주는 데스크톱 에이전트

Downloads

980

Readme

shellbase

내 컴퓨터 터미널(특히 Claude Code 세션)을 폰 브라우저로 실시간으로 보고 조작할 수 있게 해주는 데스크톱 에이전트입니다.

설치

Node.js 22 이상이 필요해요 (실시간 접속 기능이 Node 의 최신 WebSocket 기능을 써요 — 20 이하면 shellbase start 가 바로 에러 메시지를 보여주고 멈춰요). node --version 으로 확인해보세요.

npm install -g shellbase

사용법

# 구글 계정으로 로그인 (처음이면 자동으로 가입도 됨)
shellbase login

# 지금 폴더에서 터미널 세션 시작
shellbase start

# 다른 폴더에서 시작하고 싶으면
shellbase start --dir ~/projects/my-app --name "내 노트북"

shellbase start 를 실행한 뒤 shellbase.web.connectbase.world 에 같은 계정으로 접속하면 내 데스크톱 목록에 뜹니다. 선택하면 데스크톱에 접속 승인 알림이 뜨고, 승인하면 폰에서 그대로 타이핑할 수 있어요.

명령어

| 명령어 | 설명 | |---|---| | shellbase login | 구글 계정으로 로그인 | | shellbase logout | 로그아웃 | | shellbase whoami | 현재 로그인된 계정 확인 | | shellbase start [--dir <path>] [--name <name>] [--require-approval] [--no-restore] [--no-hook] | 터미널 세션 시작 | | shellbase hook install / remove / status | Claude Code 작업 완료 알림 켜기/끄기/확인 | | shellbase notify | "작업이 끝났다"고 폰에 알림 (Claude Code 훅이 자동 실행 — 직접 칠 일은 없어요) |

작업이 끝나면 폰으로 알려줘요

Claude Code 에게 긴 작업을 시켜놓고 폰을 내려놓아도, 끝나면 알 수 있어요.

  • 폰·PC 의 세션 목록과 상단 칩에 주황 점(●) 이 붙어요 — 그 세션에 들어가 보면 사라집니다
  • 앱을 열어둔 상태라면 알림창도 띄울 수 있어요 (명령창 Ctrl+Shift+P → "작업 완료 알림 켜기")
  • 앱을 아예 닫아둔 사이에 끝난 작업도 ● 로 남아 있어서, 나중에 열어보면 바로 보여요

끝난 걸 알아채는 방법은 두 가지고, 정확한 쪽이 우선입니다.

| 방법 | 정확도 | 준비 | |---|---|---| | Claude Code 훅 | 정확 (Claude 가 대답을 마치는 바로 그 순간) | shellbase hook install 한 번 | | 화면 출력 보고 짐작 | 어림짐작 | 없음 (훅이 없을 때 자동으로 대신 씀) |

shellbase start 를 처음 실행하면 훅을 걸지 한 번 물어봐요. y 를 누르면 ~/.claude/settings.json 에 알림 한 줄이 들어갑니다 — 원래 있던 설정은 그대로 두고, 고치기 전 같은 자리에 settings.json.shellbase-backup 으로 백업도 남겨요. 이미 켜져 있던 Claude Code 는 다시 시작해야 적용돼요.

shellbase hook status     # 지금 걸려 있는지 확인
shellbase hook install    # 걸기
shellbase hook remove     # 빼기 (다른 설정은 안 건드려요)
shellbase start --no-hook # 물어보지 않고 시작

훅이 없을 때 쓰는 짐작 방식은 "한동안 화면이 쉼 없이 바쁘다가(3초 이상, 글자 2KB 이상) 갑자기 4초간 조용해지면 끝난 것" 으로 봅니다. 그래서 ls 처럼 짧은 명령이나 타이핑에는 반응하지 않지만, Claude Code 가 아닌 긴 명령(빌드 등)이 끝나도 알림이 올 수 있어요.

접속 승인 정책

기본은 "내 계정으로 로그인했으면 바로 입력 가능" 입니다. 이 도구의 보안 경계는 ConnectBase 계정(구글 로그인)이에요 — 터미널 화면은 원래부터 계정 주인만 볼 수 있었고(세션 키가 내 계정만 읽을 수 있는 자리에 있어요), 화면만 봐도 민감한 내용은 다 보이기 때문에 "보기는 되고 타이핑만 막기"는 실익이 크지 않았습니다. 화면 앞에 사람이 없는 서버·도커에서는 승인할 방법 자체가 없기도 했고요.

노트북처럼 한 단계 더 두고 싶다면 --require-approval 로 예전처럼 매번 이 컴퓨터에서 y 를 눌러야 입력이 되게 할 수 있어요.

shellbase start --require-approval

여러 세션을 한 프로세스가 관리해요

shellbase start 를 한 번 실행하면 프로세스 하나가 뜨고, 그 안에서 터미널(세션)을 여러 개 관리해요. 폰에서 + 새 세션 으로 늘려도 프로세스는 그대로 하나입니다.

  • 세션 2개 기준 메모리 약 85MB (예전엔 세션마다 프로세스를 띄워서 200MB였어요)
  • 실시간 연결도 세션 수와 무관하게 1개만 사용해요
  • 프로젝트마다 세션을 하나씩 켜두고 폰 상단 칩으로 왔다갔다 하면 됩니다
  • Ctrl+C 를 누르면 그 프로세스의 모든 세션이 함께 정상 종료돼요 (열려 있던 목록은 기억해둬요 — 아래 참고)
  • 터미널을 새로 열어 shellbase start 를 또 실행해도 됩니다 (프로세스가 하나 더 생기고, 이미 켜져 있는 세션을 중복으로 복구하지는 않아요)

재시작하면 세션이 자동으로 돌아와요

열려 있던 세션 목록은 ~/.shellbase/open-sessions.json 에 기록돼요. 컴퓨터·컨테이너가 재시작되거나 Ctrl+C 로 껐다가 shellbase start 를 다시 실행하면, 그때 열려 있던 세션들을 자동으로 다시 띄워요.

shellbase start                  # 이전 세션들도 함께 복구
shellbase start --no-restore     # 복구하지 않고 이 폴더 세션 하나만
  • 폰에서 일부러 끈 세션은 복구 대상에서 빠져요 (다시 열리지 않아요)
  • 폴더가 사라졌거나, 이미 켜져 있는 세션은 조용히 건너뜁니다

폰에서 세션 열기 · 전환 · 끄기 (컴퓨터에 손 안 대고)

세션이 하나라도 켜져 있으면, 그다음부터는 폰에서 전부 할 수 있어요.

| 하고 싶은 것 | 폰에서 하는 법 | |---|---| | 세션 하나 더 열기 | 목록 화면의 + 새 세션, 또는 터미널 화면의 기기 이름(▾) → + 이 컴퓨터에서 새 세션 열기 (열리면 그 세션으로 바로 넘어가요) | | 잠깐 쓸 터미널 열기 | 터미널 화면 위쪽의 + 임시 터미널 — 지금 폴더에 하나 더 띄워요 (목록에 안 남고, 나가면 사라져요) | | 세션 갈아타기 | 터미널 화면 위쪽의 기기 이름(▾) 탭 → 원하는 세션 선택 | | 세션 끄기 | 목록의 전원 아이콘, 또는 터미널 화면의 기기 이름(▾) → 이 세션 끄기 | | 화면만 닫기 | ← 목록 으로 나가기 — 컴퓨터의 세션은 계속 살아있어요 | | 파일 열어보기·고치기 | 📁 폴더 찾기 → 목록에서 파일을 탭하면 에디터가 열려요 (수정 후 저장) | | 세션 이름 바꾸기 | 기기 이름(▾) → 세션 옆 연필 버튼 |

  • 끄기는 진짜로 꺼요. 컴퓨터에서 돌아가던 그 터미널이 종료되고 목록에서도 자동으로 사라져요 (Ctrl+C 를 누른 것과 같아요). 프로세스가 죽었는데 목록에만 남아있는 항목은 휴지통 아이콘으로 지울 수 있어요 — 그건 목록만 정리하는 버튼이에요.
  • 남의 세션은 열거나 끌 수 없어요. 요청을 보낸 쪽이 그 세션의 암호화 키를 가지고 있는지 먼저 확인하는데, 그 키는 내 계정으로만 읽을 수 있는 자리에 있거든요.
  • 폰에서 연 세션도 같은 프로세스가 관리해요. 그래서 컴퓨터에서 Ctrl+C 를 누르면 모든 세션이 함께 종료돼요(그 대신 다음 실행 때 자동 복구됩니다). 세션을 하나만 끄고 싶으면 폰에서 그 세션의 ✕ 를 쓰세요 — 나머지 세션은 그대로 유지돼요.

임시 터미널 (0.10.0+)

Claude Code 가 화면을 꽉 채우고 있을 때 git status 같은 걸 잠깐 쳐보려고 터미널을 하나 더 열곤 하는데, 그렇게 연 터미널이 목록에 계속 쌓이는 게 문제였어요. 터미널 화면 위쪽의 + 임시 터미널 로 연 것은 한 번 쓰고 버리는 터미널이에요.

  • 세션 목록에도, 상단 칩 줄에도 안 보여요 (지금 보고 있는 동안만 칩으로 보입니다)
  • 그 화면에서 나가면 스스로 종료돼요 — 다만 방금까지 뭔가 돌고 있었으면 끄지 않고 목록에 남깁니다 (하던 일이 조용히 사라지면 안 되니까요)
  • 컴퓨터를 재시작해도 되살아나지 않아요 (정식 세션만 복구 대상)
  • 브라우저를 그냥 닫아버린 경우엔, 아무도 안 보고 화면도 조용한 채로 5분이 지나면 컴퓨터가 알아서 정리해요
  • 계속 쓰고 싶어지면 임시 · 계속 쓰기 를 누르세요 — 정식 세션이 되고 이름의 (임시) 표시도 떨어져요
  • 임시 터미널에는 Claude 자동 시작이 적용되지 않아요 (명령 하나 치려고 여는 것이라 빈 터미널로 열립니다)

파일 보기·편집

📁 폴더 찾기 목록에는 폴더와 함께 파일도 나와요. 파일을 탭하면 편집기가 열리고, 고친 뒤 저장 을 누르면 그 컴퓨터의 파일이 실제로 바뀝니다. 기기에 따라 편집기가 다르게 열려요:

  • 노트북·데스크톱(넓은 화면 + 마우스): VS Code 와 같은 모나코 — 찾기·바꾸기(Ctrl+F), 커서 여러 개, 줄 접기, 미니맵, Ctrl+S 저장이 그대로 동작해요. 파일을 처음 열 때만 내려받습니다.

  • 폰: 가벼운 편집기(CodeMirror) — 터치 우선이라 좁은 화면에서 편하고, Tab 들여쓰기와 Ctrl+S 저장도 됩니다.

  • 모나코에서 JS/TS 타입 기반 자동완성은 빠져 있어요 (그 기능 파일 하나가 6.6MB 라 웹 스토리지 한도를 넘습니다). 색칠·단축키·검색은 모두 정상이에요.

  • 512KB 까지, 글자 파일만 열려요 (사진·동영상은 아래의 보기 창으로 열립니다)

  • 저장은 같은 폴더의 임시 파일에 먼저 쓴 뒤 교체해서, 저장 도중 끊겨도 원본이 깨지지 않아요

  • 파일 내용은 터미널 화면과 똑같이 세션 키로 암호화해서 주고받아요

  • 에디터는 파일을 처음 열 때만 따로 내려받아요 — 터미널만 쓰면 그만큼 안 받습니다

사진·동영상 보기 (0.14.0+)

폴더 찾기에서 사진(🖼)·동영상(🎬)·소리(🎵)·PDF(📕) 를 탭하면 편집기 대신 보기 창이 열려서 폰에서 그대로 보입니다. 동영상은 재생·되감기까지 돼요.

  • 열리는 형식: png jpg gif webp avif bmp heic tif · mp4 mov m4v webm mkv avi · mp3 m4a aac wav ogg opus flac · pdf
  • 64MB 까지, 그리고 3MB 가 넘으면 "받을까요?" 를 한 번 물어봐요 — 파일이 터미널 화면과 같은 통로로 오기 때문에, 큰 동영상을 잘못 누르면 그동안 터미널이 굼떠집니다
  • 받는 동안 진행 막대가 보이고 그만두기를 누르면 곧바로 멈춰요 (컴퓨터 쪽도 바로 손을 뗍니다)
  • 속도는 초당 300KB 남짓이에요 (실측) — 3MB 사진이면 10초쯤, 10MB 동영상이면 35초쯤
  • 사진은 눌러서 원래 크기 ↔ 화면 맞추기를 오갈 수 있어요
  • 파일은 32KB 조각으로 나눠 세션 키로 암호화해서 오고, 폰에서만 다시 하나로 붙습니다 — 중간에 저장되는 곳은 없어요
  • 브라우저가 못 여는 형식(아이폰 밖에서의 HEIC, mkv·avi 등)은 그렇게 알려주고, 경로를 터미널에 넣어주는 버튼을 보여줘요 — 그 자리에서 ffmpeg 로 바꾸면 됩니다

폰에서 사진·스크린샷 첨부 (0.7.0+)

폰 화면의 클립(📎) 버튼(PC 는 상단 바)으로 사진을 고르면, 사진이 이 컴퓨터의 ~/.shellbase/images/ 에 파일로 저장되고 그 파일 경로가 터미널에 자동으로 입력됩니다. 이어서 "이 화면 좀 봐줘" 처럼 쓰고 엔터를 누르면 Claude Code 가 그 사진을 읽어요.

  • 폰에서는 📎 버튼을 누르면 「사진 찍기 / 사진 보관함」이 함께 떠요 — 방금 찍은 스크린샷은 보관함에 있습니다
  • PC 는 스크린샷 파일을 터미널 위로 끌어다 놓으면(드래그&드롭) 바로 첨부돼요 (📎 버튼은 폰 전용)
  • 스크린샷을 복사해서 붙여넣기(Ctrl+V) 해도 첨부돼요 (PC·폰 공통)
  • 사진은 보내기 전에 폰에서 긴 변 1568px 로 줄여서 올라가요(전송이 빠르고 인식 정확도는 그대로)
  • 저장된 사진은 하루가 지나면 자동으로 지워져요, 파일 권한은 본인만 읽기(600)
  • 사진도 터미널 화면과 똑같이 세션 키로 암호화해서 전송돼요

폰에서 마이크로 말하기 (음성 → 글자)

폰 화면 오른쪽 아래 마이크 버튼을 누르고 말하면 글자로 바뀝니다. 기본값은 말한 뒤 바로 보내기(엔터까지 자동) 라서, 「완료」만 누르면 그대로 실행돼요 (Claude Code 에게 말로 시킬 때 편합니다). 확인하고 보내고 싶으면 명령창의 말한 뒤 바로 보내기 끄기 로 예전 방식(받아쓴 글자를 보여주고 보내기 ↵ 를 누르는 방식)으로 바꿀 수 있어요.

받아쓰는 곳은 두 군데고, 준비된 쪽이 자동으로 쓰입니다. 폰 화면에 어느 쪽인지 표시돼요.

| | 내 컴퓨터에서 받아쓰기 | 브라우저가 받아쓰기 | |---|---|---| | 언제 | 이 컴퓨터에 음성인식 서버가 떠 있을 때 | 그 밖의 모든 경우 | | 준비 | 서버를 직접 띄워야 함 | 필요 없음 | | 목소리가 나가는 곳 | 안 나감 (내 컴퓨터에서 끝) | 브라우저 회사 서버 (크롬=구글, 사파리=애플) | | 품질 | 좋음 | 보통 |

  • 음성인식 서버는 시작할 때 자동으로 찾아요: SHELLBASE_STT_URL → http://127.0.0.1:5005 → http://172.17.0.1:5005(도커 안에서 본 호스트) 순서
  • 주소가 다르면 SHELLBASE_STT_URL=http://127.0.0.1:9000 처럼 지정하고 다시 시작하세요. 인식 언어는 SHELLBASE_STT_LANGS=ko,en 으로 바꿀 수 있어요 (기본 ko)
  • 일부러 브라우저 쪽을 쓰고 싶으면(또는 5005 포트를 다른 프로그램이 쓰고 있으면) shellbase start --no-stt 또는 SHELLBASE_NO_STT=1
  • 필요한 서버 형식: GET /health 와 POST /transcribe_json ({audio_base64, languages} → {ok, text}) — whisper 계열 서버면 대개 이 형태입니다

⚠️ 도커로 돌릴 때, 마지막 세션을 폰에서 끄면 도커가 다시 띄워요. 세션이 0개가 되면 프로세스가 종료되는데, --restart unless-stopped 는 정상 종료(exit 0)에도 컨테이너를 자동 재시작하기 때문이에요 (실제로 확인한 동작). 즉 마지막 세션 끄기는 사실상 재시작이 됩니다. 세션이 여러 개일 때 하나만 끄는 건 프로세스가 계속 살아있으니 그대로 꺼져요. 컨테이너를 완전히 내리려면 컴퓨터에서 docker stop shellbase-agent 를 쓰세요.

터미널은 셸 시작 파일(rc)을 읽습니다

폰에서 여는 터미널도 ~/.bashrc(zsh 는 ~/.zshrc) 같은 시작 파일을 그대로 읽습니다. 프롬프트, ll 같은 줄임말, 시작 파일에서 늘려둔 PATH 가 컴퓨터 앞에 앉았을 때와 똑같이 나옵니다.

0.14.1 에서 되돌린 기본값입니다. 0.14.0 한 버전 동안만 반대로(읽지 않게) 동작했어요. 개인 별칭이 컨테이너에 딸려가 깨지는 문제(bash: gnuls: command not found) 때문이었는데, 시작 파일은 PATH 를 늘리는 사실상 유일한 통로이기도 해서 대가가 훨씬 컸습니다 — 에이전트를 systemd 서비스나 런처로 띄운 컴퓨터에서는 물려받을 환경 자체가 최소 PATH 라, ~/bin 이나 /usr/local/go/bin 에 있는 gh·go 같은 명령이 폰에서 영영 안 보이게 됩니다. 0.14.0 을 쓰시다 프롬프트가 bash-5.2$ 로 바뀌고 명령이 사라졌다면 0.14.1 로 올리세요.

일부러 개인 설정을 떼고 맨 셸로 띄우고 싶다면(여러 사람이 같은 홈 폴더를 공유하는 컨테이너 등) SHELLBASE_NO_SHELL_RC=1 shellbase start … 로 켜세요. 그러면 bash --norc --noprofile, zsh --no-rcs, fish --no-config, PowerShell -NoProfile 로 뜨고 프롬프트도 꾸밈 없는 기본값(bash-5.2$)이 됩니다. 이때는 에이전트를 켤 때의 환경변수(PATH 포함)만 물려받으므로, 필요한 경로는 에이전트를 켜는 쪽에 미리 넣어두세요.

참고

  • node-pty 를 사용해서 설치 시 네이티브 모듈을 컴파일합니다. macOS는 Xcode Command Line Tools, Linux는 build-essential(또는 배포판의 동급 패키지), Windows는 Visual Studio Build Tools가 필요할 수 있어요.
  • 폰이 (재)접속하면 지금 화면 그대로 복원돼요. 에이전트가 화면 상태를 따로 들고 있다가 그대로 보내주기 때문에, Claude Code 같은 전체화면 앱을 보다가 잠깐 끊겼다 돌아와도 화면이 깨지지 않아요 (이전 300줄까지 함께 복원).
  • 터미널 내용은 기기별 키로 암호화돼서 전송되고, 모바일에서 접속을 시도할 때마다 데스크톱에서 직접 승인해야 입력이 가능합니다.

⚠️ shellbase start 는 컴퓨터가 꺼지거나 재부팅되면 같이 꺼져요

이건 각자의 컴퓨터에서 직접 관리해야 하는 부분입니다 — ShellBase 서비스가 대신 재시작해주지 않아요. shellbase start 를 실행해둔 터미널을 닫거나, 컴퓨터를 껐다 켜거나, 프로세스가 죽으면 그 세션은 끝나고, 다시 접속하려면 직접 shellbase start 를 다시 실행해야 합니다.

컴퓨터가 꺼지지 않는 이상 자동으로 살아있게 하고 싶다면(예: 항상 켜져 있는 리눅스 서버), 아래처럼 OS의 자동 재시작 기능을 직접 설정하면 됩니다. 실제로 테스트해서 확인한 방법이에요:

Linux (systemd, 실제 검증됨) — 권장

도커로 감싸는 것보다 이 방법을 권합니다. 컨테이너 안에서는 그 터미널이 호스트의 docker·systemctl· 다른 컨테이너·호스트 서비스에 손을 댈 수 없어서, 정작 컴퓨터를 관리하려고 폰에서 접속했을 때 막힙니다. systemd 로 띄우면 재부팅 자동 복구는 똑같이 되면서 터미널 권한은 온전합니다.

mkdir -p ~/.config/systemd/user
cat > ~/.config/systemd/user/shellbase.service << 'EOF'
[Unit]
Description=ShellBase desktop agent
After=network-online.target

[Service]
Environment=PATH=/usr/local/bin:/usr/bin:/bin:%h/.nvm/current/bin
ExecStart=%h/.local/bin/shellbase start --dir %h
Restart=always
RestartSec=3

[Install]
WantedBy=default.target
EOF

systemctl --user daemon-reload
systemctl --user enable --now shellbase.service

주의할 점 3가지 (직접 겪은 문제라 적어둡니다):

  1. ExecStart 의 shellbase 경로는 which shellbase 로 직접 확인해서 넣으세요 — systemd 서비스는 평소 터미널의 PATH를 그대로 물려받지 않아서, node/shellbase를 못 찾는 경우가 흔해요. (Environment=PATH=... 에도 같은 폴더를 넣어야 해요.)
  2. 로그인 세션 없이(원격 SSH 접속도 안 하고) 완전히 백그라운드로 계속 떠있게 하려면 loginctl enable-linger $(whoami) 도 한 번 실행해야 해요. 안 하면 로그아웃할 때 같이 꺼져요.
  3. 메모리 지킴이(earlyoom)가 도는 컴퓨터라면 0.14.2 이상을 쓰세요. 지킴이 설정에는 보통 "빌드 도구를 먼저 죽여라"는 뜻으로 --prefer ^(cc1|gcc|node|npm|vite|tsc|...)$ 가 들어 있는데, 이 규칙은 명령줄이 아니라 프로세스 이름만 봅니다 — Node 로 만든 것은 전부 이름이 node 라 에이전트가 수십 MB 만 쓰고 있어도 1순위 사살 대상이 돼요(실측: oom_score 800 + 이름 보너스 300 = 1100 으로, 500MB 쓰는 프로세스보다 높았습니다). 에이전트가 죽으면 그 안의 세션이 전부 함께 죽습니다. 0.14.2 부터는 프로세스 이름을 shellbase 로 바꿔서 이 규칙에 안 걸려요.

승인 옵션은 넣지 마세요 — 기본이 "내 계정이면 바로 입력 가능"이라 무인 서버에 그대로 맞습니다. (--require-approval 을 넣으면 접속할 때마다 이 컴퓨터에서 y 를 눌러야 하는데, 화면을 안 보는 서버에서는 사실상 승인을 못 하게 돼요.)

macOS

launchd 로 같은 걸 할 수 있어요 (~/Library/LaunchAgents/ 에 .plist 등록, KeepAlive: true). 아직 저희가 macOS에서 직접 검증은 못 했어요 — 해보시고 문제 있으면 알려주세요.

Windows

작업 스케줄러(Task Scheduler)에서 "로그온 시 시작" + "실패 시 다시 시작" 옵션으로 등록하면 비슷하게 됩니다. 아직 저희가 Windows에서 직접 검증은 못 했어요.

Docker (Linux, 실제 검증됨) — 격리가 꼭 필요할 때만

⚠️ 컨테이너 안 터미널은 호스트 시스템에 손이 닿지 않습니다. 파일 작업(프로젝트 편집·빌드·git)은 홈 폴더를 마운트하므로 100% 동일하지만, docker/systemctl/다른 컨테이너/호스트 서비스는 못 씁니다 (도커의 정상적인 격리 동작). 컴퓨터 관리까지 폰에서 하려면 위의 systemd 방식을 쓰세요. /var/run/docker.sock 을 마운트하면 도커 제어는 가능해지지만, 그 순간 컨테이너가 호스트 전체를 조종할 수 있게 되어 격리의 의미가 사라집니다 — 권하지 않습니다.

컨테이너 안은 이 컴퓨터의 실제 환경과 분리돼 있어서, 홈 폴더를 통째로 볼륨(-v)으로 연결해야 git 설정·SSH 키·진짜 작업 파일들이 컨테이너 밖과 똑같이 보여요. 아래는 실제로 빌드해서 재부팅 시나리오 까지 검증한 구성이에요.

# Dockerfile
FROM node:22-bookworm-slim

RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential python3 git openssh-client ca-certificates \
    && rm -rf /var/lib/apt/lists/*

RUN npm install -g shellbase@latest

ENTRYPOINT ["shellbase"]
CMD ["start"]
docker build -t shellbase-agent .

docker run -d \
  --name shellbase-agent \
  --restart unless-stopped \
  --user $(id -u):$(id -g) \
  -v $HOME:$HOME \
  -e HOME=$HOME \
  shellbase-agent \
  start --dir $HOME --name "내 서버 (Docker)"

주의할 점 3가지 (직접 겪은 문제라 적어둡니다):

  1. Node 22 이상 이미지를 써야 해요. node:20-... 로 빌드하면 실시간 접속이 조용히 SSE 모드로 떨어져서 shellbase start 가 "네트워크가 막혔다"는 헷갈리는 에러를 내고 죽어요 — (0.1.5부터는 시작 시 Node 버전을 먼저 확인해서 바로 알려줘요.)
  2. --user $(id -u):$(id -g) 를 꼭 넣으세요. 안 넣으면 컨테이너가 root로 돌아서, 터미널 안에서 만들거나 수정한 파일이 호스트에서는 root 소유가 돼버려요(내 계정으로 못 지우고 수정 못 하는 파일이 생김).
  3. --require-approval 은 넣지 마세요. detached 컨테이너는 y 를 입력할 TTY가 없어서 승인을 못 해요. 기본값(내 계정이면 바로 입력 가능)이 이 상황에 맞습니다.

재부팅 시 자동 복구는 도커 데몬이 담당해요 — systemctl is-enabled docker 로 enabled 인지 확인하세요(보통 기본값). unless-stopped 는 컴퓨터가 재부팅되면서 데몬이 다시 뜰 때 "그때 돌아가고 있던" 컨테이너를 자동으로 복구해줘요(직접 docker stop 으로 멈춰뒀던 건 복구 안 해요 — 의도된 동작이에요). 강제 종료(kill -9, OOM 등)로 죽는 경우도 자동 재시작되는 것까지 확인했어요.