Architecture Deep Dive

oxi 생태계 해부도

하나의 Rust 워크스페이스가 어떻게 터미널 코딩 에이전트(oxicode)에서 에이전트 운영체제(oxios), 그리고 독립된 기억 엔진(oxibrain)으로 갈라져 나갔는지 — 크레이트 단위로 뜯어보고, 왜 이런 모양으로 나눴는지, 그리고 각자의 경쟁자들과 비교해 어디에 강점이 있는지 정리합니다.

oxicode · 13크레이트 · CLI+SDK oxios · 에이전트 OS · ~127K LOC oxibrain · 독립형 세컨드 브레인
01

한눈에 보기

세 프로젝트는 같은 작성자(a7garden / project-oxi)의 워크스페이스지만 결합 강도가 전부 다릅니다. oxios는 oxicode-sdk를 필수 의존성으로 물고 있고, oxibrain은 있으면 쓰고 없으면 조용히 기능을 낮추는 선택적 이웃입니다.

oxicode 13개 크레이트 워크스페이스 CLI 바이너리 + 재사용 가능한 SDK oh-my-pi(Pi) 포크 계보 oxibrowser 인프로세스 헤드리스 브라우저 oxios 에이전트 운영체제 (데몬) 커널 · 게이트웨이 · REST API 6개 크레이트 + 바이너리 ~127,000 LOC oxibrain 독립형 세컨드 브레인 불변 원장 + 재생성 가능 인덱스 필수 oxi 의존성 0개 별도 데몬으로 실행 oxicode-sdk (crates.io, 필수) oxibrowser-core (선택 기능) oxibrain-client Unix 소켓 JSON-RPC 선택적 · 끊겨도 성능 저하만 필수 의존성 선택적 의존성 (없어도 동작)
oxicode → oxios는 crates.io 버전 고정 의존성(실선), oxios ⇢ oxibrain은 소켓이 죽어도 조용히 기능만 줄어드는 선택적 연결(점선)입니다.
13
oxicode 워크스페이스 크레이트
~66K
oxicode-cli LOC (합성 루트)
6+1
oxios 라이브러리 크레이트 + 바이너리
22
KernelHandle 파사드 API 개수
13
oxibrain 워크스페이스 크레이트
0
oxibrain의 필수 oxi-* 의존성
02

oxicode 크레이트 지도

13개 워크스페이스 멤버 중 lib(bin)은 딱 두 곳뿐입니다 — 컴포지션 루트인 oxicode-cli와, 독립 실행 가능한 MCP 서버를 함께 배포하는 oxicode-mnemopi. 나머지는 전부 순수 라이브러리, oxicode-api-stability 하나만 proc-macro입니다.

크레이트형태티어역할
oxicode-cataloglibleaf모델 카탈로그 — models.dev 스냅샷 + 런타임(ollama/lmstudio) 탐색. omp pi-catalog의 직계 포트.
oxicode-hashlinelibleaf줄 단위 패치 포맷 — 순수 함수 라이브러리, 파일시스템도 에이전트도 모른다.
oxicode-lsplibleaf얇은 LSP 프로토콜 어댑터 — JSON-RPC 프레이밍만, 정책은 CLI가 가진다.
oxicode-mnemopilib binleaf로컬 SQLite 벡터 기억 엔진(FTS5+벡터). oh-my-pi Mnemopi 포트. oxicode-mnemopi-mcp 바이너리로 단독 MCP 서버도 배포.
oxicode-snapcompactlibleaf비전 LLM용 비트맵 프레임 컨텍스트 압축 — 요약 대신 텍스트를 PNG로 렌더링.
oxicode-textarealibleafCJK/이모지 캐럿 정확도를 갖춘 아토믹 뮤테이션 텍스트 에디터 위젯.
oxicode-vtui-compatlibleaf벤더링된 vtcode-ui가 독립 컴파일되도록 하는 호환 스텁.
oxicode-api-stabilityproc-macroleaf#[stable]/#[unstable]/#[internal]/#[deprecated] 안정성 티어 매크로.
oxicode-vtuilibfoundation터미널 UI 프레임워크 — 62개 테마, 마크다운 렌더러. vtcode-ui의 재벤더링.
oxicode-ailibfoundation멀티 프로바이더 스트리밍 LLM API. 내부 의존성은 catalog 하나뿐 — 워크스페이스의 진짜 기반.
oxicode-agentlibmid툴콜링 에이전트 루프 + MCP 클라이언트 + 21개 내장 툴(7개 필수).
oxicode-sdklibsdk멀티 에이전트 SDK — OxicodeBuilder + 15개 포트 트레이트. 제품이 실제로 import하는 유일한 진입점.
oxicode-clilib bintop터미널 코딩 어시스턴트 oxicode 실행 파일. 다른 거의 모든 크레이트를 소비하는 컴포지션 루트, ~66K LOC.
leaf foundation mid sdk binary catalog leaf hashline leaf lsp leaf mnemopi leaf +bin snapcompact leaf textarea leaf vtui-compat leaf api- stability proc-macro oxicode-ai 0 내부 의존 (catalog 제외) oxicode-vtui 62개 테마 oxicode-agent 툴콜링 루프 oxicode-sdk 15개 포트 계약 SDK가 행동을 소유 · 소비자는 정책만 → oxicode-cli (bin) 컴포지션 루트 · ~66,000 LOC
5개 계층, 순환 의존성 0개. 실제 간선은 20개 가까이 되지만(예: cli → mnemopi 직접 스킵) 여기서는 계층 흐름만 단순화했습니다.
인용 · oxicode-agent/src/tools.rs, oxicode-sdk/src oxicode-agentoxicode-sdk는 사실 트레이트 모양이 서로 다릅니다. agent는 AgentTool·SubagentRunner·MemoryBackend·UrlResolver 같은 "도구 컨트랙트"를 정의하고, sdk는 StateStore·EventBus·MemoryStore 같은 "포트 컨트랙트"를 정의합니다. 그래서 둘을 잇는 bridge 구조체가 3개 있습니다 — PortMemoryBackend(sdk의 MemoryStore+EmbeddingProvider → agent의 MemoryBackend), SdkUrlResolver(sdk의 InternalUrlRouter → agent의 UrlResolver), KernelToolProvider(호스트 도구 레지스트리 → sdk agent builder). oxios 같은 외부 소비자는 이 bridge들 덕분에 oxicode-sdk 단일 의존만으로 agent 레이어까지 전부 활용합니다.
03

왜 이렇게 나눴나 — 5가지 설계 원칙

AGENTS.mddocs/oxi-sdk-ownership.md에 직접 적혀 있는 원칙들입니다. 추상적인 선언이 아니라, 실제로 실패했던 사건을 근거로 삼고 있다는 점이 특징입니다.

01

SDK는 행동을, 소비자는 정책을 소유한다

2026-08-01, oxios가 oxi-sdk 0.35.0에 고정된 채 워크스페이스가 0.37.1로 올라가면서 두 레이어가 조용히 따로 진화하다 빌드가 깨진 "P0.2 사건"이 이 원칙의 근거입니다.

"SDK는 숫자 임계값, 허용목록, 티어 정책을 절대 규정하지 않는다 — 이건 소비자의 트래픽·보안·저장 예산에 달린 문제다."
02

재사용이 증명되기 전엔 쪼개지 않는다

oxicode-cli는 66K LOC짜리 "의도된 모놀리스"입니다. 독립 재사용·독립 버전관리·빌드 격리·팀 경계, 이 4가지 조건이 실제로 성립하지 않으면 더 쪼개지 말라고 명시돼 있습니다.

"do not split it into more crates... re-evaluate at ~80K LOC"
03

죽은 경계는 지운다

독립 위젯 라이브러리였던 oxicode-tui는 워크스페이스 빌드에 한 번도 들어간 적 없는 죽은 코드로 판명나 통째로 삭제됐습니다. oxicode-store/oxicode-fs도 재사용이 증명되지 않아 각각 cli/sdk 내부 모듈로 흡수됐습니다.

04

메커니즘과 정책을 분리한다

oxicode-lsp는 JSON-RPC 프레이밍만 하는 552줄짜리 얇은 어댑터입니다. 설정 탐색, 폴더 신뢰, 크래시 복구, 멀티 서버 생명주기 같은 "정책"은 전부 oxicode-cli가 가져갑니다 — 다른 제품이 프레이밍만 재사용할 수 있도록.

05

한계를 정직하게 문서화한다

oxicode-api-stability#[unstable] 매크로는 사실 문서 배지만 붙일 뿐 빌드를 막지 못합니다. 팀은 이 사실을 숨기지 않고 명시합니다.

"proc-macro는 커스텀 lint를 등록할 수 없다 — 배지는 표면을 자기설명적으로 만들 뿐, 빌드를 게이트하지 않는다. 소비자가 이걸 컴파일 실패로 바꿀 방법이 없다면, 그 애노테이션은 순전히 장식이다."
+

상류의 경계를 그대로 물려받는다

oxicode-catalog는 omp(oh-my-pi)의 pi-catalog/pi-ai 분리를 그대로 미러링합니다 — oxicode-ai → oxicode-catalog 단방향 의존만 허용, 반대 방향은 금지. 크레이트 경계 자체가 상류 프로젝트에서 상속된 설계 결정입니다.

04

oxios: 에이전트 운영체제

oxios 자체는 src/lib.rs가 없는 순수 바이너리 크레이트입니다. 6개 라이브러리 크레이트를 조립해서 하나의 데몬으로 띄우죠. README의 "Unix 스타일 fork/exec/wait/kill" 비유 중 실제로 코드에 대응하는 건 그 다섯 단어뿐이고, 나머지는 직관을 돕는 은유라는 점도 문서에 명시돼 있습니다.

channels Web (Axum) CLI Telegram — src/api, src/channels/* (RFC-026 이후 모듈) gateway oxios-gateway — 채널 애그노스틱 메시지 허브 kernel oxios-kernel — 75,185 LOC (전체의 79%) KernelHandle · 22개 API "시스템콜" Supervisor Scheduler AccessMgr AuditTrail Budget CronSched CircuitBkr BrainConnector + EventBus · StateStore · A2AProtocol · McpBridge · GitLayer(gix) · WasmSandbox … → oxios-ouroboros · oxios-markdown · oxios-calendar · oxios-mcp (내부 크레이트) "의도적으로 모놀리식" — 순환 의존 0, 별점형(star) 위상, 재사용 증명 없음 (§10) engine oxicode-sdk crates.io 전용, 필수 oxibrain 데몬 Unix 소켓, 선택적
Channels → Gateway → Kernel → Engine. 커널의 KernelHandle은 "시스템콜 테이블"로 불리며, 모든 툴은 서브시스템을 직접 참조하지 않고 반드시 이 파사드를 거칩니다.
크레이트LOC역할내부 의존
oxios-kernel75,185OS의 핵심 — 생명주기, 이벤트버스, 상태저장, KernelHandle 파사드ouroboros, markdown, calendar, mcp
oxios-markdown8,781마크다운 지식베이스 (files.md 포트) — VirtualFs, BacklinkIndex
oxios-gateway3,131채널 애그노스틱 메시지 게이트웨이, 채널별 독립 백그라운드 태스크kernel, ouroboros
oxios-calendar2,686.ics 기반 캘린더 엔진 (RFC 5545)markdown
oxios-ouroboros1,981통합 의도 처리 — UNDERSTAND→PLAN→EXECUTE→VERIFY→REPORT 루프
oxios-mcp1,954MCP 클라이언트, 커널과 독립적으로도 쓸 수 있음
oxios (bin)32,472main.rs · kernel.rs(조립기) · api/ · channels/ · remote/위 6개 전부

생명주기·실행

AgentApiExecApiExtensionApi

상태·영속화

StateApiBrainApiMemoApiTimelineApiCompressionApi

인프라

InfraApiEngineApiBrowserApiMountApi

통신

A2aApiMcpApi

보안·정체성

SecurityApiPersonaApi

통합·기타

CalendarApiEmailApiTokenMaxingApiMarketplaceApiProjectApiKnowledgeLens
RFC-026 · 크레이트 재구조화

"애플리케이션 코드를 재사용 가능한 라이브러리로 오분류했다"

2026-06-21, oxios-weboxi-sdk 0.35.0에 고정된 oxios-kernel 1.5.1을 끌어오면서 워크스페이스의 0.37.1과 충돌해 빌드가 깨졌습니다. 문제는 oxios-web/oxios-cli/oxios-telegram이 사실 아무도 재사용하지 않는, oxios 바이너리 전용 코드였다는 점.

12크레이트
(RFC-026 이전)
9RFC-026 목표
(2026-06-21)
6현재
(oxios-memory도 RFC-047로 퇴역)

채택된 원칙은 단순합니다: "crates/ = 재사용 가능한 라이브러리, src/ = oxios 바이너리(서버)." 커널 자체를 더 잘게 쪼개자는 대안(C안)은 거부됐는데, 이유는 "커널은 전송 방식에 무지해야 한다 — HTTP 의존성이 커널에 들어오면 단일 책임 원칙 위반"이었습니다.

인용 · src/kernel.rs Kernel 구조체는 정작 oxios-kernel 크레이트가 아니라 바이너리 쪽 src/kernel.rs에 삽니다. 헤더 주석이 이유를 못박습니다 — "이 모듈은 컴포넌트를 *제공*하는 게 아니라 *조립*하기 때문에 바이너리 크레이트에 산다." 그리고 부트스트랩에는 재밌는 트릭이 하나 있는데, kernel.handle()이 실제로는 두 번 만들어집니다 — 순환 참조를 끊기 위한 NoOpSupervisor 기반의 "가짜" preliminary handle 한 번, 그다음 진짜 handle 한 번. 가짜 쪽은 캐시 키를 미리 채우면 안 되기 때문에 절대 재사용되지 않습니다.
05

oxios가 oxicode-sdk를 쓰는 방식

oxios는 oxicode-agent·oxicode-ai를 직접 import하지 않습니다. 오케스트레이션은 항상 oxicode-sdk의 빌더 표면을 거칩니다 — 03에서 본 "SDK가 행동을 소유한다" 원칙이 실제 소비자 코드에서 어떻게 지켜지는지 보여주는 대목입니다.

// crates/oxios-kernel/src/agent_runtime.rs
let mut builder = engine
    .oxi()
    .agent(agent_config)
    .workspace(&workspace)
    .system_prompt(system_prompt);

if let Some(auth) = engine.authorizer() { builder = builder.authorizer(auth.clone()); }
if let Some(tracer) = engine.tracer() { builder = builder.tracer(tracer.clone()); }
if let Some(ct) = engine.cost_tracker() { builder = builder.cost_tracker(ct.clone()); }
if config.token_budget > 0 { builder = builder.with_token_budget(...); }
if config.audit_tool_calls { builder = builder.with_logging(); }

let agent = Arc::new(builder.build()?);

// 멀티턴 툴콜링 루프 — oxios는 이 스트림만 소비한다
let result = agent.run_streaming(prompt, move |event| {
    match event {
        AgentEvent::ToolExecutionStart { .. } => { ... }
        AgentEvent::ToolExecutionEnd { .. }   => { ... }
        AgentEvent::AgentEnd { .. }          => { ... }
        AgentEvent::Error { .. }             => { ... }
        _ => {}
    }
});

integration seam oxios 워크스페이스 전체에서 oxicode_sdk::는 57개 파일이 쓰지만, 대부분 oxios-kernel 안에 몰려 있습니다. oxios 전용 CSpace 툴들은 Arc<dyn oxicode_sdk::AgentTool>로 감싸져 빌드가 끝난 에이전트에 사후 등록됩니다 — SDK 빌더가 소유(owned) 값만 받기 때문입니다. oxios의 docs/ARCHITECTURE.md는 여전히 옛 oxicode_sdk::AgentLoop::run() API를 언급하지만, 실제 코드는 이미 AgentBuilderrun_streaming() 패턴으로 마이그레이션을 마쳤습니다 (RFC-014 Phase D) — 문서가 코드를 따라잡지 못한 흔한 사례입니다.

06

oxibrain: 독립된 기억

oxibrain은 oxios 컴포넌트가 아닙니다. AGENTS.md 첫 줄부터 못박습니다 — "기본 빌드는 oxi 생태계 크레이트를 0개 끌어와야 한다"고, 그리고 cargo tree | grep oxios-|oxicode-가 CI에서 실제로 이를 강제합니다.

ecosystem.md §0 "네 개의 앱, 하나의 뇌, 앱마다 동사 하나씩." oximemo(쓰다) · oxiline(시간을 관리하다) · oxios(실행하다) · oxibrain(기억하고 이해하다). 각 앱은 자기 데이터의 소스오브트루스를 유지하고, oxibrain은 그것들을 가로질러 이해합니다.
Episode Ledger 불변 · append-only · 유일한 durable 쓰기 경로 reproject 모델 호출 없이 재생성 Projection — Truth entities · statements · beliefs byte-identical 재생성 Projection — Ranking vectors · FTS · communities 동등(equivalent) 재생성 "프로젝션을 지우고 reproject하면 모델 호출 없이 그대로 복원된다" — 유일하게 잃으면 안 되는 건 원장뿐
이벤트 소싱과 같은 패턴: 원장은 진실의 유일한 원천, 프로젝션(엔티티·벡터·검색 인덱스)은 언제든 버리고 다시 만들 수 있는 캐시입니다.
크레이트역할
oxibrain-portsLlmPort · EmbeddingPort · TokenizerPort · RerankPort · ClockPort 트레이트 정의
oxibrain-core순수 도메인 로직 — temporal fold, 추출, 랭킹, 패킹 (ports/index만 의존, store는 절대 모름)
oxibrain-storeSQLite 저장 계층 — 유일하게 rusqlite를 직접 만지는 크레이트
oxibrain-llm-local / embed-local기본 어댑터 — GGUF(문법 제약 디코딩) 로컬 추론, 다국어 로컬 임베딩
oxibrain-llm-http선택적 어댑터 — OpenAI 호환 HTTP 프로바이더
oxibrain (facade)Brain 페이사드 lib — 임베디드 소비자용 진입점
oxibrain-cli단일 바이너리 oxibrain — CLI + MCP 서버 + 데몬을 서브커맨드로
oxibrain-mcpMCP 툴 서버 — 툴 개수 상한 15개로 고정
oxibrain-client외부 소비자(oxios 등)를 위한 얇은 클라이언트 — Unix 소켓 JSON-RPC, HTTP도 gRPC도 아님
RFC-047 · Implemented, v1.40.0 · 2026-08-15

oxios-memory 18,075줄을 통째로 삭제

oxios는 자체 HnswMemoryIndex를 가진 18K LOC짜리 oxios-memory 크레이트를 완전히 삭제하고, oxios-kernel/src/brain/의 얇은 BrainConnection으로 대체했습니다. 소켓 호출이 실패하면 클라이언트를 버리고 다음 호출에서 한 번 재연결을 시도할 뿐, 모든 메서드가 Option<T>를 반환해 데몬이 꺼져 있어도 에이전트 턴은 정상 종료됩니다 — "브레인은 부가적일 뿐, 절대 필수가 아니다"라는 계약(C1) 그대로입니다.

문서 부채 oxios의 README.md는 아직 RFC-047 이전의 Hot/Warm/Cold 3계층·Dream 프로세스·HNSW+TF-IDF 구조를 현재형으로 설명합니다. 실제 코드는 이미 SONA 궤적 엔진만 커널에 남기고 나머지는 전부 oxibrain 데몬에 위임한 상태 — 코드가 문서보다 먼저 나간, 흔하지만 정확히 짚을 가치가 있는 괴리입니다.

인용 · AGENTS.md §3, .github/workflows/ci.yml oxibrain은 원칙만 세워두고 안 지키는 프로젝트가 아닙니다. "P6 engine is a library — core는 MCP/HTTP/CLI를 모른다", "P7 ports at the boundary — inference/embedding/tokenization/clock은 반드시 oxibrain trait 뒤에" 같은 11개 invariant를 CI가 cargo tree -p oxibrain | grep oxios- 같은 룰로 실제 강제합니다. 이 grep이 걸리면 빌드가 깨져요 — "약속"이 아니라 "빌드 실패"로 지켜지는 경계라는 뜻입니다.
07

왜 이 형태로 만들었나

언어, 배포 형태, 실행 모델 — 이것도 크레이트 경계 못지않게 명확한 이유가 있는 설계 결정입니다. 뒤에 나오는 경쟁자 비교의 상당 부분이 사실 이 세 가지 선택에서 갈라져 나옵니다.

왜 Rust인가

GC 이벤트 루프 vs 소유권 모델

Rust를 고른 건 취향이 아니라 이 프로젝트가 풀어야 하는 문제 자체가 요구한 선택에 가깝습니다. oxios는 여러 에이전트를 프로세스처럼 fork/exec/wait/kill 하면서 동시에 굴리고, 그 상태를 EventBus·StateStore로 계속 공유해야 하는 상시 구동 시스템입니다. TypeScript/Node 계열(Claude Code, opencode, OpenClaw)이 흔히 쓰는 싱글 스레드 이벤트 루프 + GC 조합은 요청 하나 처리하고 끝나는 짧은 프로세스에서는 전혀 문제가 안 되지만, 수십 개 에이전트를 몇 시간이고 물고 있는 데몬에서는 GC 정지 시간과 메모리 상승 곡선이 그대로 운영 리스크가 됩니다. Rust는 가비지 컬렉터 없이 컴파일 타임에 메모리 소유권을 검증하니, 오래 떠 있어도 메모리 사용량이 예측 가능하고 GC로 인한 지연 스파이크가 없습니다. 게다가 13개(oxicode)+6개(oxios) 크레이트로 나눈 워크스페이스는 이 규모의 시스템을 오래 유지보수한다는 전제를 깔고 있는데, Rust의 강한 타입 시스템과 트레이트 기반 포트 계약(oxicode-sdk의 15개 포트, oxios의 KernelHandle 22개 API)은 그 크레이트 경계를 컴파일러가 강제해줍니다. TypeScript도 타입은 있지만 런타임에 보장되는 게 아니라서, 이 정도로 많은 경계를 안전하게 유지하기는 더 어렵습니다.

물론 공짜는 아닙니다. Rust는 학습 곡선이 가파르고 개발 속도 자체는 TypeScript보다 느립니다 — 오너십·라이프타임 문제로 씨름하는 시간이 분명 있습니다. 컴파일 시간도 무시 못 합니다(oxios가 dev 프로필에서 opt-level을 일부러 1로 낮춰둔 것도 이 컴파일 시간 문제를 완화하려는 조치입니다). 채용 가능한 개발자 풀도 TypeScript보다 작고요. oh-my-pi가 Rust 코어에 TypeScript 패키지를 섞은 하이브리드로 남아있는 것도 아마 이 트레이드오프를 절충한 결과일 겁니다 — oxicode/oxios는 그 절충 없이 순수 Rust로 끝까지 밀어붙인 쪽이고, 그 대가로 개발 속도보다 장기 운영 안정성을 택한 셈입니다.

왜 단일 바이너리인가

curl | bash vs npm install

단일 바이너리는 Rust를 고른 데서 자연스럽게 따라온 결과이기도 하지만, 그 자체로 독립적인 장점이 있습니다. opencode는 Bun/Node 런타임이 있어야 돌고, Claude Code는 npm install이 전제입니다 — 사용자 머신에 "이미 맞는 런타임이 깔려 있다"는 가정을 까는 겁니다. oxicode/oxios는 curl | bash 한 줄이면 끝입니다. 정적으로 링크된 바이너리 하나 안에 의존 라이브러리가 전부 고정돼 들어가니, node_modules 트리가 통째로 안고 있는 버전 충돌·서플라이체인 리스크도 구조적으로 사라집니다. 시작 속도도 다릅니다 — 인터프리터 워밍업이나 JIT 컴파일 없이 바로 실행되니, CLI처럼 자주 스폰되는 프로그램에서는 이 차이가 체감됩니다. 배포 대상도 넓어집니다 — 컨테이너 이미지에 Node 런타임 레이어를 얹을 필요가 없으니 oxios 같은 데몬을 도커에 넣어도 이미지가 가볍고, 서버든 온프레미스든 실행 파일 하나 복사하면 끝입니다.

대신 단일 바이너리는 유연성을 조금 내줍니다. 실행 중에 코드를 갈아끼우는 동적 플러그인 로딩이 스크립트 언어보다 번거롭습니다 — 실제로 oxicode도 한때 OS 레벨 동적 라이브러리(.so/.dylib)로 익스텐션을 로드하는 방식을 문서에 남겨뒀다가, 결국 WASM 기반 익스텐션 로딩으로 갈아탔습니다. 정적 링크가 주는 안정성은 그대로 가져가면서 확장성 문제를 풀려다 보니 나온 선택이었을 겁니다. 바이너리 자체 크기도 스크립트 하나짜리 npm 패키지보다는 커지고요. "단일 바이너리"와 "그래도 재사용 가능한 SDK 크레이트로는 쪼갠다"는 두 요구를 동시에 만족시키려니, 크레이트 경계 설계에 더 신경 써야 했던 것도 이 형태가 치른 비용입니다.

왜 호스트에서 데몬으로 돌리는가

상주 프로세스 vs 클라우드 위임

oxios가 CLI 한 번 실행하고 끝나는 도구가 아니라 계속 떠 있는 데몬인 이유는, 상태를 유지해야 하는 일들이 애초에 요청 단위로는 풀리지 않기 때문입니다. CronScheduler가 예약 작업을 처리하려면 뭔가는 계속 깨어있어야 하고, 여러 채널(Web/CLI/Telegram)이 같은 세션·같은 에이전트 상태를 공유하려면 그 상태를 들고 있는 프로세스가 하나 필요합니다. 매 요청마다 새로 뜨는 서버리스 모델이었다면 EventBus·StateStore를 매번 다시 조립해야 했겠죠. 데몬으로 도는 덕에 인프로세스 브라우저(oxibrowser)나 인프로세스 git(gix)도 서브프로세스를 스폰하지 않고 직접 제어할 수 있습니다 — README가 못박아둔 "No containers. No subprocess browser."가 가능한 것도 결국 이 상시 구동 모델 덕분입니다. 그리고 이 전부가 사용자 인프라 안에서만 돈다는 것, 데이터가 외부 클라우드로 안 나간다는 것도 기업이나 프라이버시에 민감한 개인에게는 실질적인 이유가 됩니다.

그런데 이 편의는 그대로 운영 부담으로 돌아옵니다. 클라우드 서비스(Claude Code Routines 같은)를 쓰면 "서버가 살아있는지" 자체를 신경 쓸 필요가 없는데, 자체 호스팅 데몬은 그 책임을 사용자가 떠안습니다. oxios가 스스로 이 문제에 부딪힌 적도 있습니다 — 예전에는 웹서버·게이트웨이 태스크를 fire-and-forget으로 띄워놓고 죽어도 감지를 못해서, oxios status는 "Running"이라고 뜨는데 실제로는 절반만 살아있는 상황이 있었습니다(RFC-030). 결국 데몬 안에 또 다른 감시자(TaskSupervisor)를 자체 구현해야 했죠. 리소스도 항상 켜져 있으니 계속 CPU·메모리를 점유하고, 그래서 Budget Manager·Resource Monitor 같은 자체 통제 장치가 필요해집니다 — 서버리스였다면 신경 안 써도 될 비용입니다. 업데이트할 때도 재시작이 필요하니 진행 중인 작업을 어떻게 안전하게 넘길지 스스로 설계해야 하고, 다른 기기에서 내 데몬에 접근하려면 클라우드처럼 그냥 로그인하면 되는 게 아니라 별도의 원격 접속 체계를 직접 만들어야 합니다(E2EE 페어링 기반 리모트 컴패니언 기능을 따로 구현한 이유, RFC-044). 데몬 모델은 "내 손 안에 다 있다"는 통제력을 주는 대신, 클라우드가 대신 해주던 운영 전부를 스스로 떠안는 거래입니다.

08

oxicode의 경쟁자들

oh-my-pi는 경쟁자라기보단 조상에 가깝습니다 — Mnemopi(기억), managed-skills(스킬 자동학습), snapcompact(비전 컨텍스트 압축) 세 서브시스템이 전부 이름 그대로 oxicode에 포팅돼 있습니다.

oxicodeoh-my-pi (omp)opencodeClaude Code
언어RustRust(~80K core) + TSTypeScript (Bun)TypeScript
배포단일 정적 바이너리바이너리 + 벤더 패키지npm / Bun 모노레포npm 패키지
아키텍처13크레이트, SDK/CLI 분리Pi 포크, LSP(14)+DAP(14)+브라우저로컬 서버 + 다중 클라이언트(TUI/데스크톱/VSCode/모바일)단일 엔진, 터미널/IDE/데스크톱/브라우저 공유
기억/RAGoxicode-mnemopi (SQLite FTS5+벡터)Mnemopi 원조 — remember/recall 툴SQLite 세션 상태CLAUDE.md + 세션 메모리
확장MCP client, WASM 익스텐션60+ 프로바이더, 31개 내장 툴Plan/Build 모드, undo/redohooks, MCP, 서브에이전트
차별점정책-메커니즘 분리, 포트 기반 SDKIDE가 내장된 코딩 에이전트 원형하나의 서버를 여러 클라이언트가 공유Anthropic 모델 전용 최적화

oh-my-pi

원조 vs 파생

사실 oh-my-pi는 경쟁자라기보다 오리지널에 가깝습니다. oxicode가 통째로 이식해 온 서브시스템만 셋(Mnemopi, managed-skills, snapcompact)이니, "누가 더 나은가"를 묻기 전에 oxicode는 oh-my-pi의 좋은 아이디어를 Rust로 재구성하면서 태어난 프로젝트라는 걸 인정하고 시작해야 합니다. 그래도 이식 과정에서 얻은 게 있습니다 — oh-my-pi는 Rust 코어(~80K줄)에 TypeScript 패키지가 섞인 하이브리드 배포인데, oxicode는 그 개념들을 전부 순수 Rust 크레이트로 다시 짜면서 단일 정적 바이너리 하나로 밀어넣었습니다. 설치가 스크립트 한 줄로 끝나고 Node·Bun 런타임을 따로 깔 필요가 없다는 뜻이죠. "SDK가 행동을 소유한다"는 크레이트 경계 규율도 oh-my-pi에는 없던 것이고, oxicode-lsp처럼 프로토콜만 딱 떼어낸 얇은 어댑터도 재사용성 면에서 더 깔끔합니다.

반대로 냉정하게 보면 기능 커버리지는 oh-my-pi가 아직 한참 앞서 있습니다. LSP 14개 오퍼레이션에 DAP(디버거 프로토콜) 14개 오퍼레이션까지 지원하는데, oxicode-lsp는 JSON-RPC 프레이밍만 하는 552줄짜리 얇은 어댑터라 디버거 통합 자체가 없습니다. oh-my-pi는 60개가 넘는 프로바이더와 31개 내장 툴, 거기에 브라우저 제어·Python 실행·서브에이전트까지 한 프로젝트 안에 다 들어있는데, oxicode-agent는 21개 툴(그중 7개만 필수)로 상대적으로 더 미니멀합니다. 결국 oxicode는 "더 잘 조직된 후발주자"고, oh-my-pi는 "기능은 더 많지만 조직은 덜 정돈된 원조"인 셈입니다.

opencode

단일 바이너리 vs client/server

opencode와 나란히 놓고 보면 가장 먼저 눈에 띄는 차이는 배포 방식입니다. opencode는 Bun/Node 위에서 도는 TypeScript 모노레포라 로컬 서버 하나가 뜨고, 그 서버에 TUI·데스크톱 앱(Electron)·VSCode 확장·모바일 클라이언트가 동시에 접속하는 client/server 구조입니다. oxicode는 그냥 정적 바이너리 하나 실행하면 끝이라 배포·설치가 압도적으로 단순합니다. 게다가 oxicode-sdk를 별도 크레이트로 떼어낸 덕분에 다른 Rust 프로젝트가 CLI는 필요 없고 에이전트 런타임만 갖다 쓰고 싶을 때 크레이트 하나만 의존성으로 걸면 됩니다 — 실제로 oxios가 정확히 이렇게 합니다. opencode에는 이런 식으로 딱 떼어서 재사용할 수 있는 "SDK 크레이트" 개념 자체가 없습니다.

그런데 이 client/server 구조가 opencode한테는 진짜 장점이기도 합니다. 서버가 세션 상태를 SQLite에 들고 있으니 터미널에서 시작한 작업을 데스크톱 앱이나 VSCode에서 이어받아 볼 수 있습니다 — oxicode처럼 단일 프로세스 TUI 중심 구조에서는 애초에 상상하기 어려운 시나리오죠. opencode는 또 Plan(읽기 전용)/Build 모드를 명시적으로 나누고 undo/redo까지 붙여놨는데, 이 정도의 세밀한 UX 다듬기는 oxicode 쪽 문서에서는 아직 확인되지 않습니다. 정리하면 oxicode는 "가볍고 재사용 가능한 엔진"에 강하고, opencode는 "여러 디바이스를 넘나드는 협업형 UX"에 강합니다.

Claude Code

오픈소스 자유 vs 수직 통합

oxicode 대 Claude Code는 "오픈소스 자유 vs 수직 통합 최적화" 싸움에 가깝습니다. oxicode는 openai·anthropic·google·vertex·azure·bedrock·ollama까지 8개 프로바이더를 다 붙여놨고 로컬 SQLite 벡터 메모리(mnemopi)까지 내장하고 있어서, 어떤 모델을 쓸지·데이터를 어디에 둘지 전부 사용자가 결정할 수 있습니다. 완전히 자체 호스팅이 가능하다는 것도 강점이고요. Claude Code는 태생적으로 Anthropic 모델에 묶여 있습니다.

근데 바로 그 "묶여 있음"이 Claude Code의 무기이기도 합니다. 같은 회사가 모델과 도구를 같이 만드니 프롬프트 설계·툴 콜링 포맷·컨텍스트 관리가 모델 특성에 맞춰 세밀하게 튜닝돼 있고, 이건 멀티 프로바이더를 지향하는 oxicode가 구조적으로 따라가기 어려운 이점입니다. 거기에 IDE 확장·데스크톱 앱·hooks·MCP·서브에이전트까지 아우르는 생태계 규모, 공식 문서와 지원 조직의 크기 자체가 비교가 안 됩니다. oxicode는 소수가 끌고 가는 프로젝트라 안정성 검증이나 엔터프라이즈 지원 트랙레코드가 아직 없죠. 모델 선택의 자유와 데이터 주권이 중요하면 oxicode, 최고 수준으로 다듬어진 단일 경험이 필요하면 Claude Code로 갈리는 그림입니다.

09

oxios의 경쟁자들

"상시 구동형 에이전트 플랫폼"이라는 카테고리 자체가 아직 좁습니다. Claude Code는 클라우드 Routines로, OpenClaw는 메신저 게이트웨이로 각자 다른 방향에서 접근합니다.

oxiosClaude Code (Routines)OpenClaw
호스팅자체 호스팅 Rust 데몬Anthropic 클라우드, 구독 기반자체 호스팅 (사용자 기기)
단위상태를 가진 에이전트 프로세스 (fork/exec/wait/kill)예약된 프롬프트 실행메신저 채널에 상주하는 개인 비서
접근 경로REST API 150+ 엔드포인트 + 대시보드API 호출 / GitHub 이벤트 트리거WhatsApp·Telegram·Slack·Discord·iMessage 게이트웨이
기억oxibrain 위임 (불변 원장 + 재생성 인덱스)명시적 영속 기억 시스템 없음확인되지 않음
프로토콜MCP + A2A(Google) 동시 지원MCP확인되지 않음
브라우저oxibrowser — 인프로세스, 서브프로세스 없음해당 없음해당 없음
네이티브 데몬 요청제품 자체가 데몬커뮤니티 요청(#28229) "not planned"로 종료제품 자체가 데몬

Claude Code · Routines

상시 프로세스 vs 예약된 프롬프트

oxios와 Claude Code의 Routines를 나란히 놓고 보면 이건 아예 다른 무게 체급의 물건입니다. Routines는 "예약된 프롬프트 실행"에 가깝습니다 — 특정 시간이나 GitHub 이벤트가 오면 정해진 프롬프트를 한 번 돌리는 것으로, 상태를 가진 에이전트 프로세스라는 개념 자체가 없습니다. 반면 oxios는 fork/exec/wait/kill로 에이전트를 진짜 프로세스처럼 다루고, REST API 150개 이상 엔드포인트로 그 전체를 프로그래밍할 수 있고, MCP와 A2A(에이전트 간 통신)를 동시에 지원합니다. 실제로 커뮤니티에서 Claude Code에 네이티브 데몬·스케줄러를 만들어달라는 요청(#28229)이 올라왔는데 Anthropic은 "not planned"로 닫아버렸습니다 — oxios가 정확히 그 빈자리를 자기 존재 이유로 삼고 있는 셈입니다. 자체 호스팅이라 데이터가 외부로 안 나간다는 것도 기업 입장에선 중요한 포인트고요.

반대로 Routines의 장점은 압도적인 편함입니다. 클릭 몇 번으로 클라우드에 바로 올라가고, 서버를 사거나 운영할 필요가 전혀 없습니다. oxios는 데몬이니 누군가는 그 프로세스가 살아있는지·리소스는 괜찮은지 신경 써야 하는데(그래서 Budget Manager·Resource Monitor 같은 걸 자체 구현했습니다), Routines는 그런 운영 부담을 Anthropic이 통째로 가져가 버립니다. 거기에 Anthropic 모델의 프롬프트 캐싱·컨텍스트 압축 같은 모델 레벨 최적화 혜택도 자동으로 따라오고, GitHub 이벤트 트리거처럼 이미 있는 SaaS 생태계와의 연결도 매끈합니다. "운영 부담 없이 가볍게 자동화만 하고 싶다"면 Routines가 압도적으로 편하고, "여러 에이전트를 프로세스처럼 부리고 싶다"면 그 그림 자체가 Routines에는 없습니다.

OpenClaw

개발자 인프라 vs 메신저 비서

OpenClaw는 접근 자체가 다릅니다. 이미 쓰고 있는 WhatsApp·Telegram·Slack·Discord·iMessage 같은 메신저 안으로 비서가 들어오는 방식이라 사용자 입장에서는 배울 게 거의 없습니다 — 그냥 메시지를 보내면 됩니다. 이 진입장벽의 낮음 덕분인지 실제로 채택 규모도 꽤 큰 것으로 조사됐습니다. oxios는 이런 손쉬운 진입로가 없습니다. REST API와 대시보드를 통해 접근하는, 명백히 개발자·파워유저를 겨냥한 물건입니다.

하지만 그 대신 oxios는 훨씬 무거운 일을 할 수 있게 설계돼 있습니다. 여러 에이전트를 동시에 프로세스처럼 굴리는 멀티 에이전트 오케스트레이션, MCP+A2A로 에이전트끼리 서로 대화하게 만드는 구조, oxibrain에 위임하는 불변 원장+재생성 프로젝션 기반의 정교한 기억 시스템까지 — 이 정도 구조를 가진 개인 비서형 제품은 조사 범위 안에서 확인되지 않았습니다(OpenClaw가 MCP·A2A를 지원하는지, 벡터 기억을 갖고 있는지는 공개된 자료로는 확인이 안 됐습니다). 브라우저도 서브프로세스 없이 인프로세스로 도는 oxibrowser를 내장하고 있고요. OpenClaw는 "이미 쓰는 메신저 안에서 만나는 개인 비서"에 강하고, oxios는 "여러 에이전트를 동시에 운용하는 백엔드 인프라"에 강한, 사실상 다른 카테고리의 제품입니다.

포지셔닝 oxios는 여러 에이전트를 프로세스처럼 동시에 굴리는 멀티 에이전트 오케스트레이션에 무게가 있고, OpenClaw는 기존 메신저 안에서 만나는 1:1 개인 비서에 무게가 있습니다. Claude Code의 Routines는 상태를 가진 "에이전트"가 아니라 "예약된 프롬프트"를 스케줄링한다는 점에서 셋 중 가장 가볍습니다.

10

정리

oxicode는 "SDK가 행동을 소유하고 소비자가 정책을 소유한다"는 원칙의 발원지이고, oxios는 그 원칙을 커널 전체 규모로 확장한 결과이며, oxibrain은 같은 규율을 기억이라는 한 도메인에 다시 적용해 완전히 독립된 제품으로 떼어낸 결과입니다. 세 프로젝트를 관통하는 건 하나 — 재사용이 증명되기 전엔 크레이트 경계를 열지 않는다는 규율이고, 재사용이 증명되면(oxios가 oxicode-sdk를, oxios가 oxibrain-client를 쓰듯) 그 경계는 곧바로 제품 간 계약이 됩니다.

소스 — 모두 로컬 워크스페이스 직접 조사 및 공개 저장소 기준, 2026-08-16
  • github.com/project-oxi/oxicode — AGENTS.md, docs/oxi-sdk-ownership.md, 13개 크레이트 Cargo.toml/src
  • github.com/project-oxi/oxios — docs/ARCHITECTURE.md, docs/rfc-026, docs/rfc-047, 6개 크레이트 + src/
  • oxibrain — doc/ARCHITECTURE.md, doc/ECOSYSTEM.md, 13개 크레이트
  • github.com/can1357/oh-my-pi, github.com/sst/opencode, github.com/openclaw/openclaw, code.claude.com/docs