Skip to content

Repository files navigation

Agent Deck

MIT License

Mac 에서 실행 중인 Codex CLI / Claude CLI 를 tmux 세션으로 관리하고, 모바일 브라우저에서 원격으로 생성·접속·삭제하는 개인용 웹 앱. 아래의 Controller는 Agent Deck 웹 서버와 세션 관리자를 함께 실행하는 로컬 프로세스를 뜻함.

  • Controller 는 localhost 에만 bind 됨. 외부 접속은 Microsoft Dev Tunnels를 사용함.
  • 로그인은 관리자 비밀번호 + 표준 TOTP 인증 앱 결합.
  • 브라우저를 닫아도, 인증이 만료되어도 tmux 안의 CLI 작업은 계속 실행된다.
  • 앱이 만들지 않은 tmux 세션은 어떤 경우에도 건드리지 않는다 (prefix + @agent_deck_uuid 이중 검증).

AI에게 설치 맡기기

macOS에서 Codex나 Claude Code처럼 터미널과 파일을 다룰 수 있는 AI에게 이 저장소 링크와 아래 프롬프트를 함께 보낸다. AI가 계정 비밀번호, TOTP 비밀, 복구 코드, 쿠키를 읽거나 출력하도록 허용하지 않는다.

이 저장소의 Agent Deck을 내 Mac에 설치하고 첫 실행 직전까지 준비해 주세요.

지켜야 할 조건:
1. 현재 작업 디렉터리가 Agent Deck checkout이면 그대로 사용하세요. 아니면 기존 checkout 경로가 있는지 나에게 물어보고, 없을 때만 설치할 경로를 물은 뒤 저장소를 clone하세요. 저장소 루트에서만 작업하세요.
2. README와 package.json을 읽고 `sw_vers`, `node --version`, `tmux -V`로 macOS, Node.js 24 이상, tmux를 확인하세요.
3. 없는 도구만 설치하세요. Homebrew가 없거나 새 설치가 필요하면 먼저 승인을 받으세요. node와 tmux는 실행에, devtunnel은 휴대폰 접속에, gitleaks는 커밋 안전 검사에 필요합니다.
4. Git 커밋 작성자 이메일이 GitHub 비공개 이메일(`...@users.noreply.github.com`)인지 확인하세요. 아니라면 실제 이메일을 출력하지 말고 저장소 로컬 Git 설정을 고치도록 나에게 안내하세요.
5. npm ci, npm run setup:hooks, npm run build, npm run typecheck, npm test, npm run check:public을 실행하세요.
6. `devtunnel user login -g`를 실행하고 내가 브라우저에서 GitHub 인증을 마칠 때까지 기다리세요. 명령이 종료 코드 0으로 끝나야 성공입니다. 다른 로그인 명령은 쓰지 말고 인증 정보나 운영체제 키체인을 읽지 마세요.
7. 내 호스트, SSH 별칭, 경로 등 개인 설정은 추적 파일에 쓰지 말고 ~/.agent-deck 아래에만 두세요. 설치 자체에는 이 값들이 필요하지 않으므로 묻지 마세요.
8. 비밀번호, TOTP 비밀, QR 내용, 복구 코드, 세션 쿠키, 터널 인증 토큰을 읽거나 로그에 출력하지 마세요.
9. 저장소 공개, push, commit, Git 이력 재작성은 하지 마세요.
10. 준비가 끝나면 실행한 명령, 바꾼 파일, 각 검사 결과, `npm start` 명령과 `http://localhost:7717` 주소를 알려주세요. 첫 관리자 설정은 내가 브라우저에서 직접 하겠습니다.

AI가 실행한 명령과 바꾼 파일을 마지막에 확인한다. 특히 개인 설정이 Git 추적 파일에 들어가지 않았는지 npm run check:public 결과를 확인한다.

직접 설치

요구사항

  • macOS, tmux, Node.js 24+ (TypeScript 를 직접 실행)
  • codex 또는 claude CLI 중 사용할 것 하나 이상. 설치 후 해당 명령을 단독 실행해 로그인까지 완료해야 함.
  • devtunnel (휴대폰 접속에 필요하며, 로컬 전용 모드에서는 생략 가능)
  • gitleaks (커밋 전 비밀 검사)

Homebrew를 사용한다면 다음과 같이 설치한다.

brew install node tmux gitleaks
brew install --cask devtunnel

저장소를 아직 받지 않았다면 공개 저장소 주소를 넣어 clone한 뒤, 이후 명령을 저장소 루트에서 실행한다.

git clone https://github.com/ts-kim/agent-deck.git
cd agent-deck
node --version # v24 이상
tmux -V

빌드와 실행

npm ci             # 잠금 파일에 고정된 의존성 설치
npm run setup:hooks # 커밋 전 개인정보·비밀 검사 활성화
npm run build      # 웹 UI 빌드 (web/dist)
npm run typecheck
npm test
npm run check:public
devtunnel user login -g # 브라우저에서 GitHub 인증, 종료 코드 0 확인
npm start          # http://localhost:7717, 이 터미널을 실행한 채 유지

npm run setup:hooks는 Git checkout과 설치된 Gitleaks가 필요하다. 압축 파일로 받은 경우 hook은 설정할 수 없으므로 clone 방식이 권장됨.

Codex는 공식 설치 안내, Claude Code는 공식 설치 안내를 따른다. 둘 중 사용할 CLI만 설치한 뒤 codex 또는 claude를 직접 실행해 로그인을 마친다.

GitHub 비공개 이메일은 GitHub의 Settings → Emails에서 확인하고 이 저장소에만 설정한다. 이 설정은 설치 실행에는 필요 없지만, pre-commit hook이 이후 커밋에서 실제 이메일 노출을 막는 데 사용함.

git config --local user.email '<GitHub에 표시된 noreply 주소>'

hook 설치는 core.hooksPath.githooks로 지정함. 기존 custom hooks 경로가 있으면 덮어쓰지 않고 실패하므로 직접 통합해야 함. 되돌리려면 git config --local --unset core.hooksPath를 실행함.

터미널에 Agent Deck controller: http://127.0.0.1:7717이 표시되면 브라우저에서 http://localhost:7717을 직접 연다. 10자 이상 비밀번호를 만들고, 브라우저에 표시된 인증 앱용 QR을 표준 TOTP 앱에 등록한 뒤 복구 코드를 저장함. Google Authenticator 외의 표준 TOTP 앱도 사용할 수 있음. 복구 코드 10개는 이때 한 번만 표시되며 각각 한 번만 사용할 수 있음.

설정 완료 전에는 공개 Tunnel이 열리지 않음. 완료되면 자동으로 Dev Tunnels를 시작하고 Controller 터미널에 휴대폰 URL과 접속용 QR을 출력함. 터널 인증에 실패해도 localhost와 tmux 세션은 계속 동작하며, devtunnel user login -g 성공 뒤 자동으로 다시 연결함.

사용 방법

  1. Mac에서 npm start로 Controller를 실행한 채 둔다.
  2. 처음 한 번 로컬 주소에서 관리자 비밀번호와 TOTP를 설정하고 복구 코드를 안전한 곳에 보관한다.
  3. Controller에 표시된 Dev Tunnels 주소를 휴대폰에서 열고 비밀번호와 TOTP로 로그인한다.
  4. 첫 로컬 세션은 새 세션Local → 설치된 codex 또는 claude → 홈 아래의 기존 작업 폴더 순서로 고른다. 원격 호스트 등록은 선택 사항임.
  5. 연결이 잠시 끊기거나 Controller를 재시작해도 tmux 작업은 계속된다. 다시 접속하면 복원된 목록에서 같은 세션을 연다.
  6. 목록 위 Usage 카드에서 Codex·Claude의 현재 한도와 주간 한도, 남은 비율, 초기화 시각을 확인한다. 자동 결과는 5분간 캐시되며 새로고침으로 즉시 다시 확인할 수 있음.
  7. Claude·Codex 세션은 사용자 메시지와 답변을 읽기 좋은 기록 화면으로 열림. 아래 입력창에서 메시지를 보내고, Agent Deck이 감지한 선택지·승인 요청은 화면에 나타난 버튼으로 응답함. 복잡한 전체화면 조작이 필요하거나 감지 결과를 확인하려면 세션 상단의 터미널 버튼을 눌러 기존 CLI 화면으로 전환함.

종료하려면 Controller 터미널에서 Ctrl+C를 누른다. Controller만 종료되며 관리 중인 tmux 세션은 남는다. 세션 자체를 끝내려면 Agent Deck 목록에서 해당 세션을 삭제한다. 삭제는 해당 tmux 세션을 종료하지만 작업 폴더의 파일은 삭제하지 않음.

외부 접속과 로컬 전용 모드

외부 접속은 Microsoft Dev Tunnels만 사용한다. 외부 접속이 필요 없으면 로컬 전용 모드로 실행한다.

모드 통신 포트 계정 비고
devtunnel (기본) 443 GitHub 로그인 고정 터널 ID 로 URL 유지 가능
off 터널 없이 이 Mac의 브라우저에서만

devtunnel 사용 시 최초 1회 로그인이 필요하다:

brew install --cask devtunnel   # 최초 1회
devtunnel user login -g         # GitHub 계정 (브라우저 인증)

터널 시작 중이거나 실행 중일 때 인증 오류가 감지되면 Controller가 멈춘 devtunnel 프로세스를 종료하고 devtunnel user login -g를 자동 실행함. 로그인 창을 연 시점부터 15분 동안은 새 로그인 창을 열지 않아 반복 팝업을 방지함. 사용자가 브라우저 인증을 마쳐 로그인 프로세스가 5분 안에 종료 코드 0으로 끝나면 Controller가 터널을 즉시 다시 시작함. 5분을 넘기면 로그인 프로세스를 종료하고 수동 로그인 안내를 표시함. 로그인에 실패하면 원격 접속은 복구 전까지 불가능하지만 관리 중인 tmux 세션은 계속 실행됨.

  • Agent Deck은 비밀번호나 토큰을 저장하지 않음. 로그인 결과는 devtunnel이 운영체제 보안 키체인에 저장함.

  • macOS 사용자 세션에서 Controller를 실행하면 devtunnel이 GitHub 브라우저 로그인을 열 수 있음. 브라우저가 열리지 않거나 Controller를 화면 없는 환경에서 실행 중이면 로컬 터미널에서 devtunnel user login -g를 직접 실행해야 함.

  • 터널 연결 복구 여부는 목록 상단의 Tunnel 상태나 Controller 로그에서 확인할 수 있음.

  • URL 고정: 재시작해도 같은 주소를 쓰려면 터널 ID 를 한 번 만들어 고정한다.

    devtunnel create -a          # 출력된 tunnel id 를 복사

    그 id 를 AGENT_DECK_DEVTUNNEL_ID 로 넘기면 해당 터널이 계정에 남아 있는 동안 재시작해도 같은 URL을 사용함. Dev Tunnels는 개발용 preview 서비스이므로 영구 URL이나 가용성을 보장하지 않음.

    AGENT_DECK_DEVTUNNEL_ID=<복사한-tunnel-id> npm start
  • 로컬 전용 실행: AGENT_DECK_TUNNEL_PROVIDER=off npm start

환경 변수

변수 기본값 설명
AGENT_DECK_PORT 7717 listen 포트
AGENT_DECK_DATA_DIR ~/.agent-deck 상태 파일·감사 로그 위치
AGENT_DECK_TMUX_SOCKET (기본 소켓) tmux -L 소켓 이름 분리
AGENT_DECK_USAGE_TMUX_SOCKET agentdeck-usage Claude 사용량 확인용 격리 tmux 소켓 이름
AGENT_DECK_MESSAGING 0 1이면 새 로컬 Claude·Codex 세션에 실험적 세션 조회·메시지 전송 도구를 등록함
AGENT_DECK_TUNNEL_PROVIDER devtunnel 공개 사용 범위는 devtunnel | off
AGENT_DECK_DEVTUNNEL_ID (매번 새 터널) 고정 터널 ID (재시작해도 URL 유지)
AGENT_DECK_CODEX_BIN / AGENT_DECK_CLAUDE_BIN / AGENT_DECK_TMUX_BIN / AGENT_DECK_DEVTUNNEL_BIN PATH 탐색 실행 파일 경로 강제
AGENT_DECK_INSECURE_COOKIE (미설정) 1 이면 Secure 쿠키 해제 (로컬 http 디버그 전용)

Claude와 Codex 사이 메시지 전달 (실험 기능)

Agent Deck이 세션 목록과 메시지 전달을 맡으므로 tmux 입력 주입 없이 Claude와 Codex가 서로 메시지를 보낼 수 있음. 공개판에서는 기본으로 비활성화되며, 같은 Mac의 Agent Deck에서 새로 만든 로컬 세션만 지원함. SSH 원격 호스트와 custom 세션은 지원하지 않음.

저장소 루트에서 환경 변수를 명시해 Controller를 시작함.

AGENT_DECK_MESSAGING=1 npm start
  • Controller를 재시작한 뒤 Agent Deck의 새 세션 화면에서 Claude 또는 Codex 세션을 새로 만들어야 함. 이미 실행 중이던 세션에는 적용되지 않음.
  • 별도 MCP 설정은 필요 없음. Agent Deck이 새 세션을 시작할 때 다음 Model Context Protocol (MCP) 도구를 해당 프로세스에만 자동 등록하며, 사용자의 전역 Claude·Codex 설정 파일은 바꾸지 않음. 로컬 Claude↔Codex뿐 아니라 Claude↔Claude, Codex↔Codex 조합도 지원함.
    • list_agent_deck_sessions: 표시명, 에이전트 종류, 실행 상태 등 메시지 대상 선택에 필요한 정보만 반환함.
    • send_agent_deck_message: list_agent_deck_sessions에서 받은 세션 ID로 다른 세션에 메시지를 보냄.
    • receive_agent_deck_messages: 기대한 메시지가 도착하지 않을 때 사용자가 에이전트에게 명시적으로 요청해 대기 메시지를 가져오는 예비 수단임.
    • acknowledge_agent_deck_message: Claude가 실시간 수신 메시지를 처리한 뒤 호출하도록 안내되는 내부 확인 도구임.

에이전트의 기능 인식 방식

Claude와 Codex는 새 세션 시작 시 Agent Deck MCP 서버가 제공하는 지침과 도구 목록을 읽어 이 기능을 알게 됨. 저장소의 AGENTS.mdCLAUDE.md에 별도 설명을 추가할 필요 없음.

  • MCP 초기화 지침이 다른 로컬 Claude·Codex 세션을 조회하고 메시지를 보낼 수 있다고 알려줌.
  • Agent Deck이 만든 세션에서 Claude 또는 Codex 자체 기능을 지정하지 않고 “세션 목록”, “다른 세션”, “다른 에이전트에게 보내기”라고 요청하면 Agent Deck이 관리하는 세션에 관한 요청으로 해석하도록 안내함.
  • “Codex 재개 대화 목록”, “Claude 대화 이력”, “현재 Codex의 백그라운드 에이전트”, “현재 세션의 서브에이전트”처럼 범위를 명시한 경우에만 각 CLI의 자체 기능을 사용하도록 안내함.
  • 각 도구의 이름·설명·입력 형식이 모델에 함께 제공되어 list_agent_deck_sessions로 대상을 찾고 send_agent_deck_message로 보내는 순서를 알 수 있음.
  • 도구가 있다는 이유만으로 세션끼리 자동 대화를 시작하지는 않음. 사용자가 요청하거나, 현재 작업상 다른 세션의 도움이 필요하다고 에이전트가 판단할 때 호출할 수 있음.
  • 다른 세션이 보낸 메시지는 Claude에는 실시간 channel 이벤트로, Codex에는 CLI 대기 메시지로 들어가 다음 작업 턴의 입력이 됨.
  • Agent Deck Controller가 Codex 시작 hook으로 내부 대화 ID를 등록한 뒤 공식 CLI queue 명령으로 전달함. Claude에는 연구 단계 channel 기능으로 전달함. 사용자가 두 기능을 따로 설정할 필요는 없음.
    • 2026-08-21 기준 Codex CLI 0.149.0, Claude Code 2.1.238에서 실행 명령과 설정 로딩을 확인함.
    • 첫 Claude 세션에서는 development channel 경고와 MCP 서버 사용 동의가 표시될 수 있음. 로컬 Agent Deck 서버임을 확인한 뒤 직접 승인해야 함.
    • Claude channel은 계정·조직 정책에 따라 차단될 수 있음. 이 경우 MCP 도구로 보내기는 가능하나 자동 수신은 되지 않을 수 있음.
    • 공급자 동작 근거: Codex hooks, Claude Code channels reference
  • 보내는 쪽 세션의 Claude/Codex 터미널에 아래처럼 자연어로 요청하면 됨.
Agent Deck에서 실행 중인 다른 세션 목록을 확인하세요.
"API 검토"라는 Codex 세션을 찾아 현재 변경 사항을 검토해 달라고 메시지를 보내세요.
답장이 오면 핵심만 알려주세요. 같은 내용으로 자동 답장을 반복하지 마세요.
  • 협업 메시지는 신뢰되지 않은 외부 입력으로 표시됨. 메시지가 파일 변경이나 명령 실행을 요청해도 수신 에이전트의 기존 승인 규칙을 건너뛰지 않음.
  • Controller가 새 세션마다 임의 토큰을 만들며, 토큰은 해당 세션이 삭제될 때까지 유효함. 원문은 에이전트 프로세스에만 전달하고 state.json에는 SHA-256 해시만 저장함. 내부 API는 localhost 요청과 해당 세션 토큰을 모두 확인함.
  • 메시지 본문은 재시도와 전달 상태 확인을 위해 권한 0600~/.agent-deck/state.json에 평문으로 저장됨.
    • 전달 대기 메시지: 전체 1,000개까지 보관하며, 전달되거나 발신·수신 세션이 삭제될 때 제거 대상이 됨.
    • 전달된 메시지: 전체에서 최근 1,000개까지 보관함.
    • 비밀번호·인증 토큰 같은 비밀은 보내지 않아야 함.
  • Claude channel과 Codex hook/queue는 설치된 CLI 버전에 따라 동작이 바뀔 수 있는 실험 경로임. 문제가 생기면 Controller를 Ctrl+C로 종료하고 평소처럼 npm start로 다시 실행한 뒤 새 세션을 만들면 메시징 없는 일반 세션으로 돌아감.

호스트 × 에이전트 (어디서 무엇을 실행할지)

새 세션은 어디서(호스트) × 무엇을(에이전트) × 경로 세 가지를 고른다.

  • Local(내장): claude / codex 를 이 Mac 에서 실행. 경로는 폴더 선택 창.
  • 원격 호스트: ~/.agent-deck/hosts.json 에 정의. 예: 개발 서버에서 claude 실행.
[
  {
    "id": "devbox",
    "name": "Development server",
    "ssh": ["ssh", "-tt", "devbox"],
    "defaultCwd": "/home/you",
    "agents": [
      {
        "id": "claude",
        "name": "claude",
        "command": "/home/you/.local/bin/agentdeck-claude",
        "resume": ["--resume"]
      }
    ]
  }
]
  • 원격 실행은 SSH keepalive를 켜고, $TMUX를 제거한 뒤 tmux new -A -s <세션>을 실행하도록 조합됨.
    • command 는 원격 호스트에 사용자가 만든 인자 전달 로그인셸 래퍼(#!/bin/bash -lexec <agent> "$@")의 실행 가능 절대 경로임. 공백 없는 단일 토큰이어야 함. 로그인 셸이 PATH(~/.local/bin 의 claude, node 번들 등)를 확보함.
    • 공백 없는 단일 토큰만 쓰는 이유: tmux 의 shell-command 파서가 인용을 신뢰 불가하게 다룬다. 래퍼가 인자를 forward 하므로 resume 인자를 단순 토큰으로 뒤에 붙일 수 있다.
    • 원격 작업 디렉터리는 절대 경로일 때만 tmux -c 로 지정된다 (그 외에는 원격 홈에서 시작). "찾아보기"로 원격 폴더를 탐색할 수도 있다.
  • resume(이어가기): 에이전트별 resume 인자 배열을 두면 세션 생성 시 "이전 대화 이어가기"가 뜬다. 실행 후 에이전트 TUI 가 이전 세션 목록을 보여줘 고른다.
    • 예: claude ["--resume"], codex ["resume"] (둘 다 picker). Local claude/codex 도 동일 지원(내장).
  • 세션 삭제 시 원격 tmux 세션(그 세션만)도 tmux kill-session -t <세션> 으로 정리된다. broad kill(kill-server)은 절대 쓰지 않는다.
  • 원격 SSH 클라이언트가 종료 코드 255로 끝나면 같은 원격 tmux 세션에 5초부터 최대 60초 간격으로 계속 재접속함. 네트워크 단절뿐 아니라 SSH 인증·설정 오류도 255일 수 있으므로 목록에 재연결 상태와 마지막 오류를 표시함. 별도 일시정지 기능은 없으며 세션 삭제 또는 255가 아닌 종료 시 재시도를 멈춤.
  • Controller가 다른 tmux 안에서 실행되어도 Agent Deck이 시작하는 로컬 tmux 명령, attach 프로세스, 원격 tmux 명령의 자식 환경에서만 부모의 TMUX·TMUX_PANE 값을 제거함. 부모 tmux나 일반 셸 환경은 변경하지 않으며, sessions should be nested with care 오류가 이 실행 경로에서 발생하는 것을 막음.
  • 원격에서 실행이 안 되는 에이전트는 hosts.json 에서 빼면 목록에 안 뜬다.

커스텀 명령 프로필 (원격 노드 세션 등, 하위 호환)

codex/claude 직접 실행이 아닌 명령 — 예: SSH 로 개발 서버의 원격 tmux 에 붙기 — 은 ~/.agent-deck/profiles.json 에 프로필로 정의한다. 프로필은 이 로컬 파일에서만 정의할 수 있고, 웹에서는 선택만 가능하다 (웹 입력이 명령이 되는 경로를 차단).

[
  {
    "id": "devbox-work",
    "name": "Development server · work",
    "description": "개발 서버 원격 tmux",
    "command": ["ssh", "-tt", "devbox", "tmux", "new", "-A", "-s", "work"],
    "killCommand": ["ssh", "devbox", "tmux", "kill-session", "-t", "work"],
    "cwd": "~"
  }
]
  • command 는 인자 배열이며 각 단어가 그대로 실행된다 (shell interpolation 없음).
  • 원격 tmux(new -A -s work)가 세션을 유지하므로, ssh 가 끊겨도 재접속하면 이어진다.
  • killCommand(선택): 세션 삭제 시 로컬 tmux 종료 전에 실행하는 인자 배열. SSH 원격 tmux 처럼 로컬 종료만으로는 안 죽는 대상을 함께 정리한다. 없으면 로컬만 정리한다. (best-effort — 원격 정리에 실패해도 앱 세션은 삭제된다.)
  • cwd 는 로컬 pane 의 작업 디렉터리 (원격 디렉터리는 command 인자로 지정).
  • 파일 수정은 재시작 없이 바로 반영된다.

인증 초기화 (TOTP 기기·복구 코드 분실)

로컬 터미널에서만 가능:

node server/src/index.ts --reset-auth

관리 세션 기록은 보존되고 비밀번호·TOTP·복구 코드·웹 로그인 세션만 초기화된다.

모바일 UI 기능

  • 사용량 대시보드: 사용자가 확인 버튼을 누른 뒤에만 조회를 시작함. Codex는 공식 App Server에서 한도·초기화 시각·토큰 활동을 읽고, Claude는 별도 tmux 소켓의 --safe-mode 세션에서 공식 /usage 화면을 확인함. 사용자 작업 세션에는 입력하지 않으며 결과를 5분간 캐시함.
  • 터미널/기록 전환: 로컬과 등록된 SSH 원격 호스트의 Claude·Codex 세션은 기록 화면으로 열리며, 상단 버튼으로 기존 터미널과 전환할 수 있음. Custom 세션은 구조화된 기록이 없어 터미널로 열림. 기록 화면은 두 CLI가 자체 저장한 JSONL 대화 파일에서 1.5초마다 추가 부분을 읽음. 메시지는 Markdown을 적용한 렌더 보기로 열리며, 상단의 Raw 버튼으로 원문을 확인할 수 있음. 사용자가 위를 읽는 동안 자동으로 아래로 끌어내리지 않으며, 새 내용이 생기면 새 메시지 ↓ 버튼으로 최신 위치로 이동할 수 있음. 일반 드래그 선택과 메시지별 복사도 지원함.
    • 메시지 입력: 기록 화면 아래 입력창에서 Enter로 전송하고 Shift+Enter로 줄을 바꿈. 로그인 뒤 세션 화면이 연결한 경로(브라우저 WebSocket → Controller의 PTY → tmux pane → CLI)로 입력을 전달하며 tmux send-keys를 사용하지 않음.
    • 선택·승인 응답: Controller가 활성 tmux pane의 최신 화면·스크롤백 30줄에서 ❯ 1. Yes / 2. No 같은 메뉴와 [y/N] 질문을 감지해 실제 문구의 버튼으로 표시함. 일반 답변 속 번호 목록은 버튼으로 바꾸지 않음. 질문 문구는 보이지만 선택지 구조를 확정할 수 없으면 ··확인(Enter)·취소(Escape) 키만 제공함.
    • 터미널 예비 경로: 전체화면 편집기와 복수 선택은 기록 화면에서 지원하지 않음. 공급자 버전 변경 등으로 인식하지 못한 UI도 터미널에서 보기로 전환해 처리함. tmux는 화면의 기본 표현이 아니라 CLI 프로세스 생존·재연결을 담당하는 백그라운드 계층으로 유지함.
    • 사용자 메시지와 AI의 진행 안내·최종 답변만 표시함. 추론 원문, 도구 호출·결과, 내부 보조 작업·메타데이터는 제외함.
    • 대화 원문을 Agent Deck 상태 파일에 복제하지 않음. 로컬 기록은 Mac에서 읽고, 원격 기록은 기존 hosts.json의 SSH 설정으로 한 번에 최대 2MB씩 읽어 사용자·AI 메시지 형식으로 변환함. SSH 자격 증명과 원격 파일 경로는 브라우저에 보내는 API 응답에 포함하지 않음.
    • 새 Claude 세션은 기록 파일과 정확히 연결할 수 있도록 시작할 때 대화 ID를 고정함. 원격 Codex 세션과 이 기능 적용 전에 만든 원격 세션은 기록 화면을 처음 열 때 같은 작업 경로에서 세션 생성 시각과 15분 이내인 파일 중 가장 가까운 기록을 선택하고, 찾은 ID를 ~/.agent-deck/state.json에 저장함. 조건에 맞는 기록이 없으면 다른 대화를 추측해 표시하지 않고 찾지 못했다는 안내를 표시함.
    • Codex가 권한 승인을 검토하려고 만든 임시 transcript는 후보에서 제외함. 이미 임시 transcript ID가 저장된 경우 그 기록에 명시된 원래 Codex 세션 ID를 확인해 상태와 화면을 자동 교정함.
  • 활동 뱃지: 해당 세션을 보는 웹 연결이 없는 동안 세션 화면에 새 출력이 생기면 목록에 초록 점이 뜸. 5초 주기 capture-pane 해시 비교로 감지함.
  • 최근 활동순 정렬: 사용자 입력, 감지된 터미널 출력, 브라우저에서 세션을 마지막으로 연 시각 중 가장 최근 값을 기준으로 목록을 자동 정렬함.
  • 히스토리 시딩: 터미널에 붙는 즉시 직전 스크롤백을 최대 5,000줄까지 먼저 복원해 브라우저 스크롤로 볼 수 있게 함.
  • 휠 스크롤: 브라우저 안 xterm 터미널 버퍼에 과거 출력이 있으면 그 안에서 스크롤함. 실행 중인 프로그램이 대체 화면을 사용해 xterm에 과거 출력이 없으면 첫 위쪽 휠에서 tmux copy-mode로 전환하고, 이후 휠로 계속 이동함. 다음 키보드 입력은 copy-mode를 자동으로 종료한 뒤 실행 중인 프로그램에도 그대로 전달함.
  • 창 전환: tmux 세션에 창이 여럿이면 터미널 상단에 창 탭이 뜬다 (‹ / 번호 / ›). 비파괴적 select-window.
  • 텍스트 복사: 마우스 왼쪽 버튼을 보조키 없이 드래그하면 선택 영역이 초록색으로 표시됨. 선택한 뒤 macOS는 Cmd+C, Windows/Linux는 Ctrl+C로 복사함. Agent Deck이 관리 세션의 tmux 마우스 모드를 자동으로 끄므로 별도 설정은 필요 없음. 선택 영역이 없을 때 Ctrl+C는 평소처럼 실행 중인 명령에 전달됨.
  • 터미널 재연결: 브라우저와 터미널 사이의 WebSocket 연결이 끊기면 즉시 한 번 시도한 뒤 10초, 30초, 1분, 5분 간격으로 재시도함. 총 5번 실패하면 자동 재시도를 멈추고 VPN을 켜라는 안내와 다시 연결 버튼을 표시함.
  • 이름 변경: 세션 목록에서 이름을 바꾸면 표시명과 tmux 메타(@agent_deck_name)가 함께 갱신된다.
  • 붙여넣기 버튼 · 글자 크기(A− / A+): 모바일 클립보드를 터미널로, 폰트 크기는 기기별로 localStorage 에 저장.
  • 폴더 선택 모달: 새 세션의 작업 디렉터리를 직접 입력하거나 "찾아보기"로 홈 하위를 탐색해 고른다 (git 저장소 표시). 서버는 홈 밖 경로를 거부한다.
  • 라이트/다크 테마: 시스템/라이트/다크 토글 (localStorage 저장, 터미널 색도 함께 전환).
  • 데스크탑 분할 뷰: 넓은 화면(≥900px)에서는 좌측 사이드바 + 우측 분할 영역. 세션을 드래그하거나 클릭해 여러 터미널을 나란히 본다 (최대 6개).

테스트

npm test           # 단위 + 통합 (tmux 는 전용 -L 소켓 사용, 사용자 세션 무접촉)
npm run typecheck
npm run check:public # 추적 파일의 개인 설정·대표적인 비밀 패턴 검사
npm run check:release # 현재 파일과 기존 Git 이력의 공개 가능 여부 검사

공개 저장소 안전장치

  • 실제 상태와 개인 설정은 첫 실행 때 권한 0700~/.agent-deck에 자동 생성되며 Git 저장소 밖에 있음. 상태·호스트·프로필 파일과 감사 로그는 이 안에만 저장됨.
  • .gitignore가 Agent Deck 상태 파일, .env, 개인 키 파일의 추가를 막음.
  • npm run setup:hooks가 저장소의 pre-commit hook을 켬. 각 커밋 전에 추적 파일 검사와 Gitleaks staged 검사를 모두 통과해야 함. 일반 설치자는 한 번 설정하면 되고, 공개·기여 작업자는 CI까지 확인함.
  • pre-commit hook은 커밋 작성자 이메일도 확인함. 공개 저장소에서는 GitHub 설정의 비공개 이메일(ID+사용자명@users.noreply.github.com)을 저장소 로컬 user.email로 사용함.
  • GitHub Actions가 push와 pull request에서 전체 이력의 비밀, 고위험 운영 의존성, 타입·테스트·빌드를 다시 검사함.
  • 로컬 hook은 --no-verify로 우회할 수 있으므로 공개 전에는 GitHub Actions 성공도 반드시 확인함.
  • 이미 만들어진 Git 이력은 .gitignore로 지워지지 않음. 과거 커밋에 개인 경로나 서버 이름이 있었다면 기존 이력을 공개하지 말고, 검사를 통과한 현재 파일로 새 공개 이력을 만든 뒤 공개함.

보안 메모

  • 원본 서버는 127.0.0.1 bind. Tunnel 경유 요청 판별에 원격지 IP 를 쓰지 않는다(무의미) — Host 헤더 + cf-* 헤더 기준.
  • 서버 측 opaque 세션 + Secure; HttpOnly; SameSite=Strict 쿠키. idle 30분 / absolute 12시간.
  • 비밀번호 Argon2id, TOTP replay 방지(사용 슬롯 기록), 로그인 rate limit(IP + 계정 전역).
  • 로컬 프로세스 실행은 인자 배열(execFile/spawn)을 사용함. 원격 파일 조회는 고정된 읽기 전용 스크립트를 base64로 SSH에 전달하며, 저장된 경로·식별자는 인용하고 허용된 기록 루트 안인지 다시 검사함.
  • 작업 디렉터리는 realpath 후 홈 하위만 허용.
  • 감사 로그는 필드 화이트리스트 — 비밀·터미널 내용이 기록될 경로가 없다.
  • 사용량 확인은 Codex/Claude가 이미 저장한 로그인을 CLI를 통해 사용하며 인증 파일·토큰을 직접 읽거나 API 응답에 포함하지 않음. Claude 검사 세션은 ~/.agent-deck/usage-workspace와 전용 tmux 소켓에서 실행되고 확인 직후 종료됨.
  • Dev Tunnels는 개발용: 주소·가용성 비보장, URL 을 아는 사람은 로그인 화면까지 도달 가능(인증으로 방어).
  • devtunnel 은 --host-header unchanged --origin-header unchanged 로 실행한다. 기본값은 Host 를 localhost 로 재작성해 "setup 은 localhost 만" 가드를 우회시킬 수 있어서다.

자동 실행 (launchd)

최초 수동 실행과 Dev Tunnels 로그인을 확인한 뒤 docs/launchd.md의 절차로 로그인 시 자동 실행을 설정할 수 있음.

About

Manage Codex and Claude tmux sessions from desktop and mobile.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages