오픈소스 칸반 Multica, 사람과 26개 AI 에이전트 한 팀 구성
8개월 만에 Star 5만178개를 받은 오픈소스 칸반 Multica는 26개 Agent CLI를 하나의 보드로 통합해 작업은 worktree, 납품은 브랜치로 처리하고 코드는 사용자 컴퓨터를 벗어나지 않는다.
중국어 원문을 AI로 번역했습니다. 고유명사와 수치는 원문 표기를 우선하며, 중요한 판단에는 아래 출처 원문을 함께 확인하세요.
1960년대, MIT의 Project MAC은 제너럴 일렉트릭과 벨 연구소를 끌어들여 야심이 대단히 큰 기계 하나를 만들었다. Multics다. 그것은 당시로서는 미친 짓으로 보였던 일, 즉 수십 명이 동시에 컴퓨터 한 대를 쓰면서도 각자 자신이 기기 전체를 독점하고 있다고 여기게 하는 일을 하려 했다. 이것이 시분할이다. 이후 벨 연구소가 빠지자, Ken Thompson은 놀고 있던 PDP-7 한 대에서 이 사상을 뼈대만 남도록 잘라내고 Unix라는 이름을 붙였다.
60년 후, 한 프로젝트가 이 역사를 다시 꺼내 들었다. Multica, 즉 Multiplexed Information and Computing Agent의 약자로, VISION 문서에서 대놓고 Multics를 오마주한 것이라고 인정한다. 다만 이번에 시분할되는 것은 컴퓨터 한 대가 아니라 하나의 팀이고, 그것을 공유하는 것은 사람만이 아니라 여러 AI 코딩 Agent이기도 하다.
한마디로 정의하면, 이것은 자체 호스팅 가능한 작업 칸반 보드로, 이슈를 Agent에게 배정하면 마치 동료에게 배정한 것과 같다. Agent는 스스로 작업을 가져가고, 당신의 기기에서 실행하며, 일하면서 댓글을 달고, 다 끝나면 브랜치를 돌려주고 당신의 검토를 기다린다.
2026년 1월에야 저장소를 만든 이 프로젝트는 8개월 만에 Star 50178개, Fork 6491개를 모았고, 가장 최근 릴리스는 이틀 전의 v0.4.44다. 오늘은 이 프로젝트가 무엇으로 이만한지를 뜯어보겠다.
아픈 것은 Agent가 없는 게 아니라 Agent가 너무 많은 것
지금의 일상을 한번 떠올려 보자. Claude Code는 터미널 탭 하나, Codex는 하나, Cursor는 또 하나. 각 Agent는 자기 세션 안에서 살고, 세션이 닫히면 맥락은 전부 증발하며, 오후 세 시에 당신은 세 번째 Agent에게 아침 여덟 시에 설명했던 배경을 다시 설명하고 있다. README가 이 장면을 묘사한 문장은 꽤 뼈아프다. Agent를 더 많이 추가할수록, 아이를 돌보는 데 쓰는 시간이 더 길어진다.
Multica의 해법은 Linear식 칸반 보드를 제어면(control plane)으로 만드는 것이다. 이슈 보드, 담당자 지정, 댓글 영역, 상태 전이, 전부 사람과 Agent가 섞인 팀을 위해 설계되었다. 담당자 지정 드롭다운에 Agent와 사람이 나란히 나타나고, Agent는 작업을 받으면 스스로 이슈에 진행 상황을 댓글로 달고, 막히면 당신을 부르며, 다 끝나면 이슈를 review 열로 끌어다 놓는다.
핵심적인 취사선택 하나에 주목하자. 그것은 모델을 만들지도, Agent를 내장하지도 않는다. Claude Code를 쓰고 싶으면 claude CLI를 알아서 설치해야 하고, Codex를 쓰고 싶으면 codex를 설치해야 한다. Multica는 그것들을 구동할 뿐이며, README의 표현에 따르면 공급자 전환은 마이그레이션 프로젝트가 아니라 드롭다운의 문제다.
이 취사선택이它的 전체 구조를 결정한다.
CLI 26개, 인터페이스 하나
백엔드는 Go로 작성되었고, Chi 라우팅에 WebSocket을 더했으며, PostgreSQL 17로 데이터를 저장하고, 프런트엔드는 Next.js 16, 데스크톱은 Electron이 Web 패키지를 그대로 재사용한다. 기술 스택 자체는 별것 아니지만, 별난 점은 26개의 제각각인 Agent CLI를 어떻게 하나의 통일된 추상으로 꼬아냈는가다.
핵심은 server/pkg/agent/agent.go의 Backend 인터페이스에 있다. Agent마다 어댑터 파일 하나씩, claude.go, codex.go, cursor.go, kimi.go가 있어, 각자 자기 CLI의 출력 스트림을 통일된 Message 이벤트, 즉 text, tool-use, tool-result, thinking으로 번역한다. 상위 계층이 보는 것은 언제나 하나의 Session, 하나의 Messages 채널에 하나의 Result 채널이다.
하지만 정말 영리한 것은 'CLI 하나에 어댑터 하나'가 아니라 프로토콜 패밀리(protocol family)라는 이 추상 계층이다. SupportedTypes에 등록된 것은 26개의 동급 백엔드가 아니라 25개의 프로토콜 패밀리다. qoder와 qoderclicn은 국제판과 중국판이 같은 ACP 백엔드를 공유하고, oh-my-pi는 pi의 JSON 프로토콜을 쓴다. server/pkg/agent/builtin_runtimes.go에서는 이것을 BuiltinRuntime 기술자(descriptor)라고 부르며, 주석에 아주 노골적으로 적혀 있다. 기존 런타임의 호환 fork를 추가하는 것은 기술자 한 줄을 추가하는 일이지, 스택을 가로지르는 변경 한 번이 아니라고.
이 화이트리스트는 데이터베이스 계층에도 못 박혀 있다. runtime_profile 테이블의 protocol_family 열에는 CHECK 제약이 붙어 있는데, migration 120에서 만들어졌고 이후 프로토콜 패밀리가 추가될 때마다 확장되어, migration 441에서 codearts를 추가하기에 이르렀다. 어댑터, 데이터베이스 제약, 프런트엔드 표시, 이 세 곳은 영원히 같은 보폭으로 움직인다.
덤으로 이스터에그 하나를 파냈다. 코드에는 사실 26번째 백엔드 zeroclaw가 이미 있는데, migration 403에서 추가된 것이지만 README의 런타임 표에는 없다. grep을 돌려도 결과가 전무하다. 즉 '26 agent CLIs'라는 문장은 코드를 세면 맞고, 문서를 세면 하나가 빠진다. 대수롭지 않지만, 반복 속도가 얼마나 빠른지, 코드가 문서보다 앞서 달린다는 것을 알 수 있다.
출신에 관한 디테일도 하나 꽤 흥미롭다. agent.go의 패키지 주석은 스스로 자백한다. 이 Backend 패턴은 "mirrors the happy-cli AgentBackend pattern, translated to idiomatic Go"라고. happy는 Claude Code를 위한 휴대폰 원격 조종을 만드는 프로젝트다. 오픈소스 세계의 염색체는 이렇게 흘러 다닌다.
작업이 곧 worktree
두 번째로 뜯어볼 만한 것은 전달 모델로, server/internal/daemon/execenv/local_worktree.go에 있다.
Agent가 당신의 기기에서 일할 때 가장 무서운 것은 그것이 당신이 편집 중인 디렉터리를 엉망으로 만드는 일이다. Multica는 각 작업에 독립적인 git worktree를 하나 발급하는데, daemon 자체의 환경 디렉터리에 만든다. 파일 서두에는 세 가지 보장이 나열되어 있는데, 상당히 잘 써 있다.
하나, Agent가 보는 것은 당신이 보는 것과 같다. 그냥 git worktree add를 하면 HEAD를 체크아웃하므로 당신의 커밋되지 않은 변경이 전부 숨어 버리는데, 그래서 그들은 당신 작업 디렉터리의 스냅숏을 worktree에 재적용하며, 추적되지 않은 파일까지 챙긴다.
둘, 당신의 디렉터리에는 단 1바이트도 쓰지 않는다. 모든 중간 산출물, 즉 per-task 맥락 파일까지 포함해 전부 일회성 worktree에 떨어지고, 마지막에 당신의 저장소에 남는 것은 그 브랜치 하나와, 이 브랜치가 누구의 것이고 무엇을 담았는지 기록하는 숨겨진 ref 하나뿐이다.
셋, 무엇도 몰래 버려서는 안 된다. Agent가 남긴 커밋되지 않은 내용은 worktree가 파괴되기 전에 대신 브랜치로 커밋해 준다.
쉽게 말하면, 전달물은 스크린샷도 아니고 채팅 기록도 아니며, 당신이 곧바로 git branch로 확인할 수 있는 진짜 브랜치다.
환경 준비 자체도 한층 격상되었다. execenv의 Prepare와 Reuse는 daemon 프로세스 안에서 실행되지 않고, multica 자체의 자식 프로세스를 fork하며, __multica_execenv_prepare라는 사설 인자로 helper 모드에 진입한다. 그 이유는 주석에 적혀 있다. 파일 시스템 호출이 만약 멈춰 버리면 자식 프로세스는 곧바로 죽일 수 있지만, 프로세스 내부의 goroutine은 깔끔하게 죽일 수 없고, 작업을 재시도한 뒤에도 그것이 여전히 쓰고 있을 수 있다.
서버와 daemon 사이는 WebSocket으로 오가며, server/internal/daemonws/hub.go에서 각 연결은 RuntimeLease를 보유하고, 연결이 성립할 때 한 번에 일괄 권한을 부여한 뒤, 이후 하트비트는 생존 상태만 갱신한다. 이 모든 것에는 실제 장애에 교육받은 냄새가 배어 있다.
초과시간 분류학 한 벌, 전부 수업료다
솔직히 말하면, agent.go의 ExecOptions를 읽는 것은 이번 분해에서 내가 가장 당신에게 보여주고 싶은 부분이다. 실행 옵션 구조체 하나에 예닐곱 가지 초과시간(timeout)이 들어 있다.
SemanticInactivityTimeout은 '돌아가고 있는 turn이 말을 잃었는가'를 관리하고, FirstTurnNoProgressTimeout은 '첫 turn이 도대체 산출을 시작했는가'를 관리하며, HandshakeTimeout은 기동 RPC를 관리하고, TurnInterruptTimeout은 취소 이후 app-server가 얼마 만에 반드시 응답해야 하는지를 관리하며, ThreadHandshakeTimeout은 다시 더 무거운 thread/start에 별도로 여유 예산을 늘려준다. 주석에서는 이 매개변수들이 서로 다른 질문에 답하기 때문에 독립적으로 움직인다고 특별히 강조한다. 각 필드 뒤에는 이슈 번호가 붙어 있는데, #3262, MUL-4424, 즉 즉흥적으로 쓴 것이 아니다.
세션 복구의 의미론은 무서울 만큼 세밀하다. Result 안의 ResumeRejected와 ResumeRejectedTransient는 서로 다른 두 개의 불리언으로, 전자는 세션이 영구히 망가져 다시 열어야만 함을, 후자는 일시적으로 이어붙일 수 없지만 세션은 아직 건강함을 뜻한다. 어떤 백엔드가 거부를 아예 감지할 수 없는지는 resumeRejectionUndetectable 목록이 따로 있는데, 주석에는 새 백엔드는 기본적으로 '보고하지 않음' 항목에 들어가며, fail closed라고 적혀 있다.
회계까지도 끝까지 파고들었다. TokenUsage의 비용 필드는 부동소수를 쓰지 않고, 1e-10 달러 단위 tick을 int64로 저장한다. 주석은 그 이유를 설명한다. xAI의 과금은 prompt가 200K 토큰을 넘으면 두 배가 되고, 한 turn이 여러 모델 호출을 집계하므로, 토큰 수에 요율을 곱해서는 단일 요청이 어느 가격 구간에 걸렸는지 도저히 복원할 수 없고, 공급자가 스스로 보고한 수치만이 정확하다.
이런 디테일은 사람을 속일 수 없다. 생산 장애로 먹여 길러진 것이다.
더 단단한 실증도 하나 있다. 기여자 순위 다섯 번째인 multica-eve, 커밋 442회로, 하는 일은 '고빈도 조회 경로에 인덱스 추가', 'disabled capabilities를 재시도 불가로 분류'와 같은 정식 엔지니어링 작업이다. 그것의 commit message를 뒤져 보면, 모든 squash 단락 뒤에 Co-authored-by: multica-agent 한 줄이 따라붙는다. 그들은 정말로 Multica로 Multica를 개발하고 있고, Agent의 코드가 곧바로 main에 들어간다.
저장소 루트의 AGENTS.md도 볼 만한데, agent 기여자를 위해 패키지 경계 규율이 빼곡히 적혀 있다. packages/core는 localStorage를 건드리지 말 것, packages/views는 next/*를 import하지 말 것, SQL을 고쳤으면 make sqlc를 기억할 것. agent를 인턴 관리하듯 관리한다.
무료로 열어 보여주지만, 남에게 열어주려면 협의해야 한다
솔직히 말하면, 이 절이 당신이 손을 대기 전에 가장 먼저 봐야 할 부분이다.
README의 구호는 open-source and self-hostable이지만, GitHub 페이지의 license 항목에 표시된 것은 Other다. LICENSE 파일을 열어 보면, 그것은 분명 완전한 Apache 2.0 텍스트이고, 앞에 Part I 추가 조항이 한 단락 붙어 있다.
조항 1a, 상업적 라이선스 없이는 이 소스 코드를 제3자에게 호스팅 서비스로 제공할 수 없다. 주목할 점은 무료조차 규제한다는 것이다. 조직 외부 사용자에게 개방된 공개 인스턴스는, 비용을 받지도 광고를 넣지도 않더라도 상업적 라이선스가 필요하다. 조직 내부 자체 사용은 제한되지 않고, fork 후 소스 코드를 공개하는 것도 호스팅으로 치지 않는다.
조항 1b는 브랜드 잠금이다. apps/web, apps/desktop, apps/mobile, packages/views, packages/ui 등 이들 디렉터리에서 파생된 인터페이스는 서면 면제를 받지 않는 한 LOGO를 건드리거나 제품 이름을 바꿀 수 없다. 순수하게 백엔드, daemon, CLI만 돌리는 것은 이 조항의 적용을 받지 않지만, 조항 1c에 이르면 당신의 사용자 문서에 제품이 Multica에 기반함을 선언하고 저장소 링크를 첨부해야 한다.
상업적 라이선스와 브랜드 면제는 두 권의 증서로, 한 권을 받았다고 다른 한 권이 딸려오지 않는다.
이치대로 따지면 내부 사용과 2차 개발에는 장애물이 없고, 조항은 아주 명확하게 쓰여 있다. 하지만 엄밀히 말해 이것은 OSI 의미의 오픈소스가 아니라, open-core 색채가 매우 진한 소스 공개(source-available)다. 이것으로 대외 플랫폼을 만들려면 먼저 메일을 보내 라이선스를 협의하라.
그것은 어디에 서 있고, 누구와 싸우는가
차원 Multica Copilot coding agent Devin / Jules happy / 포지셔닝 사람+Agent 혼합 칸반, 이슈를 배정 / Copilot에 배정, 단독 클라우드 작업 / Claude Code 휴대폰 원격 조종 / 실행 위치 당신의 기기 GitHub 클라우드 벤더 클라우드 당신의 기기 / 공급자 26개 CLI 자유 교체 Copilot 전용 자사 전용 사실상 Claude 전용 / 자체 호스팅 Docker / Helm 미지원 미지원 부분 지원 / 형태 칸반+런타임 이슈 네이티브 독립 제품 채팅 껍데기
GitHub의 Copilot coding agent가 Multica와 가장 닮은 점은 '이슈 배정'이지만, 그것은 GitHub 생태계와 자사 모델에 못 박혀 있다. Devin과 Jules는 클라우드 단독 병력으로, 개봉 즉시 사용할 수 있다는 것은 사실이고, 당신의 코드가 문을 나서야 한다는 것도 사실이다. happy는 '사람이 컴퓨터 앞에 없다'를 해결하고, Multica는 '팀이 어떻게 협업하는가'를 해결한다. 같은 트랙의 정면 경쟁자는 사실 아직 몇 안 되고, 이 카테고리는 올해에야 형태를 갖추기 시작했다.
탑승 전에 분명히 생각할 세 가지
898개의 open issue는 장식이 아니다. #4072는 Agent가 계속 대기하고 task claim이 타임아웃되는 문제이고, #3262는 Codex app-server가 running 상태에서 멈춰 출력이 없는 문제로, 스케줄링 계층과 어댑터 계층의 잔고장이며 일상에서 마주칠 확률이 낮지 않다. 26개의 백엔드에 각 CLI의 괴벽을 곱하면 테스트 매트릭스는 천문학적 숫자가 된다.
버전은 아직 0.4.x에 머물러 있다. 보름 동안 8개 버전을 냈고, README 스스로도 main이 너무 빨리 돌아가니 자주 pull 하라고 알려준다. 새 버전을 쫓는 건 짜릿하지만, 쫓다 보면 schema가 바뀌는 것도 사실이다.
또 하나의 전제 조건은, Agent를 돌리는 머신에 최소 하나의 지원되는 CLI가 설치되어 있고 로그인까지 완료되어 있어야 한다는 점이다. Multica는 그것들을 구동할 뿐, 함께 제공하지는 않는다. 클라우드 버전은 가입 즉시 사용할 수 있지만 Agent가 그쪽에서 돌아가므로, 「코드가 밖으로 나가지 않는다」는 완전한 서사를 원한다면 자체 호스팅을 해야 하고, 그 대가는 Docker와 Postgres를 돌봐야 한다는 것이다.
타워 모드
나는 줄곧 Multica에서 가장 베낄 만한 것이 특정 기능이 아니라 하나의 위치 선택이라고 생각해 왔다.
Agent 생태계에서 지금 가장 부족하지 않은 것은 실행기다. Claude Code, Codex, Cursor 모두 필사적으로 강해지고 있고, 다음 달이면 또 세 개쯤 튀어나올지도 모른다. 그 적응 표에 있는 이름들, qodercli, qoderclicn, traecli를 세어 보면, 여러분이 들어보지 못한 CLI도 꽤 있을 것이다. 27번째 CLI를 만드는 것은 막다른 길이다. Multica는 타워가 되기를 선택했고, 스스로는 영원히 이륙하지 않으며, 그저 26대 항공기의 이착륙, 적재량, 연료 소모, 사고 기록을 통일적으로 관리해 「누가 무엇을 하고 있는가」를 팀이 공유하는 구조화된 사실로 만든다.
실행 계층이 번성할수록 제어 계층의 자리는 더 값져진다. 이 판단은 실행기가 폭발하고 있는 어떤 영역에서든 재사용할 수 있다. 에디터가 그렇고, 모델 게이트웨이가 그렇고, Agent는 더욱 그렇다.
Multics의 회귀에 관해서라면, 당시의 시분할은 비싼 기계가 놀지 않게 하기 위한 것이었지만, 지금의 시분할은 비싼 사람이 Agent에 끌려 헛돌지 않게 하기 위한 것이다. VISION에 있는 그 문장 「엔지니어 두 명에 Agent 한 팀이면, 스무 명의 일을 해낼 수 있다」는 반년은 지켜볼 만한 베팅이다.
코드를 직접 뜯어보고 싶은 사람은, 저장소 링크가 서두에 있으니 로컬에서 make dev를 한 번 돌려보라. README에 있는 그 열 장의 스크린샷보다 설득력이 있다.