dsh-composer-plus 1.16.0 → 1.17.0
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.de.md +28 -15
- package/README.es.md +28 -15
- package/README.fr.md +28 -15
- package/README.hi.md +28 -15
- package/README.id.md +28 -15
- package/README.ja.md +28 -15
- package/README.ko.md +28 -15
- package/README.md +28 -15
- package/README.pt-BR.md +28 -15
- package/README.ru.md +28 -15
- package/README.tr.md +28 -15
- package/README.vi.md +28 -15
- package/README.zh.md +28 -15
- package/assets/features/contextBreakdown.webp +0 -0
- package/assets/features/handoffChat.webp +0 -0
- package/assets/features/headerFit.webp +0 -0
- package/assets/features/projectMemory.webp +0 -0
- package/assets/features/protectedFiles.webp +0 -0
- package/client.js +729 -48
- package/index.js +762 -47
- package/package.json +2 -2
- package/tether/gateway/server.mjs +1 -1
package/README.ko.md
CHANGED
|
@@ -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.
|
|
32
|
+
> dsh의 pnpm은 게시된 지 24시간이 지나지 않은 버전을 건너뜁니다. 릴리스 직후에는 버전을 붙여서 설치하세요: `dsh-composer-plus@1.17.0`.
|
|
33
33
|
|
|
34
34
|
## 기능
|
|
35
35
|
|
|
@@ -47,6 +47,7 @@ dsh plugin --profile web add dsh-composer-plus
|
|
|
47
47
|
| **Shift+Tab 계획 모드** | <a id="feature-plantoggle"></a>`Shift+Tab`은 초안 맨 앞에 `/plan `을 붙입니다(다시 누르면 제거). 채팅이 이미 계획 모드이면 `Shift+Tab`으로 계획 모드를 종료합니다. | <a href="assets/features/planToggle.webp"><img src="assets/features/planToggle.webp" width="160" alt="스크린샷: Shift+Tab 계획 모드"></a> |
|
|
48
48
|
| **입력란 포커스 유지** | <a id="feature-keepfocus"></a>`/` 명령이나 스킬을 보낸 뒤에도 커서가 입력란에 남아 바로 다시 입력할 수 있습니다. 명령을 입력하고 `Enter`를 누르는 키보드 매크로에서도 작동합니다. dsh는 명령을 처리하는 동안 입력란을 읽기 전용으로 만들고, 그때 브라우저가 포커스를 해제합니다. 이 기능은 포커스를 입력란으로 돌려놓습니다. 단, 메뉴, 대화 상자, 다른 입력 필드에 포커스가 있으면 돌려놓지 않습니다. | <a href="assets/features/keepFocus.webp"><img src="assets/features/keepFocus.webp" width="160" alt="스크린샷: 입력란 포커스 유지"></a> |
|
|
49
49
|
| **질문 카드를 창에 맞추기** | <a id="feature-questionfit"></a>에이전트가 질문하면 질문과 답변이 카드 안에서 함께 스크롤되고, **건너뛰기**와 **제출**은 아래쪽에 계속 보입니다. 카드는 창 높이(채팅 헤더와 채팅 일부를 위해 200 px를 뺀 높이)를 사용하므로 창에 따라 커지고 작아집니다. 이 기능이 없으면 dsh는 카드를 창의 60%(최대 520 px)로 제한하고 답변만 스크롤합니다. 질문이 길면 질문의 끝, 답변, 버튼이 카드 밖으로 밀려날 수 있습니다. | <a href="assets/features/questionFit.webp"><img src="assets/features/questionFit.webp" width="160" alt="스크린샷: 질문 카드를 창에 맞추기"></a> |
|
|
50
|
+
| **채팅 헤더를 창에 맞추기** | <a id="feature-headerfit"></a>좁은 창에서 dsh 채팅 헤더의 버튼(모드, 서브에이전트, 백그라운드 작업, 다음에서 열기, 브랜치 표시, 허용 표시)이 더 이상 서로 겹치지 않습니다. 채팅 제목은 최소 120 px를 유지하고, 들어가지 않는 버튼은 오른쪽의 두 번째 줄로 이동하며 모두 클릭할 수 있습니다. 모든 것이 한 줄에 들어가면(넓은 창) 헤더는 dsh의 것과 똑같습니다. 이 기능이 없으면 dsh는 제목만 줄입니다. 서브에이전트와 백그라운드 작업이 있으면 좁은 채팅 열에서 버튼이 서로 겹칩니다. 브랜치 표시(**채팅별 브랜치**)와 허용 표시(**이 채팅에서 허용**)는 이 스위치가 꺼져 있어도 헤더에 맞춰집니다. | <a href="assets/features/headerFit.webp"><img src="assets/features/headerFit.webp" width="160" alt="스크린샷: 채팅 헤더를 창에 맞추기"></a> |
|
|
50
51
|
| **원클릭 계속** | <a id="feature-continuebutton"></a>턴이 중지되거나, 실패하거나, 중간에 끊긴 뒤에는 빈 입력란에 **▶**가 표시됩니다. 한 번 클릭하면 입력란에 아무것도 쓰지 않고, 보이는 채팅 메시지도 추가하지 않은 채 기존 대화를 이어 갑니다(모델은 “멈춘 곳에서 계속하라”는 짧은 숨은 메모를 받습니다. Claude 같은 일부 제공자는 어시스턴트 답변으로 끝나는 요청을 거부하기 때문입니다). 대기열의 메시지는 그대로 남습니다. ▶는 중지된 작업만 이어 가고, 그다음에 대기열이 실행됩니다. 완료된 턴 뒤에는 일반 보내기 버튼이 그대로 있습니다. | <a href="assets/features/continueButton.webp"><img src="assets/features/continueButton.webp" width="160" alt="스크린샷: 원클릭 계속"></a> |
|
|
51
52
|
| **재시작 후 이어서 실행** | <a id="feature-resumeafterrestart"></a>기본적으로 꺼져 있습니다. **설정 → Composer Plus**에서 켜세요. 채팅이 작업하는 중에 dsh를 종료하면(또는 dsh가 닫히면), dsh를 다시 열 때 그 채팅이 자동으로 이어집니다. 이때 원클릭 계속과 같은 숨은 메모를 씁니다. 목표 라운드(`/goal`)가 실행 중이었다면 목표는 다음 라운드로 계속됩니다(dsh는 시작할 때마다 목표를 일시 중지하고, 사용자가 재개할 때까지 기다립니다). 직접 중지한 채팅, 완료된 채팅, 실패한 채팅은 이어지지 않습니다. dsh 자체에는 이 설정이 없습니다. dsh는 이런 턴을 중단됨으로 표시할 뿐입니다. | <a href="assets/features/resumeAfterRestart.webp"><img src="assets/features/resumeAfterRestart.webp" width="160" alt="스크린샷: 재시작 후 이어서 실행"></a> |
|
|
52
53
|
| **대기열 끌어서 놓기** | <a id="feature-queuereorder"></a>대기 중인 메시지에 핸들(⠿)이 생깁니다. 끌어서 순서를 바꾸거나, 핸들에 포커스를 두고 `↑` / `↓`를 누르세요. `Esc`는 이동을 취소합니다. | <a href="assets/features/queueReorder.webp"><img src="assets/features/queueReorder.webp" width="160" alt="스크린샷: 대기열 끌어서 놓기"></a> |
|
|
@@ -63,19 +64,22 @@ dsh plugin --profile web add dsh-composer-plus
|
|
|
63
64
|
| **작업 공간 트리의 브랜치** | <a id="feature-branchtree"></a>설정 → Composer Plus → **작업 공간 트리의 브랜치**(기본값은 꺼짐). 켜면 `<project>/.worktrees/`에 worktree 폴더가 있는 각 브랜치가 해당 프로젝트 안의 프로젝트로 표시됩니다. 중첩해서 보려면 dsh의 **보기 옵션** → **작업 공간 트리**를 선택하세요. 폴더가 삭제된 브랜치는 목록에서 사라지고, dsh는 그 채팅을 **그룹 없음** 아래에 표시합니다. 프로젝트 폴더에 있는 채팅의 에이전트가 브랜치를 만들고 그 브랜치로 전환하면(`git switch -c`, `git checkout -b`), 폴더에 커밋되지 않은 변경이 없을 때 프로젝트 폴더는 이전 브랜치로 돌아가고, 브랜치는 자체 폴더를 받으며, 채팅은 그곳으로 이동합니다. 복사본이 브랜치 프로젝트에서 열려 작업을 계속하고, 이전 채팅은 보관됩니다. 목록은 시작할 때, 30초마다, 각 턴이 끝난 뒤, 창으로 돌아올 때 확인됩니다. | <a href="assets/features/branchTree.webp"><img src="assets/features/branchTree.webp" width="160" alt="스크린샷: 작업 공간 트리의 브랜치"></a> |
|
|
64
65
|
| **다음 메시지 예측** | <a id="feature-nextprediction"></a>기본적으로 켜져 있습니다. **설정 → Composer Plus**에서 끌 수 있습니다. 에이전트가 턴을 마치면(중지되거나 실패한 턴 제외) 빈 입력란에 다음 메시지의 예측이 회색으로 표시되고, **Tab으로 수락** 힌트가 함께 나옵니다. `Tab`을 누르면 텍스트가 입력란에 들어가지만 보내지는 않습니다. `Esc`를 누르면 그 턴 동안 예측이 숨겨집니다. 입력을 시작해도 숨겨지고, 새 턴이 오면 새 예측으로 바뀝니다. 스위치 아래의 **모델** 메뉴에는 dsh 자체의 모델 목록이 나옵니다(dsh 모델 메뉴와 같은 목록). 기본으로 **dsh 기본값**이 선택되어 있으며, dsh의 기본 모델을 따릅니다. 턴이 끝날 때마다 짧은 모델 호출이 한 번 일어납니다. Tether에서는 예측이 빈 입력란 위에 표시됩니다. 탭하면 입력란에 들어갑니다. | <a href="assets/features/nextPrediction.webp"><img src="assets/features/nextPrediction.webp" width="160" alt="스크린샷: 다음 메시지 예측"></a> |
|
|
65
66
|
| **입력 중 자동 완성** | <a id="feature-typingcompletion"></a>기본적으로 꺼져 있습니다. **설정 → Composer Plus**에서 켤 수 있습니다. 입력하는 동안 커서 바로 뒤의 회색 텍스트가 메시지가 이어질 수 있는 내용을 보여 줍니다. `Tab`을 누르면 메시지에 추가되지만 보내지는 않습니다. `Esc`를 누르면 숨겨집니다. 사용자가 직접 이어서 쓸 말만 제안합니다. 사용자에게 하는 답변이나 지어낸 오류 문구, 이름은 제안하지 않습니다. 메시지가 끝난 것처럼 보이거나 모델이 확신하지 못하면 아무것도 표시되지 않습니다. 회색 텍스트의 다음 글자를 그대로 입력하면 텍스트가 유지되고, 새 모델 호출은 없습니다. 스위치 아래에 이 기능 전용 **모델** 메뉴가 있습니다. 첫 항목인 **다음 메시지 예측과 같음**은 **다음 메시지 예측**의 모델을 사용합니다(기본값). 기능마다 다른 모델을 쓰려면 다른 모델을 고르세요. 예를 들어 자동 완성에는 더 빠른 모델을 고를 수 있습니다. 입력을 멈출 때마다 모델을 한 번 호출하므로 예측보다 토큰을 훨씬 많이 사용합니다. 빠르고 비용이 낮은 모델을 고르세요. 슬래시 명령, 파일 칩이 있는 메시지, 커서가 끝에 있지 않을 때는 실행되지 않습니다. Tether에서는 입력하는 동안 나머지 텍스트가 입력란 위에 표시됩니다. 탭하면 추가됩니다. | <a href="assets/features/typingCompletion.webp"><img src="assets/features/typingCompletion.webp" width="160" alt="스크린샷: 입력 중 자동 완성"></a> |
|
|
66
|
-
| **프롬프트 개선** | <a id="feature-promptimprove"></a>대략적인 요청을 입력한 뒤 모델 메뉴 옆의 요술봉(**프롬프트 개선**)을 클릭하세요. 모델 호출 한 번으로 요청을 더 명확한 프롬프트로 다시 씁니다. 목표를 먼저 쓰고, 여러 부분이 있으면 짧은 번호 단계로 나누고, 실행할 검사를 적습니다. 이 채팅(되돌린 메시지 제외), 프로젝트의 README, AGENTS.md, 매니페스트, 변경된 파일, 이름이 입력한 단어와 일치하는 파일을 읽고, 사용 언어를 유지합니다. 파일 이름을 지어내지 않습니다. 새 텍스트가 초안을 대신하지만 보내지는 않습니다. 읽고 고친 뒤 `Enter`를 누르세요. `Cmd/Ctrl+Z`를 누르면 한 번에 원래 텍스트로 돌아오며, 버튼(**개선 실행 취소**)도 같습니다. 작업 중에 입력하면 새로 입력한 텍스트가 유지됩니다. `Esc`를 누르거나 한 번 더 클릭하면 취소됩니다. 설정에 전용 **모델** 메뉴가 있습니다(기본값: **채팅의 모델과 같음**). 슬래시
|
|
67
|
-
| **목표 확인** | <a id="feature-goalcheck"></a>`/goal`로 목표를 시작하세요. 에이전트가 자동 라운드에서 목표를 완료로 표시하면, 목표는 두 가지 확인을 통과해야만 닫힙니다. 먼저 프로젝트의 테스트 명령이 채팅 폴더에서 채팅의 샌드박스 모드로 실행됩니다. 명령은 직접 정한 명령이거나 `package.json`, `Makefile`, `Cargo.toml`, `go.mod` 또는 pytest에서 찾은 명령입니다. 에이전트 자신의 최신 단계가 그 테스트의 성공한 실행이었다면 다시 실행하지 않습니다. 그다음 도구가 없는 독립적인 모델 호출 한 번이 목표, 이 채팅, `git status`, 테스트 결과를 읽습니다. 확인에 실패하면 목표는 진행 중으로 남고, 에이전트가
|
|
68
|
-
|
|
|
67
|
+
| **프롬프트 개선** | <a id="feature-promptimprove"></a>대략적인 요청을 입력한 뒤 모델 메뉴 옆의 요술봉(**프롬프트 개선**)을 클릭하세요. 모델 호출 한 번으로 요청을 더 명확한 프롬프트로 다시 씁니다. 목표를 먼저 쓰고, 여러 부분이 있으면 짧은 번호 단계로 나누고, 실행할 검사를 적습니다. 이 채팅(되돌린 메시지 제외), 프로젝트의 README, AGENTS.md, 매니페스트, 변경된 파일, 이름이 입력한 단어와 일치하는 파일을 읽고, 사용 언어를 유지합니다. 파일 이름을 지어내지 않습니다. 새 텍스트가 초안을 대신하지만 보내지는 않습니다. 읽고 고친 뒤 `Enter`를 누르세요. `Cmd/Ctrl+Z`를 누르면 한 번에 원래 텍스트로 돌아오며, 버튼(**개선 실행 취소**)도 같습니다. 작업 중에 입력하면 새로 입력한 텍스트가 유지됩니다. `Esc`를 누르거나 한 번 더 클릭하면 취소됩니다. 설정에 전용 **모델** 메뉴가 있습니다(기본값: **채팅의 모델과 같음**). `/goal <objective>` 메시지에서는 목표만 **목표 확인**이 검증할 수 있는 완료 조건으로 다시 씁니다. 산출물, 통과해야 하는 검사, 채팅에 보여 줄 증거, 할 수 없는 부분의 미해결 표시, 같은 장애가 계속될 때의 중지가 들어갑니다. `/goal` 명령은 그대로 남습니다. 다른 슬래시 명령, `/goal` 제어어(`clear`, `pause`, `resume`), 파일 칩이 있는 메시지에는 쓸 수 없습니다. Tether에서는 요술봉이 입력란 옆에 있습니다. | <a href="assets/features/promptImprove.webp"><img src="assets/features/promptImprove.webp" width="160" alt="스크린샷: 프롬프트 개선"></a> |
|
|
68
|
+
| **목표 확인** | <a id="feature-goalcheck"></a>`/goal`로 목표를 시작하세요. 에이전트가 자동 라운드에서 목표를 완료로 표시하면, 목표는 두 가지 확인을 통과해야만 닫힙니다. 먼저 프로젝트의 테스트 명령이 채팅 폴더에서 채팅의 샌드박스 모드로 실행됩니다. 명령은 직접 정한 명령이거나 `package.json`, `Makefile`, `Cargo.toml`, `go.mod` 또는 pytest에서 찾은 명령입니다. 에이전트 자신의 최신 단계가 그 테스트의 성공한 실행이었다면 다시 실행하지 않습니다. 그다음 도구가 없는 독립적인 모델 호출 한 번이 목표, 이 채팅, `git status`, 테스트 결과를 읽습니다. 모델은 증거 표로 답합니다. 목표의 각 부분은 증거와 수정 방법과 함께 검증됨, 잘못됨 또는 미해결로 표시되며, 모든 부분이 검증되어야만 목표가 닫힙니다. 확인에 실패하면 목표는 진행 중으로 남고, 에이전트가 열린 각 부분을 증거와 수정 방법과 함께 읽은 뒤 다음 라운드가 이어집니다. 목표 바 아래의 행(**목표 확인**)에 테스트, 마지막 결과, 검증된 부분의 수가 표시됩니다(마우스를 올리면 표가 보입니다). **편집**에서 직접 테스트 명령과 시간 또는 토큰 제한을 정합니다. 제한을 넘으면 목표가 차단됩니다. 토큰 제한에는 채팅의 하위 에이전트도 포함됩니다. **지금 실행**은 목표를 닫지 않고 확인을 실행합니다. 설정에 전용 **모델** 메뉴가 있습니다(기본값: **채팅의 모델과 같음**). 목표를 직접 완료하면 아무것도 확인하지 않습니다. | <a href="assets/features/goalCheck.webp"><img src="assets/features/goalCheck.webp" width="160" alt="스크린샷: 목표 확인"></a> |
|
|
69
|
+
| **새 채팅에서 계속** | <a id="feature-handoffchat"></a>사이드바에서 채팅을 마우스 오른쪽 버튼으로 클릭(또는 채팅의 **…** 메뉴 열기) → **새 채팅에서 계속…**. 채팅 자체의 모델을 한 번 호출해, 채팅에 보이는 내용으로 인계 메모를 씁니다. 항목은 작업, 산출물, 완료한 일, 결정 사항, 미해결 문제, 다음 작업입니다(도구 호출과 그 결과가 증거이며, 되돌린 단계는 빠집니다). 메모는 대화 상자에 열립니다. 읽고 편집하세요. **다시 쓰기**는 새 메모를 씁니다. **새 채팅 시작**(또는 `Cmd/Ctrl+Enter`)은 같은 프로젝트에서 새 채팅을 열고, 메모와 이전 채팅 링크를 첫 메시지로 보냅니다. 이전 채팅은 그대로 남습니다. 긴 채팅이 가득 차거나 느려졌을 때, 또는 다음 날 이어서 할 때 쓰세요. 프로젝트에는 아무것도 쓰지 않습니다. | <a href="assets/features/handoffChat.webp"><img src="assets/features/handoffChat.webp" width="160" alt="스크린샷: 새 채팅에서 계속"></a> |
|
|
70
|
+
| **컨텍스트 구성** | <a id="feature-contextbreakdown"></a>오른쪽 사이드바 → `+` → **컨텍스트**. 페이지는 열린 채팅의 모델 컨텍스트를 지금 무엇이 채우고 있는지, 그리고 컨텍스트 창을 얼마나 쓰는지 보여 줍니다. 시스템 프롬프트, 프로젝트 지침(AGENTS.md), 스킬, 내 메시지, 에이전트 답변과 도구 호출, 도구 결과(도구별), MCP 결과(서버별), 도구 정의, 압축 요약, 기타 컨텍스트 메모를 각각의 토큰 수와 비율과 함께 보여 줍니다. 항목을 클릭하면 그 도구나 서버를 볼 수 있습니다. 채팅 로그만 읽으며(`/compact`와 되돌리기 이후), 모델을 호출하지 않습니다. 각 턴이 끝난 뒤와 **새로 고침**을 누르면 다시 읽습니다. 채팅이 느리거나 가득 찬 이유를 볼 때 쓰세요. 예를 들어 큰 MCP 도구 결과나 많은 도구 정의가 원인일 수 있습니다. | <a href="assets/features/contextBreakdown.webp"><img src="assets/features/contextBreakdown.webp" width="160" alt="스크린샷: 컨텍스트 구성"></a> |
|
|
71
|
+
| **보호된 파일** | <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> |
|
|
72
|
+
| **프로젝트 메모리** | <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> |
|
|
69
73
|
| **이 채팅에서 허용** | <a id="feature-allowforchat"></a>자동 검토가 확인을 요청하면 승인 카드에 **이 채팅에서 허용**이 추가됩니다. 이후 같은 채팅의 같은 도구는 인수와 관계없이 시간 제한이 끝날 때까지 허용됩니다(기본값 1시간. **설정 → Composer Plus → 이 채팅에서 허용**에서 고릅니다). 그 후에는 에이전트가 다시 묻습니다. 헤더 칩에서 허용 목록과 종료 시각을 보고 취소할 수 있습니다. 허용은 재시작 후에도 유지됩니다. | <a href="assets/features/allowForChat.webp"><img src="assets/features/allowForChat.webp" width="160" alt="스크린샷: 이 채팅에서 허용"></a> |
|
|
70
74
|
| **프로젝트 상태** | <a id="feature-projectstatus"></a>사이드바의 프로젝트 행에 그 채팅과 같은 실행 중 / 대기 중 / 완료 표시가 나타납니다. 그래서 접힌 프로젝트도 안의 채팅이 작업 중인지, 사용자의 조치가 필요한지 알려 줍니다. 사용자의 조치를 기다리는 채팅이 먼저 표시되고, 그다음 아직 열지 않은 완료된 채팅(초록색 점, 다른 채팅이 아직 실행 중일 때도 표시), 마지막으로 실행 중 표시가 나타납니다. 포인터를 올리면 자세한 내용이 보입니다. **작업 공간 트리**에서는 상위 폴더의 행에도 그 안에 있는 각 프로젝트(예: `.worktrees/` 안의 각 브랜치 폴더)의 채팅 상태가 표시되며, 폴더가 접혀 있을 때도 마찬가지입니다. | <a href="assets/features/projectStatus.webp"><img src="assets/features/projectStatus.webp" width="160" alt="스크린샷: 프로젝트 상태"></a> |
|
|
71
|
-
| **채팅 행의 Git 브랜치** | <a id="feature-sessionbranch"></a>사이드바의 각 채팅 행에 작은 회색 배지로, 채팅의 마지막 턴 때 채팅 프로젝트 폴더가 있던 git 브랜치가 표시됩니다(예: `main` 또는 `feature/login`. 분리된 HEAD는
|
|
75
|
+
| **채팅 행의 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> |
|
|
72
76
|
| **모두 읽음으로 표시** | <a id="feature-markprojectread"></a>사이드바에서 프로젝트의 **…** 버튼 → **모두 읽음으로 표시**를 클릭하세요. 그 프로젝트의 모든 채팅에서 초록색 읽지 않음 점이 한 번에 사라집니다. 다른 프로젝트의 점은 그대로 남습니다. 프로젝트에 읽지 않은 채팅이 없으면 이 항목은 회색으로 표시됩니다(**읽지 않은 채팅 없음**). | <a href="assets/features/markProjectRead.webp"><img src="assets/features/markProjectRead.webp" width="160" alt="스크린샷: 모두 읽음으로 표시"></a> |
|
|
73
77
|
| **활성 프로젝트 우선** | <a id="feature-activeprojectsfirst"></a>채팅이 실행을 시작하거나 사용자의 조치가 필요해지면, 그 프로젝트가 dsh 자체 행 애니메이션으로 사이드바 맨 위로 이동합니다(직접 끌어 올릴 때와 같은 움직임). 완료된 프로젝트는 제자리에 남으며, 평소처럼 원하는 곳으로 끌어 옮길 수 있습니다. 이동은 dsh의 프로젝트 순서에 저장되므로, 이 기능을 꺼도 현재 순서가 유지됩니다. | <a href="assets/features/projectStatus.webp"><img src="assets/features/projectStatus.webp" width="160" alt="스크린샷: 활성 프로젝트 우선"></a> |
|
|
74
78
|
| **최근 프로젝트 필터** | <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> |
|
|
75
79
|
| **모든 프로젝트 접기** | <a id="feature-collapseprojects"></a>사이드바에 열린 프로젝트가 있으면 보기 옵션(슬라이더 아이콘) 옆에 버튼이 나타납니다. 클릭하면 열린 프로젝트를 한 번에 모두 닫습니다. 예를 들어 프로젝트 5개 중 열린 3개를 한 번에 닫습니다. 열린 프로젝트가 없으면 버튼이 다시 숨겨집니다. | <a href="assets/features/collapseProjects.webp"><img src="assets/features/collapseProjects.webp" width="160" alt="스크린샷: 모든 프로젝트 접기"></a> |
|
|
76
80
|
| **상태별 정렬** | <a id="feature-statusorder"></a>사이드바 → 보기 옵션 → **정렬 기준** → **상태별**(**하나의 목록**과 함께 사용). 완료된 채팅이 먼저 옵니다(dsh의 “완료” 점. 오류로 끝난 턴에도 이 점이 붙습니다). 그다음 실행 중이거나 대기 중인 채팅, 활성 자동화(예약)가 있는 채팅, 나머지 채팅이 dsh 순서대로 옵니다. 완료된 채팅을 열면 아래로 이동합니다. 보기만 바뀝니다. 원래대로 돌아가려면 **수동** 또는 **마지막 업데이트**를 선택하세요. | <a href="assets/features/statusOrder.webp"><img src="assets/features/statusOrder.webp" width="160" alt="스크린샷: 상태별 정렬"></a> |
|
|
77
81
|
| **백그라운드 알림** | <a id="feature-notifications"></a>dsh가 백그라운드에 있을 때 턴이 끝나면(답변의 첫 줄과 함께) 알림을 받습니다. 채팅이 정말로 사용자를 기다릴 때도 알림을 받습니다. 기다리는 이유는 승인(도구 이름), 답변(질문), 계획 검토입니다. 요청이 1.5초 뒤에도 열려 있어야 알림이 갑니다. 그래서 자동으로 처리된 승인(자동 검토 허용, 다른 플러그인)은 알림을 보내지 않습니다. 요청에 답하면 알림도 바로 사라집니다. Dock/작업 표시줄 배지는 기다리는 채팅 수를 보여 줍니다. 알림을 클릭하면 그 채팅이 열립니다. | <a href="assets/features/notifications.webp"><img src="assets/features/notifications.webp" width="160" alt="스크린샷: 백그라운드 알림"></a> |
|
|
78
|
-
| **유휴 상태일 때 대기 중인 채팅 열기** | <a id="feature-idleswitch"></a>채팅이 질문을 하거나 승인 또는 계획 검토를 기다리고 있을 때(주황색 점) 30초 동안 dsh를 사용하지 않으면 dsh가 그 채팅을 엽니다.
|
|
82
|
+
| **유휴 상태일 때 대기 중인 채팅 열기** | <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> |
|
|
79
83
|
| **애플리케이션 언어** | <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> |
|
|
80
84
|
| **모바일 연결(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> |
|
|
81
85
|
| **자동 업데이트** | <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> |
|
|
@@ -160,7 +164,10 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
|
|
|
160
164
|
- **입력 중 자동 완성:** 켜기 전까지 꺼져 있습니다. 켜져 있는 동안 입력을 멈출 때마다 Host 쪽은 지금까지 입력한 텍스트와, 그 채팅에서 사용자가 직접 보낸 메시지와 에이전트의 텍스트 답변(도구 출력, 숨은 컨텍스트, 추론 제외)을 채팅 기준 최대 약 3,000자까지 **입력 중 자동 완성**에서 고른 모델(기본값: **다음 메시지 예측**의 모델)에 보냅니다. 입력을 다시 멈추면 이전 요청은 중지됩니다. 채팅에는 아무것도 저장되지 않습니다. 스위치는 `$DSH_HOME/storages/dsh-composer-plus/complete.json`(소유자 전용 파일)에 보관됩니다.
|
|
161
165
|
- **프롬프트 개선:** 요술봉을 클릭하기 전에는 아무것도 실행되지 않습니다. 클릭하면 Host 쪽은 초안, 그 채팅에서 사용자가 직접 보낸 메시지와 에이전트의 텍스트 답변(도구 출력, 숨은 컨텍스트, 추론, 되돌린 메시지 제외. 최대 약 6,000자, 가장 최근 부분), **기능 아이디어**와 같은 프로젝트 요약(파일 규칙도 같음: `.env*`나 키 파일 없음, 폴더 밖을 가리키는 심볼릭 링크 없음, FIFO 없음), `git status`가 변경됨으로 표시하는 경로, 이름에 초안과 같은 단어가 들어 있는 추적되거나 추적되지 않는(무시되지 않은) 경로 최대 30개를 **프롬프트 개선**에서 고른 모델(기본값: 채팅 자체의 모델)에 요청 한 번으로 보냅니다. 이 요약 외의 파일 내용은 보내지 않습니다. 채팅과 프로젝트에는 아무것도 쓰지 않습니다. 답변은 입력란의 초안을 바꿀 뿐이며, 보낼지는 사용자가 정합니다. 고른 모델은 `$DSH_HOME/storages/dsh-composer-plus/improve.json`(소유자 전용 파일)에 보관됩니다.
|
|
162
166
|
- **목표 확인:** 에이전트가 자동 라운드에서 `/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개)에 보관됩니다.
|
|
163
|
-
-
|
|
167
|
+
- **새 채팅에서 계속:** 클릭하기 전에는 아무것도 실행되지 않습니다. 클릭하면 Host 쪽은 채팅(목표 확인이 읽는 방식과 같음: 추론과 되돌린 단계 제외)을 채팅 자체의 모델에 보내고 인계 메모를 보여 줍니다. 새 채팅을 만드는 것은 **새 채팅 시작**뿐입니다. 프로젝트에는 아무것도 쓰지 않습니다.
|
|
168
|
+
- **컨텍스트 구성:** Host에서 채팅 로그만 읽습니다. 모델 호출도 프로젝트 파일도 없습니다.
|
|
169
|
+
- **보호된 파일:** 목록과 스위치는 `$DSH_HOME/storages/dsh-composer-plus/protected-files.json`(소유자 전용 파일)에 있습니다. 확인은 각 파일 도구 호출의 경로(와 실제 경로)만 읽으며, 파일 자체는 읽지 않습니다.
|
|
170
|
+
- **프로젝트 메모리:** 직접 켜기 전까지는 꺼져 있습니다. 켜져 있는 동안 최상위 채팅의 턴이 끝날 때마다 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도 같은 경로로 메모를 읽고 바꿉니다.
|
|
164
171
|
- **백업:** 아무것도 컴퓨터 밖으로 나가지 않습니다. 아카이브는 `~/Desktop/dsh-backups`에 저장됩니다(소유자 전용 파일). 비밀 값은 아카이브에 들어가지 않습니다. 자격 증명 파일(`.credentials.yaml`, `.env`), 키 파일(`.pem`, `.key`, `.p12`, `.pfx`), yml 파일의 token, secret, password, API 키 설정 값은 마스킹되고, 실제 사본은 같은 폴더의 `composer-plus-vault/<archive>/`(소유자 전용)에, 이 컴퓨터에만 남습니다. **다른 컴퓨터용**은 vault를 복사하지 않습니다. 그 비밀 값은 새 컴퓨터에서 다시 입력하세요. 채팅 로그, 설정, dsh 홈의 나머지 내용은 그대로 아카이브에 들어갑니다. `$DSH_HOME` 자체처럼 이 폴더를 비공개로 두세요. 백업은 `O_NOFOLLOW | O_NONBLOCK`으로 파일을 읽습니다. 심볼릭 링크는 링크로 저장하고(따라가지 않음), FIFO나 장치는 건너뜁니다. 자동 백업 스위치와 설정은 `$DSH_HOME/storages/dsh-composer-plus/auto-backup.json`에, 복구 콘솔 스위치는 `rescue-console.json`에 있습니다. dsh가 실행되는 동안에는 `running/host-<pid>.json`이 각 dsh 프로세스를 나타냅니다(복구 콘솔은 이 파일들을 읽고 복원을 거부합니다).
|
|
165
172
|
- **복구 콘솔:** 터미널 메뉴이며, 네트워크 포트를 열지 않습니다. 복원은 dsh 홈 옆의 새 폴더에만 씁니다(파일은 `O_EXCL | O_NOFOLLOW`로 쓰고, 심볼릭 링크는 마지막에 만들며 따라가지 않음). 안전하지 않은 이름(`..`, 절대 경로), 장치나 FIFO, 둘 이상의 최상위 폴더, 링크 아래의 항목이 있는 아카이브는 거부합니다.
|
|
166
173
|
|
|
@@ -182,7 +189,7 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
|
|
|
182
189
|
- **채팅 행에 브랜치 배지가 없음:** 이 버전을 설치한 뒤 그 채팅에 턴이 없었거나, 폴더가 git 저장소가 아니거나, **채팅 행의 Git 브랜치**가 꺼져 있습니다. 업데이트한 뒤에는 dsh를 다시 시작하세요(브랜치는 Host 쪽이 기록합니다).
|
|
183
190
|
- **목표 확인에 테스트가 종료 코드 127 또는 "not found"로 끝났다고 표시됨:** Finder나 Dock에서 시작한 dsh는 터미널보다 PATH가 짧을 수 있어서 `npm`, `pnpm`, `cargo`를 찾지 못합니다. 터미널에서 dsh를 시작하거나, **목표 확인** → **편집**에서 전체 경로를 쓴 테스트 명령을 직접 정하세요. **지금 실행**을 누르면 결과가 바로 표시됩니다.
|
|
184
191
|
- **목표가 닫히지 않고 에이전트가 계속 작업함:** **목표 확인**이 실패한 테스트나 남은 작업을 찾았습니다. 목표 아래의 행에 이유가 표시됩니다(자세한 내용은 결과에 포인터를 올려 보세요). 원인이나 테스트 명령을 고치거나, `/goal` 또는 목표 바로 목표를 직접 완료하세요(이 완료는 확인하지 않습니다).
|
|
185
|
-
- **릴리스 직후 설치 실패:** 버전을 붙여서 설치하세요(`dsh-composer-plus@1.
|
|
192
|
+
- **릴리스 직후 설치 실패:** 버전을 붙여서 설치하세요(`dsh-composer-plus@1.17.0`). 위의 설치 안내를 참고하세요.
|
|
186
193
|
- **지금 백업에서 "다른 백업 작업이 실행 중입니다"라고 표시됨:** 다른 dsh 창이나 복구 콘솔에서 작업이 실행 중입니다(둘은 백업 폴더의 잠금 파일 `.composer-plus.lock`을 함께 씁니다). 작업이 끝날 때까지 기다리세요. 실행 중인 작업이 없으면, 다음에 클릭할 때 종료된 프로세스의 잠금을 넘겨받습니다.
|
|
187
194
|
- **복구 콘솔에 "dsh is running"이라고 표시됨:** 먼저 dsh를 종료하세요. dsh가 정말 닫혀 있다면, 메시지에 나온 파일은 비정상 종료로 남은 것입니다. 그 파일을 삭제하고 다시 시도하세요.
|
|
188
195
|
- **복원 후 dsh가 시작되지 않거나 플러그인이 없음:** 프로필의 플러그인 패키지를 다시 설치해야 합니다. 복구 콘솔이 복원 후에 이를 제안합니다. 또는 콘솔이 나열하는 `$DSH_HOME/profiles/` 아래의 각 폴더에서 `pnpm install`을 실행하세요. vault에 없던 비밀 값(다른 컴퓨터)은 다시 입력해야 합니다. 콘솔이 그 목록을 보여 줍니다.
|
|
@@ -205,6 +212,7 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
|
|
|
205
212
|
- **이 채팅에서 허용**은 허용한 순간부터 시간 제한을 셉니다. 새 시간 제한은 유효한 허용에 즉시 적용되므로, 더 짧은 시간 제한은 허용을 즉시 끝낼 수 있습니다. 버전 1.12 이하의 허용에는 시간 정보가 없습니다. 업데이트 후 에이전트가 그 도구들에 대해 한 번 더 묻습니다.
|
|
206
213
|
- **입력란 포커스 유지**는 `/` 명령이나 스킬을 보낸 뒤에만 포커스를 돌려줍니다. dsh가 명령을 처리하는 몇 밀리초 동안 입력란이 읽기 전용이므로, 그동안 누른 키는 사라집니다. dsh의 `/` 메뉴가 아직 열려 있으면 `Enter`는 강조된 행을 선택하고 메시지를 보내지 않습니다.
|
|
207
214
|
- **질문 카드를 창에 맞추기**는 dsh의 질문 카드만 바꾸고 계획 검토 카드는 바꾸지 않습니다. 카드는 dsh의 마크업(`data-question-key`, `data-question-scroll`)으로 찾습니다. dsh 업데이트로 이 마크업이 바뀌면 카드는 dsh가 그리는 대로 보입니다. 카드 높이는 채팅이 아니라 창을 따릅니다. 좁은 사이드 패널 안의 채팅에서는 높은 카드가 채팅 위로 넘칠 수 있습니다.
|
|
215
|
+
- **채팅 헤더를 창에 맞추기**는 dsh가 생성한 클래스 이름(`_titleRow`, `_titleCluster`, `_crumbs`, `_headerActions`, `_headerUtilities`)으로 채팅 헤더를 찾습니다. dsh에 헤더 레이아웃용 훅이 없기 때문입니다. dsh 업데이트로 이 이름이 바뀌면 헤더는 dsh가 그리는 그대로 보입니다. 아주 좁은 채팅 열에서는 헤더가 두세 줄을 차지할 수 있어 메시지 위의 공간이 줄어듭니다.
|
|
208
216
|
- **모바일 연결**은 macOS에서만 작동합니다(`en0`, `openssl`, `swift`, `dns-sd` 사용). 고정 포트 19390과 19391을 쓰므로, Mac마다 한 번에 dsh 하나에서만 실행할 수 있습니다(각 Mac은 휴대폰의 Mac 목록에서 항목 하나입니다). 휴대폰은 Tether가 열려 있거나 막 백그라운드로 간 동안에만 알림을 받습니다(푸시 서비스 없음). Tether에서 "Settings → Notifications → Send notifications"를 켜기 전에는 Tether가 알림을 보내지 않습니다. 이 설정은 기본적으로 꺼져 있으며, 켤 때 iOS가 권한을 요청합니다. iOS 앱은 아직 App Store에 없습니다. Xcode로 `tether/ios`에서 빌드하세요. "Tailscale only"를 켜도 Mac에 Wi-Fi 또는 이더넷 주소가 있어야 합니다(게이트웨이는 그런 주소가 있을 때만 시작됩니다). 액세스 로그는 Mac마다 따로 있으며, 가장 최근의 시도 200개만 보관합니다. 1분 안에 반복된 시도는 새 행을 만들지 않고 같은 행의 횟수를 하나 늘립니다. Tether의 앱 잠금은 iPhone 잠금 화면의 알림 미리보기를 숨기지 않습니다. iOS 설정에서 끄세요. Tether의 초록 점은 Mac을 따릅니다. dsh에서 연 채팅은 휴대폰에서도 점이 사라집니다. Tether에서 연 채팅은 휴대폰에서만 점이 사라집니다. Mac에 있는 dsh 자체의 점은 Mac에서 그 채팅을 열 때까지 남습니다.
|
|
209
217
|
- 세션 링크는 채팅 안에서 작동하지만, 클릭해도 채팅이 열리지는 않습니다. **메시지 링크 복사**로 만든 링크는 dsh 0.2.1 이상에서만, 그리고 채팅 안의 메시지에서만 그 메시지를 엽니다(dsh 0.2.0에는 사용자 텍스트 규칙이 없으므로, 링크는 복사되지만 일반 텍스트로 보입니다). 되돌리기로 빠진 메시지나, 압축으로 dsh가 불러오는 기록에서 빠진 메시지는 보여 줄 수 없습니다. 이때 링크가 그렇다고 알려 줍니다. 🔗 버튼은 dsh의 메시지 행에 붙습니다. dsh 업데이트로 그 마크업이 바뀌면 버튼이 표시되지 않습니다.
|
|
210
218
|
- **모두 읽음으로 표시**는 공개 API가 아닌 dsh의 일부(dsh 세션 상태의 `completionUnread` 목록)를 통해 dsh 자체의 읽지 않음 점을 바꿉니다. dsh 업데이트로 이 이름이 바뀌면 항목이 표시되지 않습니다. 이 항목은 dsh의 프로젝트 "…" 메뉴에 들어가는데, 이 메뉴에는 플러그인용 슬롯이 없습니다. dsh가 이 메뉴를 바꾸면 이 항목도 표시되지 않습니다.
|
|
@@ -216,10 +224,10 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
|
|
|
216
224
|
- **이 파일을 변경한 채팅**은 **이 채팅**처럼 dsh의 파일 도구(`write`, `edit`, `str_replace_editor`)만 압니다. 명령(`bash`)으로 만든 변경은 목록에 나오지 않습니다. 저장소의 최신 채팅 300개(만든 시점 기준)를 읽고, 더 있으면 그렇다고 알려 줍니다. 최대 100행을 보여 줍니다. 이름이 바뀐 파일은 도구가 쓴 이름으로 표시됩니다. 폴더가 저장소 밖에 있는 채팅(같은 파일로 가는 다른 경로를 통한 경우도 포함)은 세지 않습니다. dsh를 시작한 뒤 처음 열 때는 저장소의 모든 채팅 로그를 읽습니다(채팅 275개에 약 4초). 그 뒤로 열 때는 그 이후에 바뀐 채팅만 읽습니다.
|
|
217
225
|
- **채팅 행의 Git 브랜치**는 현재 브랜치가 아니라, 마지막 턴이 시작되거나 끝날 때 채팅 폴더가 있던 브랜치를 보여 줍니다. 턴 밖에서 브랜치를 바꾸면 다음 턴 뒤에 표시됩니다. 이 버전 이전의 채팅에는 다음 턴까지 배지가 표시되지 않습니다. 배지는 dsh의 채팅 행 마크업 안에 들어갑니다(dsh에는 그곳에 슬롯이 없습니다). dsh 업데이트로 그 마크업이 바뀌면 배지가 표시되지 않습니다. 채팅 위의 프로젝트 행 이름이 브랜치와 같으면(예: “채팅별 브랜치” 폴더) 채팅 행에 배지가 표시되지 않지만, “하나의 목록”에서는 계속 표시됩니다.
|
|
218
226
|
- **채팅별 브랜치**를 계획 모드에서 쓸 때: dsh는 `/plan <메시지>`를 메시지가 아니라 명령으로 보냅니다. 그래서 Composer Plus가 dsh 입력란에서 명령 전송을 가로챕니다(공개 API가 아님). dsh 업데이트로 이것이 바뀌면, **새 브랜치**를 고른 상태의 `/plan <메시지>`는 열린 새 채팅에서 dsh 자체 명령으로 실행됩니다. Host가 새 채팅에서 계획 모드를 켜지 못하면 브랜치 폴더는 남고 메시지는 보내지지 않습니다. 따라서 새 채팅이 기본 모드에서 파일을 바꾸지 않습니다.
|
|
219
|
-
- **채팅별 브랜치**: 채팅의 브랜치 폴더(`<project>/.worktrees/<name>`)가 삭제되면(예: 채팅 자신의 에이전트가 worktree를 제거하고 브랜치를 삭제할 때) 채팅의 다음 단계에서 채팅이 그 폴더 밖으로 옮겨집니다. 브랜치 폴더의 프로젝트는 사이드바에서 사라지고, 채팅은 그룹 없음 아래에 표시되며 열린 상태로 유지됩니다. dsh 0.2.1 이상에서는 채팅이 프로젝트의 기본 폴더에서 계속되고, 모델은 새 폴더에 대한 안내를 받습니다. dsh 0.2.0에서는 채팅이 삭제된 폴더를 그대로 사용합니다. 그곳에서 실행하는 명령은 새 채팅을 시작할 때까지 실패합니다.
|
|
227
|
+
- **채팅별 브랜치**: 채팅의 브랜치 폴더(`<project>/.worktrees/<name>`)가 삭제되면(예: 채팅 자신의 에이전트가 worktree를 제거하고 브랜치를 삭제할 때) 채팅의 다음 단계에서 채팅이 그 폴더 밖으로 옮겨집니다. 브랜치 폴더의 프로젝트는 사이드바에서 사라지고, 채팅은 그룹 없음 아래에 표시되며 열린 상태로 유지됩니다. dsh 0.2.1 이상에서는 채팅이 프로젝트의 기본 폴더에서 계속되고, 모델은 새 폴더에 대한 안내를 받습니다. dsh 0.2.0에서는 채팅이 삭제된 폴더를 그대로 사용합니다. 그곳에서 실행하는 명령은 새 채팅을 시작할 때까지 실패합니다. 어떤 채팅도 사용하지 않는 삭제된 브랜치의 프로젝트도 사이드바에서 사라집니다. Composer Plus는 시작할 때와 30초마다 브랜치 폴더를 확인하며, 사이드바 필터가 없어도 됩니다. 채팅이 옮겨지는 동안 같은 저장소의 **새 브랜치**는 "다시 시도하세요"라고 답합니다. 스위치를 끄면 dsh 자체 오류("working-directory: directory does not exist")가 다시 표시됩니다.
|
|
220
228
|
- **작업 공간 트리의 브랜치**은(는) 클릭 없이 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의 사이드바 행에서 이를 읽습니다). 그 외에는 브랜치 프로젝트에 있습니다.
|
|
221
229
|
- **채팅에서 찾기**는 페이지가 보여 주는 것만 검색합니다. 불러온 메시지와 답변이 대상이며(이전 것은 위로 스크롤하거나 **이전 기록 로드**를 클릭하세요), 닫힌 도구 단계와 도구 출력 안의 접힌 텍스트는 검색하지 않습니다. 일치 항목은 최대 2,000개까지 셉니다(그 뒤에는 "2000+"). 브라우저의 하이라이트 API를 씁니다(Chromium 105 이상, 데스크톱 앱에는 있습니다). 더 오래된 브라우저에서는 개수와 이동은 작동하지만 색은 표시되지 않습니다. Mac에서는 `Cmd+F`(Windows와 Linux에서는 `Ctrl+F`)가 화면에 채팅이 있을 때만 이것을 엽니다. 다른 곳에서는 브라우저 자체의 찾기가 전처럼 작동합니다. Mac에서 `Ctrl+F`는 텍스트 필드에서 macOS 기능(커서를 한 글자 앞으로 이동)을 그대로 유지합니다.
|
|
222
|
-
- **유휴 상태일 때 대기 중인 채팅 열기**는 dsh 창이 보는 동작만 압니다. 다른 앱에서 하는 작업은 세지 않으므로, dsh가 백그라운드에 있으면 30초 뒤에 대기 중인 채팅을 열 수 있습니다. dsh를 앞으로 가져오지는 않습니다. 키 입력, 클릭, 마우스 이동 없이 읽기만 하면 유휴 상태로 봅니다. dsh의 주황색
|
|
230
|
+
- **유휴 상태일 때 대기 중인 채팅 열기**는 dsh 창이 보는 동작만 압니다. 다른 앱에서 하는 작업은 세지 않으므로, dsh가 백그라운드에 있으면 30초 뒤에 대기 중인 채팅을 열 수 있습니다. dsh를 앞으로 가져오지는 않습니다. 키 입력, 클릭, 마우스 이동 없이 읽기만 하면 유휴 상태로 봅니다. dsh의 주황색 점(질문, 승인, 계획 검토) 또는 초록색 점(아직 열지 않은 완료된 턴)이 있는 채팅만 봅니다. 주황색 채팅이 먼저 열립니다. 초록색 채팅을 열면 그 점이 사라지므로, 다음 초록색 채팅의 30초는 다음 키 입력, 클릭, 마우스 이동, 스크롤 휠, 터치 뒤에 시작됩니다. 돌아왔을 때 다른 초록색 점은 그대로 있습니다. 서브에이전트의 요청은 부모 채팅에 표시됩니다. 기다리는 채팅이 화면에 있는 동안에는 다른 채팅을 열지 않습니다. 답하지 않고 떠난 채팅은 다음에 30초 동안 사용하지 않으면 다시 열릴 수 있습니다. 30초는 바꿀 수 없습니다.
|
|
223
231
|
- 재시작 전에 보낸 알림을 클릭하면 dsh를 앞으로 가져오기만 합니다.
|
|
224
232
|
- 활성 프로젝트는 dsh에 저장되는 프로젝트 순서로 이동하므로, 새 순서는 재시작 후에도 유지됩니다. 어느 프로젝트에도 속하지 않은 채팅("그룹 없음")은 이동할 수 없습니다. dsh는 이 채팅을 항상 맨 마지막에 나열합니다.
|
|
225
233
|
- dsh의 사이드바 보기 옵션 메뉴에는 확장 지점이 없습니다. 그래서 최근 프로젝트 옵션은 dsh 자체 메뉴에 추가됩니다. dsh 업데이트로 이 메뉴가 바뀌면 옵션이 표시되지 않고 모든 프로젝트가 계속 보입니다. 필터는 프로젝트 행에 적용되므로 **하나의 목록**은 걸러지지 않습니다. **작업 공간 트리**에서는 안에 있는 프로젝트가 활성인 동안 상위 폴더도 계속 보이고, 최근 2시간 동안 활성이 아니었던 채팅 행도 숨겨집니다. **작업 공간**에서는 프로젝트 행만 걸러집니다. 필터는 dsh가 저장한 보기 설정(공개 API가 아님)에서 지금 어떤 보기인지 읽습니다. dsh 업데이트로 그 이름이 바뀌면 **작업 공간 트리**는 **작업 공간**처럼 걸러집니다. 프로젝트 상태도 같은 설정을 읽습니다. **작업 공간 트리**에서는 상위 폴더 행이 그 안에 있는 프로젝트의 채팅도 셉니다. dsh가 이 설정의 이름을 바꾸면 각 행은 자기 채팅만 표시합니다. **상태별**에도 같은 종류의 제한이 있습니다. dsh에는 정렬 슬롯이 없으므로, 항목과 행 순서가 dsh의 메뉴와 목록 마크업에 붙습니다.
|
|
@@ -228,10 +236,13 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
|
|
|
228
236
|
- dsh에는 **새 세션**를 열 위치를 고르는 확장 지점도 없습니다. **새 세션의 기본 작업 공간**은 공개 API가 아닌 dsh 메서드(dsh 작업 공간 서비스의 `startSession`)를 감쌉니다. dsh 업데이트로 이 이름이 바뀌면 **새 세션**는 dsh가 고른 위치(열린 프로젝트 또는 최근 프로젝트)에서 열립니다. 프로젝트를 지정하지 않는 모든 호출이 기본값을 사용합니다: 사이드바 버튼, 그 단축키, 로고, 그리고 **자동화 작업** 페이지의 **새로 만들기**도 마찬가지입니다. dsh는 시작할 때 여전히 마지막 채팅을 엽니다. 일반 폴더는 처음 사용할 때 만들어지고 프로젝트에 추가됩니다. Windows나 Linux에서 Documents 폴더를 옮겼다면 dsh 자체 폴더와 다른 폴더일 수 있습니다.
|
|
229
237
|
- dsh에는 입력란 힌트를 위한 확장 지점도 없습니다. 그래서 **다음 메시지 예측** 텍스트는 dsh 자체의 플레이스홀더(`[data-composer-placeholder]`) 위에 겹쳐 표시됩니다. dsh 업데이트로 이 마크업이 바뀌면 예측이 표시되지 않습니다. 켜져 있는 동안에는 턴이 끝날 때마다 짧은 모델 호출이 한 번 일어납니다.
|
|
230
238
|
- **입력 중 자동 완성**은 dsh 자체의 입력란 힌트(dsh가 슬래시 명령의 인수 힌트에 쓰는 `--dsh-composer-hint` 스타일)로 텍스트를 표시합니다. 슬래시 명령, 파일 칩이나 기호 칩이 있는 메시지, 커서가 메시지 끝에 있지 않을 때는 실행되지 않습니다. dsh 업데이트로 이 스타일이 바뀌면 완성 텍스트가 표시되지 않습니다. 입력을 멈출 때마다 모델 호출이 한 번 일어납니다.
|
|
231
|
-
- **프롬프트 개선**은 짧은 프로젝트 요약, 변경된 경로, 이름이 입력한 단어와 일치하는 경로만 보며, 코드 자체는 보지 않습니다. 그래서 맞는 파일을 놓칠 수 있고, 전달받은 경로만 언급합니다. 보내기 전에 새 텍스트를 읽어 보세요. 슬래시
|
|
232
|
-
- **목표 확인**은 에이전트가 자동 목표 라운드에서 한 완료만 확인합니다. 채팅에서 사용자가 요청한 완료, `/goal`, 목표 바는 확인하지 않습니다. 에이전트는 테스트나 테스트 명령의 파일을 스스로 바꿀 수 있습니다. 검증 모델은 채팅을 읽으므로 이를 알아챌 수 있지만, 양쪽 방향으로 틀릴 수 있습니다(잘못된 "완료되지 않음"은 라운드를 한 번 더 쓰고, 잘못된 "완료"는 목표를 닫습니다). 검증 모델은 채팅과 `git status`를 보며, 코드 자체는 보지 않습니다. 테스트 실행은 파일을 바꿀 수 있는 에이전트의 최신 단계가 같은 폴더에서 정확히 같은 명령을 성공적으로 실행한 에이전트 자신의 `bash` 실행일 때만 재사용합니다. 파이프(`| tail`)나 `&&`가 있는 명령은 재사용하지 않습니다. 예산은 턴이 끝날 때 측정하므로, 한 턴이 예산을 넘을 수 있습니다.
|
|
239
|
+
- **프롬프트 개선**은 짧은 프로젝트 요약, 변경된 경로, 이름이 입력한 단어와 일치하는 경로만 보며, 코드 자체는 보지 않습니다. 그래서 맞는 파일을 놓칠 수 있고, 전달받은 경로만 언급합니다. 보내기 전에 새 텍스트를 읽어 보세요. `/goal <목표>` 외의 슬래시 명령, `/goal` 제어어(`clear`, `pause`, `resume`), 파일 칩이나 기호 칩이 있는 메시지에서는 실행되지 않습니다(새 텍스트는 일반 텍스트라서 칩이 사라지기 때문입니다). `/goal` 목표에서는 초안과 컨텍스트만으로 조건을 씁니다. 너무 엄격한 조건은 목표 라운드를 더 쓰게 할 수 있으므로, 보내기 전에 읽어 보세요. 메시지는 최대 8,000자까지 가능합니다. 이미지는 그대로 첨부되어 있고, 텍스트만 바뀝니다. 클릭할 때마다 모델 호출이 한 번 일어나며, 성능이 높은 모델은 1분쯤 걸릴 수 있습니다(`Esc`로 취소).
|
|
240
|
+
- **목표 확인**은 에이전트가 자동 목표 라운드에서 한 완료만 확인합니다. 채팅에서 사용자가 요청한 완료, `/goal`, 목표 바는 확인하지 않습니다. 에이전트는 테스트나 테스트 명령의 파일을 스스로 바꿀 수 있습니다. 검증 모델은 채팅을 읽으므로 이를 알아챌 수 있지만, 양쪽 방향으로 틀릴 수 있습니다(잘못된 "완료되지 않음"은 라운드를 한 번 더 쓰고, 잘못된 "완료"는 목표를 닫습니다). 검증 모델은 채팅과 `git status`를 보며, 코드 자체는 보지 않습니다. 테스트 실행은 파일을 바꿀 수 있는 에이전트의 최신 단계가 같은 폴더에서 정확히 같은 명령을 성공적으로 실행한 에이전트 자신의 `bash` 실행일 때만 재사용합니다. 파이프(`| tail`)나 `&&`가 있는 명령은 재사용하지 않습니다. 예산은 턴이 끝날 때 측정하므로, 한 턴이 예산을 넘을 수 있습니다. 토큰 예산은 그 채팅의 하위 에이전트 채팅의 호출도 셉니다(턴이 끝날 때마다 저장된 로그에서 읽으므로, 하위 에이전트가 많은 채팅은 확인이 조금 더 오래 걸립니다). 근거 표는 검증 모델이 채팅을 직접 읽은 결과입니다. 검증됨이라고 한 부분도 중요하다면 직접 확인하세요. 확인이 실행되는 동안 `update_goal`은 기다립니다(테스트는 최대 15분, 검증은 최대 3분). 포크한 채팅은 새 채팅 ID를 받으므로, 부모 채팅 자체의 테스트 명령과 제한 없이 시작합니다. 검증까지 간 완료마다 모델 호출이 한 번 일어납니다.
|
|
241
|
+
- **보호된 파일**은 가드레일이며 샌드박스가 아닙니다. dsh 자체의 파일 도구(`read`, `read_image`, 파일에 대한 `grep`, `write`, `edit`, `str_replace_editor`)만 다룹니다. 셸 명령(`cat .env`), 에이전트가 쓴 스크립트, 하위 에이전트의 셸, MCP 도구, `glob` 목록, 폴더 전체에 대한 `grep`은 여전히 보호된 파일에 접근할 수 있습니다. 실제로 제한하려면 dsh의 샌드박스 모드를 쓰거나 비밀 값을 프로젝트 폴더 밖에 두세요. 패턴은 `*`, `**`, `?`를 알지만 `{a,b}`나 `[ab]`는 모르며, 대소문자를 구분하지 않습니다.
|
|
242
|
+
- **새 채팅에서 계속**은 채팅(메시지, 도구 호출, 각 도구 결과의 끝부분. 최대 약 60,000자, 가장 최근 부분)을 채팅 자체의 모델에 보냅니다. 인계 메모는 결정이나 파일을 빠뜨릴 수 있으므로, 시작하기 전에 읽어 보세요. 새 채팅은 메모와 링크된 채팅만 압니다(dsh는 이전 채팅을 읽기 전용 컨텍스트로 첨부합니다). 새 채팅의 모델 컨텍스트는 작게 시작하고, 이전 채팅은 그대로 남습니다. 채팅마다 한 번에 메모 작성이나 시작 하나만 실행됩니다.
|
|
243
|
+
- **컨텍스트 구성**은 dsh 자체의 규칙(토큰당 약 4자)으로 추정값을 보여 줍니다. dsh의 컨텍스트 링과 같은 규칙이며, 모델 자체의 계산과 다를 수 있습니다. 도구 정의는 가장 최근 요청의 것입니다. 채팅 로그에 있는 그대로의 컨텍스트를 보여 주며, 지금 실행 중인 턴은 다음 단계 뒤에 나타납니다.
|
|
233
244
|
- **중지 후 보낸 메시지 먼저 실행**은 채팅을 중지한 뒤에만 동작합니다(또는 실패한 턴 뒤, 아직 대기열이 있는 채팅을 열 때). 턴이 실행되는 중에 보낸 메시지는 여전히 대기열 끝에서 기다립니다. 내가 대기열에 넣은 메시지만 앞지릅니다. 대기열에 목표 라운드나 질문 답변이 기다리고 있으면 dsh 자체 순서가 유지됩니다. 공개 API가 아닌 dsh의 일부(중지된 턴이 아직 끝나는 중인지)를 읽습니다. dsh 업데이트로 그 이름이 바뀌면, 메시지는 그 턴이 끝난 뒤에만 앞으로 옮겨집니다. 서브에이전트 채팅은 dsh 자체 순서를 유지합니다.
|
|
234
|
-
- **프로젝트 메모리**는 채팅의 첫 폴더(dsh의 프로젝트 폴더)에 속합니다. `cd`로 폴더를 바꾼 채팅은 첫 프로젝트의 메모리를 계속 씁니다. 같은 파일로 가는 다른 경로로 연 같은 폴더는 메모리를 공유합니다. 채팅은 시작할 때 메모리 섹션을 고정하므로, 나중에 저장한 메모는 다음 채팅부터 보입니다(`memory_recall`은 바로 찾습니다). 검토는 모델이 남기기로 정한 것만 남깁니다. 사실을 놓치거나 틀린 것을 남길 수 있으니,
|
|
245
|
+
- **프로젝트 메모리**는 채팅의 첫 폴더(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 자체의 메모리를 읽거나 쓰지 않습니다.
|
|
235
246
|
- **백업**은 고정된 폴더 하나, `~/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 아카이브를 자기 보관 개수에 포함하며 그 아카이브를 삭제할 수 있습니다.
|
|
236
247
|
- **복원**은 dsh가 닫혀 있을 때 복구 콘솔에서만 실행되며, dsh 홈 전체를 바꿉니다. 기존 홈은 직접 삭제할 때까지 옆에 `.dsh.pre-restore-<time>`으로 남으므로, 디스크에 둘 다 들어갈 공간이 필요합니다. 채팅은 프로젝트 경로를 그대로 유지합니다. 다른 컴퓨터에서 다른 경로에 있는 프로젝트는 다시 추가할 때까지 없는 것으로 표시됩니다. dsh 홈 밖을 가리키는 심볼릭 링크(예: 다른 폴더에서 링크한 스킬)는 링크로 돌아오며, 그 대상은 그 컴퓨터에 있어야 합니다.
|
|
237
248
|
- **세션 로그 점검**은 무엇이 열리는지에 대한 dsh 자체 규칙으로 각 채팅의 최신 로그를 읽습니다. JSON이 아니거나 순서가 어긋난 행은 그 뒤에 턴 종료가 있을 때만 손상으로 칩니다(그렇지 않으면 dsh는 그 행부터의 내용을 빼고 채팅을 열기 때문에 목록에 나오지 않습니다). 로그의 이벤트를 dsh 자체의 이벤트 규칙과 비교하지는 않으므로, 정상으로 판정한 로그도 dsh 업그레이드 후에 열리지 않을 수 있습니다. 복구는 백업에서 사본을 가져옵니다. 그 백업 이후의 메시지는 그 채팅에서 사라집니다(손상된 파일은 옆에 남음). 이 dsh에서 열려 있는 채팅은 설정에서 복구되지 않습니다. dsh가 그 채팅을 잡고 있기 때문입니다.
|
|
@@ -264,7 +275,7 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
|
|
|
264
275
|
|
|
265
276
|
**loop engineering의 검증 루프처럼, 에이전트가 자기 작업을 스스로 완료로 표시하지 못하게 할 수 있나요?** 네, **목표 확인**(기본적으로 켜짐)으로 가능합니다. `/goal`로 목표를 시작하세요. 에이전트가 목표를 완료했다고 하면 프로젝트의 테스트가 실행되고, 독립적인 모델 호출이 채팅과 비교해 목표를 확인합니다. 둘 중 하나라도 실패하면 목표는 열린 상태로 남고 에이전트가 이유를 읽습니다. 목표 아래의 **목표 확인** 행에 있는 **편집**으로 직접 테스트 명령, 시간 제한, 토큰 제한을 정하세요.
|
|
266
277
|
|
|
267
|
-
**DS Bot의 메모리처럼 에이전트가 채팅이 바뀌어도 내 선호를 기억할 수 있나요?** 네, **프로젝트 메모리**(기본적으로 꺼짐)로 가능합니다. **설정 → Composer Plus**에서 켜세요. 턴이 끝날 때마다 오래 유지되는 선호와 결정이 채팅 프로젝트의 짧은 메모로 저장되고, 그 프로젝트의 새 채팅마다 이를 읽습니다. 에이전트에게 무언가를 기억하라고 하면 바로 저장합니다.
|
|
278
|
+
**DS Bot의 메모리처럼 에이전트가 채팅이 바뀌어도 내 선호를 기억할 수 있나요?** 네, **프로젝트 메모리**(기본적으로 꺼짐)로 가능합니다. **설정 → Composer Plus**에서 켜세요. 턴이 끝날 때마다 오래 유지되는 선호와 결정이 채팅 프로젝트의 짧은 메모로 저장되고, 그 프로젝트의 새 채팅마다 이를 읽습니다. 에이전트에게 무언가를 기억하라고 하면 바로 저장합니다. 메모를 보거나 바꾸려면 같은 줄의 **메모리 열기**를 누르고 바꿀 내용을 적으세요.
|
|
268
279
|
|
|
269
280
|
**dsh-backup처럼 dsh에서 채팅과 설정을 백업할 수 있나요?** 네. **설정 → Composer Plus → 백업 → 지금 백업**을 사용하세요. 같은 아카이브 형식으로 같은 폴더(`~/Desktop/dsh-backups`)에 쓰므로, dsh-backup의 아카이브도 표시되고 복원할 수 있으며, dsh-backup은 삭제해도 됩니다. 정해진 일정으로 백업하려면 **자동 백업**을 켜세요.
|
|
270
281
|
|
|
@@ -304,7 +315,7 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
|
|
|
304
315
|
|
|
305
316
|
**dsh 작업이 끝나거나 승인이 필요할 때 macOS / Windows 알림을 받으려면 어떻게 하나요?** **백그라운드 알림**을 켜 두세요(기본값). 그리고 OS 설정에서 DeepSeek Harness의 알림을 허용하세요.
|
|
306
317
|
|
|
307
|
-
**dsh가 질문하는 채팅을 스스로 열 수 있나요?** 네, **유휴 상태일 때 대기 중인 채팅 열기**(기본으로 켜짐)를 사용하세요. 채팅이 답변, 승인, 계획 검토를 기다리고 있을 때 30초 동안 dsh를 사용하지 않으면 dsh가 그 채팅을 엽니다. 입력하거나 스크롤하거나 마우스를 움직이는 동안에는 기다립니다.
|
|
318
|
+
**dsh가 질문하는 채팅을 스스로 열 수 있나요?** 네, **유휴 상태일 때 대기 중인 채팅 열기**(기본으로 켜짐)를 사용하세요. 채팅이 답변, 승인, 계획 검토를 기다리고 있을 때 30초 동안 dsh를 사용하지 않으면 dsh가 그 채팅을 엽니다. 아직 읽지 않은 턴을 마친 채팅(초록색 점)도 주황색 채팅 다음에 같은 방식으로 열립니다. 입력하거나 스크롤하거나 마우스를 움직이는 동안에는 기다립니다.
|
|
308
319
|
|
|
309
320
|
**DeepSeek Harness 인터페이스를 터키어, 스페인어, 일본어 등으로 바꾸려면 어떻게 하나요?** 설정 → Composer Plus → **애플리케이션 언어**.
|
|
310
321
|
|
|
@@ -343,6 +354,8 @@ PLAYWRIGHT=/path/to/playwright node test/browser-readme-anchors.mjs
|
|
|
343
354
|
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-keep-focus.mjs /path/to/dsh/lib/bin.js
|
|
344
355
|
# Fit question card to window (fake model asks a long question at 1280 × 820): question, answers, Skip and Submit readable, height follows the window + its thumbnail
|
|
345
356
|
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-question-fit.mjs /path/to/dsh/lib/bin.js
|
|
357
|
+
# Fit chat header to window (fake model, subagent + background jobs, branch pill, grants chip): no overlap from 1280 to 320 px, wide header unchanged + its thumbnail
|
|
358
|
+
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-header-fit.mjs /path/to/dsh/lib/bin.js
|
|
346
359
|
# Mobile connect: switch on, QR popover, a fake iPhone pairs and calls dsh through the gateway, switch off + its thumbnail
|
|
347
360
|
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-mobile-connect.mjs /path/to/dsh/lib/bin.js
|
|
348
361
|
# Resume after restart (fake slow model, real quit and start): a running chat and a goal continue, a stopped chat does not
|
package/README.md
CHANGED
|
@@ -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.
|
|
30
|
+
> dsh's pnpm skips versions younger than 24 hours. Right after a release, add the version: `dsh-composer-plus@1.17.0`.
|
|
31
31
|
|
|
32
32
|
## Features
|
|
33
33
|
|
|
@@ -45,6 +45,7 @@ Then restart dsh. (The CLI can't install into the desktop profile; the app manag
|
|
|
45
45
|
| **Shift+Tab plan mode** | <a id="feature-plantoggle"></a>`Shift+Tab` adds `/plan ` to the start of the draft (press again to remove it). If the chat is already in plan mode, `Shift+Tab` leaves it. | <a href="assets/features/planToggle.webp"><img src="assets/features/planToggle.webp" width="160" alt="Screenshot: Shift+Tab plan mode"></a> |
|
|
46
46
|
| **Keep composer focus** | <a id="feature-keepfocus"></a>After you send a `/` command or skill, the cursor stays in the composer, and you can type again at once. This also works for keyboard macros that type a command and press `Enter`. dsh makes the composer read-only while it resolves the command, and the browser then removes the focus. This feature puts the focus back, unless a menu, a dialog or another field has it. | <a href="assets/features/keepFocus.webp"><img src="assets/features/keepFocus.webp" width="160" alt="Screenshot: Keep composer focus"></a> |
|
|
47
47
|
| **Fit question card to window** | <a id="feature-questionfit"></a>When the agent asks you a question, the question and its answers scroll together in the card, and **Skip** and **Submit** stay in view at the bottom. The card uses the height of the window (less 200 px for the chat header and a strip of the chat), so it grows and shrinks with the window. Without this feature, dsh keeps the card at 60% of the window (at most 520 px) and only the answers scroll: a long question can push its own end, the answers and the buttons out of the card. | <a href="assets/features/questionFit.webp"><img src="assets/features/questionFit.webp" width="160" alt="Screenshot: Fit question card to window"></a> |
|
|
48
|
+
| **Fit chat header to window** | <a id="feature-headerfit"></a>In a narrow window, the buttons in dsh's chat header (the mode, subagents, background jobs, Open in, the branch pill and the grants chip) no longer cover each other. The chat title keeps at least 120 px; the buttons that do not fit move to a second line at the right, and each one stays clickable. When everything fits on one line (a wide window), the header is exactly dsh's. Without this feature, dsh shrinks only the title: with a subagent and background jobs, its buttons slide over each other in a narrow chat column. The branch pill (**Branch per chat**) and the grants chip (**Allow for this chat**) also fit the header when this switch is off. | <a href="assets/features/headerFit.webp"><img src="assets/features/headerFit.webp" width="160" alt="Screenshot: Fit chat header to window"></a> |
|
|
48
49
|
| **One-click Continue** | <a id="feature-continuebutton"></a>After a stopped, failed or cut-off turn, an empty composer shows **▶**. One click resumes from the existing conversation without writing in the input or adding a visible chat message (the model receives a short hidden “continue from where it stopped” note, because some providers, such as Claude, reject a request that ends on an assistant reply). Messages that wait in the queue stay there: ▶ continues only the stopped task, then the queue runs. A completed turn keeps the regular Send button. | <a href="assets/features/continueButton.webp"><img src="assets/features/continueButton.webp" width="160" alt="Screenshot: One-click Continue"></a> |
|
|
49
50
|
| **Resume after restart** | <a id="feature-resumeafterrestart"></a>Off by default: switch it on in **Settings → Composer Plus**. If you quit dsh (or it closes) while a chat is working, that chat continues by itself when you open dsh again, with the same hidden note as One-click Continue. If a goal round (`/goal`) was running, the goal goes on with its next round (dsh pauses goals at every start until you resume them). Chats that you stopped, that finished or that failed do not continue. dsh itself has no setting for this: it only marks such a turn as interrupted. | <a href="assets/features/resumeAfterRestart.webp"><img src="assets/features/resumeAfterRestart.webp" width="160" alt="Screenshot: Resume after restart"></a> |
|
|
50
51
|
| **Queue drag-and-drop** | <a id="feature-queuereorder"></a>Queued messages get a grip (⠿). Drag to reorder, or focus the grip and press `↑` / `↓`. `Esc` cancels. | <a href="assets/features/queueReorder.webp"><img src="assets/features/queueReorder.webp" width="160" alt="Screenshot: Queue drag-and-drop"></a> |
|
|
@@ -61,19 +62,22 @@ Then restart dsh. (The CLI can't install into the desktop profile; the app manag
|
|
|
61
62
|
| **Branches in the workspace tree** | <a id="feature-branchtree"></a>Settings → Composer Plus → **Branches in the workspace tree** (off by default). Each branch that has a worktree folder in `<project>/.worktrees/` then shows as a project inside its project; choose dsh's **View options** → **Workspace Tree** to see it nested. A branch whose folder is deleted leaves the list, and dsh shows its chats under **Ungrouped**. When the agent of a chat in the project folder creates a branch and switches to it (`git switch -c`, `git checkout -b`) while the folder has no uncommitted changes, the project folder goes back to its branch, the branch gets its own folder, and the chat moves into it: a copy opens in the branch project and goes on with the task, and the old chat is archived. The list is checked at start, every 30 seconds, after each turn and when you come back to the window. | <a href="assets/features/branchTree.webp"><img src="assets/features/branchTree.webp" width="160" alt="Screenshot: Branches in the workspace tree"></a> |
|
|
62
63
|
| **Next message prediction** | <a id="feature-nextprediction"></a>On by default; switch it off in **Settings → Composer Plus**. When the agent finishes a turn (not a stopped or failed one), the empty composer shows a guess of your next message in grey, with a **Tab to accept** hint. `Tab` puts the text in the composer, but does not send it. `Esc` hides it for that turn. Typing also hides it, and a new turn replaces it. The **Model** menu under the switch lists dsh's own models (the same list as dsh's model menu). **dsh default** is selected by default and follows dsh's default model. Each finished turn costs one short model call. In Tether, the guess shows above the empty composer: tap it to put it in the field. | <a href="assets/features/nextPrediction.webp"><img src="assets/features/nextPrediction.webp" width="160" alt="Screenshot: Next message prediction"></a> |
|
|
63
64
|
| **Complete while typing** | <a id="feature-typingcompletion"></a>Off by default; switch it on in **Settings → Composer Plus**. While you type, grey text right after the cursor shows how your message may go on. `Tab` adds it to the message, but does not send it. `Esc` hides it. It suggests only your own next words: never an answer to you, and no made-up error texts or names. When the message looks complete or the model is not sure, nothing shows. Typing the next letters of the grey text keeps it, with no new model call. It has its own **Model** menu under its switch. Its first entry, **Same as Next message prediction**, uses the model of **Next message prediction** (the default); pick another model to use a different one for each feature, for example a faster model for completions. It makes one model call at each pause while you type, so it uses many more tokens than the prediction: pick a fast, low-cost model. It does not run for a slash command, a message with a file chip, or when the cursor is not at the end. In Tether, the rest shows above the field while you type: tap it to add it. | <a href="assets/features/typingCompletion.webp"><img src="assets/features/typingCompletion.webp" width="160" alt="Screenshot: Complete while typing"></a> |
|
|
64
|
-
| **Improve prompt** | <a id="feature-promptimprove"></a>Type a rough request, then click the magic wand (**Improve prompt**) next to the model menu. One model call rewrites it as a clearer prompt: the goal first, short numbered steps when there are several parts, and the check to run. It reads this chat (rolled-back messages left out), the project's README, AGENTS.md and manifest, the changed files and the files whose names match your words, and keeps your language. It never makes up file names. The new text replaces your draft but is not sent: read it, edit it, then press `Enter`. `Cmd/Ctrl+Z` brings your text back in one step, and so does the button (**Undo improvement**). If you type while it works, your new text stays. `Esc` or a second click cancels. It has its own **Model** menu in Settings (default: **Same as the chat's model**). Not for slash commands or a message with a file chip. In Tether, the wand is next to the field. | <a href="assets/features/promptImprove.webp"><img src="assets/features/promptImprove.webp" width="160" alt="Screenshot: Improve prompt"></a> |
|
|
65
|
-
| **Goal check** | <a id="feature-goalcheck"></a>Start a goal with `/goal`. When the agent marks the goal complete in an automatic round, the goal closes only after two checks. First, the project's test command runs in the chat's folder, under the chat's sandbox mode. The command is your own one or the one found in `package.json`, `Makefile`, `Cargo.toml`, `go.mod` or pytest. When the agent's own newest step was a passing run of that test, it does not run again. Then one independent model call, with no tools, reads the goal, this chat, `git status` and the test result. If a check fails, the goal stays active and the agent reads
|
|
66
|
-
| **
|
|
65
|
+
| **Improve prompt** | <a id="feature-promptimprove"></a>Type a rough request, then click the magic wand (**Improve prompt**) next to the model menu. One model call rewrites it as a clearer prompt: the goal first, short numbered steps when there are several parts, and the check to run. It reads this chat (rolled-back messages left out), the project's README, AGENTS.md and manifest, the changed files and the files whose names match your words, and keeps your language. It never makes up file names. The new text replaces your draft but is not sent: read it, edit it, then press `Enter`. `Cmd/Ctrl+Z` brings your text back in one step, and so does the button (**Undo improvement**). If you type while it works, your new text stays. `Esc` or a second click cancels. It has its own **Model** menu in Settings (default: **Same as the chat's model**). On a `/goal <objective>` message it rewrites only the objective, as a completion condition that **Goal check** can verify: the outputs, the checks that must pass, the evidence to show in the chat, a part that cannot be done marked as unresolved, and a stop when the same blocker stays. The `/goal` command stays. Not for other slash commands, a `/goal` control word (`clear`, `pause`, `resume`) or a message with a file chip. In Tether, the wand is next to the field. | <a href="assets/features/promptImprove.webp"><img src="assets/features/promptImprove.webp" width="160" alt="Screenshot: Improve prompt"></a> |
|
|
66
|
+
| **Goal check** | <a id="feature-goalcheck"></a>Start a goal with `/goal`. When the agent marks the goal complete in an automatic round, the goal closes only after two checks. First, the project's test command runs in the chat's folder, under the chat's sandbox mode. The command is your own one or the one found in `package.json`, `Makefile`, `Cargo.toml`, `go.mod` or pytest. When the agent's own newest step was a passing run of that test, it does not run again. Then one independent model call, with no tools, reads the goal, this chat, `git status` and the test result. The model answers with an evidence table: each part of the goal is verified, incorrect or unresolved, with the evidence and the fix; the goal closes only when every part is verified. If a check fails, the goal stays active and the agent reads each open part with its evidence and fix, then the next round goes on. A row under the goal bar (**Goal check**) shows the test, the last result and how many parts were verified (hover it for the table). **Edit** sets your own test command and a time or token limit; over the limit the goal becomes blocked. The token limit also counts the chat's subagents. **Run now** runs the check without closing the goal. It has its own **Model** menu in Settings (default: **Same as the chat's model**). When you complete the goal yourself, nothing is checked. | <a href="assets/features/goalCheck.webp"><img src="assets/features/goalCheck.webp" width="160" alt="Screenshot: Goal check"></a> |
|
|
67
|
+
| **Continue in a new chat** | <a id="feature-handoffchat"></a>Right-click a chat in the sidebar (or open its **…** menu) → **Continue in a new chat…**. One call to the chat's own model writes a handoff note from the chat: Task, Outputs, Completed, Decisions, Open issues and Next action, from what the chat shows (tool calls and results are the evidence; steps that you rolled back are left out). The note opens in a dialog: read it and edit it. **Write again** writes a new note. **Start new chat** (or `Cmd/Ctrl+Enter`) opens a new chat in the same project with the note and a link to the old chat as its first message; the old chat stays as it is. Use it when a long chat is full or slow, or to continue tomorrow. Nothing is written to the project. | <a href="assets/features/handoffChat.webp"><img src="assets/features/handoffChat.webp" width="160" alt="Screenshot: Continue in a new chat"></a> |
|
|
68
|
+
| **Context breakdown** | <a id="feature-contextbreakdown"></a>Right sidebar → `+` → **Context**. The page shows what fills the open chat's model context now and how much of the context window it uses: the system prompt, project instructions (AGENTS.md), skills, your messages, agent replies and tool calls, tool results (by tool), MCP results (by server), tool definitions, the compact summary and other context notes, each with its tokens and its share. Click a part to see its tools or servers. It reads the chat log only, after `/compact` and rollbacks, and calls no model; it reads again after each turn and with **Refresh**. Use it to see why a chat is slow or full, for example a big MCP tool result or many tool definitions. | <a href="assets/features/contextBreakdown.webp"><img src="assets/features/contextBreakdown.webp" width="160" alt="Screenshot: Context breakdown"></a> |
|
|
69
|
+
| **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> |
|
|
70
|
+
| **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> |
|
|
67
71
|
| **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> |
|
|
68
72
|
| **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> |
|
|
69
|
-
| **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
|
|
73
|
+
| **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> |
|
|
70
74
|
| **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> |
|
|
71
75
|
| **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> |
|
|
72
76
|
| **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> |
|
|
73
77
|
| **Collapse all projects** | <a id="feature-collapseprojects"></a>While a project is open in the sidebar, a button appears next to the view options (sliders icon). Click it to close every open project at once, for example 3 open projects out of 5. The button hides again when no project is open. | <a href="assets/features/collapseProjects.webp"><img src="assets/features/collapseProjects.webp" width="160" alt="Screenshot: Collapse all projects"></a> |
|
|
74
78
|
| **Order by status** | <a id="feature-statusorder"></a>Sidebar → view options → **Order by** → **By status** (with **In one list**). Finished chats come first (dsh's “done” dot, which a turn that ended with an error also gets), then running or waiting chats, then chats with an active automation (Schedule), then the rest in dsh's order. Opening a finished chat moves it down. Only the view changes: select **Manual** or **Last updated** to go back. | <a href="assets/features/statusOrder.webp"><img src="assets/features/statusOrder.webp" width="160" alt="Screenshot: Order by status"></a> |
|
|
75
79
|
| **Background notifications** | <a id="feature-notifications"></a>While dsh is in the background you get a notification when a turn finishes (first line of the reply), or when a chat really waits for you: an approval (tool name), an answer (the question) or a plan review. A request must still be open 1.5 s later, so approvals answered automatically (Auto Review grants, other plugins) stay silent, and a notification is withdrawn as soon as its request is answered. The Dock/taskbar badge counts waiting chats. Clicking opens that chat. | <a href="assets/features/notifications.webp"><img src="assets/features/notifications.webp" width="160" alt="Screenshot: Background notifications"></a> |
|
|
76
|
-
| **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), and you do not use dsh for 30 seconds, dsh opens that chat.
|
|
80
|
+
| **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> |
|
|
77
81
|
| **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> |
|
|
78
82
|
| **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> |
|
|
79
83
|
| **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> |
|
|
@@ -158,7 +162,10 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
|
|
|
158
162
|
- **Complete while typing:** off until you switch it on. While it is on, at each pause while you type, the Host half sends the text that you typed so far and the chat's own user messages and agent text replies (no tool output, no hidden context, no reasoning), at most about 3,000 characters of chat, to the model chosen under **Complete while typing** (by default the model of **Next message prediction**). A newer pause stops the older request. Nothing is saved in the chat. The switch is in `$DSH_HOME/storages/dsh-composer-plus/complete.json` (owner-only file).
|
|
159
163
|
- **Improve prompt:** nothing runs until you click the magic wand. Then the Host half sends your draft, the chat's own user messages and agent text replies (no tool output, no hidden context, no reasoning, no rolled-back messages; at most about 6,000 characters, the newest part), the same project summary as **Feature ideas** (with the same file rules: no `.env*` or key files, no symlink out of the folder, no FIFO), the paths that `git status` lists as changed and up to 30 tracked or untracked (not ignored) paths whose names share words with your draft, to the model chosen under **Improve prompt** (by default the chat's own model), as one request. File contents other than that summary are not sent. Nothing is written to the chat or the project: the answer only replaces your draft in the composer, and you decide whether to send it. The model choice is in `$DSH_HOME/storages/dsh-composer-plus/improve.json` (owner-only file).
|
|
160
164
|
- **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).
|
|
161
|
-
- **
|
|
165
|
+
- **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.
|
|
166
|
+
- **Context breakdown:** reads only the chat log on the Host; no model call, no project file.
|
|
167
|
+
- **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.
|
|
168
|
+
- **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.
|
|
162
169
|
- **Backup:** nothing leaves your machine. Archives go to `~/Desktop/dsh-backups` (owner-only files). Secrets are not in an archive: credential files (`.credentials.yaml`, `.env`), key files (`.pem`, `.key`, `.p12`, `.pfx`) and the values of token, secret, password and API key settings in the yml files are masked; their real copies stay in `composer-plus-vault/<archive>/` in the same folder (owner-only), on this computer only. **For another computer** copies no vault: enter those secrets again there. Your chat logs, settings and the rest of the dsh home are in the archive as they are: keep the folder private, as `$DSH_HOME` itself. The backup reads files with `O_NOFOLLOW | O_NONBLOCK`; a symbolic link is stored as a link (never followed) and a FIFO or device is skipped. The automatic backup switch and settings are in `$DSH_HOME/storages/dsh-composer-plus/auto-backup.json`, the rescue console switch in `rescue-console.json`, and while dsh runs, `running/host-<pid>.json` names each dsh process (the rescue console reads them to refuse a restore).
|
|
163
170
|
- **Rescue console:** a terminal menu; it opens no network port. A restore writes only into a new folder next to the dsh home (files with `O_EXCL | O_NOFOLLOW`, symbolic links last and never followed) and refuses an archive with an unsafe name (`..`, an absolute path), a device or FIFO, more than one top folder or an entry below a link.
|
|
164
171
|
|
|
@@ -180,7 +187,7 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
|
|
|
180
187
|
- **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).
|
|
181
188
|
- **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.
|
|
182
189
|
- **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).
|
|
183
|
-
- **Install fails right after a release:** add the version (`dsh-composer-plus@1.
|
|
190
|
+
- **Install fails right after a release:** add the version (`dsh-composer-plus@1.17.0`), see the install note above.
|
|
184
191
|
- **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.
|
|
185
192
|
- **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.
|
|
186
193
|
- **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.
|
|
@@ -203,6 +210,7 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
|
|
|
203
210
|
- **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.
|
|
204
211
|
- **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.
|
|
205
212
|
- **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.
|
|
213
|
+
- **Fit chat header to window** finds dsh's chat header by its generated class names (`_titleRow`, `_titleCluster`, `_crumbs`, `_headerActions`, `_headerUtilities`), because dsh has no layout hook for it. If a dsh update renames them, the header shows as dsh draws it. In a very narrow chat column the header can take two or three lines, so the chat area above the messages gets lower.
|
|
206
214
|
- **Mobile connect** works on macOS only (it uses `en0`, `openssl`, `swift` and `dns-sd`). It uses fixed ports 19390 and 19391, so only one dsh on each Mac can run it at a time (each Mac is one entry in the phone's Mac list). The phone gets notifications only while Tether is open or just went to the background (no push service). Tether sends them only after you switch on **Settings → Notifications → Send notifications** in Tether. This switch is off by default, and iOS asks for the permission when you switch it on. The iOS app is not on the App Store yet: build it from `tether/ios` with Xcode. **Tailscale only** still needs a Wi-Fi or Ethernet address on the Mac (the gateway starts only with one). The access log is per Mac and keeps only the newest 200 attempts; a repeated attempt within a minute counts up one row. Tether's app lock does not hide notification previews on the iPhone Lock Screen: turn them off in iOS Settings. Tether's green dots follow the Mac: a chat that you open in dsh loses its dot on the phone too. A chat that you open in Tether loses its dot on the phones only; dsh's own dot on the Mac stays until you open the chat there.
|
|
207
215
|
- A session link works inside chats; clicking it does not open the chat. A **Copy message link** link opens its message only on dsh 0.2.1 and later, and only from a message in a chat (dsh 0.2.0 has no user-text rules, so there the link is copied but shows as plain text). A message that a rollback took out, or that compaction removed from the history that dsh loads, cannot be shown: the link then says so. The 🔗 buttons attach to dsh's message rows; if a dsh update changes that markup, they do not show.
|
|
208
216
|
- **Mark all as read** changes dsh's own unread dots through a part of dsh that is not a public API (the `completionUnread` list of dsh's session status). If a dsh update renames it, the item does not show. The item goes into dsh's project "…" menu, which has no slot for plugins; if dsh changes that menu, the item does not show either.
|
|
@@ -214,10 +222,10 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
|
|
|
214
222
|
- **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.
|
|
215
223
|
- **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”.
|
|
216
224
|
- **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.
|
|
217
|
-
- **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.
|
|
225
|
+
- **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").
|
|
218
226
|
- **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.
|
|
219
227
|
- **Find in chat** searches only what the page shows: the messages and replies that are loaded (scroll up or click **Load earlier** for older ones), not tool steps that are closed and not the text inside a tool's output that is folded. It counts at most 2,000 matches (then "2000+"). It uses the browser's highlight API (Chromium 105 and later; the desktop app has it): in an older browser the count and the moves work without the color. `Cmd+F` on a Mac (`Ctrl+F` on Windows and Linux) opens it only while a chat is on screen; elsewhere the browser's own find works as before. On a Mac, `Ctrl+F` keeps its macOS use in text fields (the cursor moves one character forward).
|
|
220
|
-
- **Open waiting chat when idle** knows only what dsh's own window sees: work in another app does not count, so while dsh is in the background it can open a waiting chat after 30 seconds. It does not bring dsh to the front. Reading without a key, a click or a mouse move counts as idle. It looks only at chats with dsh's orange dot (a question, an approval or a plan review); a subagent's request shows in its parent chat. Nothing opens while a waiting chat is on screen; a chat that you left without an answer can open again after the next 30 seconds without use. The 30 seconds cannot be changed.
|
|
228
|
+
- **Open waiting chat when idle** knows only what dsh's own window sees: work in another app does not count, so while dsh is in the background it can open a waiting chat after 30 seconds. It does not bring dsh to the front. Reading without a key, a click or a mouse move counts as idle. It looks only at chats with dsh's orange dot (a question, an approval or a plan review) or green dot (a finished turn that you have not opened); a subagent's request shows in its parent chat. Orange chats open first. Opening a green chat removes its dot, so the next green chat waits for your next key, click, mouse move, scroll wheel or touch before its 30 seconds start: when you come back, the other green dots are still there. Nothing opens while a waiting chat is on screen; a chat that you left without an answer can open again after the next 30 seconds without use. The 30 seconds cannot be changed.
|
|
221
229
|
- A notification sent before a restart only brings dsh to the front when clicked.
|
|
222
230
|
- Active projects are moved with dsh's saved project order, so the new order is kept after a restart. Chats outside any project ("Ungrouped") can't be moved; dsh always lists them last.
|
|
223
231
|
- dsh has no extension point in the sidebar's view options menu, so the recent projects option is added to dsh's own menu. If a dsh update changes that menu, the option is not shown and all projects stay visible. The filter works on project rows, so **In one list** is not filtered. In **Workspace Tree**, a parent folder stays while a project inside it is active, and the chat rows that were not active in the last 2 hours hide too; in **WorkSpace**, only project rows are filtered. The filter reads which view dsh shows from dsh's saved view setting (not a public API); if a dsh update renames it, **Workspace Tree** is filtered like **WorkSpace**. Project status reads the same setting: in **Workspace Tree**, a parent folder's row also counts the chats of the projects inside it; if dsh renames the setting, each row shows only its own chats. **By status** has the same kind of limit: dsh has no order slot, so the item and the row order attach to dsh's menu and list markup.
|
|
@@ -226,10 +234,13 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
|
|
|
226
234
|
- dsh has no hook that chooses where **New session** opens either. **Default workspace for New session** wraps a method of dsh that is not a public API (`startSession` of dsh's workspace service). If a dsh update renames it, **New session** opens where dsh chooses (the open or the most recent project). Every call that names no project uses the default: the sidebar button, its shortcut, the logo, and also **New** on the **Automation tasks** page. dsh still opens the last chat when it starts. The general folder is made and added to your projects at the first use; on Windows or Linux with a moved Documents folder it can be a different folder from dsh's own.
|
|
227
235
|
- dsh has no extension point for a composer hint either, so the **Next message prediction** text sits over dsh's own placeholder (`[data-composer-placeholder]`). If a dsh update changes that markup, no prediction shows. While it is on, each finished turn costs one short model call.
|
|
228
236
|
- **Complete while typing** shows its text through dsh's own composer hint (the `--dsh-composer-hint` style that dsh uses for a slash command's argument hint). It does not run for a slash command, a message with a file or symbol chip, or when the cursor is not at the end of the message. If a dsh update changes that style, no completion shows. Each pause while you type costs one model call.
|
|
229
|
-
- **Improve prompt** sees only a short project summary, the changed paths and the paths whose names match your words: not the code itself. So it can miss the right file, and it names only paths that it was given. Read the new text before you send it. It does not run for a slash command or a message with a file or symbol chip (the new text is plain text, so it would lose the chip), and a message can have at most 8,000 characters. Images stay attached: only the text changes. Each click costs one model call; a strong model can take a minute (`Esc` cancels).
|
|
230
|
-
- **Goal check** checks only a completion that the agent makes in an automatic goal round: a completion that you ask for in the chat, `/goal` and the goal bar are not checked. The agent can change the tests or the test command's files itself; the verifier reads the chat and can see that, but it can be wrong in both directions (a wrong "not done" costs one more round; a wrong "done" closes the goal). The verifier sees the chat and `git status`, not the code itself. A test run is reused only when the agent's newest step that can change files was its own passing `bash` run of exactly the same command in the same folder; a command with a pipe (`| tail`) or `&&` is not reused. The budget is measured when a turn ends, so one turn can go past it.
|
|
237
|
+
- **Improve prompt** sees only a short project summary, the changed paths and the paths whose names match your words: not the code itself. So it can miss the right file, and it names only paths that it was given. Read the new text before you send it. It does not run for a slash command other than `/goal <objective>`, for a `/goal` control word (`clear`, `pause`, `resume`) or for a message with a file or symbol chip (the new text is plain text, so it would lose the chip), and a message can have at most 8,000 characters. For a `/goal` objective it writes conditions only from the draft and the context; a condition that is too strict can cost goal rounds, so read it before you send it. Images stay attached: only the text changes. Each click costs one model call; a strong model can take a minute (`Esc` cancels).
|
|
238
|
+
- **Goal check** checks only a completion that the agent makes in an automatic goal round: a completion that you ask for in the chat, `/goal` and the goal bar are not checked. The agent can change the tests or the test command's files itself; the verifier reads the chat and can see that, but it can be wrong in both directions (a wrong "not done" costs one more round; a wrong "done" closes the goal). The verifier sees the chat and `git status`, not the code itself. A test run is reused only when the agent's newest step that can change files was its own passing `bash` run of exactly the same command in the same folder; a command with a pipe (`| tail`) or `&&` is not reused. The budget is measured when a turn ends, so one turn can go past it. The token budget also counts the calls of the chat's subagent chats (read from their saved logs at each turn end, so a chat with many subagents takes a little longer to check). The evidence table comes from the verifier's own reading of the chat: a part that it calls verified still needs your own look when it matters. `update_goal` waits while the check runs (the test at most 15 minutes, the verifier at most 3 minutes). A fork gets a new chat id, so it starts without the parent's own test command and limits. Each completion that reaches the verifier costs one model call.
|
|
239
|
+
- **Protected files** is a guard rail, not a sandbox. It covers dsh's own file tools (`read`, `read_image`, `grep` on a file, `write`, `edit`, `str_replace_editor`). A shell command (`cat .env`), a script that the agent writes, a subagent's shell, an MCP tool, a `glob` listing and a `grep` over a whole folder can still reach a protected file. For a real limit, use dsh's sandbox modes or keep secrets out of the project folder. Patterns know `*`, `**` and `?`, not `{a,b}` or `[ab]`, and they ignore letter case.
|
|
240
|
+
- **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.
|
|
241
|
+
- **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.
|
|
231
242
|
- **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.
|
|
232
|
-
- **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;
|
|
243
|
+
- **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.
|
|
233
244
|
- **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.
|
|
234
245
|
- **Restore** runs only in the rescue console, while dsh is closed: it replaces the whole dsh home. The old one stays next to it as `.dsh.pre-restore-<time>` until you remove it, so the disk needs room for both. Chats keep their project paths: on another computer, a project at another path shows as missing until you add it again. Symbolic links that point outside the dsh home (for example skills linked from another folder) come back as links; their targets must exist on that computer.
|
|
235
246
|
- **Session log check** reads the newest log of each chat with dsh's own rules for what opens: a row that is not JSON or is out of order counts as damage only when a turn end comes after it (else dsh opens the chat without the rows from there, so it is not listed). It does not check a log's events against dsh's own event rules, so a log that it calls healthy can still fail to open after a dsh upgrade. A repair takes the copy from a backup: the messages after that backup are lost from that chat (the damaged file stays next to it). A chat that is open in this dsh is not repaired in Settings: dsh holds it.
|
|
@@ -262,7 +273,7 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
|
|
|
262
273
|
|
|
263
274
|
**Can the agent stop marking its own work as done, like the verifier loops in loop engineering?** Yes, with **Goal check** (on by default): start a goal with `/goal`. When the agent says the goal is complete, the project's tests run and an independent model call checks the goal against the chat; if either fails, the goal stays open and the agent reads why. Set your own test command, a time limit or a token limit with **Edit** in the **Goal check** row under the goal.
|
|
264
275
|
|
|
265
|
-
**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.
|
|
276
|
+
**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.
|
|
266
277
|
|
|
267
278
|
**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.
|
|
268
279
|
|
|
@@ -302,7 +313,7 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
|
|
|
302
313
|
|
|
303
314
|
**How do I get macOS / Windows notifications when a dsh task finishes or needs approval?** Keep **Background notifications** on (default) and allow notifications for DeepSeek Harness in the OS settings.
|
|
304
315
|
|
|
305
|
-
**Can dsh open the chat that asks me a question by itself?** Yes, with **Open waiting chat when idle** (on by default): when a chat waits for an answer, an approval or a plan review and you do not use dsh for 30 seconds, dsh opens it. While you type, scroll or move the mouse, it waits.
|
|
316
|
+
**Can dsh open the chat that asks me a question by itself?** Yes, with **Open waiting chat when idle** (on by default): when a chat waits for an answer, an approval or a plan review and you do not use dsh for 30 seconds, dsh opens it. A chat that finished a turn that you have not read (the green dot) opens the same way, after the orange ones. While you type, scroll or move the mouse, it waits.
|
|
306
317
|
|
|
307
318
|
**How do I switch the DeepSeek Harness interface to Turkish, Spanish, Japanese…?** Settings → Composer Plus → **Application language**.
|
|
308
319
|
|
|
@@ -341,6 +352,8 @@ PLAYWRIGHT=/path/to/playwright node test/browser-readme-anchors.mjs
|
|
|
341
352
|
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-keep-focus.mjs /path/to/dsh/lib/bin.js
|
|
342
353
|
# Fit question card to window (fake model asks a long question at 1280 × 820): question, answers, Skip and Submit readable, height follows the window + its thumbnail
|
|
343
354
|
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-question-fit.mjs /path/to/dsh/lib/bin.js
|
|
355
|
+
# Fit chat header to window (fake model, subagent + background jobs, branch pill, grants chip): no overlap from 1280 to 320 px, wide header unchanged + its thumbnail
|
|
356
|
+
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-header-fit.mjs /path/to/dsh/lib/bin.js
|
|
344
357
|
# Mobile connect: switch on, QR popover, a fake iPhone pairs and calls dsh through the gateway, switch off + its thumbnail
|
|
345
358
|
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-mobile-connect.mjs /path/to/dsh/lib/bin.js
|
|
346
359
|
# Resume after restart (fake slow model, real quit and start): a running chat and a goal continue, a stopped chat does not
|