dsh-composer-plus 1.18.0 → 1.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ko.md CHANGED
@@ -14,7 +14,7 @@
14
14
 
15
15
  <p align="center"><img src="docs/images/hero.webp" width="820" alt="Composer Plus를 사용하는 DeepSeek Harness: 실행 중인 프로젝트는 사이드바에 회전 표시가 나타나고, 변경 사항 패널은 git diff를 보여 줍니다"></p>
16
16
 
17
- 비공식 커뮤니티 플러그인입니다. 네트워크 호출은 업데이트 확인(GitHub 릴리스와 npm 레지스트리)뿐입니다. 시작할 때 이 호출을 막으려면 **자동 업데이트**를 끄세요. **기능 아이디어**는 **기능 제안**을 클릭할 때만 채팅 자체의 모델을 호출합니다. **다음 메시지 예측**(기본값: 켜짐)은 턴이 끝날 때마다 설정에서 고른 모델(다른 모델을 고르지 않으면 dsh의 기본 모델)을 클릭 없이 한 번 호출합니다. 이 호출을 막으려면 **설정 → Composer Plus**에서 끄세요. **입력 중 자동 완성**(기본값: 꺼짐)은 사용자가 켠 뒤에 입력을 멈출 때마다 이 기능에서 고른 모델(기본값: 예측의 모델)을 호출합니다. **프롬프트 개선**은 요술봉을 클릭할 때만 모델을 호출합니다. **목표 확인**(기본값: 켜짐)은 에이전트가 자동 라운드에서 `/goal`을 완료로 표시할 때마다 모델을 한 번 호출합니다. **모바일 연결**(기본값: 꺼짐)은 사용자가 켠 뒤에만 로컬 네트워크나 tailnet에서 오는 iPhone 연결을 받습니다.
17
+ 비공식 커뮤니티 플러그인입니다. 네트워크 호출은 업데이트 확인(GitHub 릴리스와 npm 레지스트리)뿐입니다. 시작할 때 이 호출을 막으려면 **자동 업데이트**를 끄세요. **기능 아이디어**는 **기능 제안**을 클릭할 때만 채팅 자체의 모델을 호출합니다. **다음 메시지 예측**(기본값: 켜짐)은 턴이 끝날 때마다 설정에서 고른 모델(다른 모델을 고르지 않으면 dsh의 기본 모델)을 클릭 없이 한 번 호출합니다. 이 호출을 막으려면 **설정 → Composer Plus**에서 끄세요. **입력 중 자동 완성**(기본값: 꺼짐)은 사용자가 켠 뒤에 입력을 멈출 때마다 이 기능에서 고른 모델(기본값: 예측의 모델)을 호출합니다. **프롬프트 개선**은 요술봉을 클릭할 때만 모델을 호출합니다. **작업 보드**는 보드에서 시작한 각 작업의 태그를 만들 때 새 채팅의 모델을 한 번 호출합니다. **목표 확인**(기본값: 켜짐)은 에이전트가 자동 라운드에서 `/goal`을 완료로 표시할 때마다 모델을 한 번 호출합니다. **모바일 연결**(기본값: 꺼짐)은 사용자가 켠 뒤에만 로컬 네트워크나 tailnet에서 오는 iPhone 연결을 받습니다.
18
18
 
19
19
  ## 설치
20
20
 
@@ -29,7 +29,7 @@ dsh plugin --profile web add dsh-composer-plus
29
29
 
30
30
  그런 다음 dsh를 다시 시작하세요. (CLI는 데스크톱 프로필에 설치할 수 없습니다. 데스크톱 프로필은 앱이 관리합니다.)
31
31
 
32
- > dsh의 pnpm은 게시된 지 24시간이 지나지 않은 버전을 건너뜁니다. 릴리스 직후에는 버전을 붙여서 설치하세요: `dsh-composer-plus@1.18.0`.
32
+ > dsh의 pnpm은 게시된 지 24시간이 지나지 않은 버전을 건너뜁니다. 릴리스 직후에는 버전을 붙여서 설치하세요: `dsh-composer-plus@1.19.1`.
33
33
 
34
34
  ## 기능
35
35
 
@@ -71,11 +71,11 @@ dsh plugin --profile web add dsh-composer-plus
71
71
  | **계획된 단계** | <a id="feature-plannedsteps"></a>기본적으로 꺼져 있습니다. **설정 → Composer Plus**에서 켜세요. 에이전트는 `plan_next_steps` 도구를 받습니다. 명령과 같은 메시지에서 다음 명령을 정확한 인수와 조건과 함께 계획할 수 있습니다(예: “빌드가 통과하면 `npm test` 실행”). 결과가 조건을 충족하면 Composer Plus가 새 모델 호출 없이 다음 단계를 직접 실행하므로 긴 채팅의 토큰 사용량이 줄어듭니다. 단계는 채팅에 “Composer Plus · Planned steps: ran `test` … without a model call”이라는 짧은 줄로 표시되고, 그 뒤에 도구 호출과 결과가 이어집니다. `bash`, `read`, `grep`, `glob` 단계만 해당되며 승인, 샌드박스, 보호된 파일은 각 단계에 평소처럼 적용됩니다. 조건이 맞지 않을 때, 두 단계가 동시에 준비될 때, 마지막 단계 뒤, 그리고 메시지를 보낼 때 모델이 다시 답합니다. 이 아이디어는 HarnessMM(arXiv 2610.32813)에서 왔습니다. | <a href="assets/features/plannedSteps.webp"><img src="assets/features/plannedSteps.webp" width="160" alt="스크린샷: 계획된 단계"></a> |
72
72
  | **보호된 파일** | <a id="feature-protectedfiles"></a>기본적으로 켜져 있습니다. 에이전트 자체의 파일 도구는 지정한 패턴과 일치하는 파일을 읽거나 바꿀 수 없습니다. **읽기와 쓰기** 패턴에서는 파일에 대한 `read`, `read_image`, `grep`이 거부되고, 두 종류 모두에서 `write`, `edit`, `str_replace_editor`가 거부됩니다. 에이전트는 이유를 읽고 사용자에게 물어보라는 안내를 받습니다. 기본 패턴은 `.env*`, `*.pem`, `*.key`입니다. 설정 → Composer Plus → **보호된 파일**: 패턴을 추가하고(예: `published/**` 또는 `config/*.yml`), 종류를 클릭해 **읽기와 쓰기**와 **쓰기만** 사이에서 전환하고, ✕로 삭제하거나 **기본값 사용**을 클릭하세요. `/`가 없는 패턴은 모든 폴더의 파일 이름과 일치합니다. 이것은 가드레일이며 샌드박스가 아닙니다. 셸 명령(`cat .env`), 스크립트, MCP 도구는 여전히 파일에 접근할 수 있습니다(제한 사항 참고). | <a href="assets/features/protectedFiles.webp"><img src="assets/features/protectedFiles.webp" width="160" alt="스크린샷: 보호된 파일"></a> |
73
73
  | **차단된 명령** | <a id="feature-blockedcommands"></a>기본적으로 켜져 있으며, 목록은 비어 있습니다. 에이전트의 셸 명령(`bash`, `pwsh`)은 지정한 규칙과 일치하는 명령을 실행할 수 없습니다. **차단** 규칙은 호출을 거부하고(에이전트는 이유를 읽고 사용자에게 물어보라는 안내를 받습니다), **먼저 묻기** 규칙은 dsh의 승인 카드를 표시하며, 명령은 사용자가 허용할 때만 실행됩니다. 설정 → Composer Plus → **차단된 명령**: 규칙을 입력하고(예: `npm publish`, `git push --force` 또는 `ssh *192.168.2.19`), 종류를 클릭해 **차단**과 **먼저 묻기** 사이에서 전환한 뒤 **추가**를 클릭하세요. 규칙의 종류를 클릭하면 바꿀 수 있고, ✕로 삭제할 수 있습니다. 규칙은 명령 이름과 그 뒤에 이 순서로 와야 하는 단어입니다. `*`는 모든 텍스트와 일치합니다. `&&`, `;`, `\|` 뒤, `$(…)`, `bash -c "…"` 또는 `eval` 안, `sudo`나 `env` 뒤에 있는 명령도 찾습니다. 이것은 가드레일이며 샌드박스가 아닙니다. 변수(`$CMD`), 스크립트 파일, 다른 프로그램은 여전히 명령을 실행할 수 있습니다(제한 사항 참고). | <a href="assets/features/blockedCommands.webp"><img src="assets/features/blockedCommands.webp" width="160" alt="스크린샷: 차단된 명령"></a> |
74
- | **작업 보드** | <a id="feature-taskboard"></a>왼쪽 사이드바 → **작업 보드**. 사용자와 에이전트가 함께 쓰는 dsh 프로젝트의 칸반 보드입니다. 열은 **할 일**, **진행 중**, **검토**, **완료**입니다(**백로그**도 있습니다. 아래 참고). 왼쪽에서 프로젝트나 **모든 프로젝트**를 고르세요. **새 작업**(또는 `n`)을 누르면 새 카드가 열립니다. 제목을 입력하고 `Enter`를 누르세요. 카드를 다른 열이나 두 카드 사이로 끌어다 놓을 수 있습니다. 카드를 클릭하면 **상태**, **태그**, **수동**(에이전트가 건너뜀), 설명(Markdown), 댓글을 보고 바꿀 수 있습니다. `/`는 모든 프로젝트를 검색하고, `h`는 수동 작업만 보여 주며, 내보내기 버튼은 보드를 Markdown이나 JSON으로 저장합니다. 에이전트는 보드 도구를 받습니다. 채팅에서 "보드에서 다음 작업을 가져와"라고 하면 에이전트가 **할 일**의 맨 위 카드를 **진행 중**으로 옮기고, 한 일을 댓글로 남긴 뒤 **검토**로 옮깁니다. **완료**로 옮기는 것은 사용자입니다. 열린 작업이 있는 프로젝트에서는 각 채팅이 이 규칙을 자동으로 받습니다. 설정 → Composer Plus → **작업 보드**에 **백로그** 열 스위치가 있습니다. 이 열의 카드는 에이전트가 사용자에게 맡깁니다. | <a href="assets/features/taskBoard.webp"><img src="assets/features/taskBoard.webp" width="160" alt="스크린샷: 작업 보드"></a> |
74
+ | **작업 보드** | <a id="feature-taskboard"></a>왼쪽 사이드바 → **작업 보드**. 사이드바와 같은 실시간 상태를 보여 주는 dsh 채팅의 칸반 보드입니다. 승인, 답변 또는 계획 검토를 기다리는 채팅은 주황색 점과 함께 **검토**에, 실행 중인 채팅은 **진행 중**에, 끝난 채팅은 **완료**에 있습니다(열기 전까지 초록색). 왼쪽에서 프로젝트나 **모든 프로젝트**를 고르세요. 채팅별 브랜치 폴더는 해당 프로젝트로 취급됩니다. 목록 위의 **프로젝트 검색**에 입력하면 이름으로 프로젝트를 찾을 수 있습니다(대소문자와 악센트는 구분하지 않으며, `Esc`를 누르면 입력란이 비워집니다). **최근 2시간 내 활성**을 클릭하면 대기 중이거나 실행 중인 채팅, 확인하지 않은 채 끝난 채팅 또는 최근 2시간 안에 바뀐 채팅이 있는 프로젝트만 표시됩니다(이 설정은 이 기기에 저장됩니다). **새 작업**(또는 `n`)에는 프롬프트만 입력합니다. `Enter`를 누르면 프로젝트에서 새 채팅이 시작되고, 카드가 **할 일**에 표시되며, dsh가 채팅 이름을 짓고 채팅의 모델이 태그를 최대 3개 씁니다. 카드를 클릭하면 채팅이 열립니다. 주황색 카드에서 **답변**을 클릭하면 보드에서 바로 답할 수 있습니다. 승인 요청에는 **거부** 또는 **한 번 허용**, 계획에는 **승인** 또는 **변경 요청**, 질문에는 선택지와 직접 쓴 텍스트로 답합니다. **끝난 채팅 숨기기**는 이 기기에서 **완료**를 숨깁니다. | <a href="assets/features/taskBoard.webp"><img src="assets/features/taskBoard.webp" width="160" alt="스크린샷: 작업 보드"></a> |
75
75
  | **프로젝트 메모리** | <a id="feature-projectmemory"></a>기본적으로 꺼져 있습니다. **설정 → Composer Plus**에서 켜세요. 프로젝트 폴더마다 자체 메모리가 있으며, 그 프로젝트의 이후 채팅이 읽습니다. DS Bot이 Bot마다 메모리를 두는 것과 같습니다. 턴이 끝날 때마다 채팅의 모델을 한 번 호출해 새 메시지(되돌린 메시지 제외)를 읽고, 오래 유지되는 선호, 결정, 사실을 짧은 메모로 저장하며, 오래된 메모를 바꾸거나 지웁니다. 에이전트도 직접 메모를 저장, 삭제, 검색할 수 있습니다(`memory_remember`, `memory_forget`, `memory_recall`). 메모는 전역일 수도 있으며, 이때는 모든 프로젝트가 읽습니다. 새 채팅은 시스템 프롬프트에서 메모를 받습니다. 나중에 저장한 메모는 다음 채팅부터 보입니다. 파일은 dsh 홈 폴더의 Markdown(`storages/dsh-composer-plus/memory/`)이며 프로젝트 폴더에는 절대 저장되지 않습니다. 같은 줄의 **메모리 열기**는 저장된 모든 메모를 프로젝트별(및 전역 메모리)로 묶어 보여 주며 필터도 있습니다. 바꿀 내용을 자신의 말로 적고(예: "yarn 대신 pnpm을 써") **변경 미리 보기**를 누르세요. dsh의 기본 모델이 변경을 제안하고, **적용**을 눌러야만 저장됩니다. Tether에서는: 채팅 제목 메뉴 → Project memory. | <a href="assets/features/projectMemory.webp"><img src="assets/features/projectMemory.webp" width="160" alt="스크린샷: 프로젝트 메모리"></a> |
76
76
  | **이 채팅에서 허용** | <a id="feature-allowforchat"></a>자동 검토가 확인을 요청하면 승인 카드에 **이 채팅에서 허용**이 추가됩니다. 이후 같은 채팅의 같은 도구는 인수와 관계없이 시간 제한이 끝날 때까지 허용됩니다(기본값 1시간. **설정 → Composer Plus → 이 채팅에서 허용**에서 고릅니다). 그 후에는 에이전트가 다시 묻습니다. 헤더 칩에서 허용 목록과 종료 시각을 보고 취소할 수 있습니다. 허용은 재시작 후에도 유지됩니다. | <a href="assets/features/allowForChat.webp"><img src="assets/features/allowForChat.webp" width="160" alt="스크린샷: 이 채팅에서 허용"></a> |
77
77
  | **프로젝트 상태** | <a id="feature-projectstatus"></a>사이드바의 프로젝트 행에 그 채팅과 같은 실행 중 / 대기 중 / 완료 표시가 나타납니다. 그래서 접힌 프로젝트도 안의 채팅이 작업 중인지, 사용자의 조치가 필요한지 알려 줍니다. 사용자의 조치를 기다리는 채팅이 먼저 표시되고, 그다음 아직 열지 않은 완료된 채팅(초록색 점, 다른 채팅이 아직 실행 중일 때도 표시), 마지막으로 실행 중 표시가 나타납니다. 포인터를 올리면 자세한 내용이 보입니다. **작업 공간 트리**에서는 상위 폴더의 행에도 그 안에 있는 각 프로젝트(예: `.worktrees/` 안의 각 브랜치 폴더)의 채팅 상태가 표시되며, 폴더가 접혀 있을 때도 마찬가지입니다. | <a href="assets/features/projectStatus.webp"><img src="assets/features/projectStatus.webp" width="160" alt="스크린샷: 프로젝트 상태"></a> |
78
- | **채팅 행의 Git 브랜치** | <a id="feature-sessionbranch"></a>사이드바의 각 채팅 행에 작은 회색 배지로, 채팅의 마지막 턴 때 채팅 프로젝트 폴더가 있던 git 브랜치가 표시됩니다(예: `main` 또는 `feature/login`. 분리된 HEAD는 브랜치가 없으므로 배지가 표시되지 않습니다). 한 프로젝트에서 서로 다른 브랜치에 있는 두 채팅이 더 이상 똑같아 보이지 않으며, 잘못된 브랜치에서 채팅을 이어 가려 할 때 바로 알 수 있습니다. 배지에 포인터를 올리면 전체 이름이 보입니다. Host 쪽은 턴이 시작될 때와 끝날 때 브랜치를 읽습니다(`git branch --show-current`, 읽기 전용). 이 기능을 설치한 뒤 턴이 없는 채팅이나 git 저장소가 아닌 폴더에는 배지가 표시되지 않습니다. 채팅 위의 프로젝트 행 이름이 브랜치와 같으면(예: “채팅별 브랜치” 폴더) 채팅 행에 배지가 표시되지 않지만, “하나의 목록”에서는 계속 표시됩니다. | <a href="assets/features/sessionBranch.webp"><img src="assets/features/sessionBranch.webp" width="160" alt="스크린샷: 채팅 행의 Git 브랜치"></a> |
78
+ | **채팅 행의 Git 브랜치** | <a id="feature-sessionbranch"></a>사이드바의 “하나의 목록” 보기에서는 각 채팅 행에 작은 회색 배지로, 채팅의 마지막 턴 때 채팅 프로젝트 폴더가 있던 git 브랜치가 표시됩니다(예: `main` 또는 `feature/login`. 분리된 HEAD는 브랜치가 없으므로 배지가 표시되지 않습니다). 한 프로젝트에서 서로 다른 브랜치에 있는 두 채팅이 더 이상 똑같아 보이지 않으며, 잘못된 브랜치에서 채팅을 이어 가려 할 때 바로 알 수 있습니다. 배지에 포인터를 올리면 전체 이름이 보입니다. Host 쪽은 턴이 시작될 때와 끝날 때 브랜치를 읽습니다(`git branch --show-current`, 읽기 전용). 이 기능을 설치한 뒤 턴이 없는 채팅이나 git 저장소가 아닌 폴더에는 배지가 표시되지 않습니다. “작업 공간”과 “작업 공간 트리”에서는 채팅이 이미 프로젝트 행 아래에 있으므로 어떤 채팅 행에도 배지가 표시되지 않습니다. | <a href="assets/features/sessionBranch.webp"><img src="assets/features/sessionBranch.webp" width="160" alt="스크린샷: 채팅 행의 Git 브랜치"></a> |
79
79
  | **모두 읽음으로 표시** | <a id="feature-markprojectread"></a>사이드바에서 프로젝트의 **…** 버튼 → **모두 읽음으로 표시**를 클릭하세요. 그 프로젝트의 모든 채팅에서 초록색 읽지 않음 점이 한 번에 사라집니다. 다른 프로젝트의 점은 그대로 남습니다. 프로젝트에 읽지 않은 채팅이 없으면 이 항목은 회색으로 표시됩니다(**읽지 않은 채팅 없음**). | <a href="assets/features/markProjectRead.webp"><img src="assets/features/markProjectRead.webp" width="160" alt="스크린샷: 모두 읽음으로 표시"></a> |
80
80
  | **활성 프로젝트 우선** | <a id="feature-activeprojectsfirst"></a>채팅이 실행을 시작하거나 사용자의 조치가 필요해지면, 그 프로젝트가 dsh 자체 행 애니메이션으로 사이드바 맨 위로 이동합니다(직접 끌어 올릴 때와 같은 움직임). 완료된 프로젝트는 제자리에 남으며, 평소처럼 원하는 곳으로 끌어 옮길 수 있습니다. 이동은 dsh의 프로젝트 순서에 저장되므로, 이 기능을 꺼도 현재 순서가 유지됩니다. | <a href="assets/features/projectStatus.webp"><img src="assets/features/projectStatus.webp" width="160" alt="스크린샷: 활성 프로젝트 우선"></a> |
81
81
  | **최근 프로젝트 필터** | <a id="feature-recentprojects"></a>사이드바 → 보기 옵션(슬라이더 아이콘) → **최근 2시간 내 활성**. 이 옵션을 선택하면 사이드바에는 최근 2시간 안에 활성 채팅이 있었던 프로젝트만 표시됩니다. 활성 채팅은 그 시간 안에 업데이트된 채팅, 실행 중이거나 대기 중인 채팅, 열려 있는 채팅, 아직 열지 않은 완료된 채팅(dsh의 초록색 “완료” 점)입니다. 마지막 경우는 2시간이 지나도 해당됩니다. 이런 채팅이 없는 프로젝트는 숨겨지며, 새 프로젝트와 빈 프로젝트도 숨겨집니다. **작업 공간 트리**에서는 안에 있는 프로젝트가 활성인 동안 상위 폴더가 계속 표시되고, 최근 2시간 안에 활성 상태가 아니었던 채팅도 숨겨지므로 최근 채팅만 표시됩니다. 모든 프로젝트를 다시 보려면 옵션을 다시 선택하세요. 선택은 이 기기에 저장됩니다. | <a href="assets/features/recentProjects.webp"><img src="assets/features/recentProjects.webp" width="160" alt="스크린샷: 최근 프로젝트 필터"></a> |
@@ -85,7 +85,7 @@ dsh plugin --profile web add dsh-composer-plus
85
85
  | **유휴 상태일 때 대기 중인 채팅 열기** | <a id="feature-idleswitch"></a>채팅이 질문을 하거나 승인 또는 계획 검토를 기다리고 있을 때(주황색 점), 또는 아직 읽지 않은 턴을 마쳤을 때(초록색 점) 30초 동안 dsh를 사용하지 않으면 dsh가 그 채팅을 엽니다. 주황색 채팅이 초록색 채팅보다 먼저 열립니다. 각 그룹에서는 가장 오래 기다린 채팅이 먼저 열리고, 다음 채팅은 다시 30초 동안 사용하지 않으면 열립니다. 키 입력, 클릭, 마우스 이동, 스크롤 휠, 터치가 있으면 30초를 다시 셉니다. 포커스가 있는 입력란에 텍스트가 있거나, 텍스트를 선택했거나, 메뉴나 대화 상자가 열려 있어도 전환하지 않습니다. 기다리는 채팅이 화면에 있는 동안에는 아무것도 바뀌지 않습니다. 답하지 않고 기다리는 채팅을 떠나면, 다음에 30초 동안 사용하지 않을 때 그 채팅이 다시 열릴 수 있습니다. 초록색 채팅이 열리면 그 점은 사라집니다. 다음 초록색 채팅은 dsh를 다시 사용한 뒤 30초 동안 사용하지 않을 때 열립니다. dsh가 백그라운드에 있을 때도 작동하지만, dsh가 앞으로 나오지는 않습니다. | <a href="assets/features/idleSwitch.webp"><img src="assets/features/idleSwitch.webp" width="160" alt="스크린샷: 유휴 상태일 때 대기 중인 채팅 열기"></a> |
86
86
  | **애플리케이션 언어** | <a id="feature-language"></a>설정 → Composer Plus → **애플리케이션 언어**에서 dsh 인터페이스 전체를 Türkçe, Español, Português (Brasil), Français, Deutsch, Русский, 日本語, 한국어, Bahasa Indonesia, Tiếng Việt, हिन्दी 중 하나로 바꿉니다(아래 참고). | <a href="assets/features/language.webp"><img src="assets/features/language.webp" width="160" alt="스크린샷: 애플리케이션 언어"></a> |
87
87
  | **모바일 연결(iPhone)** | <a id="feature-mobileconnect"></a>[Tether](tether/) 앱으로 iPhone에서 dsh를 사용하세요. 같은 Wi-Fi나 [Tailscale](https://tailscale.com)을 통해 연결합니다. **설정 → Composer Plus**에서 켜세요(이 Mac에서 네트워크 포트를 열기 때문에 기본적으로 꺼져 있습니다). 그다음 사이드바 왼쪽 아래의 **모바일 연결**을 클릭하세요. iPhone 카메라(**Open in Tether**를 탭)나 Tether의 **Scan code**로 QR 코드를 스캔하고, **Connect**를 탭한 뒤 **Approve**를 클릭하세요. 먼저 Tether를 설치하세요. Tether가 없으면 카메라가 이 코드를 열 수 없습니다. 휴대폰에서 채팅을 보고, 메시지를 보내고(사진 포함: 입력란의 **+** → Camera, Photos 또는 Paste image), 승인과 질문에 답하고, 모델과 에이전트를 바꿀 수 있습니다. Mac은 원하는 만큼 페어링할 수 있으며, 앱 왼쪽 위의 Mac 이름으로 Mac을 전환합니다. **모바일 연결** 패널에는 페어링된 iPhone이 마지막 연결 시각과 함께 표시되며, **Remove**를 누르면 그 iPhone의 연결이 즉시 끊깁니다. “Tailscale only”는 로컬 네트워크의 연결을 거부하고(공유 Wi-Fi용), 액세스 로그는 누가 연결을 시도했는지 보여 줍니다. Tether에서는 “Settings → Privacy”에서 Face ID로 앱을 잠급니다. | <a href="assets/features/mobileConnect.webp"><img src="assets/features/mobileConnect.webp" width="160" alt="스크린샷: 모바일 연결(iPhone)"></a> |
88
- | **자동 업데이트** | <a id="feature-autoupdate"></a>dsh가 시작되면 플러그인이 [최신 GitHub 릴리스](https://github.com/furkancak1r/dsh-composer-plus/releases/latest)를 확인합니다. 더 새로운 버전이고 npm에도 올라와 있으면, dsh 자체 플러그인 관리자(설정 → 플러그인과 같은 경로)로 정확히 그 버전을 설치하고 알려 줍니다. 새 버전을 로드하려면 dsh를 다시 시작하세요. **설정 → Composer Plus → Composer Plus 업데이트**에서 버전을 볼 수 있고, **업데이트 확인** / **지금 업데이트** 버튼도 있습니다. 새 버전으로 dsh를 처음 시작하면 **Composer Plus N의 새로운 기능** 창이 그 버전의 릴리스 노트를 한 번 보여 줍니다(같은 업데이트 확인에서 받은 내용이며 추가 네트워크 호출은 없습니다). **닫기** 또는 `Esc`로 닫습니다. | <a href="assets/features/autoUpdate.webp"><img src="assets/features/autoUpdate.webp" width="160" alt="스크린샷: 자동 업데이트"></a> |
88
+ | **자동 업데이트** | <a id="feature-autoupdate"></a>dsh가 시작되면 플러그인이 [최신 GitHub 릴리스](https://github.com/furkancak1r/dsh-composer-plus/releases/latest)를 확인합니다. 더 새로운 버전이고 npm에도 올라와 있으면, dsh 자체 플러그인 관리자(설정 → 플러그인과 같은 경로)로 정확히 그 버전을 설치하고 알려 줍니다. 새 버전을 로드하려면 dsh를 다시 시작하세요. **설정 → Composer Plus → Composer Plus 업데이트**에서 버전을 볼 수 있고, **업데이트 확인** / **지금 업데이트** 버튼도 있습니다. 새 버전으로 dsh를 처음 시작하면 **Composer Plus N의 새로운 기능** 창이 그 버전의 릴리스 노트를 **애플리케이션 언어**에서 고른 언어로 한 번 보여 줍니다(노트는 새 버전에 함께 들어 있으며 추가 네트워크 호출은 없습니다. 그 언어의 노트가 없으면 영어 노트를 보여 줍니다). **닫기** 또는 `Esc`로 닫습니다. | <a href="assets/features/autoUpdate.webp"><img src="assets/features/autoUpdate.webp" width="160" alt="스크린샷: 자동 업데이트"></a> |
89
89
  | **백업** | <a id="feature-backup"></a>설정 → Composer Plus → **백업** → **지금 백업**은 dsh 홈 전체(채팅, 설정, 플러그인, MCP, 스킬)를 체크섬과 함께 `~/Desktop/dsh-backups`의 아카이브 하나에 씁니다. 아카이브에서 비밀 값은 마스킹됩니다. 자격 증명 파일, 키 파일(`.pem`, `.key`), yml 설정의 token, secret, password 값은 이 컴퓨터에만, 폴더의 `vault`에 남습니다. `cache/`, `dsh-runtimes/`, `node_modules`는 아카이브에 들어가지 않습니다(dsh가 다시 만듭니다). 목록의 각 백업에는 **검사**(끝까지 읽음), **다른 컴퓨터용**(새 컴퓨터로 복사할 폴더, 복구 콘솔 포함), **삭제**가 있습니다. 같은 폴더에 있는 dsh-backup의 아카이브도 표시되고 사용할 수 있습니다. 복원하려면 dsh를 종료하고 복구 콘솔을 사용하세요. | <a href="assets/features/backup.webp"><img src="assets/features/backup.webp" width="160" alt="스크린샷: 백업"></a> |
90
90
  | **자동 백업** | <a id="feature-autobackup"></a>**자동 백업**을 켜세요(기본적으로 꺼져 있습니다. 각 사본은 캐시를 뺀 dsh 홈과 크기가 거의 같습니다). 얼마나 자주 백업할지(**간격**: 6시간에서 7일, 기본값 24시간)와 백업을 몇 개 남길지(**보관**: 3에서 14, 기본값 7)를 고르세요. 다음 백업 시각은 스위치 아래에 표시됩니다. 실패한 백업도 그곳에 표시되고, 30분 뒤에 다시 시도합니다. dsh나 Composer Plus가 새 버전으로 시작하면, 시작 직후 새 버전이 데이터를 오래 쓰기 전에 스냅샷을 만듭니다(가장 최신 두 개가 남고, **업그레이드 전**으로 표시됩니다). | <a href="assets/features/autoBackup.webp"><img src="assets/features/autoBackup.webp" width="160" alt="스크린샷: 자동 백업"></a> |
91
91
  | **세션 로그 점검** | <a id="feature-sessiondoctor"></a>**세션 로그 검사**는 모든 채팅의 로그를 읽고, dsh가 열 수 없는 로그를 나열합니다(깨진 프레임, 잘린 레코드, 잘못된 시퀀스 번호). 마지막 부분만 덜 쓰인 로그는 나열되지 않습니다. dsh가 직접 고칩니다. **백업에서 복구**는 정상 사본이 있는 가장 최신 백업에서 사본을 되돌려 놓고, 손상된 파일은 그 옆에 보관합니다(`.corrupt-<시각>`). 그 백업 이후에 작성된 메시지는 사본에 없습니다. 이 dsh에서 열려 있는 채팅은 여기서 복구되지 않습니다. dsh를 종료하고 복구 콘솔에서 복구하세요. | <a href="assets/features/sessionDoctor.webp"><img src="assets/features/sessionDoctor.webp" width="160" alt="스크린샷: 세션 로그 점검"></a> |
@@ -169,7 +169,7 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
169
169
  - **목표 확인:** 에이전트가 자동 라운드에서 `/goal`을 완료로 표시할 때(또는 **지금 실행**을 클릭할 때)만 실행됩니다. Host 쪽은 테스트 명령을 채팅 폴더에서 채팅의 샌드박스 모드로 실행합니다(dsh 자체의 `bash` 도구와 같음: 같은 파일 접근 정책. 그 샌드박스를 시작할 수 없으면 테스트를 실행하지 않고 확인은 실패합니다). 명령을 찾으려고 `package.json`, `Makefile`, `Cargo.toml`, `go.mod`, `pyproject.toml`, `pytest.ini`만 폴더 안의 일반 파일로 읽습니다(폴더 밖을 가리키는 심볼릭 링크 없음, FIFO 없음). 그다음 목표, 목표가 시작된 뒤의 채팅(사용자의 메시지, 에이전트의 답변, 1,000자로 자른 도구 호출, 각 도구 결과의 마지막 2,000자. 추론과 되돌린 단계 제외. 최대 약 60,000자, 가장 최근 부분), `git status --short`, 테스트 출력의 끝부분을 **목표 확인**에서 고른 모델(기본값: 채팅 자체의 모델)에 도구 없는 요청 한 번으로 보냅니다. 도구 출력에는 에이전트가 읽은 내용이 들어 있을 수 있으므로, 채팅 자체와 마찬가지로 이 요청에 파일의 일부가 들어갈 수 있습니다. 채팅과 프로젝트에는 아무것도 쓰지 않습니다. 직접 정한 테스트 명령, 제한, 마지막 결과(출력의 끝부분 포함), 고른 모델은 `$DSH_HOME/storages/dsh-composer-plus/goal-check.json`(소유자 전용 파일, 최신 채팅 500개)에 보관됩니다.
170
170
  - **새 채팅에서 계속:** 클릭하기 전에는 아무것도 실행되지 않습니다. 클릭하면 Host 쪽은 채팅(목표 확인이 읽는 방식과 같음: 추론과 되돌린 단계 제외)을 채팅 자체의 모델에 보내고 인계 메모를 보여 줍니다. 새 채팅을 만드는 것은 **새 채팅 시작**뿐입니다. 프로젝트에는 아무것도 쓰지 않습니다.
171
171
  - **컨텍스트 구성:** Host에서 채팅 로그만 읽습니다. 모델 호출도 프로젝트 파일도 없습니다.
172
- - **작업 보드:** 보드(작업의 제목, 설명, 태그, 댓글, 프로젝트 폴더 경로와 그 짧은 ID)는 `$DSH_HOME/storages/dsh-composer-plus/board.json`(소유자 전용 파일)에 있습니다. 스위치는 그 옆의 `board-switch.json`에 있습니다. 아무것도 컴퓨터 밖으로 나가지 않으며, 프로젝트 폴더에는 아무것도 쓰지 않습니다. 보드 도구는 사용자가 보드에 쓴 내용을 에이전트에게 주므로, 에이전트가 작업을 읽으면 그 텍스트가 채팅의 모델에 전달됩니다. 손상된 보드 파일은 `board.json.broken-<time>`으로 보관되고, 보드는 빈 상태로 시작합니다.
172
+ - **작업 보드:** 보드는 이 창에 있는 dsh 자체 목록에서 dsh 자체 채팅을 보여 주며, 자체 채팅 데이터를 추가하지 않습니다. 작업을 시작하면 Host 쪽이 고른 프로젝트에 새 채팅을 만들고, 사용자가 거기서 직접 입력한 것처럼 프롬프트를 첫 메시지로 보냅니다. 그래서 승인, 샌드박스, 채팅의 모델이 평소처럼 적용됩니다. 그런 다음 태그를 최대 3개 얻기 위해 프롬프트(처음 4,000자만, 다른 것은 없음)를 도구 없이 요청 한 번으로 그 채팅의 모델에 더 보냅니다. 각 작업의 프롬프트, 태그, 시작 시각은 `$DSH_HOME/storages/dsh-composer-plus/board-chats.json`(소유자 전용 파일, 최신 2,000개)에 보관됩니다. 스위치는 그 옆의 `board-switch.json`에 있습니다. 프로젝트 폴더에는 아무것도 쓰지 않습니다. **답변**은 채팅 자체의 카드와 같은 방식으로 dsh 자체의 대기 중인 요청에 답변을 보냅니다. 이전 버전의 예전 작업 목록(`board.json`)은 디스크에 그대로 남으며 읽지 않습니다.
173
173
  - **보호된 파일:** 목록과 스위치는 `$DSH_HOME/storages/dsh-composer-plus/protected-files.json`(소유자 전용 파일)에 있습니다. 확인은 각 파일 도구 호출의 경로(와 실제 경로)만 읽으며, 파일 자체는 읽지 않습니다.
174
174
  - **차단된 명령:** 규칙과 스위치는 `$DSH_HOME/storages/dsh-composer-plus/blocked-commands.json`(소유자 전용 파일)에 있습니다. 확인은 각 `bash`와 `pwsh` 호출의 명령 텍스트만 읽으며, 아무것도 실행하거나 보내지 않습니다.
175
175
  - **프로젝트 메모리:** 직접 켜기 전까지는 꺼져 있습니다. 켜져 있는 동안 최상위 채팅의 턴이 끝날 때마다 Host 쪽이 지난 검토 이후 그 채팅의 새 메시지(사용자 메시지와 에이전트의 텍스트 답변. 도구 출력, 추론, 숨은 컨텍스트, 되돌린 메시지는 제외. 분기한 채팅에서는 부모 채팅의 복사본 제외. 최대 약 16,000자)와 저장된 메모를, 도구 없는 요청 한 번으로 채팅 자체의 모델에 보냅니다. 메모는 `$DSH_HOME/storages/dsh-composer-plus/memory/` 아래의 Markdown 파일(소유자만 읽고 쓸 수 있음)입니다. 프로젝트 폴더마다 `projects/<id>/`(`<id>`는 폴더 실제 경로의 해시이며, `project.json`에 폴더가 적힙니다), `global/`, `journal.jsonl`(각 변경과 변경 전후의 줄), `reviewed.json`(각 채팅을 어디까지 읽었는지)이 있습니다. 프로젝트 폴더에는 아무것도 쓰지 않습니다. 키, 토큰, 비밀번호, 신분증 번호처럼 보이는 메모는 거부합니다. 프로젝트의 메모는 그 폴더의 새 채팅마다 시스템 프롬프트에 들어가므로, 그 채팅의 모든 요청과 함께 모델에 전달됩니다. 스위치는 같은 위치의 `memory.json`에 있습니다. **메모리 열기**는 **변경 미리 보기**를 누르기 전에는 아무것도 보내지 않습니다. 누르면 보이는 메모와 사용자의 글을 도구 없는 한 번의 요청으로 dsh의 기본 모델에 보냅니다. 변경은 **적용**을 눌러야만 기록되며 저널에는 `editor`로 남습니다. Tether도 같은 경로로 메모를 읽고 바꿉니다.
@@ -191,10 +191,10 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
191
191
  - **재시작 후 채팅이 이어지지 않음:** dsh를 종료할 때 재시작 후 이어서 실행이 꺼져 있었거나, 그 턴을 직접 중지했거나, 턴이 이미 끝났거나(완료 또는 실패), 채팅이 보관되었거나, 실행 중인 채팅이 20개보다 많았습니다(가장 최근 채팅 20개만 이어짐).
192
192
  - **재시작 후 대기열이 비어 있음:** 대기열을 비우는 것은 dsh 자체의 종료입니다. 재시작 후 이어서 실행은 이어서 실행하는 채팅에서만 대기열을 되돌립니다. 다른 채팅에서는 메시지를 다시 보내세요. 종료 직전에 삭제한 메시지가 돌아올 수 있습니다. 그때는 다시 삭제하세요.
193
193
  - **GitHub 이슈 열기에 "gh could not open the issue"가 표시됨:** 이 메시지는 `gh` 자체 출력의 첫 줄입니다. 터미널에서 `gh auth status`를 실행하고 `gh auth login`으로 로그인하세요. 채팅 폴더에 GitHub 원격 저장소가 있어야 합니다(`git remote -v`). "not installed or not on the PATH of dsh"는 dsh가 `gh`를 찾지 못했다는 뜻입니다. 설치하거나, `gh`가 작동하는 터미널에서 dsh를 시작하세요.
194
- - **채팅 행에 브랜치 배지가 없음:** 이 버전을 설치한 뒤 그 채팅에 턴이 없었거나, 폴더가 git 저장소가 아니거나, **채팅 행의 Git 브랜치**가 꺼져 있습니다. 업데이트한 뒤에는 dsh를 다시 시작하세요(브랜치는 Host 쪽이 기록합니다).
194
+ - **채팅 행에 브랜치 배지가 없음:** 사이드바가 “하나의 목록” 보기가 아니거나(“작업 공간”과 “작업 공간 트리”에서는 어떤 채팅 행에도 배지가 없음), 이 버전을 설치한 뒤 그 채팅에 턴이 없었거나, 폴더가 git 저장소가 아니거나, **채팅 행의 Git 브랜치**가 꺼져 있습니다. 업데이트한 뒤에는 dsh를 다시 시작하세요(브랜치는 Host 쪽이 기록합니다).
195
195
  - **목표 확인에 테스트가 종료 코드 127 또는 "not found"로 끝났다고 표시됨:** Finder나 Dock에서 시작한 dsh는 터미널보다 PATH가 짧을 수 있어서 `npm`, `pnpm`, `cargo`를 찾지 못합니다. 터미널에서 dsh를 시작하거나, **목표 확인** → **편집**에서 전체 경로를 쓴 테스트 명령을 직접 정하세요. **지금 실행**을 누르면 결과가 바로 표시됩니다.
196
196
  - **목표가 닫히지 않고 에이전트가 계속 작업함:** **목표 확인**이 실패한 테스트나 남은 작업을 찾았습니다. 목표 아래의 행에 이유가 표시됩니다(자세한 내용은 결과에 포인터를 올려 보세요). 원인이나 테스트 명령을 고치거나, `/goal` 또는 목표 바로 목표를 직접 완료하세요(이 완료는 확인하지 않습니다).
197
- - **릴리스 직후 설치 실패:** 버전을 붙여서 설치하세요(`dsh-composer-plus@1.18.0`). 위의 설치 안내를 참고하세요.
197
+ - **릴리스 직후 설치 실패:** 버전을 붙여서 설치하세요(`dsh-composer-plus@1.19.1`). 위의 설치 안내를 참고하세요.
198
198
  - **지금 백업에서 "다른 백업 작업이 실행 중입니다"라고 표시됨:** 다른 dsh 창이나 복구 콘솔에서 작업이 실행 중입니다(둘은 백업 폴더의 잠금 파일 `.composer-plus.lock`을 함께 씁니다). 작업이 끝날 때까지 기다리세요. 실행 중인 작업이 없으면, 다음에 클릭할 때 종료된 프로세스의 잠금을 넘겨받습니다.
199
199
  - **복구 콘솔에 "dsh is running"이라고 표시됨:** 먼저 dsh를 종료하세요. dsh가 정말 닫혀 있다면, 메시지에 나온 파일은 비정상 종료로 남은 것입니다. 그 파일을 삭제하고 다시 시도하세요.
200
200
  - **복원 후 dsh가 시작되지 않거나 플러그인이 없음:** 프로필의 플러그인 패키지를 다시 설치해야 합니다. 복구 콘솔이 복원 후에 이를 제안합니다. 또는 콘솔이 나열하는 `$DSH_HOME/profiles/` 아래의 각 폴더에서 `pnpm install`을 실행하세요. vault에 없던 비밀 값(다른 컴퓨터)은 다시 입력해야 합니다. 콘솔이 그 목록을 보여 줍니다.
@@ -214,6 +214,7 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
214
214
  - **채팅 삭제**에는 dsh의 보관 기능(dsh 0.2.0 이상)이 필요합니다. 15초 안에 멈추지 않거나 다른 dsh가 잡고 있는 채팅(또는 그 하위 에이전트 채팅 중 하나)은 보관된 상태로 남고, 아무것도 이동하지 않습니다. macOS가 아닌 시스템에서는 휴지통 폴더가 채팅 기록과 같은 디스크에 있어야 합니다. 열려 있는 채팅을 삭제하면, 그 채팅은 dsh를 다시 시작할 때까지 dsh 메모리에 보관되고 숨겨진 상태로 남습니다. 휴지통은 직접 비우세요. dsh는 휴지통을 비우지 않습니다.
215
215
  - dsh의 대기열에는 `move` 동작이 없습니다. 그래서 플러그인의 Host 쪽이 dsh의 대기열 안에서 대기 중인 메시지 자체를 옮깁니다(한 번의 변경, 같은 메시지). 이미지나 파일이 있는 메시지도 이동할 수 있습니다. 내 메시지만 이동할 수 있습니다. 대기열에 있는 목표 라운드나 질문에 대한 답변은 제자리에 남습니다. 끄는 중에 메시지 전송이 시작되면 아무것도 이동하지 않고, 알림으로 이를 알려 줍니다.
216
216
  - 새 버전이 dsh 설정을 하나도 바꾸지 않으면 dsh 0.2.1은 업데이트를 바로 로드합니다. 그 밖의 경우와 dsh 0.2.0에서는 업데이트를 로드하려면 dsh를 다시 시작하세요. 플러그인은 dsh를 대신 재시작하지 않습니다. dsh 플러그인 관리자가 없는 웹/CLI 프로필은 새 버전을 알리기만 합니다.
217
+ - **Composer Plus N의 새로운 기능**은 **애플리케이션 언어**의 언어로 노트를 보여 줍니다. 다른 지역이 붙은 UI 언어는 기본 언어의 노트를 받습니다(`en-GB`는 영어 노트, `zh-TW`는 `zh`의 중국어 노트). 노트가 없는 언어(다른 언어 팩이 추가한 언어, 또는 `pt-BR`이 아닌 `pt-PT`)에서는 영어 노트를 보여 줍니다. 노트는 새 버전에 함께 들어 있습니다. 실행 중인 사본에 읽을 수 있는 노트 파일(`release-notes.json`)이 없으면 GitHub의 영어 노트를 보여 줍니다.
217
218
  - **이 채팅에서 허용**은 허용한 순간부터 시간 제한을 셉니다. 새 시간 제한은 유효한 허용에 즉시 적용되므로, 더 짧은 시간 제한은 허용을 즉시 끝낼 수 있습니다. 버전 1.12 이하의 허용에는 시간 정보가 없습니다. 업데이트 후 에이전트가 그 도구들에 대해 한 번 더 묻습니다.
218
219
  - **입력란 포커스 유지**는 `/` 명령이나 스킬을 보낸 뒤에만 포커스를 돌려줍니다. dsh가 명령을 처리하는 몇 밀리초 동안 입력란이 읽기 전용이므로, 그동안 누른 키는 사라집니다. dsh의 `/` 메뉴가 아직 열려 있으면 `Enter`는 강조된 행을 선택하고 메시지를 보내지 않습니다.
219
220
  - **질문 카드를 창에 맞추기**는 dsh의 질문 카드만 바꾸고 계획 검토 카드는 바꾸지 않습니다. 카드는 dsh의 마크업(`data-question-key`, `data-question-scroll`)으로 찾습니다. dsh 업데이트로 이 마크업이 바뀌면 카드는 dsh가 그리는 대로 보입니다. 카드 높이는 채팅이 아니라 창을 따릅니다. 좁은 사이드 패널 안의 채팅에서는 높은 카드가 채팅 위로 넘칠 수 있습니다.
@@ -227,7 +228,7 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
227
228
  - **이 채팅**은 dsh의 파일 도구(`write`, `edit`, `str_replace_editor`)가 쓴 파일만 셉니다. 명령(`bash`)이 바꾼 파일은 이 보기에 없고, **커밋 안 됨**에 표시됩니다. 채팅의 턴 되돌리기 스냅샷이 없으면(턴 되돌리기 꺼짐, dsh-rewind-plugin 설치됨, 또는 플러그인보다 오래된 채팅) 보기는 마지막 커밋과 비교하고 그렇다고 알려 줍니다. 턴 되돌리기는 채팅마다 최신 스냅샷 50개를 보관합니다. 더 긴 채팅에서는 보기가 보관된 가장 오래된 스냅샷과 비교하고, 어느 메시지부터인지 알려 주며, 그 이전의 변경은 세지 않습니다. **공백 변경 숨기기**는 `git diff -w`입니다. 줄 안의 공백만 바뀐 줄도 숨겨집니다.
228
229
  - **GitHub 이슈 열기**에는 dsh의 PATH에 있는 GitHub CLI(`gh`)와 채팅 폴더의 GitHub 원격 저장소가 필요합니다. 최대 60초 동안 실행됩니다. `gh`가 더 오래 걸리면, 이슈가 GitHub에는 만들어졌지만 목록에는 링크가 없을 수 있습니다(다시 클릭하기 전에 GitHub를 확인하세요. 목록은 끝난 실행에서만 링크를 읽으므로, 다시 클릭하면 두 번째 이슈가 열릴 수 있습니다). GitHub 원격 저장소가 둘 이상인 폴더는 `gh` 자체의 기본값(`gh repo set-default`)을 씁니다.
229
230
  - **이 파일을 변경한 채팅**은 **이 채팅**처럼 dsh의 파일 도구(`write`, `edit`, `str_replace_editor`)만 압니다. 명령(`bash`)으로 만든 변경은 목록에 나오지 않습니다. 저장소의 최신 채팅 300개(만든 시점 기준)를 읽고, 더 있으면 그렇다고 알려 줍니다. 최대 100행을 보여 줍니다. 이름이 바뀐 파일은 도구가 쓴 이름으로 표시됩니다. 폴더가 저장소 밖에 있는 채팅(같은 파일로 가는 다른 경로를 통한 경우도 포함)은 세지 않습니다. dsh를 시작한 뒤 처음 열 때는 저장소의 모든 채팅 로그를 읽습니다(채팅 275개에 약 4초). 그 뒤로 열 때는 그 이후에 바뀐 채팅만 읽습니다.
230
- - **채팅 행의 Git 브랜치**는 현재 브랜치가 아니라, 마지막 턴이 시작되거나 끝날 때 채팅 폴더가 있던 브랜치를 보여 줍니다. 턴 밖에서 브랜치를 바꾸면 다음 턴 뒤에 표시됩니다. 이 버전 이전의 채팅에는 다음 턴까지 배지가 표시되지 않습니다. 배지는 dsh의 채팅 행 마크업 안에 들어갑니다(dsh에는 그곳에 슬롯이 없습니다). dsh 업데이트로 그 마크업이 바뀌면 배지가 표시되지 않습니다. 채팅 위의 프로젝트 행 이름이 브랜치와 같으면(예: “채팅별 브랜치” 폴더) 채팅 행에 배지가 표시되지 않지만, “하나의 목록”에서는 계속 표시됩니다.
231
+ - **채팅 행의 Git 브랜치**는 현재 브랜치가 아니라, 마지막 턴이 시작되거나 끝날 때 채팅 폴더가 있던 브랜치를 보여 줍니다. 턴 밖에서 브랜치를 바꾸면 다음 턴 뒤에 표시됩니다. 이 버전 이전의 채팅에는 다음 턴까지 배지가 표시되지 않습니다. 배지는 dsh의 채팅 행 마크업 안에 들어갑니다(dsh에는 그곳에 슬롯이 없습니다). dsh 업데이트로 그 마크업이 바뀌면 배지가 표시되지 않습니다. 배지는 “하나의 목록”에서만 표시됩니다.
231
232
  - **채팅별 브랜치**를 계획 모드에서 쓸 때: dsh는 `/plan <메시지>`를 메시지가 아니라 명령으로 보냅니다. 그래서 Composer Plus가 dsh 입력란에서 명령 전송을 가로챕니다(공개 API가 아님). dsh 업데이트로 이것이 바뀌면, **새 브랜치**를 고른 상태의 `/plan <메시지>`는 열린 새 채팅에서 dsh 자체 명령으로 실행됩니다. Host가 새 채팅에서 계획 모드를 켜지 못하면 브랜치 폴더는 남고 메시지는 보내지지 않습니다. 따라서 새 채팅이 기본 모드에서 파일을 바꾸지 않습니다.
232
233
  - **채팅별 브랜치**: 채팅의 브랜치 폴더(`<project>/.worktrees/<name>`)가 삭제되면(예: 채팅 자신의 에이전트가 worktree를 제거하고 브랜치를 삭제할 때) 채팅의 다음 단계에서 채팅이 그 폴더 밖으로 옮겨집니다. 브랜치 폴더의 프로젝트는 사이드바에서 사라지고, 채팅은 그룹 없음 아래에 표시되며 열린 상태로 유지됩니다. dsh 0.2.1 이상에서는 채팅이 프로젝트의 기본 폴더에서 계속되고, 모델은 새 폴더에 대한 안내를 받습니다. dsh 0.2.0에서는 채팅이 삭제된 폴더를 그대로 사용합니다. 그곳에서 실행하는 명령은 새 채팅을 시작할 때까지 실패합니다. 어떤 채팅도 사용하지 않는 삭제된 브랜치의 프로젝트도 사이드바에서 사라집니다. Composer Plus는 시작할 때와 30초마다 브랜치 폴더를 확인하며, 사이드바 필터가 없어도 됩니다. 채팅이 옮겨지는 동안 같은 저장소의 **새 브랜치**는 "다시 시도하세요"라고 답합니다. 스위치를 끄면 dsh 자체 오류("working-directory: directory does not exist")가 다시 표시됩니다.
233
234
  - **작업 공간 트리의 브랜치**은(는) 클릭 없이 git에 씁니다. 채팅을 옮길 때 프로젝트 폴더를 이전 브랜치로 되돌리고(`git switch`) worktree를 추가합니다(`git worktree add`). 브랜치, worktree, 파일은 절대 삭제하지 않습니다. dsh는 채팅의 폴더를 바꿀 수 없으므로, 옮겨진 채팅은 복사본(새 id를 가진 dsh 자체 포크)이고 이전 채팅은 보관됩니다. 복사본은 멈춘 작업을 이어서 합니다. 브랜치가 생겼을 때 실행 중이던 도구 호출은 거부로 끝나고, 에이전트는 새 폴더에서 그것을 다시 실행합니다. 이전 채팅의 목표는 함께 옮겨지지 않습니다. 폴더가 저장소의 메인 폴더인 채팅만 옮겨지며, 그 턴에서 만들고 전환한 브랜치(`git switch -c`, `git checkout -b`)일 때만 옮겨집니다. `git branch`만으로 만든 브랜치, 커밋되지 않은 변경이 있는 폴더, 연결된 worktree, 하위 폴더는 아무것도 옮기지 않습니다. 트리에는 `<project>/.worktrees/` 바로 아래에 있고 브랜치가 있는 worktree만 표시됩니다. 분리된(detached) worktree나 다른 위치의 worktree는 표시되지 않습니다. 복사본은 원래 채팅이 열려 있던 채팅일 때만 저절로 열립니다(플러그인은 dsh의 사이드바 행에서 이를 읽습니다). 그 외에는 브랜치 프로젝트에 있습니다.
@@ -248,7 +249,7 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
248
249
  - **새 채팅에서 계속**은 채팅(메시지, 도구 호출, 각 도구 결과의 끝부분. 최대 약 60,000자, 가장 최근 부분)을 채팅 자체의 모델에 보냅니다. 인계 메모는 결정이나 파일을 빠뜨릴 수 있으므로, 시작하기 전에 읽어 보세요. 새 채팅은 메모와 링크된 채팅만 압니다(dsh는 이전 채팅을 읽기 전용 컨텍스트로 첨부합니다). 새 채팅의 모델 컨텍스트는 작게 시작하고, 이전 채팅은 그대로 남습니다. 채팅마다 한 번에 메모 작성이나 시작 하나만 실행됩니다.
249
250
  - **컨텍스트 구성**은 dsh 자체의 규칙(토큰당 약 4자)으로 추정값을 보여 줍니다. dsh의 컨텍스트 링과 같은 규칙이며, 모델 자체의 계산과 다를 수 있습니다. 도구 정의는 가장 최근 요청의 것입니다. 채팅 로그에 있는 그대로의 컨텍스트를 보여 주며, 지금 실행 중인 턴은 다음 단계 뒤에 나타납니다.
250
251
  - **계획된 단계**는 모델이 실제로 계획할 때만 토큰을 절약합니다. 켜져 있는 동안에는 모델이 계획하지 않는 채팅에서도 모든 요청에 `plan_next_steps` 도구와 짧은 지침(약 500토큰)이 포함됩니다. 조건은 적힌 내용만 증명합니다(예: 빌드 종료 코드가 0이었음). 작업이 올바르다는 것은 증명하지 않습니다. `ok`는 dsh 자체의 결과 표시(`[exit code: N]`, 시간 초과, 샌드박스 거부)를 읽습니다. 0이 아닌 종료 코드 없이 실패한 명령은 통과로 처리됩니다. 단계는 한 번에 하나씩 실행되며, 동시에 준비된 두 단계는 모델에게 돌아갑니다. 단계의 메시지는 채팅 모델의 어시스턴트 메시지로 저장됩니다(dsh에는 플러그인이 쓴 메시지를 나타내는 표시가 없습니다). 그래서 그 텍스트에 Composer Plus가 실행했다고 적혀 있습니다. Tether에는 없습니다.
251
- - **작업 보드**는 dsh의 프로젝트만 압니다. 프로젝트 밖의 채팅에서는 **모든 프로젝트**가 표시되고, 채팅별 브랜치 폴더(`<project>/.worktrees/<name>`)는 해당 프로젝트로 취급됩니다. 프로젝트 ID(`acme#12`)는 폴더 이름에서 오며, dsh에서 프로젝트 이름을 바꿔도 그대로입니다. "보드를 최신 상태로 유지" 규칙은 그 프로젝트에 열린 작업이 있을 때만 채팅에 들어갑니다. 한 번 받은 채팅은 규칙을 유지합니다. 에이전트에게는 **완료**, **백로그**, 수동 작업을 사용자에게 맡기라고 알리지만, 도구가 이를 거부하지는 않습니다. 에이전트가 그런 카드를 옮길 수도 있습니다. 기능이 켜져 있는 동안 보드 도구는 모든 채팅의 도구 목록에 들어갑니다(요청마다 약 1,000 토큰). 보드를 쓰지 않으면 끄세요. 페이지가 보이는 동안 2초마다 보드를 읽으므로, 에이전트의 변경은 그 시간 안에 표시됩니다. 에이전트가 같은 필드를 바꾸는 동안 사용자가 편집한 텍스트는 저장되지 않습니다. 패널에 새 텍스트와 이유가 표시됩니다. 이미지, 컴퓨터 간 git 동기화, 네트워크 공유는 없습니다(Kanzo에는 있습니다). 아이디어와 디자인은 emanuele-em의 [Kanzo](https://github.com/emanuele-em/kanzo)(AGPL-3.0)에서 왔습니다. Composer Plus는 그 코드를 쓰지 않습니다.
252
+ - **작업 보드**는 dsh가 이 창에 나열하는 채팅을 보여 줍니다. 프로젝트 밖의 채팅은 **모든 프로젝트**에만 표시되고, 채팅별 브랜치 폴더(`<project>/.worktrees/<name>`)는 해당 프로젝트로 취급됩니다. 카드의 열은 채팅의 실시간 상태이므로 카드를 끌어 옮길 수 없습니다. 채팅은 턴이 끝나면(오류나 중지 후에도) **완료**로 가고, 다시 실행되면 **진행 중**으로 돌아갑니다. 초록색 점은 dsh 자체의 완료 점이며, dsh는 이 점을 이 창에만 보관합니다. 페이지를 다시 불러오면 끝난 채팅이 이 점 없이 표시됩니다. **완료**에는 최신 채팅 50개가 표시됩니다(나머지는 **이전 작업 N개 보기**로 볼 수 있습니다). **프로젝트 검색**은 프로젝트를 이름으로만 찾고, 폴더 경로로는 찾지 않습니다. **최근 2시간 내 활성**은 프로젝트의 모든 채팅이 2시간보다 오래되었고 유휴 상태이며 읽은 상태일 때 그 프로젝트를 숨깁니다. 선택한 프로젝트는 보드에 계속 표시됩니다. 태그는 시작한 작업마다 모델 호출 한 번으로 만들어지므로 틀릴 수 있으며, 보드에서 시작하지 않은 채팅에는 태그가 없습니다. 제목은 dsh 자체의 채팅 제목입니다(dsh의 제목 서비스가 채팅의 모델로 만듭니다). 제목이 오기 전까지 카드에는 프롬프트의 첫 줄이 표시됩니다. dsh가 아는 `/` 명령(`/plan`, `/goal`)으로 시작하는 프롬프트는 그 명령으로 실행됩니다. **답변**은 채팅의 가장 최근 요청에만 답합니다. 그 요청이 다른 곳(다른 창, Tether, 자동 검토)에서 이미 답변되었거나 채팅이 새로운 것을 물으면, 패널이 그렇게 알려 주고 아무것도 보내지 않습니다. 이전 버전에는 댓글과 에이전트 도구가 있는 작업 목록이 있었지만 이제 없어졌으며, 예전 `board.json`은 표시되지 않습니다. 아이디어와 디자인은 emanuele-em의 [Kanzo](https://github.com/emanuele-em/kanzo)(AGPL-3.0)에서 왔습니다. Composer Plus는 그 코드를 쓰지 않습니다.
252
253
  - **중지 후 보낸 메시지 먼저 실행**은 채팅을 중지한 뒤에만 동작합니다(또는 실패한 턴 뒤, 아직 대기열이 있는 채팅을 열 때). 턴이 실행되는 중에 보낸 메시지는 여전히 대기열 끝에서 기다립니다. 내가 대기열에 넣은 메시지만 앞지릅니다. 대기열에 목표 라운드나 질문 답변이 기다리고 있으면 dsh 자체 순서가 유지됩니다. 공개 API가 아닌 dsh의 일부(중지된 턴이 아직 끝나는 중인지)를 읽습니다. dsh 업데이트로 그 이름이 바뀌면, 메시지는 그 턴이 끝난 뒤에만 앞으로 옮겨집니다. 서브에이전트 채팅은 dsh 자체 순서를 유지합니다.
253
254
  - **프로젝트 메모리**는 채팅의 첫 폴더(dsh의 프로젝트 폴더)에 속합니다. `cd`로 폴더를 바꾼 채팅은 첫 프로젝트의 메모리를 계속 씁니다. 같은 파일로 가는 다른 경로로 연 같은 폴더는 메모리를 공유합니다. 채팅은 시작할 때 메모리 섹션을 고정하므로, 나중에 저장한 메모는 다음 채팅부터 보입니다(`memory_recall`은 바로 찾습니다). 검토는 모델이 남기기로 정한 것만 남깁니다. 사실을 놓치거나 틀린 것을 남길 수 있으니, **메모리 열기**에서 확인하고 그곳에서 바꾸거나, dsh가 닫혀 있을 때 파일을 직접 고치세요. **메모리 열기**는 선택한 프로젝트의 메모와 전역 메모(모든 메모를 선택하면 모든 프로젝트, 최대 약 60,000자이며 나머지는 개수만 표시되고 그 요청에서는 바꿀 수 없음)와 사용자의 글을 채팅의 모델이 아니라 dsh의 기본 모델로 보냅니다. 미리 보기는 Mac에 30분 동안, dsh를 다시 시작할 때까지 보관됩니다. 그사이 검토나 에이전트가 메모를 바꾸면 **적용**이 거부되므로 다시 미리 보기를 하세요. **적용**은 미리 보기의 변경을 모두 저장하거나 하나도 저장하지 않습니다. 저장할 수 없는 변경이 하나라도 있으면(예: MEMORY.md가 가득 찬 경우) 메모는 그대로 남고 이유가 표시됩니다. 사용자 메시지가 있는 턴이 끝날 때마다 모델 호출이 한 번 듭니다. 호출이 실패하면 다음 턴 뒤에 같은 메시지를 다시 읽습니다. 서브에이전트 채팅은 검토하지 않습니다. 아이디어와 파일 형식은 [DS Bot](https://github.com/Fei2411/DS-Bot)(Apache-2.0)에서 왔습니다. Composer Plus는 그 코드를 쓰지 않으며, DS Bot 자체의 메모리를 읽거나 쓰지 않습니다.
254
255
  - **백업**은 고정된 폴더 하나, `~/Desktop/dsh-backups`만 씁니다(dsh-backup의 기본 폴더이므로 그 아카이브도 계속 쓸 수 있습니다). 다른 폴더를 고르는 설정은 없습니다. 아카이브 크기는 `cache/`와 `dsh-runtimes/`를 뺀 dsh 홈과 거의 같습니다(측정: Apple Silicon에서 1.6 GB의 파일이 약 30초 만에 830 MB 아카이브가 되었고, 그동안 dsh는 계속 응답했습니다). 읽는 동안 바뀐 파일은 백업이 그 파일을 열었을 때의 상태로 저장됩니다. 그래서 열려 있는 채팅의 로그가 잘린 레코드로 끝날 수 있으며, dsh가 다음에 쓸 때 이를 복구합니다. 마스킹은 yml 파일의 비밀 값을 한 줄에 있는 키 이름(`token:`, `apiKey:`, …)으로 찾습니다. 플로 맵(`{token: x}`) 안, 그런 키 아래의 목록 안, JSON 파일 안(예: `.json` 파일에 있는 MCP 서버의 `apiKey`), 또는 다른 이름 아래에 있는 비밀 값은 아카이브에 남습니다. dsh-backup의 유형별 아카이브(`dsh-t-…`)는 목록에 나오지 않습니다. **다른 컴퓨터용**은 아카이브를 복사합니다(APFS에서는 클론이므로 추가 공간이 들지 않음). vault는 함께 복사되지 않습니다. **지금 백업**은 어떤 백업도 삭제하지 않습니다. 자동 백업은 Composer Plus가 만든 최신 백업을 보관하고(**자동 백업**의 **보관** 설정), 자신이 만든 더 오래된 백업을 삭제합니다. 업그레이드 전 스냅샷은 따로 셉니다(최신 2개가 남음). dsh-backup의 아카이브는 삭제되지 않습니다. **삭제**로 지우세요. dsh-backup이 아직 설치되어 있으면, dsh-backup은 Composer Plus 아카이브를 자기 보관 개수에 포함하며 그 아카이브를 삭제할 수 있습니다.
@@ -285,7 +286,7 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
285
286
 
286
287
  **DS Bot의 메모리처럼 에이전트가 채팅이 바뀌어도 내 선호를 기억할 수 있나요?** 네, **프로젝트 메모리**(기본적으로 꺼짐)로 가능합니다. **설정 → Composer Plus**에서 켜세요. 턴이 끝날 때마다 오래 유지되는 선호와 결정이 채팅 프로젝트의 짧은 메모로 저장되고, 그 프로젝트의 새 채팅마다 이를 읽습니다. 에이전트에게 무언가를 기억하라고 하면 바로 저장합니다. 메모를 보거나 바꾸려면 같은 줄의 **메모리 열기**를 누르고 바꿀 내용을 적으세요.
287
288
 
288
- **Kanzo처럼 에이전트와 하나의 작업 보드를 함께 쓸 수 있나요?** 네, **작업 보드**(기본적으로 켜짐)로 가능합니다. 왼쪽 사이드바에서 열고 **새 작업**으로 작업을 추가하세요. 채팅에서 에이전트에게 "보드에서 다음 작업을 가져와"라고 하면, 에이전트가 카드를 **진행 중**으로 옮기고, 한 일을 댓글로 남긴 뒤 **검토**로 옮깁니다. 직접 할 작업은 **수동**으로 표시하세요.
289
+ **모든 채팅을 칸반 보드로 보고 거기서 새 채팅을 시작할 수 있나요?** 네, **작업 보드**(기본적으로 켜짐)로 가능합니다. 왼쪽 사이드바에서 여세요. 각 채팅은 **진행 중**, **검토**(사용자를 기다림) 또는 **완료**에 있는 카드입니다. **새 작업**에는 프롬프트만 입력하면 그 프롬프트로 새 채팅이 시작됩니다. 주황색 카드에서 **답변**을 클릭하면 채팅을 열지 않고 답할 수 있습니다.
289
290
 
290
291
  **dsh-backup처럼 dsh에서 채팅과 설정을 백업할 수 있나요?** 네. **설정 → Composer Plus → 백업 → 지금 백업**을 사용하세요. 같은 아카이브 형식으로 같은 폴더(`~/Desktop/dsh-backups`)에 쓰므로, dsh-backup의 아카이브도 표시되고 복원할 수 있으며, dsh-backup은 삭제해도 됩니다. 정해진 일정으로 백업하려면 **자동 백업**을 켜세요.
291
292
 
@@ -407,7 +408,7 @@ PLAYWRIGHT=/path/to/playwright node test/browser-continue-queue.mjs /path/to/dsh
407
408
  SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-queue-stop-send.mjs /path/to/dsh/lib/bin.js
408
409
  # Edit queued message in place with images and files (slow fake model) + its thumbnail
409
410
  SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-queue-edit.mjs /path/to/dsh/lib/bin.js
410
- # Task board: the page, the agent tools (fake model), drag and drop, search, the switch
411
+ # Task board: a prompt starts a chat, AI tags, live columns, Answer on the board, Hide finished, the switch
411
412
  SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-task-board.mjs /path/to/dsh/lib/bin.js
412
413
  ```
413
414
 
package/README.md CHANGED
@@ -12,7 +12,7 @@ Codex-style quality-of-life features for the [DeepSeek Harness](https://github.c
12
12
 
13
13
  <p align="center"><img src="docs/images/hero.webp" width="820" alt="DeepSeek Harness with Composer Plus: the running project shows a spinner in the sidebar and the Changes panel shows a git diff"></p>
14
14
 
15
- Unofficial community plugin. The only network calls are the update check (GitHub releases and the npm registry); switch off **Automatic updates** to stop them at startup. **Feature ideas** calls your chat's own model only when you click **Suggest features**. **Next message prediction** (on by default) calls the model chosen in Settings (dsh's default unless you pick another) once after each finished turn, without a click. Switch it off in **Settings → Composer Plus** to stop these calls. **Complete while typing** (off by default) calls its chosen model (by default the prediction's) at each pause while you type, after you switch it on. **Improve prompt** calls a model only when you click its magic wand. **Goal check** (on by default) calls a model once each time the agent marks a `/goal` complete in an automatic round. **Mobile connect** (off by default) accepts iPhone connections from your local network or tailnet only after you switch it on.
15
+ Unofficial community plugin. The only network calls are the update check (GitHub releases and the npm registry); switch off **Automatic updates** to stop them at startup. **Feature ideas** calls your chat's own model only when you click **Suggest features**. **Next message prediction** (on by default) calls the model chosen in Settings (dsh's default unless you pick another) once after each finished turn, without a click. Switch it off in **Settings → Composer Plus** to stop these calls. **Complete while typing** (off by default) calls its chosen model (by default the prediction's) at each pause while you type, after you switch it on. **Improve prompt** calls a model only when you click its magic wand. **Task board** calls the new chat's model once for the tags of each task that you start on the board. **Goal check** (on by default) calls a model once each time the agent marks a `/goal` complete in an automatic round. **Mobile connect** (off by default) accepts iPhone connections from your local network or tailnet only after you switch it on.
16
16
 
17
17
  ## Install
18
18
 
@@ -27,7 +27,7 @@ dsh plugin --profile web add dsh-composer-plus
27
27
 
28
28
  Then restart dsh. (The CLI can't install into the desktop profile; the app manages it.)
29
29
 
30
- > dsh's pnpm skips versions younger than 24 hours. Right after a release, add the version: `dsh-composer-plus@1.18.0`.
30
+ > dsh's pnpm skips versions younger than 24 hours. Right after a release, add the version: `dsh-composer-plus@1.19.1`.
31
31
 
32
32
  ## Features
33
33
 
@@ -69,11 +69,11 @@ Then restart dsh. (The CLI can't install into the desktop profile; the app manag
69
69
  | **Planned steps** | <a id="feature-plannedsteps"></a>Off by default: switch it on in **Settings → Composer Plus**. The agent gets the tool `plan_next_steps`: in the same message as a command, it can plan the next commands with their exact arguments and a condition, for example "run `npm test` when the build passes". When the result meets the condition, Composer Plus runs the next step itself, without a new model call, so a long chat uses fewer tokens. The step shows in the chat as a short line, "Composer Plus · Planned steps: ran `test` … without a model call", followed by its tool call and its result. Only `bash`, `read`, `grep` and `glob` steps; approvals, the sandbox and Protected files apply to each step as usual. The model answers again when a condition fails, when two steps are ready at the same time, after the last step, and when you send a message. The idea comes from HarnessMM (arXiv 2610.32813). | <a href="assets/features/plannedSteps.webp"><img src="assets/features/plannedSteps.webp" width="160" alt="Screenshot: Planned steps"></a> |
70
70
  | **Protected files** | <a id="feature-protectedfiles"></a>On by default. The agent's own file tools cannot read or change files that match your patterns: `read`, `read_image` and `grep` on a file are refused for **read and write** patterns, and `write`, `edit` and `str_replace_editor` for both kinds. The agent reads why and is told to ask you. The defaults are `.env*`, `*.pem` and `*.key`. Settings → Composer Plus → **Protected files**: add a pattern (for example `published/**` or `config/*.yml`), click its kind to switch between **read and write** and **write only**, remove it with ✕, or **Use the defaults**. A pattern without `/` matches a file name in any folder. This is a guard rail, not a sandbox: a shell command (`cat .env`), a script or an MCP tool can still reach the file (see Limits). | <a href="assets/features/protectedFiles.webp"><img src="assets/features/protectedFiles.webp" width="160" alt="Screenshot: Protected files"></a> |
71
71
  | **Blocked commands** | <a id="feature-blockedcommands"></a>On by default, with an empty list. The agent's shell commands (`bash`, `pwsh`) cannot run a command that matches your rules: a **block** rule refuses the call (the agent reads why and is told to ask you), an **ask first** rule shows dsh's approval card, and the command runs only when you allow it. Settings → Composer Plus → **Blocked commands**: type a rule (for example `npm publish`, `git push --force` or `ssh *192.168.2.19`), click the kind to switch between **block** and **ask first**, then **Add**; click a rule's kind to change it, remove it with ✕. A rule is a command name and words that must come after it in this order; `*` matches any text. It also finds the command after `&&`, `;`, `\|`, inside `$(…)`, `bash -c "…"` or `eval`, and after `sudo` or `env`. This is a guard rail, not a sandbox: a variable (`$CMD`), a script file or another program can still run the command (see Limits). | <a href="assets/features/blockedCommands.webp"><img src="assets/features/blockedCommands.webp" width="160" alt="Screenshot: Blocked commands"></a> |
72
- | **Task board** | <a id="feature-taskboard"></a>Left sidebar → **Task board**. A kanban board of your dsh projects for you and the agents: **Todo**, **Doing**, **Review** and **Done** (and **Backlog**, see below). Pick a project or **All projects** on the left. **New task** (or `n`) opens a new card: type its title and press `Enter`. Drag a card to another column or between two cards. Click a card to see and change its **Status**, **Tags**, **Human** (agents skip it), description (Markdown) and comments. `/` searches every project, `h` shows only human tasks, the export button saves the board as Markdown or JSON. Agents get board tools: ask a chat to "take the next task from the board" and it moves the top **Todo** card to **Doing**, comments on what it did and moves it to **Review**; you move it to **Done**. In a project with open tasks, each chat gets this rule by itself. Settings → Composer Plus → **Task board** has the **Backlog** column switch: agents leave its cards to you. | <a href="assets/features/taskBoard.webp"><img src="assets/features/taskBoard.webp" width="160" alt="Screenshot: Task board"></a> |
72
+ | **Task board** | <a id="feature-taskboard"></a>Left sidebar → **Task board**. A kanban board of your dsh chats with the live state that the sidebar shows: a chat that waits for your approval, answer or plan review is in **Review** with an orange dot, a running chat is in **Doing**, a finished chat is in **Done** (green until you open it). Pick a project or **All projects** on the left; a Branch per chat folder counts as its project. Type in **Search projects** above the list to find a project by its name (case and accents do not matter; `Esc` empties the box), and click **Active in the last 2 hours** to show only projects with a chat that waits, runs, finished unseen or changed in the last 2 hours (kept on this device). **New task** (or `n`) takes only a prompt: `Enter` starts a new chat in the project, the card shows in **Todo**, dsh names the chat and the chat's model writes up to 3 tags. Click a card to open its chat. On an orange card, click **Answer** to answer it on the board: **Reject** or **Allow once**, **Approve** or **Request changes** for a plan, or the options and your own text for a question. **Hide finished** hides **Done** on this device. | <a href="assets/features/taskBoard.webp"><img src="assets/features/taskBoard.webp" width="160" alt="Screenshot: Task board"></a> |
73
73
  | **Project memory** | <a id="feature-projectmemory"></a>Off by default: switch it on in **Settings → Composer Plus**. Each project folder gets its own memory, which later chats of that project read, as DS Bot keeps one per Bot. After each finished turn, one call to the chat's model reads the new messages (not rolled-back ones) and keeps your lasting preferences, decisions and facts as short notes, and changes or removes old ones. The agent can also save, remove and search notes itself (`memory_remember`, `memory_forget`, `memory_recall`). A note can also be global: every project reads it. A new chat gets the notes in its system prompt; a note saved later shows from the next chat. The files are Markdown under the dsh home (`storages/dsh-composer-plus/memory/`), never in the project folder. **Open memory** in the same row shows every saved note, grouped by project (and the global memory), with a filter. Write what to change in your own words (for example "I switched from yarn to pnpm"), then **Preview changes**: dsh's default model proposes the changes, and only **Apply** saves them. In Tether: chat title menu → Project memory. | <a href="assets/features/projectMemory.webp"><img src="assets/features/projectMemory.webp" width="160" alt="Screenshot: Project memory"></a> |
74
74
  | **Allow for this chat** | <a id="feature-allowforchat"></a>When Auto Review asks you, the approval card gets **Allow for this chat**: the same tool in the same chat is allowed from then on, with any arguments, until the time limit ends (1 hour by default; choose it under **Settings → Composer Plus → Allow for this chat**). Then the agent asks again. A header chip lists the grants with their end time and revokes them. Grants survive a restart. | <a href="assets/features/allowForChat.webp"><img src="assets/features/allowForChat.webp" width="160" alt="Screenshot: Allow for this chat"></a> |
75
75
  | **Project status** | <a id="feature-projectstatus"></a>A project row in the sidebar shows the same spinner / waiting / done marker as its chats, so a collapsed project still tells you a chat inside is working or needs you. A chat waiting for you shows first, then a finished chat you have not opened yet (the green dot, also while another chat still runs), then the spinner. Hover it for details. In **Workspace Tree**, the row of a parent folder also shows the chats of each project inside it (for example each branch folder in `.worktrees/`), also while it is collapsed. | <a href="assets/features/projectStatus.webp"><img src="assets/features/projectStatus.webp" width="160" alt="Screenshot: Project status"></a> |
76
- | **Git branch on chat rows** | <a id="feature-sessionbranch"></a>Each chat row in the sidebar shows a small grey pill with the git branch that the chat's project folder was on at the chat's last turn (for example `main` or `feature/login`; a detached HEAD has no branch and shows no pill). Two chats of one project on different branches no longer look the same, and you see at once when you are about to continue a chat on the wrong branch. Hover the pill for the full name. The Host half reads the branch (`git branch --show-current`, read-only) when a turn starts and when it ends; a chat with no turn since you installed this, or a folder that is not a git repository, shows no pill. A chat under a project row with its branch's name (a “Branch per chat” folder) shows no pill, except in “In one list”. | <a href="assets/features/sessionBranch.webp"><img src="assets/features/sessionBranch.webp" width="160" alt="Screenshot: Git branch on chat rows"></a> |
76
+ | **Git branch on chat rows** | <a id="feature-sessionbranch"></a>In the sidebar's “In one list” view, each chat row shows a small grey pill with the git branch that the chat's project folder was on at the chat's last turn (for example `main` or `feature/login`; a detached HEAD has no branch and shows no pill). Two chats of one project on different branches no longer look the same, and you see at once when you are about to continue a chat on the wrong branch. Hover the pill for the full name. The Host half reads the branch (`git branch --show-current`, read-only) when a turn starts and when it ends; a chat with no turn since you installed this, or a folder that is not a git repository, shows no pill. In “WorkSpace” and “Workspace Tree”, no chat row shows the pill, because the chat is already under its project row. | <a href="assets/features/sessionBranch.webp"><img src="assets/features/sessionBranch.webp" width="160" alt="Screenshot: Git branch on chat rows"></a> |
77
77
  | **Mark all as read** | <a id="feature-markprojectread"></a>In the sidebar, click a project's **…** button → **Mark all as read**. Every chat in that project loses its green unread dot at once; other projects keep theirs. The item is greyed out (**No unread chats**) when the project has none. | <a href="assets/features/markProjectRead.webp"><img src="assets/features/markProjectRead.webp" width="160" alt="Screenshot: Mark all as read"></a> |
78
78
  | **Active projects first** | <a id="feature-activeprojectsfirst"></a>When a chat starts running or needs you, its project moves to the top of the sidebar with dsh's own row animation (the same move as dragging it there). Finished projects stay where they are; drag them anywhere as usual. Moves are saved to dsh's project order, so turning this off keeps the current order. | <a href="assets/features/projectStatus.webp"><img src="assets/features/projectStatus.webp" width="160" alt="Screenshot: Active projects first"></a> |
79
79
  | **Recent projects filter** | <a id="feature-recentprojects"></a>Sidebar → view options (sliders icon) → **Active in the last 2 hours**. While it is selected, the sidebar shows only projects with a chat that was active in the last 2 hours: a chat updated in that time, a running or waiting chat, the open chat, or a finished chat that you did not open yet (dsh's green “done” dot), also after the 2 hours. Projects without such a chat are hidden, also new and empty ones. In **Workspace Tree**, a parent folder stays while a project inside it is active, and the chats that were not active in the last 2 hours hide too, so only the recent chats show. Select it again to show all projects. The choice is kept on this device. | <a href="assets/features/recentProjects.webp"><img src="assets/features/recentProjects.webp" width="160" alt="Screenshot: Recent projects filter"></a> |
@@ -83,7 +83,7 @@ Then restart dsh. (The CLI can't install into the desktop profile; the app manag
83
83
  | **Open waiting chat when idle** | <a id="feature-idleswitch"></a>When a chat asks a question, or waits for an approval or a plan review (the orange dot), or finishes a turn that you have not read yet (the green dot), and you do not use dsh for 30 seconds, dsh opens that chat. Orange chats open before green ones. In each group, the one that waits longest opens first; the next one opens after another 30 seconds without use. A key, a click, a mouse move, the scroll wheel or a touch starts the 30 seconds again. Text in the field that has the focus, selected text, or an open menu or dialog also stops the switch. While a waiting chat is on screen, nothing moves. When you leave a waiting chat without an answer, it can open again after the next 30 seconds without use. When a green chat opens, its dot goes; the next green chat opens only after you use dsh again and then do not use it for 30 seconds. This also works while dsh is in the background, but dsh does not come to the front. | <a href="assets/features/idleSwitch.webp"><img src="assets/features/idleSwitch.webp" width="160" alt="Screenshot: Open waiting chat when idle"></a> |
84
84
  | **Application language** | <a id="feature-language"></a>Settings → Composer Plus → **Application language** switches the whole dsh interface to Türkçe, Español, Português (Brasil), Français, Deutsch, Русский, 日本語, 한국어, Bahasa Indonesia, Tiếng Việt or हिन्दी (see below). | <a href="assets/features/language.webp"><img src="assets/features/language.webp" width="160" alt="Screenshot: Application language"></a> |
85
85
  | **Mobile connect (iPhone)** | <a id="feature-mobileconnect"></a>Use dsh from your iPhone with the [Tether](tether/) app, on the same Wi-Fi or over [Tailscale](https://tailscale.com). Switch it on in **Settings → Composer Plus** (it is off by default, because it opens a network port on this Mac). Then click **Mobile connect** at the bottom left of the sidebar: scan the QR code with the iPhone Camera (tap **Open in Tether**) or with **Scan code** in Tether, tap **Connect** and click **Approve**. Tether must be installed first: without it the Camera cannot open the code. The phone shows your chats, sends messages (with photos: the composer's **+** → Camera, Photos or Paste image), answers approvals and questions, and switches models and agents. Pair as many Macs as you like: the Mac name at the top left of the app switches between them. The **Mobile connect** panel lists the paired iPhones with their last connection: **Remove** cuts one off at once. **Tailscale only** refuses the local network (for a shared Wi-Fi), and the access log shows who tried to connect. In Tether, **Settings → Privacy** locks the app with Face ID. | <a href="assets/features/mobileConnect.webp"><img src="assets/features/mobileConnect.webp" width="160" alt="Screenshot: Mobile connect (iPhone)"></a> |
86
- | **Automatic updates** | <a id="feature-autoupdate"></a>When dsh starts, the plugin checks the [latest GitHub release](https://github.com/furkancak1r/dsh-composer-plus/releases/latest). If it is newer and already on npm, it installs that exact version through dsh's own plugin manager (the same path as Settings → Plugins) and notifies you. Restart dsh to load it. **Settings → Composer Plus → Composer Plus updates** shows the version and has **Check for updates** / **Update now**. The first time dsh starts with the new version, a **What’s new in Composer Plus N** window shows the release notes of that version once (taken from the same update check, no extra network call); **Close** or `Esc` closes it. | <a href="assets/features/autoUpdate.webp"><img src="assets/features/autoUpdate.webp" width="160" alt="Screenshot: Automatic updates"></a> |
86
+ | **Automatic updates** | <a id="feature-autoupdate"></a>When dsh starts, the plugin checks the [latest GitHub release](https://github.com/furkancak1r/dsh-composer-plus/releases/latest). If it is newer and already on npm, it installs that exact version through dsh's own plugin manager (the same path as Settings → Plugins) and notifies you. Restart dsh to load it. **Settings → Composer Plus → Composer Plus updates** shows the version and has **Check for updates** / **Update now**. The first time dsh starts with the new version, a **What’s new in Composer Plus N** window shows the release notes of that version once, in the language of **Application language** (they come with the new version, no extra network call; a language without notes shows the English notes); **Close** or `Esc` closes it. | <a href="assets/features/autoUpdate.webp"><img src="assets/features/autoUpdate.webp" width="160" alt="Screenshot: Automatic updates"></a> |
87
87
  | **Backup** | <a id="feature-backup"></a>Settings → Composer Plus → **Backup** → **Back up now** writes your whole dsh home (chats, settings, plugins, MCP, skills) into one archive in `~/Desktop/dsh-backups`, with a checksum. Secrets are masked in the archive: credential files, key files (`.pem`, `.key`) and the token, secret and password values of the yml settings stay on this computer only, in the folder's `vault`. `cache/`, `dsh-runtimes/` and `node_modules` are not archived (dsh makes them again). Each backup in the list has **Check** (reads it fully), **For another computer** (a folder to copy to the new computer, with the rescue console) and **Delete**. dsh-backup's archives in the same folder show and work too. To restore, quit dsh and use the rescue console. | <a href="assets/features/backup.webp"><img src="assets/features/backup.webp" width="160" alt="Screenshot: Backup"></a> |
88
88
  | **Automatic backup** | <a id="feature-autobackup"></a>Switch on **Automatic backup** (off by default: each copy is about as large as your dsh home without its cache). Choose how often (**Every**: 6 hours to 7 days, 24 hours by default) and how many backups stay (**Keep**: 3 to 14, 7 by default). The next time shows under the switch; a failed backup shows there too and is tried again 30 minutes later. When dsh or Composer Plus starts with a new version, a snapshot comes soon after the start, before the new version has used your data for long (the two newest stay, marked **Before an upgrade**). | <a href="assets/features/autoBackup.webp"><img src="assets/features/autoBackup.webp" width="160" alt="Screenshot: Automatic backup"></a> |
89
89
  | **Session log check** | <a id="feature-sessiondoctor"></a>**Check session logs** reads every chat's log and lists the ones that dsh cannot open (a broken frame, a cut record, a wrong sequence number). A torn tail is not listed: dsh repairs it itself. **Repair from backups** puts back the copy from the newest backup that has a healthy one and keeps the damaged file next to it (`.corrupt-<time>`). Messages written after that backup are not in the copy. A chat that is open in this dsh is not repaired here: quit dsh and repair it in the rescue console. | <a href="assets/features/sessionDoctor.webp"><img src="assets/features/sessionDoctor.webp" width="160" alt="Screenshot: Session log check"></a> |
@@ -167,7 +167,7 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
167
167
  - **Goal check:** it runs only when the agent marks a `/goal` complete in an automatic round (or when you click **Run now**). The Host half runs the test command in the chat's folder with the chat's sandbox mode (as dsh's own `bash` tool: the same file-access policy; when that sandbox cannot start, the test does not run and the check fails). It reads only `package.json`, `Makefile`, `Cargo.toml`, `go.mod`, `pyproject.toml` and `pytest.ini` to find the command, as regular files inside the folder (no symlink out of it, no FIFO). Then it sends the goal, the chat since the goal started (your messages, the agent's replies, tool calls cut to 1,000 characters and the last 2,000 characters of each tool result; no reasoning, no rolled-back steps; at most about 60,000 characters, the newest part), `git status --short` and the end of the test output to the model chosen under **Goal check** (by default the chat's own model), as one request with no tools. Tool output can contain what the agent read, so this request can hold parts of your files, as the chat itself does. Nothing is written to the chat or the project. Your test command, the limits, the last result (with the end of its output) and the model choice are in `$DSH_HOME/storages/dsh-composer-plus/goal-check.json` (owner-only file, newest 500 chats).
168
168
  - **Continue in a new chat:** nothing runs until you click it. Then the Host half sends the chat (as Goal check reads it: no reasoning, no rolled-back steps) to the chat's own model and shows the note; only **Start new chat** makes a new chat. Nothing is written to the project.
169
169
  - **Context breakdown:** reads only the chat log on the Host; no model call, no project file.
170
- - **Task board:** the board (titles, descriptions, tags and comments of your tasks, the project folder paths and their short ids) is in `$DSH_HOME/storages/dsh-composer-plus/board.json` (owner-only file); the switch is in `board-switch.json` next to it. Nothing leaves your machine and nothing is written to a project folder. The board tools give the agents what you wrote on the board, so the text of a task reaches the chat's model when an agent reads it. A broken board file is kept as `board.json.broken-<time>` and the board starts empty.
170
+ - **Task board:** the board shows dsh's own chats from dsh's own lists in this window; it adds no chat data of its own. When you start a task, the Host half makes a new chat in the project you chose and sends your prompt to it as its first message, as if you typed it there, so approvals, the sandbox and the chat's model apply as usual. Then it sends the prompt (its first 4,000 characters, nothing else) to that chat's model in one more request, with no tools, for up to 3 tags. The prompt, the tags and the start time of each task are kept in `$DSH_HOME/storages/dsh-composer-plus/board-chats.json` (owner-only file, the newest 2,000); the switch is in `board-switch.json` next to it. Nothing is written to a project folder. **Answer** sends your answer to dsh's own pending request, the same way the chat's own card does. The old task list of earlier versions (`board.json`) stays on disk as it was and is not read.
171
171
  - **Protected files:** the list and the switch are in `$DSH_HOME/storages/dsh-composer-plus/protected-files.json` (owner-only file). The check reads only the path of each file tool call (and its real path), never the file.
172
172
  - **Blocked commands:** the rules and the switch are in `$DSH_HOME/storages/dsh-composer-plus/blocked-commands.json` (owner-only file). The check reads only the command text of each `bash` and `pwsh` call; it runs nothing and sends nothing.
173
173
  - **Project memory:** off until you switch it on. While it is on, after each finished turn of a top-level chat, the Host half sends the chat's own new messages since the last review (your messages and the agent's text replies; no tool output, no reasoning, no hidden context, no rolled-back messages; a fork's copy of its parent is left out; at most about 16,000 characters) and the saved notes to the chat's own model, as one request with no tools. The notes are Markdown files under `$DSH_HOME/storages/dsh-composer-plus/memory/` (owner-only files): `projects/<id>/` for each project folder (`<id>` is a hash of the folder's real path; `project.json` names the folder), `global/`, `journal.jsonl` (every change with the line before and after) and `reviewed.json` (how far each chat was read). Nothing is written to the project folder. Notes that look like a key, a token, a password or an ID number are refused. The notes of a project go into the system prompt of each new chat in that folder, so they reach the model with every request of that chat. The switch is in `memory.json` next to it. **Open memory** sends nothing until you click **Preview changes**; then it sends the notes it shows and your text to dsh's default model, as one request with no tools. Its changes are written only on **Apply**, with `editor` in the journal. Tether reads and changes the notes through the same route.
@@ -189,10 +189,10 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
189
189
  - **A chat did not continue after a restart:** Resume after restart was off when dsh quit, you stopped that turn yourself, the turn had ended (done or failed), the chat was archived, or more than 20 chats were running (the newest 20 continue).
190
190
  - **The queue is empty after a restart:** dsh itself empties the queue when it quits. Resume after restart puts it back only in a chat that it continues; in other chats, send the messages again. A message that you removed just before the quit can come back: remove it again.
191
191
  - **Open GitHub issue says "gh could not open the issue":** the message is `gh`'s own first line. Run `gh auth status` in a terminal and log in with `gh auth login`; the chat's folder must have a GitHub remote (`git remote -v`). "not installed or not on the PATH of dsh" means dsh did not find `gh`: install it, or start dsh from a terminal where `gh` works.
192
- - **No branch pill on a chat row:** the chat had no turn since you installed this version, its folder is not a git repository, or **Git branch on chat rows** is off. After an update, restart dsh (the Host half records the branch).
192
+ - **No branch pill on a chat row:** the sidebar is not in “In one list” (in “WorkSpace” and “Workspace Tree”, no chat row shows a pill), the chat had no turn since you installed this version, its folder is not a git repository, or **Git branch on chat rows** is off. After an update, restart dsh (the Host half records the branch).
193
193
  - **Goal check says the test exited with code 127 or "not found":** dsh started from the Finder or the Dock can have a shorter PATH than your terminal, so it does not find `npm`, `pnpm` or `cargo`. Start dsh from a terminal, or set your own test command with the full path under **Goal check** → **Edit**. **Run now** shows the result at once.
194
194
  - **The goal does not close and the agent keeps working:** **Goal check** found a failing test or missing work; the row under the goal shows why (hover the result for the details). Fix the cause or the test command, or complete the goal yourself with `/goal` or the goal bar (that is not checked).
195
- - **Install fails right after a release:** add the version (`dsh-composer-plus@1.18.0`), see the install note above.
195
+ - **Install fails right after a release:** add the version (`dsh-composer-plus@1.19.1`), see the install note above.
196
196
  - **Back up now says "another backup action is running":** an action runs in another dsh window or in the rescue console (they share a lock file, `.composer-plus.lock`, in the backup folder). Wait for it. If no action runs, the lock of a closed process is taken over at the next click.
197
197
  - **The rescue console says "dsh is running":** quit dsh first. If dsh is really closed, the file named in the message is left from a crash: remove it and try again.
198
198
  - **After a restore, dsh does not start or a plugin is missing:** the plugin packages of a profile must be installed again. The rescue console offers it after a restore; or run `pnpm install` in each folder under `$DSH_HOME/profiles/` that it lists. Secrets that were not in the vault (another computer) must be entered again: the console lists them.
@@ -212,6 +212,7 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
212
212
  - **Delete chat** needs dsh's archive (dsh 0.2.0 and later). A chat (or one of its subagent chats) that does not stop within 15 s, or that another dsh holds, stays archived and nothing moves. On other systems than macOS the trash folder must be on the same disk as the chat history. An open chat that you delete stays in dsh's memory, archived and hidden, until dsh restarts. Empty the Trash yourself; dsh does not.
213
213
  - dsh's queue has no `move` action, so the plugin's Host moves the queued message itself in dsh's queue (one change, the same message). Messages with images or files move too. Only your own messages move: a goal round or a question reply in the queue stays where it is. If a message starts to send while you drag, nothing moves and a notice says so.
214
214
  - dsh 0.2.1 loads an update at once when the new version changes no dsh settings; otherwise, and on dsh 0.2.0, restart dsh to load it. The plugin never restarts dsh for you. Web/CLI profiles without dsh's plugin manager only report a new version.
215
+ - **What’s new in Composer Plus N** shows the notes in the language of **Application language**. A UI language with another region gets the notes of its base language (`en-GB` gets the English notes, `zh-TW` the Chinese notes of `zh`). A language without notes (one that another language pack adds, or `pt-PT`, which is not `pt-BR`) shows the English notes. The notes come with the new version. When the running copy has no readable notes file (`release-notes.json`), the window shows the English notes from GitHub.
215
216
  - **Allow for this chat** counts the time limit from the moment of the grant. A new time limit applies at once to the grants that run, so a shorter one can end them at once. Grants from version 1.12 and earlier have no time: after the update, the agent asks once again for those tools.
216
217
  - **Keep composer focus** gives the focus back only after a `/` command or skill. While dsh resolves the command, the composer stays read-only for a few milliseconds, so keys pressed in that time are lost. If dsh's `/` menu is still open, `Enter` picks the highlighted row and does not send.
217
218
  - **Fit question card to window** changes only dsh's question card, not the plan review card. It finds the card by dsh's markup (`data-question-key`, `data-question-scroll`); if a dsh update changes that markup, the card shows as dsh draws it. The card's height follows the window, not the chat: in a chat in a narrow side panel, a tall card can still reach above the chat.
@@ -225,7 +226,7 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
225
226
  - **This chat** counts only files that dsh's file tools (`write`, `edit`, `str_replace_editor`) wrote. Files that a command (`bash`) changed are not in this view; they show under **Uncommitted**. Without a Turn rollback snapshot of the chat (Turn rollback off, dsh-rewind-plugin installed, or a chat older than the plugin), the view compares with the last commit and says so. Turn rollback keeps the 50 newest snapshots of a chat: in a longer chat, the view compares with the oldest kept one, says from which message, and does not count earlier changes. **Hide whitespace changes** is `git diff -w`: a line that changed only in spaces inside it is hidden too.
226
227
  - **Open GitHub issue** needs the GitHub CLI (`gh`) on the PATH of dsh and a GitHub remote in the chat's folder. It runs at most 60 s; if `gh` takes longer, the issue can exist on GitHub without its link in the list (click again: the list reads the link only from a finished run, so look on GitHub before you open a second one). A folder with more than one GitHub remote uses `gh`'s own default (`gh repo set-default`).
227
228
  - **Chats that changed this file** knows only dsh's file tools (`write`, `edit`, `str_replace_editor`), as **This chat**: a change made by a command (`bash`) is not listed. It reads the newest 300 chats of the repository (by when they were made) and says so when there are more; it shows at most 100 rows. A renamed file is listed under the name that the tool wrote. A chat whose folder is outside the repository (also through another path to the same files) is not counted. The first open after a dsh start reads every chat log of the repository (about 4 s for 275 chats); later opens read only the chats that changed since.
228
- - **Git branch on chat rows** shows the branch of the chat's folder when its last turn started or ended, not the branch now: a branch switch outside a turn shows after the next turn. Chats from before this version show no pill until their next turn. The pill sits in dsh's chat row markup (dsh has no slot there); if a dsh update changes that markup, no pill shows. A chat under a project row with its branch's name (a “Branch per chat” folder) shows no pill, except in “In one list”.
229
+ - **Git branch on chat rows** shows the branch of the chat's folder when its last turn started or ended, not the branch now: a branch switch outside a turn shows after the next turn. Chats from before this version show no pill until their next turn. The pill sits in dsh's chat row markup (dsh has no slot there); if a dsh update changes that markup, no pill shows. The pill shows only in “In one list”.
229
230
  - **Branch per chat** in plan mode: dsh sends `/plan <message>` as a command, not as a message, so Composer Plus takes the command's submit in dsh's composer (not a public API). If a dsh update changes it, `/plan <message>` with **New branch** chosen runs in the open New chat as dsh's own command. When the Host cannot turn on plan mode in the new chat, the branch folder stays and the message is not sent, so the new chat does not change files in the default mode.
230
231
  - **Branch per chat**: when a chat's branch folder (`<project>/.worktrees/<name>`) is deleted, for example when the chat's own agent removes the worktree and deletes the branch, the chat's next step moves the chat out of it. Its branch folder project goes from the sidebar, and the chat shows under Ungrouped and stays open. On dsh 0.2.1 and later the chat continues in the main project folder, and the model gets a note about the new folder. On dsh 0.2.0 the chat keeps the deleted folder: a command there fails until you start a new chat. A project of a deleted branch that no chat uses also leaves the sidebar: Composer Plus checks the branch folders at start and every 30 seconds, also with no sidebar filter. While a chat moves, **New branch** in the same repository answers "try again". With the switch off, dsh's own error shows again ("working-directory: directory does not exist").
231
232
  - **Branches in the workspace tree** writes to git without a click: when it moves a chat, it switches the project folder back to its branch (`git switch`) and adds a worktree (`git worktree add`). It never deletes a branch, a worktree or a file. dsh cannot change the folder of a chat, so a moved chat is a copy (dsh's own fork, with a new id) and the old chat is archived. The copy continues the stopped task; a tool call that was running when the branch appeared ends with a refusal, and the agent runs it again in the new folder. A goal of the old chat does not move with it. Only a chat whose folder is the repository's main folder moves, and only for a branch that it created and switched to in that turn (`git switch -c`, `git checkout -b`): a branch made with `git branch` alone, a folder with uncommitted changes, a linked worktree or a subfolder moves nothing. Only worktrees directly in `<project>/.worktrees/` with a branch show in the tree; a detached worktree or one elsewhere does not. The copy opens by itself only when its chat was the open one (the plugin reads dsh's sidebar row for that); else it is in the branch project.
@@ -246,7 +247,7 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
246
247
  - **Continue in a new chat** sends the chat (messages, tool calls and the end of each tool result, at most about 60,000 characters, the newest part) to the chat's own model. The note can miss a decision or a file: read it before you start. The new chat knows only the note and the linked chat (dsh attaches the old chat as read-only context); its model context starts small, the old chat stays as it is. One note or start per chat at a time.
247
248
  - **Context breakdown** shows estimates with dsh's own rule (about 4 characters per token), the same rule as dsh's context ring; the model's own count can differ. Tool definitions are the ones of the newest request. It shows the context as the chat log has it; a turn that runs now appears after its next step.
248
249
  - **Planned steps** saves tokens only when the model plans: while it is on, each request carries the `plan_next_steps` tool and a short instruction (about 500 tokens), also in chats where the model never plans. A condition proves only what it says (for example: the build exit code was 0), not that the work is right. `ok` reads dsh's own result marks (`[exit code: N]`, timeouts, sandbox denials); a command that fails without a non-zero exit code passes. Steps run one at a time; two steps that are ready at the same time go back to the model. The step's message is stored as an assistant message of the chat's model (dsh has no mark for a message that a plugin wrote), so its text says that Composer Plus ran it. Not in Tether.
249
- - **Task board** knows only dsh's projects: a chat outside a project shows **All projects**, and a Branch per chat folder (`<project>/.worktrees/<name>`) counts as its project. The project ids (`acme#12`) come from the folder name and stay when you rename the project in dsh. The rule "keep the board current" goes into a chat only when its project has open tasks; a chat that got it keeps it. Agents are told to leave **Done**, **Backlog** and human tasks to you, but the tools do not refuse it: an agent can still move such a card. The board tools are in every chat's tool list while the feature is on (about 1,000 tokens per request); switch it off if you do not use the board. The page reads the board every 2 seconds while it shows; a change by an agent shows within that time. A text that you edit while an agent changes the same field is not saved: the panel shows the new text and the reason. No images, no git sync between computers and no sharing over the network (Kanzo has them). The idea and the look come from [Kanzo](https://github.com/emanuele-em/kanzo) by emanuele-em (AGPL-3.0); Composer Plus uses no code from it.
250
+ - **Task board** shows the chats that dsh lists in this window: a chat outside a project shows only in **All projects**, and a Branch per chat folder (`<project>/.worktrees/<name>`) counts as its project. A card's column is the chat's live state, so cards cannot be dragged: a chat goes to **Done** when its turn ends, also after an error or a stop, and back to **Doing** when it runs again. The green dot is dsh's own done dot, which dsh keeps only in this window: after a reload, finished chats show without it. **Done** shows the newest 50 chats (**Show N older** shows the rest). **Search projects** finds a project by its name only, not by its folder path. **Active in the last 2 hours** hides a project when each of its chats is older than 2 hours, idle and read; the board still shows the project that you picked. The tags come from one model call per started task: they can be wrong, and a chat that you did not start on the board has none. The title is dsh's own chat title (dsh's title service, with the chat's model); until it comes, the card shows the first line of the prompt. A prompt that starts with a `/` command that dsh knows (`/plan`, `/goal`) runs as that command. **Answer** answers only the newest request of the chat: when the chat answered it elsewhere (another window, Tether, Auto Review) or asks something new, the panel says so and sends nothing. Earlier versions had a task list with comments and agent tools; they are gone, and the old `board.json` is not shown. The idea and the look come from [Kanzo](https://github.com/emanuele-em/kanzo) by emanuele-em (AGPL-3.0); Composer Plus uses no code from it.
250
251
  - **Send after Stop goes first** works only after you stop the chat (or after a turn that failed, or when you open a chat that still has a queue): a message that you send while a turn runs still waits at the end of the queue. It moves only past your own queued messages: when a goal round or a question reply waits in the queue, dsh's own order stays. It reads a part of dsh that is not a public API (whether the stopped turn still ends); if a dsh update renames it, the message moves only after that turn has ended. Subagent chats keep dsh's own order.
251
252
  - **Project memory** belongs to the chat's first folder (dsh's project folder): a chat that changes its folder with `cd` keeps its first project's memory, and the same folder opened through another path to the same files shares it. A chat freezes its memory section when it starts, so a note saved later shows from the next chat (`memory_recall` finds it at once). The review keeps only what the model decides to keep: it can miss a fact or keep a wrong one; check them in **Open memory** and change them there, or edit the files by hand while dsh is closed. **Open memory** sends the notes of the selected project and the global notes (all projects when you select All notes; at most about 60,000 characters, the rest is counted and cannot change in that request) and your text to dsh's default model, not to the chat's model. A preview is kept on the Mac for 30 minutes and until dsh restarts; when a review or the agent changes the notes in between, **Apply** refuses and you preview again. **Apply** saves all the changes of a preview or none: when one change cannot be saved (for example, MEMORY.md is full), the notes stay as they were and the reason shows. Each finished turn with a message from you costs one model call; a failed call reads the same messages again after the next turn. Subagent chats are not reviewed. The idea and the file format come from [DS Bot](https://github.com/Fei2411/DS-Bot) (Apache-2.0); Composer Plus uses no code from it, and it never reads or writes DS Bot's own memory.
252
253
  - **Backup** keeps one fixed folder, `~/Desktop/dsh-backups` (dsh-backup's default, so its archives stay usable); there is no setting for another folder. An archive is about as large as the dsh home without `cache/` and `dsh-runtimes/` (measured: 1.6 GB of files gave an 830 MB archive in about 30 s on Apple Silicon; dsh stayed responsive). A file that changes while it is read is stored as it was when the backup opened it, so an open chat's log can end in a cut-off record, which dsh repairs at its next write. Masking finds a secret in a yml file by its key name on one line (`token:`, `apiKey:`, …); a secret in a flow map (`{token: x}`), in a list under such a key, in a JSON file (for example an MCP server's `apiKey` in a `.json` file) or under another name stays in the archive. dsh-backup's typed archives (`dsh-t-…`) are not listed. **For another computer** copies the archive (a clone on APFS: no extra space); the vault does not go with it. **Back up now** deletes no backup. An automatic backup keeps the newest backups that Composer Plus made (the **Keep** setting of **Automatic backup**) and deletes its older ones; snapshots before an upgrade are counted apart (the newest 2 stay). Archives of dsh-backup are never deleted: remove them with **Delete**. While dsh-backup is still installed, it counts the Composer Plus archives in its own keep count and can delete them.
@@ -283,7 +284,7 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
283
284
 
284
285
  **Can the agent remember my preferences across chats, like DS Bot's memory?** Yes, with **Project memory** (off by default): switch it on in **Settings → Composer Plus**. After each turn, your lasting preferences and decisions are kept as short notes for the chat's project, and each new chat in that project reads them. Ask the agent to remember something and it saves it at once. To see or change the notes, click **Open memory** in the same row and write what to change.
285
286
 
286
- **Can my agents and I share one task board, like Kanzo?** Yes, with **Task board** (on by default): open it in the left sidebar and add tasks with **New task**. In a chat, ask the agent to "take the next task from the board": it moves the card to **Doing**, comments on what it did and moves it to **Review**. Mark a task **Human** to keep it for yourself.
287
+ **Can I see all my chats as a kanban board and start new ones from it?** Yes, with **Task board** (on by default): open it in the left sidebar. Each chat is a card in **Doing**, **Review** (it waits for you) or **Done**. **New task** takes only a prompt and starts a new chat with it; click **Answer** on an orange card to answer it without opening the chat.
287
288
 
288
289
  **Can dsh back up my chats and settings, like dsh-backup?** Yes: **Settings → Composer Plus → Backup → Back up now**. It writes the same archive format into the same folder (`~/Desktop/dsh-backups`), so dsh-backup's archives show and restore too, and you can remove dsh-backup. Switch on **Automatic backup** for a schedule.
289
290
 
@@ -405,7 +406,7 @@ PLAYWRIGHT=/path/to/playwright node test/browser-continue-queue.mjs /path/to/dsh
405
406
  SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-queue-stop-send.mjs /path/to/dsh/lib/bin.js
406
407
  # Edit queued message in place with images and files (slow fake model) + its thumbnail
407
408
  SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-queue-edit.mjs /path/to/dsh/lib/bin.js
408
- # Task board: the page, the agent tools (fake model), drag and drop, search, the switch
409
+ # Task board: a prompt starts a chat, AI tags, live columns, Answer on the board, Hide finished, the switch
409
410
  SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-task-board.mjs /path/to/dsh/lib/bin.js
410
411
  ```
411
412