HTTP API 레퍼런스

ccmux 데몬은 세션 나열, 프로젝트 데이터 읽기 및 원격 클라이언트 구축을 위해 HTTP 및 JSON API를 노출합니다. 이 참조는 연결 설정, 신뢰 모델, 끝점 및 응답 유형을 다룹니다.

경로와 유형은 ccmux source. 이전 데몬 버전은 여기에 설명된 모든 엔드포인트를 지원하지 않을 수 있습니다. 실행 중인 버전의 상태 엔드포인트를 확인하세요.

전송 및 도달 가능성

동일한 경로가 두 가지 전송을 통해 제공됩니다.

운송 주소 기본값
로컬 유닉스 소켓 ~/.local/state/ccmux/ccmuxd.sock (모드 0600) 항상 켜짐
tailnet HTTP http://TAILNET-IPv4:PORT (포트 기본값 7474) 끄기

다른 장치에서 데몬에 도달하려면 데몬 호스트: 설정 daemon.listen_tailnet = true (선택 사항 daemon.tailnet_port) ~/.config/ccmux/config.toml ccmuxd를 다시 시작하세요. 바인딩 주소는 호스트의 주소입니다. tailscale ip -4. Tailscale가 실행되고 있지 않으면 tailnet 수신기가 자동으로 시작되지 않습니다(Unix 소켓만 제공됨).

인증 및 신뢰 모델 - 먼저 읽어보세요

HTTP API에는 애플리케이션 수준 인증이 없습니다. 전달자 토큰 없음, API 키 없음, 요청별 서명 없음, IP 허용 목록 없음. 신뢰 경계는 다음과 같습니다. Tailscale tailnet: 데몬의 호스트에 연결할 수 있는 모든 호스트 100.x.x.x:7474 는 모든 엔드포인트를 호출할 수 있습니다 — 목록/생성/종료/이름 바꾸기/키 보내기, 완전한 대화형 터미널에 연결, 메모/대화/사용법을 읽어보세요.

이를 다음으로 보호하세요. Tailscale ACL, 앱 수준 인증이 아닙니다. 데몬의 tailnet IP로 라우팅할 수 있는 모든 항목을 완전히 신뢰할 수 있는 것으로 취급합니다.

요청당 2개의 엔드포인트가 검증되며 부트스트랩 장치 신뢰 + 푸시에만 해당됩니다. API를 보호하기 위한 것이 아닙니다.

오류 형태

오류는 다음과 같습니다. 일반 텍스트 (text/plain): 단일 라인 메시지, 아님 JSON 봉투. 확인해보세요 상태 코드, 본문을 휴먼 메시지의 문자열로 읽습니다. 성공적인 JSON 응답은 다음과 같습니다. application/json.

코드 의미
200 OK (JSON 본체)
204 OK, 본문 없음(kill / send-keys / 장치 등록)
400 잘못된 입력/검증 실패
401 유효하지 않거나 만료된 페어링 토큰(/v1/pair 에만 해당)
404 찾을 수 없음 — 또는 이 데몬은 엔드포인트보다 이전 버전입니다.
405 잘못된 HTTP 방법
500 서버 / tmux / 비계 오류
503 기능을 사용할 수 없습니다(예: /v1/pair-tokenlisten_tailnet 꺼짐)

API는 다음과 같이 진화합니다. 추가 JSON 필드(모든 선택 필드는 omitempty) 및 추가 경로. 치료하다 404 전체 엔드포인트에서 "이 데몬은 해당 기능보다 오래되었습니다"라고 인식하고 정상적으로 성능이 저하됩니다.

엔드포인트 요약

메소드 경로 응답
GET /v1/health HealthInfo
GET /v1/peers []PeerInfo
GET /v1/sessions []SessionState
POST /v1/sessions SessionState (생성 또는 연결)
POST /v1/sessions/bare NewBareSessionResponse
POST /v1/sessions/NAME/kill 204
POST /v1/sessions/NAME/rename SessionState
POST /v1/sessions/NAME/send-keys 204
GET /v1/sessions/NAME/preview PreviewResponse
GET /v1/sessions/NAME/attach 웹소켓(대화형 PTY)
GET /v1/projects []ProjectInfo
POST /v1/projects NewProjectResponse
GET /v1/conversations []Conversation
GET /v1/usage?window=… AgentUsage
GET /v1/notes?project=…[&file=…] []NoteEntry 또는 NoteContent
GET /v1/notes/search?project=…&q=… []SearchHit
GET /v1/events SSE 스트림 SessionEvent
POST /v1/pair-token (유닉스 전용) PairTokenResponse
POST /v1/pair PairResponse
POST /v1/devices 204
POST /v1/devices/test 204

(경로가 표시되는 곳 NAME tmux 세션 이름 경로 세그먼트입니다. /v1/sessions/{name}/kill.)

엔드포인트 세부정보

세션

대화형 터미널 — GET /v1/sessions/NAME/attach (웹소켓)

실제 웹소켓에 연결된 WebSocket으로 업그레이드 tmux attach-session PTY: 진정한 대화형 터미널(라이브 출력, 입력, 크기 조정) 없음 SSH/mosh. 용도 coder/websocket 프레이밍.

초기 PTY 크기는 다음과 같습니다. 80x24 첫 번째 크기 조정까지. 서버는 25초마다 핑을 보내고 기한은 10초입니다. 탁구에 응답하거나 분해를 예상합니다. InsecureSkipVerify 가 설정되었습니다(아니요 Origin 확인). 소켓만 닫기 분리하다; tmux 세션이 계속 실행됩니다. 폴링보다 이것을 선호합니다 /preview 대화형 보기의 경우.

프로젝트

대화, 사용법, 메모

실시간 업데이트 — GET /v1/events (SSE)

text/event-stream. 각각 data: 프레임은 JSON입니다. SessionEvent; kindcreated / killed / state_change / needs_input. 하트비트: : connected 오픈 시, : ping 20초마다(다음으로 시작하는 주석 줄) : 은 무시할 수 있습니다.) 안 event: drops / data: N 프레임은 N개의 이벤트를 놓쳤으며 다시 가져와야 함을 의미합니다. /v1/sessions 재동기화합니다.

건강 및 발견

페어링 및 푸시(모바일)

기본 푸시(APN/iOS, FCM/Android) 및 SSH 키 설치에 대한 선택적 흐름을 통해 장치에서 다음을 수행할 수 있습니다. ssh/mosh 첨부합니다. 아님 tailnet을 통해 읽기/작동 엔드포인트를 사용하는 데 필요합니다.

두 가지 전환 시 실행을 푸시합니다. 세션이 시작됩니다. needs_inputactive → idle ("에이전트 완료"). 푸시의 세션 ID는 다음과 같습니다. local/SESSIONNAME. APN과 FCM은 기본적으로 꺼짐 서버 측 구성이 필요합니다. FCM 라우팅이 존재하지만 Android 전송이 아직 연결되지 않았습니다.

종류

복사됨 internal/daemon/protocol.go (JSON 태그가 있는 Go 구조체).

type SessionState struct {
	Name        string    `json:"name"`
	Host        string    `json:"host"`         // "local" or a remote host name
	Project     string    `json:"project"`
	Path        string    `json:"path"`         // session working directory
	State       string    `json:"state"`        // active|idle|needs_input|error|unknown
	Attached    bool      `json:"attached"`
	Windows     int       `json:"windows"`
	Created     time.Time `json:"created"`
	LastChange  time.Time `json:"last_change"`
	PromptCount int       `json:"prompt_count"`
	Agent       string    `json:"agent,omitempty"`
}

type HealthInfo struct {
	OK        bool   `json:"ok"`
	Hostname  string `json:"hostname"`
	Version   string `json:"version"`
	Sessions  int    `json:"sessions"`
	SleepMode string `json:"sleep_mode"` // off|safe|dangerous|very_dangerous
}

type SessionEvent struct {
	At      time.Time    `json:"at"`
	Kind    string       `json:"kind"` // state_change|created|killed|needs_input
	Session SessionState `json:"session"`
}

type NewSessionRequest struct {
	Project  string `json:"project"`
	Path     string `json:"path"`     // defaults to PROJECTS_ROOT/PROJECT
	Continue bool   `json:"continue"` // start the agent with --continue
	Name     string `json:"name,omitempty"`
	Agent    string `json:"agent,omitempty"`
}

type NewBareSessionRequest struct {
	Name  string `json:"name,omitempty"`
	Path  string `json:"path,omitempty"`
	Agent string `json:"agent,omitempty"`
}
type NewBareSessionResponse struct {
	Session string `json:"session"`
	Path    string `json:"path"`
	Host    string `json:"host"`
}

type NewProjectRequest struct {
	Name  string `json:"name"`
	Agent string `json:"agent,omitempty"`
}
type NewProjectResponse struct {
	Session string `json:"session"`
	Path    string `json:"path"`
	Host    string `json:"host"`
}

type ProjectInfo struct {
	Name      string    `json:"name"`
	Host      string    `json:"host"`
	Path      string    `json:"path"` // absolute on the daemon host
	HasGit    bool      `json:"has_git"`
	HasCM     bool      `json:"has_cm"`
	HasAgents bool      `json:"has_agents,omitempty"`
	HasDocs   bool      `json:"has_docs"`
	Agent     string    `json:"agent,omitempty"`
	Modified  time.Time `json:"modified"`
}

type PeerInfo struct {
	Hostname   string `json:"hostname"`
	Addr       string `json:"addr"` // tailnet IPv4
	OS         string `json:"os"`
	Online     bool   `json:"online"`
	RunsCCMuxd bool   `json:"runs_ccmuxd"`
	Port       *int   `json:"port,omitempty"`
}

type Conversation struct {
	ID       string    `json:"id"` // agent UUID (its --resume id)
	Agent    string    `json:"agent"`
	Project  string    `json:"project,omitempty"`
	Path     string    `json:"path,omitempty"`
	Preview  string    `json:"preview,omitempty"`
	Modified time.Time `json:"modified"`
}

type AgentUsage struct {
	Claude      UsageSummary `json:"claude"`
	Codex       UsageSummary `json:"codex"`
	Antigravity UsageSummary `json:"antigravity"`
}
type UsageSummary struct {
	HasData       bool    `json:"has_data"`
	WindowSeconds int     `json:"window_seconds"`
	Prompts       int     `json:"prompts"`
	InputTokens   int     `json:"input_tokens"`
	OutputTokens  int     `json:"output_tokens"`
	EstimatedCost float64 `json:"estimated_cost"` // USD
}

type NoteEntry struct {
	Rel      string    `json:"rel"`
	Dir      string    `json:"dir"`
	Display  string    `json:"display"`
	Modified time.Time `json:"modified"`
}
type NoteContent struct {
	Rel     string `json:"rel"`
	Content string `json:"content"`
}
type SearchHit struct {
	Rel     string `json:"rel"`
	LineNum int    `json:"line_num"`
	Snippet string `json:"snippet"`
}

type PreviewResponse struct {
	Lines   int    `json:"lines"`
	Content string `json:"content"`
}

type RenameRequest   struct{ Name string `json:"name"` }
type SendKeysRequest struct{ Keys string `json:"keys"` }

type PairRequest struct {
	Token       string `json:"token"`
	PublicKey   string `json:"public_key"`
	DeviceToken string `json:"device_token,omitempty"`
	APNsEnv     string `json:"apns_env,omitempty"` // development|production
}
type PairResponse      struct{ Hostname string `json:"hostname"`; Version string `json:"version"` }
type PairTokenResponse struct{ Token string `json:"token"`; URL string `json:"url"` }
type RegisterDeviceRequest struct {
	Token     string `json:"token"`
	Env       string `json:"env,omitempty"` // apns: development|production; fcm: empty
	PublicKey string `json:"public_key"`
	Provider  string `json:"provider,omitempty"` // apns (default) | fcm
}
// POST /v1/devices/test body is { "public_key": "..." }

클라이언트측 미러링을 위한 유효성 검사 규칙

예시

# Health (over the tailnet)
curl -s http://100.75.64.20:7474/v1/health | jq

# List sessions
curl -s http://100.75.64.20:7474/v1/sessions | jq

# Type a reply into a session and press Enter
curl -s -X POST http://100.75.64.20:7474/v1/sessions/c-auth/send-keys \
  -H 'content-type: application/json' \
  -d '{"keys":"yes, ship it\n"}'

# Peek at the last 40 lines of a pane
curl -s 'http://100.75.64.20:7474/v1/sessions/c-auth/preview?lines=40' | jq -r .content

# Subscribe to live events
curl -sN http://100.75.64.20:7474/v1/events

Go 참조 클라이언트는 internal/daemon/client.go 은 정식 소비자이자 메소드 → 엔드포인트의 유용한 맵입니다.

ccmux 개선에 참여해 주세요

버그, 이해하기 어려운 설명, 어색한 번역을 발견하셨나요? 작은 개선도 환영합니다. 이슈를 등록하거나 풀 리퀘스트를 보내 주세요.


오류나 오래된 내용을 발견하셨나요? GitHub에서 이 페이지를 편집하세요..