CH 05 · 명령행에서 실행하기: headless + CLI
본장 목표
이전 장들은 모두 Web UI에서 클릭했습니다. 이 장에서는 형태를 바꿉니다. 인터페이스가 전혀 없는 상태에서, 터미널에서 명령 한 줄로 dsh가 일을 끝내고 종료합니다. 그것이 headless입니다. 그 사이에 dsh "실행기"가 열 수 있는 모든 문도 함께 살펴봅니다. 스크립트, CI, 배치 작업에 나중에 요긴하게 쓰입니다.
먼저 이해하기: dsh는 다중 진입 실행기입니다
dsh는 "그 웹 페이지" 하나가 아닙니다. 실행기입니다. 같은 Harness, 같은 플러그인 스택이 다른 형태로도 뜹니다.
공식 진입점은 다음 문들입니다.
| 진입점 | 용도 | 풀이 |
|---|---|---|
web | 인터페이스가 있는 웹 워크벤치 | 이전 장에서 사용한 그것 |
headless | 작업 하나를 돌리고 답을 출력한 뒤 종료 | 명령행 일회성 작업. 이 장의 주인공 |
sdk | JSON-RPC stdio 서비스 | 다른 애플리케이션이 호출할 수 있도록 백엔드 역할 |
acp | ACP stdio 서비스 | 자동화 클라이언트에 서비스 제공 |
plugin | 프로필 단위 플러그인 관리 | 플러그인 설치, 프로필에 의존성 추가 |
어느 문으로 들어가든, 아래에서 일하는 플러그인 스택은 동일합니다. CH 02에서 "모든 것은 플러그인"이라고 했습니다. 이제 와서 체감하실 겁니다. "진입점"조차 플러그인의 조합이라는 점이요.
headless: 한 문장, 한 작업
headless는 명령행 모드에서의 일회성 작업입니다. 사용법은 아주 단순합니다.
dsh --profile headless "what you want it to do"그 동작을 공식 한 문장으로 요약하면 이렇습니다. 새 영속 세션을 연다 → 일을 한다 → 최종 답을 출력한다 → 종료한다.
몇 가지 핵심 포인트.
- 작업 폴더 = 명령을 실행할 때의 현재 폴더. 어디서 실행하든 그곳이 작업 폴더가 됩니다(Web UI처럼 수동으로 고를 필요 없음).
- "새 영속 세션을 연다"는 말 그대로입니다. headless 실행 한 번은 현재 폴더를 작업 폴더로 하는 새 세션을 열어
$DSH_HOME/sessions에 저장하는 것과 같습니다. 헷갈리기 쉬우니 풀어 드리겠습니다. — 파일 차원에서는 세션이 작업 폴더별로 저장되며,C:\Users\<사용자 이름>\.dsh\sessions\바로 아래에서 작업 폴더 경로 기반의 폴더(예:--E-software-workspace-...--)를 직접 볼 수 있고, 그 안에 압축된 세션 파일이 들어 있습니다. Web UI 차원에서는 headless로 돌린 세션이 (현 버전 기준) 자동으로 어떤 작업 폴더 그룹에도 들어가지 않고 미분류(Ungrouped) 카테고리에 표시됩니다. 파일 저장은 작업 폴더 기준, UI 표시는 미분류. 이 둘은 별개입니다. 아래 실습에서 직접 확인합니다. - 기본 모델은
deepseek-v4-flash. CLI 시나리오는 UI도 없고 이미지도 필요 없으니, 공식 기본값이 가장 가성비 좋은 flash입니다. - UI는 없지만 전체 파이프라인은 다 있습니다. 컨텍스트 주입, 계획, 도구 호출, 사고, 마무리. 빠지는 것 없이 다만 화면에 그려 주지 않을 뿐입니다.
실습: 첫 headless 작업
Agent에게 "큰 작업"을 줍니다. 저장소를 읽고, 아키텍처를 요약하고, 한 문서로 정리해 달라고 시킵니다. 작업 폴더에서 실행합니다.
dsh --profile headless "Read the deepseek-harness subdirectory's code and docs, summarize the overall architecture of DeepSeek Harness (plugin mechanism, layering, entry points, main packages and directories), and write a Chinese markdown architecture document saved to the current directory with the filename deepseek-harness-arch.md"실행 후 출력된 결과.
Done. I read the key source and docs in the deepseek-harness subdirectory, organized it into a Chinese architecture document and saved it to the current directory.
File: E:\software-workspace\DeepSeek harness demo\deepseek-harness-arch.md (about 295 lines)Web UI로 돌아가 이 세션을 확인해 봅니다. 세션 목록에 있는데, 미분류(Ungrouped) 카테고리에 나타나지 어떤 작업 폴더 그룹에도 자동으로 들어가지 않습니다(headless 세션은 자동 그룹화되지 않으며, 이것이 현 버전의 실제 동작).

오른쪽에는 전체 실행 과정이 보입니다. 컨텍스트 주입 → 사고(Think) → Pwsh 디렉터리 목록 → 문서 읽기 → 파일 쓰기. 하단 통계 막대는 1 turn · 18 steps, LLM 2m1s, cache hit 92%, input 1.1M tokens.
CLI 파라미터 치트시트
| 명령 | 효과 |
|---|---|
dsh --profile <이름> "작업" | 지정한 프로필로 시작(headless도 그중 하나) |
dsh web | --profile web의 별칭. Web UI 실행 |
dsh --dump-config | 합쳐진 전체 구성 트리 출력(문제 해결 보물, 아래 참조) |
dsh --dump-default-config | 사용자 변경 전의 기본 구성 트리 출력 |
dsh --patch <경로> | 프로필 위에 구성 한 층을 더 쌓음 |
dsh plugin --profile <이름> add <패키지> | 프로필에 플러그인 설치 |
dsh --help | 실행기 자체 도움말 보기 |
--dump-config만 따로 짚어 봅니다. 프로필에 대해 최종적으로 적용되는 플러그인 조합을 출력합니다. 실제로 돌려 봅니다.

보이는 것은 @deepseek-ai/dsh-* 플러그인들이 한 줄로 길게 쌓여 트리를 이룬 모습입니다. llm(모델), session(세션), credentials(키), session-persistence-jsonl(세션 영속화) 등등. 그리고 agent-default-model이 deepseek-v4-flash로 설정되어 있다는 것도 바로 보입니다. 문제를 만나거나 "이 동작은 어디서 온 거지"를 파악하고 싶을 때, 가장 먼저 구성 트리를 덤프하십시오.
더 편리한 트릭이 있습니다. 그냥 AI에게 이 명령을 직접 돌리라고 시키는 것. 예를 들어 어떤 세션에서 "기본 모델이 내가 원하는 모델이 아닌 이유를 알아내려면 dsh --profile headless --dump-config를 써서 현재 구성 트리를 확인해 주세요" 또는 "어떤 플러그인이 적용되지 않는 것 같은데 확인해 주세요"라고 부탁합니다. AI가 직접 --dump-config를 실행하고, 구성 트리를 읽고, 한 항목씩 따져 가며 원인을 찾아 줍니다. 이 조합은 문제 해결에서 꽤 강한 한 수입니다.
headless를 쓸 때와 web을 쓸 때
| 시나리오 | 선택 |
|---|---|
| Agent가 일하는 모습을 보면서 중간에 끊고, 단계별로 문제를 찾고 싶다 | web |
| 스크립트, CI, 스케줄 작업, 배치 처리, 결과만 중요하다 | headless |
| 다른 프로그램/도구가 dsh의 기능을 호출해야 한다 | sdk / acp |
| 구성을 확인하거나 시작 시 문제를 잡고 싶다 | --dump-config / --help |
공식 경계도 기억해 두십시오. headless 한 번 호출은 작업 하나만 돌리고 상호작용 후속이 없습니다. 여러 턴이 필요하거나 작업을 지켜보고 싶다면 web으로 돌아가야 합니다.
이 장에서 배운 것
아래 항목들을 스스로 완수할 수 있으면 합격입니다.
- [ ] dsh의 진입점 네 가지 이상(web / headless / sdk / acp / plugin)을 설명하고 각각 무엇을 하는지 말할 수 있다
- [ ]
dsh --profile headless "작업"으로 명령행 일회성 작업을 돌리고 그 동작(새 세션 → 일 → 답 출력 → 종료)을 설명할 수 있다 - [ ] headless의 작업 폴더는 명령을 실행할 때의 현재 폴더이며, 매 실행이 영속 세션을 새로 연다($DSH_HOME/sessions 아래 작업 폴더별로 저장. Web UI 세션 목록에서 headless 세션은 미분류에 표시) 는 것을 알고 있다
- [ ] headless가 적합한 시나리오(배치, CI, 스케줄, 저장소 분석)와 공식 경계(호출당 작업 1개, 상호작용 없음)를 말할 수 있다
- [ ]
dsh --dump-config로 구성 트리를 보고, 그 문제 해결 용도를 알고 있다 - [ ] 주어진 시나리오에 web과 headless 중 어느 쪽을 쓸지 판단할 수 있다
