AI 에이전트를 위한 SSH 기반 프로젝트 문서 관리
요약
AI 에이전트가 프로젝트 문서와 작업 노트를 효율적으로 관리할 수 있도록 SSH 기반의 파일 시스템 인터페이스를 제공하는 docs-ssh 프로젝트를 소개합니다. 메인 저장소와 분리된 환경에서 에이전트가 직접 파일을 읽고 쓸 수 있는 셸 네이티브 접근 방식을 제안합니다.
핵심 포인트
- AI 에이전트가 접근하기 쉬운 SSH 기반 문서 관리 도구 docs-ssh 공개
- 메인 코드 저장소와 프로젝트 지식/로그를 분리하여 관리 가능
- 에이전트가 grep, find 등 셸 도구를 사용하여 문서를 탐색하도록 유도
- 인간을 위한 브라우저 뷰어와 에이전트를 위한 SSH 인터페이스 동시 지원
저는 AI 에이전트가 생성한 디자인 노트와 구현 계획을 어디에 두어야 할지 고민해 왔습니다.
저는 종종 Superpowers 스타일의 계획 및 문서 워크플로우를 사용합니다. 무언가를 구현하기 전에, SDD(Software Design Document)와 유사한 문서에 사양(spec)과 구현 방향을 작성합니다. 이 워크플로우는 유용하지만, 생성된 모든 문서를 저장소(repository)에 영구적으로 보관하는 것은 별로 좋아하지 않습니다.
코드는 빌드와 테스트가 있어 중단(breakage)을 확인하기 쉽습니다. 하지만 오래된 디자인 노트와 구현 계획은 다릅니다. 이들은 매우 쉽게 구식이 되며, AI 에이전트가 항상 오래된 문서를 주의 깊게 읽는 것도 아닙니다. 일부 문서는 반드시 저장소에 포함되어야 하지만, 모든 것이 그곳에 머물게 되면 지속적인 프로젝트 지식과 일시적인 작업 로그가 서로 뒤섞이기 시작합니다.
저는 AI 에이전트가 쉽게 읽고 쓸 수 있으면서도, 인간이 나중에 여전히 찾아볼 수 있고, 메인 저장소와는 어느 정도 거리를 유지할 수 있는 장소를 원했습니다.
그 결과 docs-ssh라는 작은 OSS(Open Source Software) 프로젝트를 만들게 되었습니다.
SSH를 통한 문서 관리 (Docs over SSH)
영감을 얻은 것 중 하나는 Supabase Docs over SSH였습니다.
AI 에이전트는 파일 작업에 능숙합니다. 만약 그렇다면, 문서를 웹 UI나 커스텀 API를 통해서만 노출하는 것보다 SSH를 통해 파일 시스템(filesystem) 형태로 보여주는 것이 더 적합할 수 있습니다.
문서를 검색하는 방법에는 여러 가지가 있습니다:
- 원본 파일 읽기 (read raw files)
- grep 또는 ripgrep으로 검색
- RAG (Retrieval-Augmented Generation)를 위한 인덱스 구축
- 에이전트에게 셸 도구(shell tools)를 제공하여 탐색하게 하기
물론 RAG는 유용합니다. 하지만 특정 텍스트 조각이 왜 검색되지 않았는지 이유를 파악하기 어려운 경우가 있습니다. 개인적으로 저는 에이전트가 find, rg, read-range를 사용하고, 자신이 어떻게 검색했는지에 대한 흔적을 남기는 패턴을 선호합니다.
docs-ssh는 그 방향으로 나아가는 하나의 실험입니다. 이 도구는 문서와 작업 노트를 AI 에이전트를 위한 셸 네이티브 파일 시스템(shell-native filesystem)으로 취급하는 동시에, 인간을 위한 브라우저 뷰어(browser viewer)를 유지합니다.
docs-ssh란 무엇인가
docs-ssh는 SSH를 통해 프로젝트 문서, 이슈(issues), 그리고 작업(tasks)을 다루기 위한 로컬 퍼스트(local-first) 도구입니다.
로컬에서 실행할 때의 흐름은 대략 다음과 같습니다:
pnpm install
pnpm run build
npm link
...
기본적으로 SSH 서버는 127.0.0.1:2222에서 실행되며, 뷰어(viewer)는 http://127.0.0.1:3000에서 실행됩니다.
다른 터미널에서 다음 명령어로 확인할 수 있습니다:
docs-ssh status --json
ssh localhost -p 2222 bootstrap --json
에이전트(agent)가 이를 사용하게 하려면, CLI 로그인을 먼저 시작하세요:
docs-ssh login --json
이 명령은 브라우저 로그인을 열고, 로컬에 임시 SSH 식별자(identity)를 생성하며, 공개 키(public key)를 뷰어의 CLI 로그인 API로 전송하고, SSH 세션을 생성합니다. 응답에는 sshCommand, identityFile, username, server, project, expiresAt과 같은 필드가 포함되어 있어, 에이전트가 해당 정보를 사용하여 SSH를 통해 연결할 수 있습니다.
리포지토리(repository) 수준의 프로젝트 설정을 위해, docs-ssh는 .docs-ssh.toml을 사용합니다.
docs-ssh config init
예시는 다음과 같습니다:
host = "docs-ssh-local"
viewer_origin = "http://localhost:3000"
project = "docs-ssh"
host는 SSH 설정 별칭(alias)입니다. 로컬 개발을 위해 다음과 같이 정의할 수 있습니다:
Host docs-ssh-local
HostName localhost
Port 2222
또한 CLI에서 에이전트용 지침(instructions)을 생성할 수도 있습니다:
docs-ssh skill --output .agents/skills/docs-ssh/SKILL.md
docs-ssh agents --output AGENTS.md --append
이 시점에서 에이전트는 기본적인 흐름을 학습할 수 있습니다: docs-ssh status --json 확인, 필요한 경우 docs-ssh login --json 실행, bootstrap --json 읽기, 그 다음 /projects/<slug>/issues 및 /projects/<slug>/tasks와 같은 위치에 쓰기 작업을 수행하는 방식입니다.
파일 시스템의 구조
현재 버전의 docs-ssh에서 SSH 세션은 다음과 같은 경로들을 노출합니다:
/README.md
/home
/projects/<slug>
...
/home은 인증된 주체(authenticated principal)를 위한 개인용 지속 가능 저장소(private durable storage)입니다. 저는 이를 개인적인 메모와 초안을 작성하는 데 사용합니다.
/projects/<slug>/issues는 프로젝트 이슈 트래킹(issue tracking)을 위한 공간입니다. 여기에는 수행해야 할 작업, 중요성, 상태, 다음 조치(next actions), 그리고 관련 작업 결과에 대한 링크가 저장됩니다.
/projects/<slug>/tasks는 연구 및 작업 결과물을 위한 공간입니다. 로그, 결론, 검증 결과, 제안서 및 아티팩트 (artifacts)를 각 작업별 디렉토리에 저장할 수 있습니다.
예를 들어, 저는 에이전트에게 다음과 같은 명령어를 실행하도록 요청할 수 있습니다. 여기서 <ssh-command>는 docs-ssh login --json에 의해 반환된 sshCommand입니다.
<ssh-command> bootstrap --json
<ssh-command> cat /README.md
<ssh-command> cat /projects/docs-ssh/README.md
...
더 큰 파일의 경우, 에이전트는 cat 대신 read-range를 사용할 수 있습니다.
<ssh-command> read-range -n /README.md 1 80
SSH 라운드 트립 (round trips)을 줄이기 위한 batch 기능도 있습니다.
printf '%s\n' \
'find /projects/docs-ssh/tasks -maxdepth 1 -type f' \
'read-range -n /README.md 1 40'
...
이는 단일 SSH exec에서 여러 명령어를 실행하며, 명령어당 하나의 JSON 객체를 반환합니다. 이러한 구조는 에이전트가 사용하기에 상당히 편리합니다.
인증 (Authentication)
SSH를 통한 Supabase Docs는 공개 문서를 읽기 위해 구축되었습니다. 개인 또는 팀의 작업 노트를 위해서는 인증과 프로젝트 경계(project boundaries)가 필요했습니다.
현재 docs-ssh에는 다음 기능이 포함되어 있습니다:
- 브라우저 뷰어를 위한 OIDC 로그인
- 테넌트 (tenant), 주체 (principal) 및 프로젝트 관리
- SSH 공개 키 (public key) 등록
- 임시 SSH 세션
- API 토큰으로부터 SSH 세션을 생성하기 위한
docs-ssh token login
일반적인 CLI 로그인 흐름은 브라우저를 사용하여 SSH 세션을 승인합니다:
docs-ssh login --json
서버 측 에이전트 및 자동화된 작업의 경우, 브라우저 로그인이 항상 적합한 것은 아닙니다. 따라서 docs-ssh는 베어러 토큰 (bearer token)으로부터 SSH 세션을 생성하는 흐름도 제공합니다:
docs-ssh token login \
--token dssh_... \
--host docs-ssh \
...
이것은 아직 완성된 호스팅 서비스라기보다는 기반(foundation)에 가깝습니다. 저의 개인 LAN이나 작은 서버에는 충분하지만, 실제 서비스가 되려면 운영, 권한 및 라이프사이클 관리 (lifecycle management)에 대한 더 많은 작업이 필요할 것입니다.
내부 구조 (Internal structure)
구현은 Node 24 기반의 TypeScript로 되어 있습니다.
높은 수준(high level)에서 보면, 다음과 같은 부분들로 구성됩니다:
CLI
|
+-- SSH server
...
SSH 서버는 ssh2를 사용하며, 셸은 just-bash를 기반으로 합니다. 일반적인 ssh로 접속하지만, 실제로 얻게 되는 것은 docs-ssh가 제공하는 파일 시스템과 명령 인터페이스(command surface)입니다.
bootstrap --json은 세션 매니페스트(session manifest)를 반환합니다. 에이전트는 현재 프로젝트, 사용 가능한 경로 및 범위를 이해하기 위해 이를 가장 먼저 읽어야 합니다.
read-range는 에이전트가 거대한 파일을 한꺼번에 읽는 것을 방지합니다. batch는 SSH 실행(execs) 횟수를 줄여줍니다. 이 두 명령어가 존재하는 이유는 LLM 에이전트가 컨텍스트 윈도우(context window)를 가득 채우지 않으면서도 셸을 통해 문서를 조사할 수 있을 때 훨씬 더 실용적으로 변하기 때문입니다.
브라우저 뷰어는 인간을 위한 것입니다. AI 에이전트를 거치지 않더라도 브라우저에서 저장된 이슈와 작업 결과를 탐색할 수 있습니다. 주요 사용 사례는 마크다운(Markdown) 및 텍스트 파일을 읽는 것입니다.
이것이 유용한 이유
주요 목표는 에이전트의 작업 컨텍스트(work context)를 저장소(repository)와 약간 분리하여 유지하는 것입니다.
예를 들어, docs-ssh는 다음과 같은 것들을 담을 수 있습니다:
- 구현 전의 연구 노트 (research notes)
- 폐기될 수도 있는 계획들
- 이슈가 되기 전의 작업 로그
- 에이전트를 위한 개인용 보조 노트
- 작업 후의 검증 결과 및 인수인계 노트
저장소에 속해야 하는 문서는 저장소에 그대로 두어야 합니다. README 파일, 운영 런북(runbooks), 그리고 지속적인 설계 기록으로 남아야 하는 ADR(Architecture Decision Records) 등은 저장소에 보관하는 것이 더 좋습니다.
하지만 에이전트 협업 과정에서 발생하는 모든 중간 산출물(intermediate artifact)이 저장소로 들어가게 되면, 저장소는 불필요한 정보로 소란스러워집니다(noisy). docs-ssh는 이러한 중간 계층을 흡수하기 위해 설계되었습니다.
또 다른 이점은 에이전트 기반 검색(agentic search)에 대한 관측 가능성(observability)입니다.
RAG(Retrieval-Augmented Generation) 결과만 볼 때는 왜 특정 후보가 나타났는지, 혹은 왜 다른 후보가 누락되었는지 파악하기 어려울 수 있습니다. SSH 파일 시스템과 셸 명령어를 사용하면 에이전트가 어떤 디렉토리를 방문했는지, 어떤 키워드를 시도했는지, 그리고 실제로 어떤 파일을 읽었는지 조사하기가 더 쉽습니다.
SSH가 유일하게 가능한 인터페이스는 아닙니다. HTTP API, MCP, 또는 로컬 파일 시스템 (local filesystem)을 사용하여 유사한 시스템을 구축할 수도 있습니다. 하지만 SSH는 이미 기존 도구 및 에이전트와 잘 작동합니다. ls, find, rg, cat은 에이전트가 이미 사용하는 방법을 알고 있는 일반적인 작업들입니다.
벤치마크 (Benchmark)
저는 단순히 느낌(vibes)만으로 docs-ssh가 에이전트 기반 검색 (agentic search)에 좋은지 판단하고 싶지 않습니다.
따라서 이 저장소에는 bench/multihop-rag 아래에 벤치마크 하네스 (benchmark harness)가 포함되어 있습니다.
첫 번째 대상은 MultiHop-RAG입니다. 하나의 질문에 답하기 위해서는 종종 여러 문서에 걸친 증거가 필요하며, 이는 단순한 단일 문구 검색 (single-passage retrieval)보다 docs-ssh의 사용 사례에 더 가깝습니다.
현재 하네스는 흐름을 가져오기 (fetch), 정규화 (normalize), 구체화 (materialize), 실행 (run), 그리고 점수 매기기 (score) 단계로 나눕니다. 정답 (Gold answers)과 뒷받침하는 증거는 하네스 내에 유지되며, docs-ssh 프로젝트 트리는 읽기 가능한 코퍼스 (corpus)만을 포함합니다.
에이전트에게 보여지는 코퍼스는 가공되지 않은 덤프 (raw dump)가 아닙니다. 구체화하기 전에, 저는 AI를 사용하여 파일에 제목과 메타데이터 (metadata)를 추가한 다음, category/source/slugified-title__documentId.md와 같은 레이아웃에 배치합니다. 원본 소스에 유용한 제목이나 분류가 없는 경우, AI가 배치하기 전에 이를 채워 넣습니다. 즉, 코퍼스를 임베딩 인덱스 (embedding index)로 변환하는 대신, 먼저 인간과 AI 에이전트 모두가 읽을 수 있는 파일 구조로 형성합니다.
제가 관심을 두는 비교 대상은 대략 다음과 같습니다:
- BM25
- 밀집 검색 (dense retrieval)
- 하이브리드 검색 (hybrid retrieval)
- 하이브리드 재순위화 (hybrid rerank)
- docs-ssh 직접 검색 (direct retrieval)
- 로컬 벡터 검색 (local vector search) 도구를 가진 에이전트
- docs-ssh를 통해 파일 시스템을 탐색하는 에이전트
다음은 100개의 케이스를 대상으로 한 가벼운 벤치마크의 초기 결과입니다. 데이터셋은 Hugging Face의 yixuantt/MultiHopRAG이며, 구체화된 코퍼스는 609개의 문서로 구성됩니다. 에이전트 모델은 gpt-5.4-mini, 추론 노력 (reasoning effort)은 low, 그리고 Top K는 5입니다.
| mode | cases | errors | any@1 | any@5 | all@5 | recall@5 | MRR@10 | avg latency | p95 latency |
|---|---|---|---|---|---|---|---|---|---|
| BM25 | 100 | 0 | 0.790 | 0.960 | 0.450 | 0.741 | 0.861 | 7ms | 14ms |
| ... |
검색 품질(retrieval quality)만 놓고 보면, docs-ssh 에이전트는 강력합니다. 100개 사례 중 99개 사례에서 최소 하나 이상의 골드 증거 문서(gold evidence document)를 상위 5개 안에 배치했습니다. 73개 사례에서는 필요한 모든 골드 증거 문서를 상위 5개 안에 배치했습니다.
하지만 RAG(Retrieval-Augmented Generation) 스타일의 베이스라인(baselines)과 비교하면 매우 느립니다. BM25는 평균 7ms, Hybrid는 평균 194ms였으며, Hybrid + rerank조차 평균 약 1.7초였습니다. docs-ssh 에이전트는 평균 약 88초였으며, p95(95퍼센타일)는 약 169초였습니다. 검색 품질은 높지만, 이는 대화형 검색 UI나 요청 시점의 검색(request-time retrieval)에 사용하기에는 너무 무겁습니다.
중요한 주의 사항은 이것이 "rg로 로컬 폴더를 검색하는 것이 느리다"는 것을 의미하지는 않는다는 점입니다. docs-ssh 에이전트 실행은 SSH를 통해 Bash 기반의 파일 시스템 및 명령 인터페이스를 거칩니다. 이 수치에는 docs-ssh의 셸(shell) 구현, 마운트 가능한 파일 시스템 계층, SSH 실행 오버헤드, 그리고 에이전트 자체의 탐색 전략(exploration strategy)이 포함되어 있습니다. 이는 로컬 파일 시스템에서 rg를 직접 실행하는 것과는 별개로 해석되어야 합니다.
저장된 트레이스(traces)를 보면 심각한 컨텍스트 압박(context pressure)도 나타납니다. 광범위한 rg 및 rg --files 출력은 매우 커질 수 있습니다. 이 실행 과정에서 도구 출력값의 중앙값(median)은 약 75.7 KB, 평균 출력은 약 127.6 KB, p95 출력은 약 368.5 KB였습니다.
결과적으로 docs-ssh 스타일의 코퍼스(corpus)는 에이전트가 벡터 인덱스(vector index) 없이도 강력한 다중 문서 검색(multi-document retrieval)을 수행할 수 있게 해줍니다. 하지만 지연 시간(latency)과 컨텍스트 사용량이 매우 큽니다.
이것을 곧바로 "AI 친화적(AI-friendly)"이라고 부를 수 있을지는 확신할 수 없습니다. 그럼에도 불구하고 유용한 방향으로 보입니다. 즉, 문서를 인간이 직접 검사할 수 없는 임베딩 구조(embedding structure)로 먼저 변환하는 대신, 적절한 검색 품질을 유지하면서 인간과 AI 에이전트 모두가 읽을 수 있는 구조를 유지할 수 있습니다.
다음에 개선하고 싶은 점
이는 여전히 대부분 개인적인 실험 단계이므로, UX (사용자 경험) 측면에서 개선할 점이 많습니다.
- 브라우저 뷰어 (browser viewer) 개선
- 호스팅 사용을 위한 설정 정리
- API 토큰 및 SSH 세션 흐름의 조작 편의성 향상
- 프로젝트 및 소스 관리 UX 개선
- 에이전트 대응 기술 (agent-facing skill) 개선
- just-bash 기반에서 부하가 발생하는 탐색 경로의 속도 향상
batch및read-range를 통한 검색 효율성 개선
벤치마크는 한 가지 문제를 매우 명확하게 보여줍니다. 광범위한 rg (ripgrep) 실행과 대규모 파일 목록 조회가 지연 시간 (latency) 및 컨텍스트 (context) 사용량에 직접적인 영향을 미친다는 점입니다. 저는 모든 것을 just-bash를 통해 단순히 스트리밍하는 방식을 피하고 싶습니다. 출력 제한, 절단 (truncation), 검색 전용 헬퍼 (helpers), 그리고 더 가벼운 파일 시스템 백엔드 (filesystem backend)는 모두 탐색해 볼 가치가 있습니다.
만약 이것이 호스팅 서비스가 된다면, 인증 (authentication), 프로젝트 권한 (project permissions), 토큰 생명주기 (token lifecycle), 감사 로그 (audit logs), 그리고 운영 비용에 대해서도 더 많은 작업이 필요합니다.
하지만 제 로컬 머신이나 LAN을 위한 작은 도구로서는 이미 충분히 유용하게 느껴집니다.
요약
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기