claude-wrapper: Claude Code CLI를 위한 타입 안전 Rust 래퍼
요약
이 라이브러리는 Claude Code CLI를 위한 타입 안전한 Rust 래퍼입니다. 빌더 패턴을 적용하여 각 서브커맨드를 타입 지정된 인터페이스로 제공하며, 비동기 및 동기 API를 모두 지원합니다. 세션 관리, 히스토리 추적, 다양한 고급 기능을 프로그램적으로 쉽게 사용할 수 있도록 설계되었습니다.
핵심 포인트
- Claude Code CLI의 타입을 안전하게 래핑하여 사용 편의성을 높임.
- 빌더 패턴을 적용해 각 서브커맨드를 타입 지정된 인터페이스로 제공함.
- 비동기(tokio) 및 동기 API를 모두 지원하며, 세션 관리 기능이 강력함.
- 세션 히스토리, 에이전트 등 온디스크 상태에 대한 읽기 인트로스펙션을 지원함.
claude-wrapper
Claude Code CLI를 위한 타입 안전(type-safe) Rust 래퍼입니다.
개요 (Overview)
claude-wrapper는 claude CLI에 빌더 패턴(builder-pattern) 인터페이스를 제공합니다. 각 서브커맨드는 타입이 지정된 빌더이며, 타입이 지정된 출력을 생성합니다. 이 디자인은 docker-wrapper 및 terraform-wrapper와 동일한 형태를 따릅니다.
기능:
-
QueryCommand를 통한claude -p전체 커버리지 -
기능 플래그(feature flags) 기반의 비동기(Async, tokio) 및 동기(blocking, std::thread + wait-timeout) API
-
단기 프로세스용 임시(Transient)
Session:--resume연속성을 가진 턴별 서브프로세스, 누적 비용 + 히스토리, 선택적BudgetTracker하드 스톱, 스트리밍 -
DuplexSession을 통한 호스트 측 히스토리/비용/예산 기록을 위한Conversation -
NDJSON 스트리밍 이벤트 (
stream_query/stream_query_sync) -
타입이 지정된 도구 권한 패턴 (
ToolPattern) -
CLI를 실행하지 않고 Claude Code의 온디스크 상태에 대한 읽기 측 인트로스펙션: 세션 히스토리, 에이전트(agents), 스킬(skills), 사용자 정의 명령(custom commands), 설정(settings), 백그라운드 작업(background jobs), 워크트리(worktrees)
-
MCP 서버 관리: 목록 보기, 가져오기, 추가, JSON으로 추가, 제거, 데스크톱에서 추가, 로그인, 로그아웃, 서비스 제공, 프로젝트 선택 초기화
-
플러그인 및 마켓플레이스 서브커맨드
-
기타 서브커맨드:
doctor,install,update,project purge,auto-mode, 그리고ultrareview(클라우드 호스팅 멀티 에이전트 코드 리뷰) -
인증(Auth):
status,login,logout,setup-token -
프로그램적
.mcp.json생성을 위한McpConfigBuilder(선택적 임시 파일 백킹 포함) -
고정 또는 지수 백오프(exponential backoff)를 사용한 재시도 정책(Retry policy)
-
권한 우회 모드(env-var gated)를 위한 선택적
DangerousClient -
아직 래핑되지 않은 서브커맨드를 위한
RawCommand탈출구(escape hatch)
설치 (Installation)
cargo add claude-wrapper
기본 기능: ["async", "json", "tempfile"]. tokio를 완전히 제거하여 동기 전용 빌드를 하려면:
claude-wrapper = { version = "0.13", default-features = false, features = ["json", "sync"] }
Quick start (async)
use claude_wrapper::{Claude, QueryCommand};
#[tokio::main]
...
Quick start (sync)
sync 기능을 활성화하고 use ClaudeCommandSyncExt:
use claude_wrapper::{Claude, ClaudeCommandSyncExt, QueryCommand};
fn main() -> claude_wrapper::Result<()> {
...
동기 API는 std::process::Command와 wait-timeout을 사용하여 SIGKILL-on-deadline 경로를 처리하며, stdout 및 stderr에 대한 전용 리더 스레드를 사용하므로 자식 프로세스가 파이프 버퍼 백프레셔(backpressure)로 인해 절대 블록되지 않습니다. 이는 비동기 버전의 동작을 기능별로 일치시킵니다 (타임아웃, 재시도, 대용량 출력 처리, 스트리밍을 위한 non-Send 핸들러).
Two-layer builder
Claude 클라이언트는 공유 설정(바이너리 경로, 환경, 타임아웃, 기본 재시도 정책)을 유지합니다. 명령어 빌더는 호출별 옵션을 보유하며 execute(&claude) (또는 execute_sync)를 호출합니다.
let claude = Claude::builder()
.env("AWS_REGION", "us-west-2")
.timeout_secs(300)
...
Claude 옵션:
binary()--claude바이너리 경로 (기본적으로 PATH에서 자동 감지)working_dir()/with_working_dir()-- 명령을 실행할 작업 디렉토리env()/envs()-- 모든 명령어에 적용되는 환경 변수clear_env()--env()/envs()를 적용하기 전에 상속된 자식 환경을 지움arg()-- 모든 서브커맨드 앞에 적용되는 전역 인자timeout_secs()/timeout()-- 명령어 타임아웃 (기본값 없음)retry()-- 모든 명령어에 적용되는 기본RetryPolicyprocess_group()-- 각 자식을 자체 Unix 프로세스 그룹으로 격리 (기본 활성화)kill_grace()-- 대기 종료 경로에서 SIGKILL 전에 선택적 유예 시간termination_signal()-- SIGTERM (기본값) 또는 해당 유예 기간 동안 옵트인된 SIGINToutput_limit()-- 캡처된 stdout 및 stderr의 바이트 상한선 (기본값 없음)
Claude는 다음 것도 노출합니다:
cli_version()/cli_version_sync()-- 파싱된CliVersioncheck_version()/check_version_sync()-- 최소 버전 확인을 주장함 (assert a minimum version)
대기 중인 취소(Awaited cancellation)
QueryCommand::execute_cancellable 및 execute_json_cancellable은 ()으로 해결되는 모든 future를 받습니다. 이 미래가 해결되면, 래퍼는 소유된 프로세스 그룹을 종료하고 직접적인 자식을 회수(reaps)한 다음 Error::Cancelled를 반환합니다. 구성된 타임아웃도 동일한 정산 경로를 사용합니다.
일반적인 execute future를 드롭하는 것은 여전히 즉각적인 프로세스 그룹 정리(cleanup)를 유발하지만, 소멸자는 회수를 기다릴 수 없습니다. 호출자가 실행을 중지된 것으로 기록하기 전에 터미널 정산이 필요한 경우 취소 가능한 메서드를 사용하십시오.
CLI가 에스컬레이션 전에 분리된 도구를 취소하도록 하려면, SIGINT와 짧은 유예 기간에 옵트인하는 것이 좋습니다:
use claude_wrapper::{Claude, TerminationSignal};
use std::time::Duration;
...
종료를 기다리면(awaited shutdown) 경계가 지정된 버퍼 내에서 출력을 비우고 폐기한 후, 소유 그룹에 SIGKILL을 보내고 직접 자식을 회수합니다. 취소 및 타임아웃은 정리 과정 중 CLI가 성공적으로 종료되더라도 원래의 오류를 유지합니다. 이는 또한 블로킹 타임아웃, 스트리밍, 그리고 듀플렉스(duplex) 종료 오버런에도 적용됩니다. DuplexSession::interrupt()는 프로세스 종료와 별개인 프로토콜 요청으로 남아 있습니다.
기본값은 변경되지 않았습니다: grace가 없다는 것은 즉각적인 SIGKILL을 의미합니다. 소프트 신호 및 grace는 소유된 Unix 프로세스 그룹에만 적용됩니다. process_group(false)를 사용하거나 다른 플랫폼에서는 종료 시 직접 자식만을 죽입니다. Future를 드롭하는 것은 항상 즉각적인 하드 클린업을 사용합니다. 소유 그룹을 벗어나는 후손들은 CLI의 협조적 정리(cooperative cleanup)가 필요하며, 래퍼는 이들의 종료를 보장할 수 없습니다.
경계 지정 출력 캡처
버퍼링된 실행은 자식의 stdout과 stderr를 EOF까지 읽으므로, 최대 메모리는 CLI가 출력하기로 결정한 내용에 따라 달라집니다. output_limit()은 상한선을 설정합니다:
let claude = Claude::builder()
.output_limit(4 * 1024 * 1024)
.build()?;
이 상한선은 각 스트림에 독립적으로 적용되므로, 쌍은 최대 설정된 바이트의 두 배를 유지합니다. 이 한계에 도달하면 자식 프로세스 그룹을 종료(kill_grace 준수), 직접 자식을 회수하고, 어떤 스트림에서 초과했는지 이름을 지정하는 Error::OutputLimitExceeded { stream, limit_bytes }를 반환합니다. 이는 잘린 성공이 아니며, 호출자는 완전한 답변과 합의된 용량을 초과한 답변을 구분할 수 있습니다. 상한선에 도달하기 전에 캡처된 출력은 반환되는 대신 warn 레벨로 기록됩니다.
기본 상한선은 없습니다. output_limit()이 설정되지 않은 경우, 캡처 동작은 변경되지 않습니다.
이는 버퍼링된 경로(execute, execute_json 및 이들의 취소 가능하고 블로킹 형태)를 제한합니다. 스트리밍 실행은 도착하는 대로 이벤트를 전달하므로 영향을 받지 않습니다.
자식 환경 정책
자식 프로세스는 호환성을 위해 기본적으로 부모 프로세스의 환경을 상속받습니다.
명시적으로 구성된 환경이 필요한 호스트는 이를 비울 수 있습니다:
let claude = Claude::builder()
.clear_env()
.env("PATH", "/usr/local/bin:/usr/bin:/bin")
...
clear_env()는 호출 순서에 독립적입니다: env() / envs()가 그 앞에 오든 뒤에 오든 명시된 항목은 유지됩니다. 버퍼링, stdin, 타임아웃, 재시도, 스트리밍, 동기(sync), 듀플렉스 자식 모두 동일한 정책을 사용합니다.
환경을 비우는 것은 직접적인 Claude CLI 자식이 상속받는 것만을 제어할 뿐입니다. 이는 운영체제나 프로세스 격리가 아닙니다. 같은 UID를 가진 자식은 OS가 허용하는 경우 여전히 접근 가능한 파일을 읽거나 다른 프로세스를 검사할 수 있습니다. 호출자는 배포에 적합한 최소한의 PATH, 로케일(locale), config-home, credential, proxy, Git, SSH 항목을 선택할 책임이 있습니다.
명령어 빌더 (Command builders)
| 카테고리 | 빌더 |
|---|---|
| Query | QueryCommand |
| ... |
모든 빌더는 ClaudeCommand (args(), 비동기 execute)를 구현합니다. sync 기능을 사용하면, ClaudeCommandSyncExt가 모든 명령어에 대해 CommandOutput을 반환하는 포괄적인 execute_sync를 제공합니다. QueryCommand는 재시도 정책을 준수하는 내재적인 execute_sync / execute_json_sync를 추가로 가지고 있습니다. AuthStatusCommand는 execute_json_sync를 가집니다.
QueryCommand
claude -p의 전체 커버리지. 일반 옵션들은 다음과 같습니다:
| 메서드 | CLI 플래그 | 용도 |
|---|---|---|
model() | --model | 모델 별칭 또는 전체 ID |
| ... |
패스스루 인자(Passthrough arguments)는 타입이 지정된 옵션과의 충돌을 포함하여 검증되지 않습니다. Claude CLI가 중복되거나 지원되지 않는 플래그의 동작 방식을 결정합니다. 특정 입력 또는 출력 형식에 의존하는 프론트엔드는 자체적으로 충돌하는 패스스루 옵션을 거부해야 합니다. 인자가 모든 명령어에 적용되어야 하는 경우 ClaudeBuilder::arg를 사용하십시오.
Raw 세션 플래그 (다중 턴(multi-turn)의 경우 Session 선호):
| 메서드 | CLI 플래그 |
|---|---|
continue_session() | --continue |
| ... |
Bypass-permissions 모드는 DangerousClient를 통해서만 사용 가능합니다. 아래를 참조하십시오.
JSON 출력
let result = QueryCommand::new("generate a user struct")
.output_format(OutputFormat::Json)
.json_schema(r#"{\
| | `DuplexSession` | `Session` |
|---|---|---|
| 프로세스 모델 | 턴(turn) 전반에 걸쳐 열린 단일 자식 프로세스 | 턴당 새로운 서브프로세스, `--resume` 연속성 지원 |
| ... | | |
| 내장 비용/히스토리 추적 | 없음 (TurnResult는 턴별임) | 예 (`total_cost_usd`, `history`, `BudgetTracker`) |
| 적합한 용도 | 장시간 실행되는 호스트 | 단기 실행 프로세스 |
### `DuplexSession` (장시간 실행되는 호스트에 권장)
대화가 진행되는 동안 하나의 `claude` 서브프로세스를 stream-json duplex 모드로 유지합니다. 사용자 메시지는 stdin을 통해 전송되며, 토큰별 UI 업데이트를 위해 사용하고, 비동기 콜백을 통해 답변 승인 프롬프트에 응답하며, `interrupt()`로 턴을 깔끔하게 취소할 수 있습니다.
```rust
use claude_wrapper::Claude;
use claude_wrapper::duplex::{DuplexOptions, DuplexSession, InboundEvent};
...
interrupt(), respond_to_permission(), 그리고 전체 인터페이스에 대한 자세한 내용은 duplex 모듈 문서를 참조하세요.
Session (단기 실행 프로세스용)
턴마다 임시 서브프로세스를 생성하고, --resume을 통해 이들 간에 session_id를 전파합니다. 히스토리, 누적 비용을 추적하며, 하드 스톱(hard-stop) 상한선을 위해 BudgetTracker와 통합됩니다. 각 턴이 독립적으로 존재할 수 있고 호스트 프로세스가 장시간 실행되지 않는 경우 적합합니다.
use std::sync::Arc;
use claude_wrapper::{Claude, QueryCommand};
use claude_wrapper::session::Session;
...
기존 세션 재개하기:
let mut resumed = Session::resume(claude, "sess-abc123");
let next = resumed.send("pick up where we left off").await?;
AI 자동 생성 콘텐츠
본 콘텐츠는 GitHub Claude Ecosystem의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기