dsh-composer-plus 1.24.0 → 1.25.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.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.24.0`.
32
+ > dsh의 pnpm은 게시된 지 24시간이 지나지 않은 버전을 건너뜁니다. 릴리스 직후에는 버전을 붙여서 설치하세요: `dsh-composer-plus@1.25.0`.
33
33
 
34
34
  ## 기능
35
35
 
@@ -75,7 +75,11 @@ dsh plugin --profile web add dsh-composer-plus
75
75
  | **보호된 파일** | <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> |
76
76
  | **차단된 명령** | <a id="feature-blockedcommands"></a>기본적으로 켜져 있으며, 목록은 비어 있습니다. 에이전트의 셸 명령(`bash`, `pwsh`)은 지정한 규칙과 일치하는 명령을 실행할 수 없습니다. **차단** 규칙은 호출을 거부하고(에이전트는 이유를 읽고 사용자에게 물어보라는 안내를 받습니다), **먼저 묻기** 규칙은 dsh의 승인 카드를 표시하며, 명령은 사용자가 허용할 때만 실행됩니다. 설정 → Composer Plus → **차단된 명령**: 규칙을 입력하고(예: `npm publish`, `git push --force` 또는 `ssh *192.168.2.19`), 종류를 클릭해 **차단**과 **먼저 묻기** 사이에서 전환한 뒤 **추가**를 클릭하세요. 규칙의 종류를 클릭하면 바꿀 수 있고, ✕로 삭제할 수 있습니다. 규칙은 명령 이름과 그 뒤에 이 순서로 와야 하는 단어입니다. `*`는 모든 텍스트와 일치합니다. `&&`, `;`, `\|` 뒤, `$(…)`, `bash -c "…"` 또는 `eval` 안, `sudo`나 `env` 뒤에 있는 명령도 찾습니다. 이것은 가드레일이며 샌드박스가 아닙니다. 변수(`$CMD`), 스크립트 파일, 다른 프로그램은 여전히 명령을 실행할 수 있습니다(제한 사항 참고). | <a href="assets/features/blockedCommands.webp"><img src="assets/features/blockedCommands.webp" width="160" alt="스크린샷: 차단된 명령"></a> |
77
77
  | **작업 보드** | <a id="feature-taskboard"></a>왼쪽 사이드바 → **작업 보드**. dsh 어디서나 `Cmd+Shift+K`(Windows와 Linux에서는 `Ctrl+Shift+K`)를 눌러도 열립니다. 사이드바와 같은 실시간 상태를 보여 주는 dsh 채팅의 칸반 보드입니다. 승인, 답변 또는 계획 검토를 기다리는 채팅은 주황색 점과 함께 **검토**에, 실행 중인 채팅은 **진행 중**에, 아직 열지 않은 끝난 채팅은 **완료**에 있습니다(초록색). 채팅을 열면 그 카드는 **완료**에서 저절로 빠집니다. 초록색 카드 아래의 **최근 완료 (N)**을 클릭하면 읽은 끝난 채팅을 볼 수 있습니다(최신 10개, 그다음 **이전 작업 N개 보기**; 열림/닫힘 상태는 이 기기에 저장됩니다). 보드 뒤에서 열린 채로 끝난 채팅(**새 작업**)은 열 때까지 초록색으로 남습니다. 보드 위쪽의 프로젝트 이름을 클릭하면 프로젝트 목록이 열립니다. 여기서 프로젝트나 **모든 프로젝트**를 고르세요. 채팅별 브랜치 폴더는 해당 프로젝트로 취급됩니다. 목록은 고른 뒤, `Esc`를 누르거나 목록 밖을 클릭하면 닫힙니다. 목록 맨 위의 **프로젝트 검색**에 입력하면 이름으로 프로젝트를 찾을 수 있습니다(대소문자와 악센트는 구분하지 않으며, `Esc`를 누르면 입력란이 비워집니다). `Enter`를 누르면 첫 번째로 일치하는 프로젝트가 선택됩니다. **최근 2시간 내 활성**을 클릭하면 대기 중이거나 실행 중인 채팅, 확인하지 않은 채 끝난 채팅 또는 최근 2시간 안에 바뀐 채팅이 있는 프로젝트만 표시됩니다(이 설정은 이 기기에 저장됩니다). **새 작업**(또는 `n`)은 보드가 보여 주는 프로젝트에서 dsh 자체의 새 채팅을 엽니다(**모든 프로젝트**일 때는 dsh의 새 세션이 고르는 프로젝트). 그래서 다른 채팅에서처럼 파일을 추가하고, 명령을 쓰고, 모델을 고를 수 있습니다. 첫 메시지를 보내면 자동으로 보드로 돌아옵니다. 그때까지 채팅은 **진행 중**의 맨 위에서 **새 작업**으로 기다립니다. 클릭해서 첫 메시지를 쓰세요. 응답을 기다리는 채팅이 있는 프로젝트에는 프로젝트 목록에서 주황색 점이 붙습니다(어느 채팅이든 기다리는 동안에는 위쪽 프로젝트 이름에도 붙습니다). dsh가 채팅 이름을 짓고 채팅의 모델이 그 메시지에서 태그를 최대 3개 씁니다. 카드를 클릭하면 채팅이 열립니다. 주황색 카드(또는 그 카드의 **답변**)를 클릭하면 보드에서 바로 답할 수 있습니다. 채팅 전체는 패널의 **채팅 열기**로 엽니다. 승인 요청에는 **거부** 또는 **한 번 허용**, 계획에는 **승인** 또는 **변경 요청**, 질문에는 선택지와 직접 쓴 텍스트로 답합니다. 끝난 카드에서 **×** 버튼을 클릭하면 그 카드를 보드에서 뺍니다. **최근 완료**를 열고 **완료** 맨 위의 **모두 빼기**를 클릭하면 그 카드들을 보드에서 뺍니다. 먼저 어느 프로젝트의 카드가 몇 개 빠지는지 보여 주며, 읽지 않은(초록색) 카드는 남습니다. 그 뒤 8초 동안 **실행 취소**를 누르면 카드가 돌아옵니다. **완료** 아래의 **뺀 카드 (N)**에는 보드에서 뺀 카드가 나열되고, **보드에 되돌리기**는 그중 하나를 다시 **완료**에 표시합니다. 채팅은 삭제되지 않습니다. 채팅은 dsh의 사이드바에 남고, 보드는 다시 시작한 뒤에도 이를 기억하며(Tether도 같은 보드를 보여 줍니다), 다시 실행되는 채팅은 보드로 돌아옵니다. **진행 중**의 카드를 가리키면(또는 키보드 포커스를 옮기면) 진행 상황을 볼 수 있습니다. 실행된 시간, 할 일 목록의 단계, 지금 실행 중인 도구, 에이전트의 마지막 줄이 표시됩니다. 설정 → Composer Plus → 작업 보드의 **마우스를 올리면 진행 상황 표시**에서 **빠름(AI 없음)**(기본값: 채팅만 읽음) 또는 **AI 요약**(채팅의 모델을 한 번 짧게 호출해 한두 문장도 씀)을 고릅니다. | <a href="assets/features/taskBoard.webp"><img src="assets/features/taskBoard.webp" width="160" alt="스크린샷: 작업 보드"></a> |
78
- | **어시스턴트** | <a id="feature-assistant"></a>기본적으로 꺼져 있습니다. **설정 → Composer Plus**에서 켜세요. 그다음 왼쪽 사이드바에서 **어시스턴트**(**작업 보드** 바로 아래)를 클릭하세요. ChatGPT나 Grok 채팅처럼 개인 어시스턴트로 쓰는, 오래 유지되는 채팅 하나가 열립니다. 첫 클릭은 `~/Assistant` 폴더를 만들고, 이를 “Assistant” 프로젝트로 추가하고, workspace-write 권한 모드와 dsh의 기본 모델로 채팅을 시작합니다. 이후의 클릭은 매번 같은 채팅을 엽니다(보관된 채팅은 돌아오고, 삭제된 채팅은 다시 만들어집니다). 미리 알림을 부탁하면(“2분 뒤에 물 마시라고 알려 줘”) dsh의 예약 작업을 사용합니다. 그래서 그 시각에 미리 알림이 채팅을 실행하고, 모바일 연결이 켜져 있으면 Tether가 “Turn finished” 알림을 보냅니다. 웹 검색을 부탁하거나 다른 채팅에 대해 물어볼 수도 있습니다. 모든 프로젝트의 채팅(실행 중, 사용자를 기다림, 유휴)을 나열하고 한 채팅의 최신 메시지를 읽을 수 있습니다. 또한 채팅에 메시지를 보내고, 프로젝트에서 새 채팅을 시작하고, 실행 중인 채팅을 중지하거나 채팅을 보관할 수 있습니다. 이 네 가지 작업은 각각 먼저 dsh의 승인 카드를 보여 주며(Tether에서도), **한 번 허용**을 클릭하기 전에는 아무 일도 일어나지 않습니다. 삭제 도구는 없습니다. 이 도구와 짧은 지침은 이 채팅에만 있습니다. 웹 페이지나 다른 채팅에서 읽은 텍스트는 명령이 아니라 데이터로 취급됩니다. 매번 알려 주는 대신 프로필을 이 프로젝트의 메모리(**프로젝트 메모리**, 주제 “profil”)에 저장해 두세요. | <a href="assets/features/assistant.webp"><img src="assets/features/assistant.webp" width="160" alt="스크린샷: 어시스턴트"></a> |
78
+ | **어시스턴트** | <a id="feature-assistant"></a>기본적으로 켜져 있습니다(**설정 → Composer Plus**에서 끌 수 있습니다). 왼쪽 사이드바에서 **어시스턴트**(**작업 보드** 바로 아래)를 클릭하세요. ChatGPT나 Grok 채팅처럼 개인 어시스턴트로 쓰는, 오래 유지되는 채팅 하나가 열립니다. 첫 클릭은 `~/Assistant` 폴더를 만들고, 이를 “Assistant” 프로젝트로 추가하고, workspace-write 권한 모드와 dsh의 기본 모델로 채팅을 시작합니다. 이후의 클릭은 매번 같은 채팅을 엽니다(보관된 채팅은 돌아오고, 삭제된 채팅은 다시 만들어집니다). 채팅에 아직 메시지가 없으면 입력란 위에 짧은 카드가 나타나 어시스턴트가 하는 일과 요청 예시 세 가지를 보여 줍니다. 첫 메시지를 보내면 사라집니다. 미리 알림을 부탁하면(“2분 뒤에 물 마시라고 알려 줘”) dsh의 예약 작업을 사용합니다. 그래서 그 시각에 미리 알림이 채팅을 실행하고, 모바일 연결이 켜져 있으면 Tether가 “Turn finished” 알림을 보냅니다. 백그라운드에서 일하는 친구에게 말하듯이 말을 걸어 보세요. 시간이 걸리는 작업(조사, 여러 단계)은 그 작업만의 백그라운드 하위 에이전트로 넘어가고, 채팅은 무엇을 시작했는지 한 줄로 알려 준 뒤 바로 다음 메시지를 받을 수 있습니다. 첫 번째 주제가 아직 실행 중일 때 두 번째 주제를 꺼내도 됩니다. 주제마다 자기 하위 에이전트가 생기고, 각 결과는 준비되는 대로 이 채팅으로 돌아옵니다. 웹 검색을 부탁하거나 다른 채팅에 대해 물어볼 수도 있습니다. 모든 프로젝트의 채팅(실행 중, 사용자를 기다림, 유휴)을 나열하고 한 채팅의 최신 메시지를 읽을 수 있습니다. 또한 채팅에 메시지를 보내고, 프로젝트에서 새 채팅을 시작하고, 실행 중인 채팅을 중지하거나 채팅을 보관할 수 있습니다. 이 네 가지 작업은 각각 먼저 dsh의 승인 카드를 보여 주며(Tether에서도), **한 번 허용**을 클릭하기 전에는 아무 일도 일어나지 않습니다. 삭제 도구는 없습니다. 이 도구와 짧은 지침은 이 채팅에만 있습니다. 웹 페이지나 다른 채팅에서 읽은 텍스트는 명령이 아니라 데이터로 취급됩니다. 매번 알려 주는 대신 프로필을 이 프로젝트의 메모리(**프로젝트 메모리**, 주제 “profil”)에 저장해 두세요. | <a href="assets/features/assistant.webp"><img src="assets/features/assistant.webp" width="160" alt="스크린샷: 어시스턴트"></a> |
79
+ | **채팅과 분리된 어시스턴트** | <a id="feature-assistantapart"></a>기본적으로 켜져 있습니다(**설정 → Composer Plus**에서 끌 수 있습니다). 어시스턴트 채팅이 왼쪽 사이드바의 채팅 목록에서 빠지므로 프로젝트 채팅들 사이에 놓이지 않습니다. **어시스턴트**로 여세요. 다른 채팅이 없는 동안에는 “Assistant” 프로젝트도 빠집니다. 사이드바 검색으로는 여전히 채팅을 찾을 수 있습니다. **어시스턴트** 행의 점이 어시스턴트의 상태를 보여 줍니다: 작업 중(백그라운드 주제가 실행되는 동안 포함), 사용자를 기다림(주황색: 승인, 질문 또는 계획 검토), 새 답변(초록색). 어시스턴트 채팅이 열려 있는 동안에는 **어시스턴트** 행이 열린 행으로 표시됩니다. 끄면 채팅이 목록으로 돌아오고 행에 점이 없습니다. | <a href="assets/features/assistantApart.webp"><img src="assets/features/assistantApart.webp" width="160" alt="스크린샷: 채팅과 분리된 어시스턴트"></a> |
80
+ | **어시스턴트는 메시지만** | <a id="feature-assistantchatview"></a>기본적으로 켜져 있습니다(**설정 → Composer Plus**에서 끌 수 있습니다). 어시스턴트 채팅이 봇과의 대화처럼 보입니다. 도구 호출, 추론, 단계 그룹, “Completed in” 행이 숨겨지고, 내 메시지, 어시스턴트의 답변, 오류, 승인 카드가 보입니다. 다른 채팅은 바뀌지 않습니다. 어시스턴트의 작업 단계를 다시 보려면 끄세요. | <a href="assets/features/assistantChatView.webp"><img src="assets/features/assistantChatView.webp" width="160" alt="스크린샷: 어시스턴트는 메시지만"></a> |
81
+ | **항상 여유 있는 어시스턴트** | <a id="feature-assistantfree"></a>기본적으로 켜져 있습니다(**설정 → Composer Plus**에서 끌 수 있습니다). 어시스턴트 채팅은 바로 답하고 긴 작업으로 바빠지지 않습니다. 자기 짧은 도구(내 채팅, 미리 알림, 메모리, 하위 에이전트)만 호출합니다. 웹 검색, 웹 페이지, 파일, 명령 같은 다른 모든 단계는 백그라운드 하위 에이전트로 넘어갑니다. 채팅은 무엇을 시작했는지 한 줄로 알려 주고 바로 다음 메시지를 받을 수 있으며, 결과는 준비되면 채팅으로 돌아옵니다. 하위 에이전트는 평소처럼 작동합니다. 어시스턴트 채팅에 하위 에이전트 도구가 없으면(권한 모드 또는 프로필 때문) 이 규칙은 아무것도 하지 않고 **설정**에 그렇게 표시됩니다. | <a href="assets/features/assistantFree.webp"><img src="assets/features/assistantFree.webp" width="160" alt="스크린샷: 항상 여유 있는 어시스턴트"></a> |
82
+ | **어시스턴트의 채팅 소식** | <a id="feature-assistantnotify"></a>기본적으로 꺼져 있습니다. 소식 한 줄마다 어시스턴트 채팅의 모델 턴이 하나씩 쓰이므로 토큰을 씁니다. **설정 → Composer Plus**에서 켜세요. 그러면 다른 채팅이 긴 턴(1분 이상)을 끝내거나, 실패하거나, 30초 동안 사용자를 기다리면(승인, 질문 또는 계획 검토) 어시스턴트가 자기 채팅에서 알려 줍니다. 채팅마다 짧은 한 줄이며, 채팅의 제목과 프로젝트가 들어 있습니다. 소식은 15초 동안 모이고 최대 2분에 한 번 옵니다. 어시스턴트가 작업 중이면 그 턴이 끝날 때까지 기다립니다. 사용자가 중지한 채팅, 짧은 턴, 어시스턴트 자신의 채팅은 소식이 되지 않습니다. **모바일 연결(iPhone)** 기능이 켜져 있으면 Tether가 어시스턴트의 평소 “Turn finished” 알림을 받습니다. | <a href="assets/features/assistantNotify.webp"><img src="assets/features/assistantNotify.webp" width="160" alt="스크린샷: 어시스턴트의 채팅 소식"></a> |
79
83
  | **프로젝트 메모리** | <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> |
80
84
  | **메모리 버전 기록** | <a id="feature-memoryhistory"></a>**프로젝트 메모리** 가 켜져 있는 동안 기본으로 켜집니다. 메모리를 저장할 때마다(에이전트, 턴 후 검토, **메모리 열기**) 저장 전 메모의 사본이 보관됩니다. **메모리 열기** 에서 프로젝트나 **전역 메모리** 를 선택한 다음 **기록** 을 누르면 날짜별 버전과 각 버전 뒤에 메모리를 바꾼 주체가 표시됩니다. 버전을 선택하면 복원 시 바뀌는 내용을 diff로 보고 **복원** 할 수 있습니다. 복원 전의 메모도 보관되므로 복원을 되돌릴 수 있습니다. 메모리마다 최신 50개 버전이 남습니다. Tether에서는: 채팅 제목 메뉴 → Project memory → History. | <a href="assets/features/memoryHistory.webp"><img src="assets/features/memoryHistory.webp" width="160" alt="스크린샷: 메모리 버전 기록"></a> |
81
85
  | **메모리를 AGENTS.md로 내보내기** | <a id="feature-memoryexport"></a>**메모리 열기** 에서 프로젝트를 선택한 다음 **AGENTS.md로 내보내기** 를 누르면 그 프로젝트의 메모가 폴더의 `AGENTS.md` 에 있는 표시된 섹션에 기록됩니다. 커밋해서 팀이나 다른 에이전트 도구와 공유할 수 있습니다. 먼저 변경 내용을 diff로 보고, **AGENTS.md 쓰기** 를 눌러야만 저장됩니다. 다음 내보내기는 이 섹션만 바꿉니다. 전역 메모리, 출처, 날짜는 넣지 않습니다. Tether에서는: 채팅 제목 메뉴 → Project memory → Export to AGENTS.md. | <a href="assets/features/memoryExport.webp"><img src="assets/features/memoryExport.webp" width="160" alt="스크린샷: 메모리를 AGENTS.md로 내보내기"></a> |
@@ -104,7 +108,7 @@ dsh plugin --profile web add dsh-composer-plus
104
108
  | **선택지 버튼** | <a id="feature-optionpicks"></a>답변이 선택지 목록("선택지" 제목 또는 굵은 "선택지" 줄 아래의 1~9개 번호 목록, "다음 단계"와 앱 언어의 같은 단어도 포함)으로 끝나면 답변 아래에 선택지마다 버튼이 표시됩니다. 클릭하면 선택지 전체가 담긴 "Option N: …"이 직접 입력한 것처럼 내 메시지로 전송됩니다. "(권장)" 표시가 있는 선택지는 강조됩니다. 버튼은 최신 답변 아래에만, 채팅이 대기 중이고 입력란이 비어 있을 때 표시되며, 이미 선택한 답변과 롤백으로 철회된 답변에는 표시되지 않습니다. 버튼이 표시되는 동안 다음 메시지 예측은 추측을 보여 주지 않습니다. 에이전트의 질문 카드에서는 1–9 키가 클릭과 같이 해당 선택지를 고릅니다(답변 입력란 안과 질문이 나타난 뒤 처음 0.8초 동안은 제외). | <a href="assets/features/optionPicks.webp"><img src="assets/features/optionPicks.webp" width="160" alt="스크린샷: 선택지 버튼"></a> |
105
109
  | **애플리케이션 언어** | <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> |
106
110
  | **모바일 연결(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> |
107
- | **원격 컴퓨터** | <a id="feature-remotecomputers"></a>[Tailscale](https://tailscale.com)을 통해 다른 Mac의 dsh를 열고, 이 dsh 창에서 사용하세요. 각 Mac의 **설정 → Composer Plus**에서 켜세요(네트워크 포트를 열기 때문에 기본적으로 꺼져 있습니다). 열려는 Mac에서 **다른 컴퓨터에서 이 Mac 열기 허용**을 켜고, **페어링 링크 만들기**를 클릭한 뒤 링크를 복사하세요. 이 Mac에서는 왼쪽 사이드바의 컴퓨터 선택 메뉴(브랜드 이름 오른쪽, **새 세션** 위)에서 **컴퓨터 추가…** 항목을 고르고, 링크를 붙여 넣은 뒤 **이름**을 입력하고(이 Mac이나 다른 컴퓨터와 같은 이름은 쓸 수 없습니다) **연결**을 클릭하세요. 그다음 다른 Mac에서 **승인**을 클릭하세요. 이제 선택 메뉴에 **이 Mac**과 내 컴퓨터들이 표시됩니다. 하나를 고르면 그 컴퓨터의 dsh가 이 창을 채우며, 그 컴퓨터의 채팅, 사이드바, 도구, 파일을 그대로 쓸 수 있습니다. 그동안 이 Mac은 뒤에서 계속 실행됩니다. 선택 메뉴는 같은 위치에 있고 **이 Mac으로 돌아가기**로 표시됩니다. 클릭하면 돌아옵니다. 컴퓨터가 두 대 이상이면 클릭할 때 메뉴가 열리고, 거기서 **이 Mac**이나 다른 컴퓨터를 고릅니다. 설정 패널에서 컴퓨터의 이름을 바꾸거나 제거할 수 있고, 이 Mac을 열 수 있는 컴퓨터 목록도 볼 수 있습니다(**제거**를 누르면 그 컴퓨터의 연결이 즉시 끊깁니다). | <a href="assets/features/remoteComputers.webp"><img src="assets/features/remoteComputers.webp" width="160" alt="스크린샷: 원격 컴퓨터"></a> |
111
+ | **원격 컴퓨터** | <a id="feature-remotecomputers"></a>[Tailscale](https://tailscale.com)을 통해 다른 Mac의 dsh를 열고, 이 dsh 창에서 사용하세요. 각 Mac의 **설정 → Composer Plus**에서 켜세요(네트워크 포트를 열기 때문에 기본적으로 꺼져 있습니다). 열려는 Mac에서 **다른 컴퓨터에서 이 Mac 열기 허용**을 켜고, **페어링 링크 만들기**를 클릭한 뒤 링크를 복사하세요. 이 Mac에서는 왼쪽 사이드바의 컴퓨터 선택 메뉴(브랜드 이름 오른쪽, **새 세션** 위)에서 **컴퓨터 추가…** 항목을 고르고, 링크를 붙여 넣은 뒤 **이름**을 입력하고(이 Mac이나 다른 컴퓨터와 같은 이름은 쓸 수 없습니다) **연결**을 클릭하세요. 그다음 다른 Mac에서 **승인**을 클릭하세요. 이제 선택 메뉴에 **이 Mac**과 내 컴퓨터들이 표시됩니다. 하나를 고르면 그 컴퓨터의 dsh가 이 창을 채우며, 그 컴퓨터의 채팅, 사이드바, 도구, 파일을 그대로 쓸 수 있습니다. 그동안 이 Mac은 뒤에서 계속 실행됩니다. 선택 메뉴는 같은 위치에 있고 **이 Mac으로 돌아가기**로 표시됩니다. 클릭하면 돌아옵니다. 다른 컴퓨터가 한 대뿐이면 선택 메뉴를 클릭할 때 이 Mac과 그 컴퓨터 사이에서 바로 전환됩니다(메뉴는 열리지 않습니다). 전체 메뉴(**컴퓨터 추가…**)를 열려면 선택 메뉴를 오른쪽 클릭하세요. 컴퓨터가 두 대 이상이면 클릭할 때 메뉴가 열리고, 거기서 **이 Mac**이나 다른 컴퓨터를 고릅니다. 설정 패널에서 컴퓨터의 이름을 바꾸거나 제거할 수 있고, 이 Mac을 열 수 있는 컴퓨터 목록도 볼 수 있습니다(**제거**를 누르면 그 컴퓨터의 연결이 즉시 끊깁니다). | <a href="assets/features/remoteComputers.webp"><img src="assets/features/remoteComputers.webp" width="160" alt="스크린샷: 원격 컴퓨터"></a> |
108
112
  | **자동 업데이트** | <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`로 닫습니다. 노트 아래에 GitHub 별표를 부탁하는 한 줄이 30일에 한 번까지 표시됩니다(네트워크 호출 없음). **GitHub에서 별표 주기** 또는 **다시 묻지 않기**를 누르면 다시 표시되지 않습니다. 설정 → 플러그인 이나 복사한 폴더로 업데이트한 뒤에도 새 버전마다 한 번 이 창이 표시됩니다. 처음 설치할 때는 표시되지 않습니다. 업데이트 행의 **이 버전의 새로운 기능** 으로 다시 열 수 있습니다. 실행 중인 버전보다 새 버전이 디스크에 있으면 행에 dsh를 다시 시작하라고 표시됩니다. | <a href="assets/features/autoUpdate.webp"><img src="assets/features/autoUpdate.webp" width="160" alt="스크린샷: 자동 업데이트"></a> |
109
113
  | **켬/끔 필터** | <a id="feature-featurefilter"></a>**설정 → Composer Plus**의 **기능 검색** 옆에 있습니다. **전체**는 모든 기능을, **켬**은 스위치가 켜진 기능만, **끔**은 스위치가 꺼진 기능만 보여 줍니다. 기준은 각 행의 스위치이며, dsh Host가 저장하는 스위치(예: **모바일 연결**)도 포함됩니다. 검색과 함께 작동합니다. 단어를 입력하고 **끔**을 고르면 꺼 둔 기능을 찾을 수 있습니다. **켬** 또는 **끔**을 고른 상태에서 전환한 행은 필터를 다시 고를 때까지 남아 있으므로 포커스가 그 스위치에 머뭅니다. **켬**과 **끔**에서는 **애플리케이션 언어**와 **Composer Plus 업데이트** 행이 숨겨집니다(스위치가 없기 때문입니다). 설정은 매번 **전체**로 열립니다. | <a href="assets/features/featureFilter.webp"><img src="assets/features/featureFilter.webp" width="160" alt="스크린샷: 켬/끔 필터"></a> |
110
114
  | **이슈 보고** | <a id="feature-issuereport"></a>설정 → Composer Plus → **이슈 보고…**(소개 문구 아래), 또는 사이드바에서 채팅을 마우스 오른쪽 버튼으로 클릭(또는 채팅의 **…** 메뉴 열기) → **Composer Plus 이슈 보고…**. 유형을 고르세요: **버그**, **기능 요청**, **개선**, **번역** 또는 **질문**. 자신의 말과 언어로 설명한 뒤 **초안 쓰기**를 클릭하세요(또는 `Cmd/Ctrl+Enter`). dsh의 기본 모델을 한 번 호출해 영어 이슈를 씁니다. 이슈에는 유형의 접두어가 붙은 제목(예: `[Bug]`)과 그 유형의 섹션(버그의 경우: What happened, Steps to reproduce, Expected, Actual), 그리고 Composer Plus, dsh, 시스템 버전이 적힌 줄 하나가 들어갑니다. 제목과 설명을 읽고 편집하세요. **다시 쓰기**는 새 초안을 씁니다. **이슈 열기**는 GitHub CLI(`gh`) 로그인으로 Composer Plus GitHub 저장소에 이슈를 열고 그 링크를 보여 줍니다. 이슈는 공개됩니다. 키나 비밀번호처럼 보이는 텍스트는 거부됩니다. `gh`로 열 수 없으면 **GitHub에서 대신 열기**가 초안이 채워진 GitHub 자체 페이지를 엽니다. | <a href="assets/features/issueReport.webp"><img src="assets/features/issueReport.webp" width="160" alt="스크린샷: 이슈 보고"></a> |
@@ -199,7 +203,7 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
199
203
  - **새 채팅에서 계속:** 클릭하기 전에는 아무것도 실행되지 않습니다. 클릭하면 Host 쪽은 채팅(목표 확인이 읽는 방식과 같음: 추론과 되돌린 단계 제외)을 채팅 자체의 모델에 보내고 인계 메모를 보여 줍니다. 새 채팅을 만드는 것은 **새 채팅 시작**뿐입니다. 프로젝트에는 아무것도 쓰지 않습니다.
200
204
  - **컨텍스트 구성:** Host에서 채팅 로그만 읽습니다. 모델 호출도 프로젝트 파일도 없습니다.
201
205
  - **작업 보드:** 보드는 이 창에 있는 dsh 자체 목록에서 dsh 자체 채팅을 보여 주며, 자체 채팅 데이터를 추가하지 않습니다. **새 작업**은 dsh 자체의 새 채팅을 열고, 첫 메시지는 사용자가 dsh의 입력란에 씁니다. 그래서 승인, 샌드박스, 채팅의 모델이 평소처럼 적용됩니다. Host 쪽은 그 채팅의 첫 메시지를 카드의 프롬프트로 보관하고, 태그를 최대 3개 얻기 위해 그 메시지(처음 4,000자만, 다른 것은 없음)를 도구 없이 요청 한 번으로 그 채팅의 모델에 더 보냅니다. 각 작업의 프롬프트, 태그, 시작 시각은 `$DSH_HOME/storages/dsh-composer-plus/board-chats.json`(소유자 전용 파일, 최신 2,000개)에 보관됩니다. **×** 버튼이나 **모두 빼기**로 보드에서 뺀 채팅의 ID(최신 5,000개)도 이 파일에 보관됩니다. 스위치는 그 옆의 `board-switch.json`에 있습니다. 프로젝트 폴더에는 아무것도 쓰지 않습니다. **답변**은 채팅 자체의 카드와 같은 방식으로 dsh 자체의 대기 중인 요청에 답변을 보냅니다. 이전 버전의 예전 작업 목록(`board.json`)은 디스크에 그대로 남으며 읽지 않습니다. **마우스를 올리면 진행 상황 표시**는 이 Mac에서 채팅 로그를 읽습니다. **빠름(AI 없음)**(기본값)에서는 아무것도 보내지 않습니다. **AI 요약**에서는 실행 중인 카드의 진행 상황 상자가 보이는 동안(또는 Tether의 보드가 열려 있는 동안, 실행 중인 카드 최대 8개에 대해) Host 쪽이 그 채팅의 가장 최근 부분(최대 약 6,000자: 사용자 메시지, 에이전트의 텍스트 답변, 도구 호출과 그 결과의 끝부분. 추론과 되돌린 메시지는 제외)을 도구 없는 요청 한 번으로 채팅의 모델에 보냅니다. 채팅이 진행된 뒤에만 다시 보내며, 채팅마다 최대 20초에 한 번입니다. 메모는 메모리에만 보관됩니다. 설정은 `$DSH_HOME/storages/dsh-composer-plus/board-progress.json`(소유자 전용 파일)에 있습니다.
202
- - **어시스턴트:** 어시스턴트 채팅은 `~/Assistant`에 있는 일반 dsh 채팅입니다. 모델 호출은 다른 채팅처럼 dsh의 기본 모델로 갑니다. 도구는 이 Mac에서 다른 채팅의 로그(제목, 프로젝트, 상태, 그리고 chat_read로는 최신 메시지)를 읽고, 모델이 도구를 호출할 때만 그 내용을 모델에 넘깁니다. 채팅에 보내기, 시작, 중지, 보관은 각각 사용자의 승인을 기다립니다. 채팅 ID는 `$DSH_HOME/storages/dsh-composer-plus/assistant.json`에, 스위치는 `assistant-switch.json`에 보관됩니다(소유자 전용 파일). 미리 알림과 자동화는 dsh 자체의 예약 작업입니다. 이 채팅이 보내는 모델 요청과 웹 검색 말고는 아무것도 이 Mac 밖으로 나가지 않습니다.
206
+ - **어시스턴트:** 어시스턴트 채팅은 `~/Assistant`에 있는 일반 dsh 채팅입니다. 모델 호출은 다른 채팅처럼 dsh의 기본 모델로 갑니다. 도구는 이 Mac에서 다른 채팅의 로그(제목, 프로젝트, 상태, 그리고 chat_read로는 최신 메시지)를 읽고, 모델이 도구를 호출할 때만 그 내용을 모델에 넘깁니다. 채팅에 보내기, 시작, 중지, 보관은 각각 사용자의 승인을 기다립니다. 채팅 ID는 `$DSH_HOME/storages/dsh-composer-plus/assistant.json`에, 스위치는 `assistant-switch.json`에 보관됩니다(소유자 전용 파일). 미리 알림과 자동화는 dsh 자체의 예약 작업입니다. 이 채팅이 보내는 모델 요청과 웹 검색 말고는 아무것도 이 Mac 밖으로 나가지 않습니다. 어시스턴트를 봇처럼 쓰는 스위치는 상태를 `assistant-free.json`과 `assistant-notify.json`에 보관합니다(소유자 전용 파일). **어시스턴트의 채팅 소식**은 다른 채팅에 대한 짧은 한 줄(제목, 프로젝트, 마지막 답변이나 오류의 최대 300자)을 어시스턴트 채팅에 넣으므로, 그 텍스트도 어시스턴트의 모델로 갑니다. 기다리는 소식은 메모리에만 있습니다.
203
207
  - **보호된 파일:** 목록과 스위치는 `$DSH_HOME/storages/dsh-composer-plus/protected-files.json`(소유자 전용 파일)에 있습니다. 확인은 각 파일 도구 호출의 경로(와 실제 경로)만 읽으며, 파일 자체는 읽지 않습니다.
204
208
  - **차단된 명령:** 규칙과 스위치는 `$DSH_HOME/storages/dsh-composer-plus/blocked-commands.json`(소유자 전용 파일)에 있습니다. 확인은 각 `bash`와 `pwsh` 호출의 명령 텍스트만 읽으며, 아무것도 실행하거나 보내지 않습니다.
205
209
  - **비밀 값 입력:** 값은 답변 요청 안에서만 카드에서(또는 요청 본문을 기록하지 않는 게이트웨이를 거쳐 Tether에서) Host로 갑니다. Host는 값을 `$DSH_HOME/storages/dsh-composer-plus/secrets/<임의 이름>`에 씁니다(폴더 0700, 파일 0600). 프로젝트, 채팅 기록, 도구 결과에는 아무것도 들어가지 않습니다. Host는 그 채팅의 이후 도구 결과에서 값을 `[secret]`으로 바꾸기 위해 값을 메모리에 보관합니다. 파일과 이 사본은 그 채팅의 턴이 끝날 때와 dsh가 시작될 때 삭제됩니다. 스위치는 같은 위치의 `secrets.json`에 있습니다. 에이전트가 이 파일로 실행하는 명령은 그 명령이 보내는 곳으로 값을 보낼 수 있습니다. 그것이 이 기능의 목적입니다.
@@ -226,7 +230,7 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
226
230
  - **채팅 행에 브랜치 배지가 없음:** 사이드바가 “하나의 목록” 보기가 아니거나(“작업 공간”과 “작업 공간 트리”에서는 어떤 채팅 행에도 배지가 없음), 이 버전을 설치한 뒤 그 채팅에 턴이 없었거나, 폴더가 git 저장소가 아니거나, **채팅 행의 Git 브랜치**가 꺼져 있습니다. 업데이트한 뒤에는 dsh를 다시 시작하세요(브랜치는 Host 쪽이 기록합니다).
227
231
  - **목표 확인에 테스트가 종료 코드 127 또는 "not found"로 끝났다고 표시됨:** Finder나 Dock에서 시작한 dsh는 터미널보다 PATH가 짧을 수 있어서 `npm`, `pnpm`, `cargo`를 찾지 못합니다. 터미널에서 dsh를 시작하거나, **목표 확인** → **편집**에서 전체 경로를 쓴 테스트 명령을 직접 정하세요. **지금 실행**을 누르면 결과가 바로 표시됩니다.
228
232
  - **목표가 닫히지 않고 에이전트가 계속 작업함:** **목표 확인**이 실패한 테스트나 남은 작업을 찾았습니다. 목표 아래의 행에 이유가 표시됩니다(자세한 내용은 결과에 포인터를 올려 보세요). 원인이나 테스트 명령을 고치거나, `/goal` 또는 목표 바로 목표를 직접 완료하세요(이 완료는 확인하지 않습니다).
229
- - **릴리스 직후 설치 실패:** 버전을 붙여서 설치하세요(`dsh-composer-plus@1.24.0`). 위의 설치 안내를 참고하세요.
233
+ - **릴리스 직후 설치 실패:** 버전을 붙여서 설치하세요(`dsh-composer-plus@1.25.0`). 위의 설치 안내를 참고하세요.
230
234
  - **지금 백업에서 "다른 백업 작업이 실행 중입니다"라고 표시됨:** 다른 dsh 창이나 복구 콘솔에서 작업이 실행 중입니다(둘은 백업 폴더의 잠금 파일 `.composer-plus.lock`을 함께 씁니다). 작업이 끝날 때까지 기다리세요. 실행 중인 작업이 없으면, 다음에 클릭할 때 종료된 프로세스의 잠금을 넘겨받습니다.
231
235
  - **복구 콘솔에 "dsh is running"이라고 표시됨:** 먼저 dsh를 종료하세요. dsh가 정말 닫혀 있다면, 메시지에 나온 파일은 비정상 종료로 남은 것입니다. 그 파일을 삭제하고 다시 시도하세요.
232
236
  - **복원 후 dsh가 시작되지 않거나 플러그인이 없음:** 프로필의 플러그인 패키지를 다시 설치해야 합니다. 복구 콘솔이 복원 후에 이를 제안합니다. 또는 콘솔이 나열하는 `$DSH_HOME/profiles/` 아래의 각 폴더에서 `pnpm install`을 실행하세요. vault에 없던 비밀 값(다른 컴퓨터)은 다시 입력해야 합니다. 콘솔이 그 목록을 보여 줍니다.
@@ -260,7 +264,7 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
260
264
  - **질문 카드를 창에 맞추기**는 dsh의 질문 카드만 바꾸고 계획 검토 카드는 바꾸지 않습니다. 카드는 dsh의 마크업(`data-question-key`, `data-question-scroll`)으로 찾습니다. dsh 업데이트로 이 마크업이 바뀌면 카드는 dsh가 그리는 대로 보입니다. 카드 높이는 채팅이 아니라 창을 따릅니다. 좁은 사이드 패널 안의 채팅에서는 높은 카드가 채팅 위로 넘칠 수 있습니다.
261
265
  - **채팅 헤더를 창에 맞추기**는 dsh가 생성한 클래스 이름(`_titleRow`, `_titleCluster`, `_crumbs`, `_headerActions`, `_headerUtilities`)으로 채팅 헤더를 찾습니다. dsh에 헤더 레이아웃용 훅이 없기 때문입니다. dsh 업데이트로 이 이름이 바뀌면 헤더는 dsh가 그리는 그대로 보입니다. 아주 좁은 채팅 열에서는 헤더가 두세 줄을 차지할 수 있어 메시지 위의 공간이 줄어듭니다.
262
266
  - **모바일 연결**은 macOS에서만 작동합니다(`en0`, `openssl`, `swift`, `dns-sd` 사용). 고정 포트 19390과 19391을 쓰므로, Mac마다 한 번에 dsh 하나에서만 실행할 수 있습니다(각 Mac은 휴대폰의 Mac 목록에서 항목 하나입니다). `apns.json`에 APNs 키가 있으면(`tether/README.md` 참고) Mac이 Apple 푸시 서비스로 알림을 보내므로 Tether가 닫혀 있어도 알림이 옵니다. Mac은 깨어 있고 dsh가 열려 있어야 합니다. 키가 없으면 휴대폰은 Tether가 열려 있거나 막 백그라운드로 간 동안에만 알림을 받습니다. Tether에서 "Settings → Notifications → Send notifications"를 켜기 전에는 Tether가 알림을 보내지 않습니다. Tether는 이 설정과 시간대를 페어링된 Mac마다 따로 저장합니다. 이 설정은 Mac마다 기본적으로 꺼져 있으며, 켤 때 iOS가 권한을 요청합니다. iOS 앱은 아직 App Store에 없습니다. Xcode로 `tether/ios`에서 빌드하세요. "Tailscale only"를 켜도 Mac에 Wi-Fi 또는 이더넷 주소가 있어야 합니다(게이트웨이는 그런 주소가 있을 때만 시작됩니다). 액세스 로그는 Mac마다 따로 있으며, 가장 최근의 시도 200개만 보관합니다. 1분 안에 반복된 시도는 새 행을 만들지 않고 같은 행의 횟수를 하나 늘립니다. 각 알림에는 Mac과 채팅의 프로젝트(`Studio Mac · recipe-box`), 채팅 제목, 본문이 표시됩니다. Turn finished에는 에이전트의 마지막 답변이 표시됩니다. APNs 키가 있으면 이 본문은 Apple의 푸시 서비스를 거칩니다. Tether의 앱 잠금은 iPhone 잠금 화면의 알림 미리보기를 숨기지 않습니다. iOS 설정에서 끄세요. Tether의 초록 점은 Mac을 따릅니다. dsh에서 연 채팅은 휴대폰에서도 점이 사라집니다. Tether에서 연 채팅은 휴대폰에서만 점이 사라집니다. Mac에 있는 dsh 자체의 점은 Mac에서 그 채팅을 열 때까지 남습니다.
263
- - **원격 컴퓨터**를 쓰려면 두 Mac 모두에 Tailscale이 있어야 하고, 여는 대상 Mac에 이 기능을 켠 Composer Plus가 있어야 합니다. 그 Mac은 잠자기 상태가 아니어야 하며 dsh가 실행 중이어야 합니다. 선택 메뉴는 왼쪽 사이드바가 열려 있을 때만 표시됩니다(아이콘만 보이는 상태에서는 표시되지 않습니다). 다른 Mac의 페이지에 자체 선택 메뉴가 없으면(그쪽 Composer Plus가 1.23.0보다 오래된 경우) 이 Mac의 선택 메뉴가 같은 위치에서 그 페이지 위에 표시됩니다. 그쪽이 1.23.0이면 선택 메뉴에 그 Mac의 이름이 표시됩니다. 돌아오려면 그 메뉴에서 **이 Mac**을 고르세요. 연 컴퓨터마다 그 페이지가 메모리에 남으며, 이 기능을 끄거나 dsh를 다시 시작할 때까지 유지됩니다. 데스크톱 앱에서 다른 Mac의 페이지는 임베드된 페이지입니다. dsh 자체의 키보드 단축키(예: 새 채팅)는 그 안에서 작동하지 않으며, 파일 다운로드, 마이크, 알림도 그곳에서 작동하지 않습니다. 포트 19392를 씁니다(Mac마다 다른 컴퓨터를 받아들일 수 있는 dsh는 하나뿐입니다). 다른 Mac의 페이지에서 선택 메뉴는 이 Mac의 컴퓨터들 사이에서만 전환하므로, 다른 Mac을 거쳐 세 번째 Mac을 열 수 없습니다.
267
+ - **원격 컴퓨터**를 쓰려면 두 Mac 모두에 Tailscale이 있어야 하고, 여는 대상 Mac에 이 기능을 켠 Composer Plus가 있어야 합니다. 그 Mac은 잠자기 상태가 아니어야 하며 dsh가 실행 중이어야 합니다. 선택 메뉴는 왼쪽 사이드바가 열려 있을 때만 표시됩니다(아이콘만 보이는 상태에서는 표시되지 않습니다). 다른 Mac의 페이지에 자체 선택 메뉴가 없으면(그쪽 Composer Plus가 1.23.0보다 오래된 경우) 이 Mac의 선택 메뉴가 같은 위치에서 그 페이지 위에 표시됩니다. 그쪽이 1.23.0이면 선택 메뉴에 그 Mac의 이름이 표시됩니다. 돌아오려면 그 메뉴에서 **이 Mac**을 고르세요. 연 컴퓨터마다 그 페이지가 메모리에 남으며, 이 기능을 끄거나 dsh를 다시 시작할 때까지 유지됩니다. 컴퓨터가 응답하지 않았다면(잠자기 상태였거나 Tailscale이 꺼져 있었다면) 그 페이지는 남지 않습니다. 다시 선택하면 페이지를 다시 불러옵니다. 데스크톱 앱에서 다른 Mac의 페이지는 임베드된 페이지입니다. dsh 자체의 키보드 단축키(예: 새 채팅)는 그 안에서 작동하지 않으며, 파일 다운로드, 마이크, 알림도 그곳에서 작동하지 않습니다. 포트 19392를 씁니다(Mac마다 다른 컴퓨터를 받아들일 수 있는 dsh는 하나뿐입니다). 다른 Mac의 페이지에서 선택 메뉴는 이 Mac의 컴퓨터들 사이에서만 전환하므로, 다른 Mac을 거쳐 세 번째 Mac을 열 수 없습니다. 원클릭 전환은 페어링되어 있고 연결할 수 있는 컴퓨터만 셉니다(다시 페어링해야 하는 컴퓨터는 세지 않습니다). 그런 컴퓨터가 한 대뿐이면 **컴퓨터 추가…**는 오른쪽 클릭(터치스크린에서는 길게 누르기)으로 여는 메뉴나 **설정 → Composer Plus → 원격 컴퓨터**에 있습니다.
264
268
  - 세션 링크는 채팅 안에서 작동하지만, 클릭해도 채팅이 열리지는 않습니다. **메시지 링크 복사**로 만든 링크는 dsh 0.2.1 이상에서만, 그리고 채팅 안의 메시지에서만 그 메시지를 엽니다(dsh 0.2.0에는 사용자 텍스트 규칙이 없으므로, 링크는 복사되지만 일반 텍스트로 보입니다). 되돌리기로 빠진 메시지나, 압축으로 dsh가 불러오는 기록에서 빠진 메시지는 보여 줄 수 없습니다. 이때 링크가 그렇다고 알려 줍니다. 🔗 버튼은 dsh의 메시지 행에 붙습니다. dsh 업데이트로 그 마크업이 바뀌면 버튼이 표시되지 않습니다.
265
269
  - **모두 읽음으로 표시**는 공개 API가 아닌 dsh의 일부(dsh 세션 상태의 `completionUnread` 목록)를 통해 dsh 자체의 읽지 않음 점을 바꿉니다. dsh 업데이트로 이 이름이 바뀌면 항목이 표시되지 않습니다. 이 항목은 dsh의 프로젝트 "…" 메뉴에 들어가는데, 이 메뉴에는 플러그인용 슬롯이 없습니다. dsh가 이 메뉴를 바꾸면 이 항목도 표시되지 않습니다.
266
270
  - **대기 중인 메시지 제자리 편집**은 그사이 전송이 시작된 메시지를 바꾸지 않고, 그사이 바뀐 메시지(예: iPhone의 Tether에서 바꾼 메시지)를 덮어쓰지 않으며, 알림으로 이를 알려 줍니다. 새 이미지에는 이미지를 받는 모델이 필요하고(dsh 자체의 이미지 제한이 적용됩니다), 새 파일은 업로드가 끝나야 저장할 수 있습니다. 내 대기 중인 메시지만 편집할 수 있고, 대기열의 목표 라운드나 질문에 대한 답변은 편집할 수 없습니다. 플러그인을 업데이트한 뒤에는 텍스트만 바꾸는 편집만 바로 되며, 이미지나 파일이 있는 메시지를 저장하려면 먼저 dsh를 다시 시작해야 합니다(Host 쪽은 시작할 때 로드됩니다).
@@ -296,7 +300,8 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
296
300
  - **터키어 스킬 팩**은 서드파티 스킬을 설치합니다. 규칙은 Composer Plus가 아니라 작성자의 GitHub 저장소에서 오며, 새 버전은 우리가 검토하지 않은 채 다음 일일 확인부터 사용됩니다. 확인은 파일이 GitHub가 해당 커밋에 나열한 파일과 같다는 것만 증명하며, 규칙이 좋다는 것을 증명하지는 않습니다. 스킬을 언제 불러올지는 모델이 정합니다(이름으로 직접 부를 수도 있습니다). 규칙은 터키어 글에만 적용됩니다. Host 쪽은 브라우저가 마지막으로 알린 언어를 사용합니다. 두 브라우저가 서로 다른 언어를 쓰면 가장 최근 것이 적용됩니다. GitHub는 로그인 없이 시간당 60회의 API 호출만 허용합니다. 확인이 거부되면 설치된 사본을 유지하고 설정에 이유를 표시합니다.
297
301
  - **코드베이스 정리**에는 스킬의 고정된 사본(caldoai/skills, 커밋 f3cf477)이 들어 있습니다. 원본의 변경은 새 Composer Plus 버전으로만 들어옵니다. 이 스킬은 많은 파일을 바꿀 수 있는 긴 목표를 실행하며, 하위 에이전트와 확인 작업이 많은 토큰을 씁니다. 테스트가 없는 부분에서는 모르는 사이에 동작이 바뀔 수 있습니다. 별도 브랜치에서 시작하고 병합 전에 diff를 읽으세요. 프로젝트, 사용자 지정 스킬 폴더 또는 `~/.dsh/skills`에 같은 이름의 스킬이 있으면 그 스킬이 대신 쓰입니다. 스위치가 꺼져 있으면 `/untangle-codebase`는 일반 텍스트로 모델에 전달됩니다.
298
302
  - **작업 보드**는 dsh가 이 창에 나열하는 채팅을 보여 줍니다. 프로젝트 밖의 채팅은 **모든 프로젝트**에만 표시되고, 채팅별 브랜치 폴더(`<project>/.worktrees/<name>`)는 해당 프로젝트로 취급됩니다. 카드의 열은 채팅의 실시간 상태이므로 카드를 끌어 옮길 수 없습니다. 채팅은 턴이 끝나면(오류나 중지 후에도) **완료**로 가고, 다시 실행되면 **진행 중**으로 돌아갑니다. 초록색 점은 dsh 자체의 완료 점이며, dsh는 이 점을 이 창에만 보관합니다. 페이지를 다시 불러오면 끝난 채팅이 이 점 없이 표시됩니다. **완료**에는 최신 채팅 50개가 표시됩니다(나머지는 **이전 작업 N개 보기**로 볼 수 있습니다). **프로젝트 검색**은 프로젝트를 이름으로만 찾고, 폴더 경로로는 찾지 않습니다. **최근 2시간 내 활성**은 프로젝트의 모든 채팅이 2시간보다 오래되었고 유휴 상태이며 읽은 상태일 때 그 프로젝트를 숨깁니다. 선택한 프로젝트는 보드에 계속 표시됩니다. **새 작업**은 이 창의 가장 최근 새 채팅만 기억합니다. 첫 메시지 전에 다른 채팅을 열면, 그 채팅은 사용자가 거기에 쓸 때까지 **진행 중**의 맨 위에 **새 작업**으로 남지만, 자동으로 보드로 돌아오는 것은 가장 최근 채팅뿐입니다. 페이지를 다시 불러오면 메시지가 없는 새 채팅은 보드에 없습니다(dsh는 그 채팅을 빈 새 세션으로 보관합니다). 태그는 작업마다 그 첫 메시지를 바탕으로 한 모델 호출 한 번으로 만들어지므로 틀릴 수 있으며, 보드에서 시작하지 않은 채팅에는 태그가 없습니다. 제목은 dsh 자체의 채팅 제목입니다(dsh의 제목 서비스가 채팅의 모델로 만듭니다). 제목이 오기 전까지 카드에는 첫 메시지의 첫 줄이 표시됩니다. **×** 버튼과 **모두 빼기**는 카드를 보드에서 빼기만 합니다. 채팅은 삭제되지 않습니다. **실행 취소**는 이 창에서 8초 동안만 표시됩니다. 그 뒤에는 **뺀 카드 (N)** → **보드에 되돌리기**로 카드를 되돌릴 수 있고, 다시 실행되는 채팅은 자동으로 돌아옵니다. **모두 빼기**는 먼저 확인을 묻고, 표시된 프로젝트에서 읽은 끝난 카드를 뺍니다(**모든 프로젝트**에서는 모든 프로젝트의 카드). **이전 작업 N개 보기** 뒤에 있는 카드도 뺍니다. 읽지 않은(초록색) 카드는 남습니다. dsh는 초록색 점을 이 창에만 보관하므로, 페이지를 다시 불러온 뒤에는 모두 빼기가 아직 답변을 읽지 않은 카드도 뺄 수 있습니다. 이 목록은 이 Mac에 보관되며 모든 창과 Tether에 적용됩니다. 목록이 채팅 5,000개에 이르면 가장 오래된 채팅이 돌아옵니다. **답변**은 채팅의 가장 최근 요청에만 답합니다. 그 요청이 다른 곳(다른 창, Tether, 자동 검토)에서 이미 답변되었거나 채팅이 새로운 것을 물으면, 패널이 그렇게 알려 주고 아무것도 보내지 않습니다. 이전 버전에는 댓글과 에이전트 도구가 있는 작업 목록이 있었지만 이제 없어졌으며, 예전 `board.json`은 표시되지 않습니다. 아이디어와 디자인은 emanuele-em의 [Kanzo](https://github.com/emanuele-em/kanzo)(AGPL-3.0)에서 왔습니다. Composer Plus는 그 코드를 쓰지 않습니다. `Cmd+Shift+K`는 dsh 단축키입니다. Linux의 브라우저에서는 기본 키가 없으므로 dsh의 키보드 단축키 페이지에서 설정하세요. 브라우저 확장 프로그램이나 다른 앱이 이 키를 먼저 사용할 수도 있습니다. 카드는 dsh 자체의 초록색 점이 사라질 때(채팅을 열었을 때) **완료**에서 빠집니다. 보드 뒤에서 열린 채팅으로 끝난 채팅은 그 채팅이 위에 패널 없이 보일 때 빠집니다. 이 읽음 상태는 dsh 자체의 점처럼 이 dsh 창 안에만 있습니다. 다시 불러오거나 다른 창에서는 끝난 채팅이 모두 읽은 것으로 보이므로 **최근 완료**에 있습니다.
299
- - **어시스턴트**는 이 Mac의 모든 창에서 채팅 하나를 씁니다. workspace-write 권한 모드로 실행됩니다. 파일은 `~/Assistant` 안에만 쓰고, 그 밖에서 실행하는 명령은 먼저 묻습니다. 채팅을 승인이 없는 모드(전체 액세스)로 바꾸면 dsh가 모든 승인을 거부하므로, 어시스턴트는 채팅에 보내기, 시작, 중지, 보관을 할 수 없습니다. 승인 카드는 이 여섯 도구만 지킵니다. 그 모드의 다른 채팅과 마찬가지로, 어시스턴트의 셸 명령은 여전히 네트워크에 접근할 수 있습니다. dsh 0.2.0과 0.2.1에서 dsh의 예약 도구는 어시스턴트 채팅 자신의 미리 알림만 보고, 다른 채팅의 자동화는 보지 못합니다. dsh 0.2.2부터는 모든 예약 작업을 나열하고 바꿉니다. chats_list는 보관된 채팅, 빈 채팅, 하위 에이전트 채팅과 어시스턴트 채팅 자신을 빼고 보여 줍니다. “사용자를 기다림”은 실행 중인 채팅에 열린 승인, 질문 또는 계획 검토가 있다는 뜻입니다. chat_read는 사용자의 메시지와 에이전트의 답변(도구 출력 제외)을 최대 50개 메시지, 약 24,000자까지 돌려줍니다. chat_archive는 아직 실행 중이거나 활성 미리 알림이 있는 채팅을 거부합니다. 모델은 읽은 텍스트에 여전히 속을 수 있습니다. 승인 카드가 마지막 확인이므로, **한 번 허용**을 클릭하기 전에 읽어 보세요.
303
+ - **어시스턴트**는 이 Mac의 모든 창에서 채팅 하나를 씁니다. workspace-write 권한 모드로 실행됩니다. 파일은 `~/Assistant` 안에만 쓰고, 그 밖에서 실행하는 명령은 먼저 묻습니다. 채팅을 승인이 없는 모드(전체 액세스)로 바꾸면 dsh가 모든 승인을 거부하므로, 어시스턴트는 채팅에 보내기, 시작, 중지, 보관을 할 수 없습니다. 승인 카드는 이 여섯 도구만 지킵니다. 그 모드의 다른 채팅과 마찬가지로, 어시스턴트의 셸 명령은 여전히 네트워크에 접근할 수 있습니다. dsh 0.2.0과 0.2.1에서 dsh의 예약 도구는 어시스턴트 채팅 자신의 미리 알림만 보고, 다른 채팅의 자동화는 보지 못합니다. dsh 0.2.2부터는 모든 예약 작업을 나열하고 바꿉니다. chats_list는 보관된 채팅, 빈 채팅, 하위 에이전트 채팅과 어시스턴트 채팅 자신을 빼고 보여 줍니다. “사용자를 기다림”은 실행 중인 채팅에 열린 승인, 질문 또는 계획 검토가 있다는 뜻입니다. chat_read는 사용자의 메시지와 에이전트의 답변(도구 출력 제외)을 최대 50개 메시지, 약 24,000자까지 돌려줍니다. chat_archive는 아직 실행 중이거나 활성 미리 알림이 있는 채팅을 거부합니다. 모델은 읽은 텍스트에 여전히 속을 수 있습니다. 승인 카드가 마지막 확인이므로, **한 번 허용**을 클릭하기 전에 읽어 보세요. 병렬 주제는 dsh의 하위 에이전트 도구를 씁니다. 이 도구가 없는 프로필이나 권한 모드에서는 이전 방식이 유지됩니다(한 번에 주제 하나, 다음 메시지는 대기열에서 기다리거나 실행 중인 턴에 끼어듭니다). 무엇이 긴 작업인지는 모델이 정하므로, 짧은 질문도 한 턴을 차지할 수 있습니다. 각 주제의 하위 에이전트는 자기 토큰으로 실행됩니다. dsh가 다시 시작되면 실행 중인 주제는 멈춥니다(그 결과는 돌아오지 않습니다). 결과는 어시스턴트 채팅의 새 턴으로 돌아오므로, 턴 중간에 입력하는 동안에는 기다립니다.
304
+ - **채팅과 분리된 어시스턴트**와 **어시스턴트는 메시지만**은 dsh 자체의 행을 스타일 규칙으로 숨깁니다. 행은 dsh의 사이드바와 채팅 마크업(`data-row-key`, `data-chat-flow-kind`)으로 찾습니다. dsh 업데이트로 이 마크업이 바뀌면 어시스턴트 채팅이 목록에 다시 보이거나 작업 단계가 다시 보입니다. 행은 삭제되지 않고 숨겨질 뿐입니다. 사이드바에서 dsh의 키보드 탐색은 숨겨진 행에도 닿을 수 있습니다. **항상 여유 있는 어시스턴트**는 어시스턴트 채팅의 도구 호출 중 짧은 도구가 아닌 것을 모두 거부합니다. 그러면 모델은 그 단계를 하위 에이전트에 넘기지만, 거부된 호출을 먼저 시도할 수 있어 모델 단계를 한 번 더 씁니다. 승인 카드가 사용자를 기다리는 동안 어시스턴트 채팅은 여전히 바쁜 상태로 셉니다. 최신 요청에 하위 에이전트 도구가 없으면(그 도구가 없는 권한 모드나 프로필) 이 규칙은 아무것도 하지 않습니다. **어시스턴트의 채팅 소식**은 소식 묶음마다 어시스턴트 채팅의 모델 턴을 시작하므로 토큰을 씁니다. **모바일 연결(iPhone)** 기능이 켜져 있으면 끝난 채팅 하나에 대해 휴대폰에 알림이 두 개 올 수 있습니다(채팅 자신의 알림과 어시스턴트의 알림). 기다리는 소식은 dsh가 다시 시작되면 사라집니다. 이 Mac의 채팅만 봅니다.
300
305
  - **중지 후 보낸 메시지 먼저 실행**은 채팅을 중지한 뒤에만 동작합니다(또는 실패한 턴 뒤, 아직 대기열이 있는 채팅을 열 때). 턴이 실행되는 중에 보낸 메시지는 여전히 대기열 끝에서 기다립니다. 내가 대기열에 넣은 메시지만 앞지릅니다. 대기열에 목표 라운드나 질문 답변이 기다리고 있으면 dsh 자체 순서가 유지됩니다. 공개 API가 아닌 dsh의 일부(중지된 턴이 아직 끝나는 중인지)를 읽습니다. dsh 업데이트로 그 이름이 바뀌면, 메시지는 그 턴이 끝난 뒤에만 앞으로 옮겨집니다. 서브에이전트 채팅은 dsh 자체 순서를 유지합니다.
301
306
  - **프로젝트 메모리**는 채팅의 첫 폴더(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 자체의 메모리를 읽거나 쓰지 않습니다.
302
307
  - **메모리 버전 기록** 은 메모리(각 프로젝트와 전역 메모리)마다 최신 50개 버전을 보관하고, 더 오래된 것은 지웁니다. 한 버전은 메모 하나가 아니라 그 프로젝트의 메모리 전체입니다. **복원** 은 그 버전의 모든 파일(주제 포함)을 되돌리며, 버전을 연 뒤에 메모리가 바뀌었으면 거부합니다. 복원 전의 메모리는 새 버전이 되므로 복원을 되돌릴 수 있습니다. 스위치가 꺼져 있는 동안에는 새 버전을 보관하지 않고 **복원** 도 거부됩니다. 보관된 버전은 남습니다. 이 기능 이전의 버전은 없습니다. 기록은 설치 후 첫 저장부터 시작합니다.
@@ -350,7 +355,9 @@ dsh `0.2.0-rc.2`(데스크톱과 웹)와 `0.2.1-rc.2`(웹)에서 테스트했습
350
355
 
351
356
  **모든 채팅을 칸반 보드로 보고 거기서 새 채팅을 시작할 수 있나요?** 네, **작업 보드**(기본적으로 켜짐)로 가능합니다. 왼쪽 사이드바에서 여세요. 각 채팅은 **진행 중**, **검토**(사용자를 기다림) 또는 **완료**에 있는 카드입니다. **새 작업**은 프로젝트에서 dsh의 새 채팅을 열고, 첫 메시지를 보내면 보드로 돌아옵니다. 주황색 카드에서 **답변**을 클릭하면 채팅을 열지 않고 답할 수 있습니다. **완료**의 **모두 빼기**는 먼저 확인을 묻고, 읽은 끝난 카드를 보드에서 뺍니다. **실행 취소**와 **뺀 카드 (N)**로 카드를 되돌릴 수 있으며, 채팅은 dsh에 남습니다.
352
357
 
353
- **알림을 주고 다른 채팅도 관리해 주는 개인 어시스턴트 채팅을 쓸 수 있나요?** 네, **어시스턴트**(기본적으로 꺼짐)로 가능합니다. 설정 → Composer Plus에서 켠 다음, 왼쪽 사이드바에서 **어시스턴트**를 클릭하세요. dsh의 예약 작업으로 미리 알림을 설정하고, 웹을 검색하고, 채팅을 나열하고 읽습니다. 채팅에 메시지를 보내거나 채팅을 시작, 중지, 보관하는 일은 사용자가 승인한 뒤에만 합니다. 프로필은 그 프로젝트 메모리에 “profil” 주제로 저장해 두세요.
358
+ **알림을 주고 다른 채팅도 관리해 주는 개인 어시스턴트 채팅을 쓸 수 있나요?** 네, **어시스턴트**(기본적으로 켜짐)로 가능합니다. 왼쪽 사이드바에서 **어시스턴트**를 클릭하세요. dsh의 예약 작업으로 미리 알림을 설정하고, 웹을 검색하고, 채팅을 나열하고 읽습니다. 채팅에 메시지를 보내거나 채팅을 시작, 중지, 보관하는 일은 사용자가 승인한 뒤에만 합니다. 프로필은 그 프로젝트 메모리에 “profil” 주제로 저장해 두세요.
359
+
360
+ **어시스턴트가 채팅 목록에서 빠져 봇처럼 일할 수 있나요?** 네. **채팅과 분리된 어시스턴트**는 어시스턴트 채팅을 사이드바 목록에서 빼고 그 상태를 **어시스턴트** 행에 보여 줍니다(사용자를 기다리는 동안 주황색). **어시스턴트는 메시지만**은 작업 단계를 숨깁니다. **항상 여유 있는 어시스턴트**는 더 긴 단계를 모두 백그라운드 하위 에이전트에 넘기게 하므로, 어시스턴트가 바로 답합니다. **어시스턴트의 채팅 소식**(기본적으로 꺼짐, 토큰을 씀)은 다른 채팅이 끝나거나, 실패하거나, 사용자를 기다릴 때 어시스턴트가 알려 주게 합니다.
354
361
 
355
362
  **dsh-backup처럼 dsh에서 채팅과 설정을 백업할 수 있나요?** 네. **설정 → Composer Plus → 백업 → 지금 백업**을 사용하세요. 같은 아카이브 형식으로 같은 폴더(`~/Desktop/dsh-backups`)에 쓰므로, dsh-backup의 아카이브도 표시되고 복원할 수 있으며, dsh-backup은 삭제해도 됩니다. 정해진 일정으로 백업하려면 **자동 백업**을 켜세요.
356
363
 
@@ -504,8 +511,10 @@ SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-queue-stop-send.mjs /pat
504
511
  SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-queue-edit.mjs /path/to/dsh/lib/bin.js
505
512
  # Task board: New task opens dsh's new chat and comes back after the first message, AI tags, live columns, Answer on the board, × with Undo, Clear all with its question (unread cards stay), Removed and Put back (kept after a restart), the switch
506
513
  SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-task-board.mjs /path/to/dsh/lib/bin.js
507
- # Assistant: off by default, sidebar row under Task board, one chat in ~/Assistant (workspace-write), a reminder that runs the chat, chats_list, chat_send after its approval card, an injected chat_send rejected, no tools in other chats, automations of other chats (dsh 0.2.2+), switch off
514
+ # Assistant: on by default, sidebar row under Task board, one chat in ~/Assistant (workspace-write), a reminder that runs the chat, chats_list, chat_send after its approval card, an injected chat_send rejected, no tools in other chats, automations of other chats (dsh 0.2.2+), switch off
508
515
  SHOT=1 CHECK_DELAY=20 PLAYWRIGHT=/path/to/playwright node test/browser-assistant.mjs /path/to/dsh/lib/bin.js
516
+ # Assistant welcome card: shows above the input on the first open of the assistant chat, goes with the switch and with the first message, not in other chats
517
+ PLAYWRIGHT=/path/to/playwright node test/browser-assistant-welcome.mjs /path/to/dsh/lib/bin.js
509
518
  ```
510
519
 
511
520
  ```sh
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.24.0`.
30
+ > dsh's pnpm skips versions younger than 24 hours. Right after a release, add the version: `dsh-composer-plus@1.25.0`.
31
31
 
32
32
  ## Features
33
33
 
@@ -73,7 +73,11 @@ Then restart dsh. (The CLI can't install into the desktop profile; the app manag
73
73
  | **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> |
74
74
  | **Blocked commands** | <a id="feature-blockedcommands"></a>On by default, with an empty list. The agent's shell commands (`bash`, `pwsh`) cannot run a command that matches your rules: a **block** rule refuses the call (the agent reads why and is told to ask you), an **ask first** rule shows dsh's approval card, and the command runs only when you allow it. Settings → Composer Plus → **Blocked commands**: type a rule (for example `npm publish`, `git push --force` or `ssh *192.168.2.19`), click the kind to switch between **block** and **ask first**, then **Add**; click a rule's kind to change it, remove it with ✕. A rule is a command name and words that must come after it in this order; `*` matches any text. It also finds the command after `&&`, `;`, `\|`, inside `$(…)`, `bash -c "…"` or `eval`, and after `sudo` or `env`. This is a guard rail, not a sandbox: a variable (`$CMD`), a script file or another program can still run the command (see Limits). | <a href="assets/features/blockedCommands.webp"><img src="assets/features/blockedCommands.webp" width="160" alt="Screenshot: Blocked commands"></a> |
75
75
  | **Task board** | <a id="feature-taskboard"></a>Left sidebar → **Task board**, or press `Cmd+Shift+K` (`Ctrl+Shift+K` on Windows and Linux) anywhere in dsh. A kanban board of your dsh chats with the live state that the sidebar shows: a chat that waits for your approval, answer or plan review is in **Review** with an orange dot, a running chat is in **Doing**, a finished chat that you did not open yet is in **Done** (green). When you open a chat, its card leaves **Done** by itself; click **Recently finished (N)** under the green cards to see the finished chats that you read (the newest 10, then **Show N older**; open or closed is kept on this device). A chat that finishes while it is open behind the board (a **New task**) stays green until you open it. Click the project name at the top of the board to open the project list, then pick a project or **All projects**; a Branch per chat folder counts as its project. The list closes after the pick, with `Esc` or with a click outside it. Type in **Search projects** at the top of the list to find a project by its name (case and accents do not matter; `Esc` empties the box) and press `Enter` to pick the first match, and click **Active in the last 2 hours** to show only projects with a chat that waits, runs, finished unseen or changed in the last 2 hours (kept on this device). **New task** (or `n`) opens dsh's own new chat in the project that the board shows (with **All projects**, the project that dsh's New session picks), so you can add files, use commands and pick the model as in any chat. When your first message goes, the board comes back by itself. Until then the chat waits at the top of **Doing** as **New task**: click it to write the first message. A project with a chat that waits for you has an orange dot in the project list (the project name at the top has it too while any chat waits). dsh names the chat and the chat's model writes up to 3 tags from that message. Click a card to open its chat. Click an orange card (or its **Answer**) to answer it on the board; the panel has **Open chat** for the whole chat: **Reject** or **Allow once**, **Approve** or **Request changes** for a plan, or the options and your own text for a question. Click **×** on a finished card to take it off the board, or open **Recently finished** and click **Clear all** at the top of **Done** to take those cards off it: it first shows how many cards of which project go, and unread (green) cards stay. For 8 seconds after, **Undo** puts the cards back; **Removed (N)** under **Done** lists the cards that are off the board, and **Put back** shows one in **Done** again. No chat is deleted: the chats stay in dsh's sidebar, the board remembers this after a restart (Tether shows the same board), and a chat that runs again comes back. Point at a card in **Doing** (or move the keyboard focus to it) to see its progress: how long it runs, the step of its todo list, the tool that runs now and the agent's last line. In Settings → Composer Plus → Task board, **Progress on hover** picks **Fast (no AI)** (the default: it reads the chat only) or **AI summary** (one short call to the chat's model also writes one or two sentences). | <a href="assets/features/taskBoard.webp"><img src="assets/features/taskBoard.webp" width="160" alt="Screenshot: Task board"></a> |
76
- | **Assistant** | <a id="feature-assistant"></a>Off by default: switch it on in **Settings → Composer Plus**. Then click **Assistant** in the left sidebar (right under **Task board**): it opens one lasting chat that you use as your personal assistant, like a ChatGPT or Grok chat. The first click makes the folder `~/Assistant`, adds it as the project "Assistant" and starts the chat with the workspace-write permission mode and dsh's default model; each later click opens the same chat (an archived one comes back, a deleted one is made again). Ask it to remind you ("remind me to drink water in 2 minutes"): it uses dsh's scheduled tasks, so the reminder runs the chat at that time, and Tether sends its "Turn finished" notification when Mobile connect is on. Ask it to search the web, or about your other chats: it can list the chats of all projects (running, waiting for you or idle) and read the newest messages of one. It can also send a message to a chat, start a new chat in a project, stop a running chat or archive one: each of these four actions shows dsh's approval card first (also in Tether), and nothing happens until you click **Allow once**. It has no delete tool. Only this chat has these tools and its short instructions; text that it reads in a web page or another chat counts as data, not as an order. Keep your profile in this project's memory (**Project memory**, topic "profil") instead of telling it each time. | <a href="assets/features/assistant.webp"><img src="assets/features/assistant.webp" width="160" alt="Screenshot: Assistant"></a> |
76
+ | **Assistant** | <a id="feature-assistant"></a>On by default (switch it off in **Settings → Composer Plus**). Click **Assistant** in the left sidebar (right under **Task board**): it opens one lasting chat that you use as your personal assistant, like a ChatGPT or Grok chat. The first click makes the folder `~/Assistant`, adds it as the project "Assistant" and starts the chat with the workspace-write permission mode and dsh's default model; each later click opens the same chat (an archived one comes back, a deleted one is made again). While the chat has no message yet, a short card above the input says what the assistant does and shows three example requests; it goes away with your first message. Ask it to remind you ("remind me to drink water in 2 minutes"): it uses dsh's scheduled tasks, so the reminder runs the chat at that time, and Tether sends its "Turn finished" notification when Mobile connect is on. Talk to it like a friend who works in the background: a task that takes longer (research, several steps) goes to a background subagent of its own, the chat says in one line what it started and is free at once. Open a second topic while the first still runs: each topic gets its own subagent, and each result comes back in this chat when it is ready. Ask it to search the web, or about your other chats: it can list the chats of all projects (running, waiting for you or idle) and read the newest messages of one. It can also send a message to a chat, start a new chat in a project, stop a running chat or archive one: each of these four actions shows dsh's approval card first (also in Tether), and nothing happens until you click **Allow once**. It has no delete tool. Only this chat has these tools and its short instructions; text that it reads in a web page or another chat counts as data, not as an order. Keep your profile in this project's memory (**Project memory**, topic "profil") instead of telling it each time. | <a href="assets/features/assistant.webp"><img src="assets/features/assistant.webp" width="160" alt="Screenshot: Assistant"></a> |
77
+ | **Assistant apart from chats** | <a id="feature-assistantapart"></a>On by default (switch it off in **Settings → Composer Plus**). The assistant chat leaves the chat list in the left sidebar, so it does not sit among your project chats: open it with **Assistant**. Its project "Assistant" goes too while it holds no other chat; the sidebar search still finds the chat. A dot on the **Assistant** row shows the assistant's state: working (also while a background topic runs), waiting for you (orange: an approval, a question or a plan review) or a new reply (green). While the assistant chat is open, the **Assistant** row shows as the open one. Switched off, the chat is back in the list and the row has no dot. | <a href="assets/features/assistantApart.webp"><img src="assets/features/assistantApart.webp" width="160" alt="Screenshot: Assistant apart from chats"></a> |
78
+ | **Assistant messages only** | <a id="feature-assistantchatview"></a>On by default (switch it off in **Settings → Composer Plus**). The assistant chat looks like a chat with a bot: tool calls, thinking, step groups and the "Completed in" row are hidden, and you see your messages, its replies, errors and the approval cards. Other chats do not change. Switch it off to see the assistant's work steps again. | <a href="assets/features/assistantChatView.webp"><img src="assets/features/assistantChatView.webp" width="160" alt="Screenshot: Assistant messages only"></a> |
79
+ | **Assistant always free** | <a id="feature-assistantfree"></a>On by default (switch it off in **Settings → Composer Plus**). The assistant chat answers at once and is never busy with a long job: it calls only its own short tools (your chats, reminders, memory and subagents). Every other step, such as a web search, a web page, a file or a command, goes to a background subagent; the chat says in one line what it started and is free for your next message, and the result comes back in the chat when it is ready. Its subagents work as usual. When the assistant chat has no subagent tool (its permission mode or profile), the rule does nothing and **Settings** says so. | <a href="assets/features/assistantFree.webp"><img src="assets/features/assistantFree.webp" width="160" alt="Screenshot: Assistant always free"></a> |
80
+ | **Assistant news from chats** | <a id="feature-assistantnotify"></a>Off by default: each news line is a model turn of the assistant chat, so it uses tokens. Switch it on in **Settings → Composer Plus**. Then the assistant tells you, in its own chat, when another chat finishes a long turn (1 minute or more), fails, or waits for you (an approval, a question or a plan review) for 30 seconds: one short line per chat, with the chat's title and project. News is collected for 15 seconds and comes at most every 2 minutes; while the assistant works, it waits until that turn ends. A chat that you stopped, a short turn and the assistant's own chat give no news. With **Mobile connect (iPhone)** on, Tether gets the assistant's usual "Turn finished" notification. | <a href="assets/features/assistantNotify.webp"><img src="assets/features/assistantNotify.webp" width="160" alt="Screenshot: Assistant news from chats"></a> |
77
81
  | **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> |
78
82
  | **Memory version history** | <a id="feature-memoryhistory"></a>On by default while **Project memory** is on. Before each save of the memory (the agent, the review after a turn, **Open memory**), a copy of the notes as they were is kept. In **Open memory**, select a project or **Global memory**, then **History**: the versions by date and who changed the memory after each one. Select a version to see what a restore changes as a diff, then **Restore**. The notes before a restore are kept too, so you can undo it. The newest 50 versions of each memory stay. In Tether: chat title menu → Project memory → History. | <a href="assets/features/memoryHistory.webp"><img src="assets/features/memoryHistory.webp" width="160" alt="Screenshot: Memory version history"></a> |
79
83
  | **Export memory to AGENTS.md** | <a id="feature-memoryexport"></a>In **Open memory**, select a project, then **Export to AGENTS.md**: the notes of that project go into a marked section of `AGENTS.md` in its folder, so you can commit them and share them with your team and other agent tools. You see the change as a diff first; only **Write AGENTS.md** saves it. The next export replaces only that section. The global memory, sources and dates stay out. In Tether: chat title menu → Project memory → Export to AGENTS.md. | <a href="assets/features/memoryExport.webp"><img src="assets/features/memoryExport.webp" width="160" alt="Screenshot: Export memory to AGENTS.md"></a> |
@@ -102,7 +106,7 @@ Then restart dsh. (The CLI can't install into the desktop profile; the app manag
102
106
  | **Option buttons** | <a id="feature-optionpicks"></a>When an answer ends with a list of options (a numbered list of 1 to 9 items under an "Options" heading or a bold "Options" line, also "Next steps" and the same words in the app's languages), a button for each option shows under the answer. A click sends "Option N: …" with the whole option as your message, as if you typed it. The option marked "(recommended)" is marked. The buttons show only under the newest answer, while the chat is idle and the composer is empty; a picked answer and an answer that a rollback withdrew show none. While they show, Next message prediction makes no guess. On a question card of the agent, the keys 1–9 pick that option, as a click does (not in the answer field, and not in the first 0.8 seconds after the question shows). | <a href="assets/features/optionPicks.webp"><img src="assets/features/optionPicks.webp" width="160" alt="Screenshot: Option buttons"></a> |
103
107
  | **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> |
104
108
  | **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> |
105
- | **Remote computers** | <a id="feature-remotecomputers"></a>Open the dsh of your other Macs over [Tailscale](https://tailscale.com) and use them in this dsh window. Switch it on in **Settings → Composer Plus** on each Mac (it is off by default, because it opens network ports). On the Mac that you want to open, switch on **Let other computers open this Mac**, click **Create pairing link** and copy the link. On this Mac, pick **Add a computer…** in the computer picker of the left sidebar (right of the brand, above **New session**), paste the link, type a **Name** (not the name of this Mac or of another computer), click **Connect**, then click **Approve** on the other Mac. The picker then lists **This Mac** and your computers: pick one and its dsh fills this window, with its own chats, sidebar, tools and files, while this Mac keeps running behind it. The picker stays in the same place and says **Back to this Mac**: click it to come back. With more than one computer, the click opens the menu, where you pick **This Mac** or another computer. The Settings panel renames and removes computers, and lists the computers that can open this Mac (**Remove** cuts one off at once). | <a href="assets/features/remoteComputers.webp"><img src="assets/features/remoteComputers.webp" width="160" alt="Screenshot: Remote computers"></a> |
109
+ | **Remote computers** | <a id="feature-remotecomputers"></a>Open the dsh of your other Macs over [Tailscale](https://tailscale.com) and use them in this dsh window. Switch it on in **Settings → Composer Plus** on each Mac (it is off by default, because it opens network ports). On the Mac that you want to open, switch on **Let other computers open this Mac**, click **Create pairing link** and copy the link. On this Mac, pick **Add a computer…** in the computer picker of the left sidebar (right of the brand, above **New session**), paste the link, type a **Name** (not the name of this Mac or of another computer), click **Connect**, then click **Approve** on the other Mac. The picker then lists **This Mac** and your computers: pick one and its dsh fills this window, with its own chats, sidebar, tools and files, while this Mac keeps running behind it. The picker stays in the same place and says **Back to this Mac**: click it to come back. With one other computer, a click on the picker switches between this Mac and it at once (no menu); right-click the picker for the whole menu (**Add a computer…**). With more computers, the click opens the menu, where you pick **This Mac** or another computer. The Settings panel renames and removes computers, and lists the computers that can open this Mac (**Remove** cuts one off at once). | <a href="assets/features/remoteComputers.webp"><img src="assets/features/remoteComputers.webp" width="160" alt="Screenshot: Remote computers"></a> |
106
110
  | **Automatic updates** | <a id="feature-autoupdate"></a>When dsh starts, the plugin checks the [latest GitHub release](https://github.com/furkancak1r/dsh-composer-plus/releases/latest). If it is newer and already on npm, it installs that exact version through dsh's own plugin manager (the same path as Settings → Plugins) and notifies you. Restart dsh to load it. **Settings → Composer Plus → Composer Plus updates** shows the version and has **Check for updates** / **Update now**. The first time dsh starts with the new version, a **What’s new in Composer Plus N** window shows the release notes of that version once, in the language of **Application language** (they come with the new version, no extra network call; a language without notes shows the English notes); **Close** or `Esc` closes it. Below the notes, one line asks for a GitHub star, at most once in 30 days (no network call); after **Star on GitHub** or **Do not ask again**, it does not show again. The window also shows after an update from Settings → Plugins or a copied folder, once per new version; not at the first install. **What’s new in this version** in the update row opens it again. When a newer version is on disk than the one that runs, the row says to restart dsh. | <a href="assets/features/autoUpdate.webp"><img src="assets/features/autoUpdate.webp" width="160" alt="Screenshot: Automatic updates"></a> |
107
111
  | **On/off filter** | <a id="feature-featurefilter"></a>Next to **Search features** in **Settings → Composer Plus**: **All** shows every feature, **On** only the features whose switch is on, and **Off** only the ones whose switch is off. Each row's own switch decides, also a switch that dsh's Host keeps (for example **Mobile connect**). It works with the search: type a word and pick **Off** to find a feature that you switched off. A row that you switch while **On** or **Off** is picked stays until you pick a filter again, so the focus stays on its switch. **On** and **Off** hide the **Application language** and **Composer Plus updates** rows (they have no switch). Settings opens with **All** each time. | <a href="assets/features/featureFilter.webp"><img src="assets/features/featureFilter.webp" width="160" alt="Screenshot: On/off filter"></a> |
108
112
  | **Report an issue** | <a id="feature-issuereport"></a>Settings → Composer Plus → **Report an issue…** (under the intro), or right-click a chat in the sidebar (or open its **…** menu) → **Report a Composer Plus issue…**. Pick a type: **Bug**, **Feature request**, **Improvement**, **Translation** or **Question**. Describe it in your own words and language, then click **Write draft** (or `Cmd/Ctrl+Enter`). One call to dsh's default model writes an English issue: a title with the type's prefix (for example `[Bug]`) and the sections of that type (for a bug: What happened, Steps to reproduce, Expected, Actual), plus one line with the Composer Plus, dsh and system versions. Read and edit the title and the description; **Write again** writes a new draft. **Open issue** opens it in the Composer Plus GitHub repository with your GitHub CLI (`gh`) login and shows its link. The issue is public: text that looks like a key or a password is refused. When `gh` cannot open it, **Open on GitHub instead** opens GitHub's own page with the draft filled in. | <a href="assets/features/issueReport.webp"><img src="assets/features/issueReport.webp" width="160" alt="Screenshot: Report an issue"></a> |
@@ -197,7 +201,7 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
197
201
  - **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.
198
202
  - **Context breakdown:** reads only the chat log on the Host; no model call, no project file.
199
203
  - **Task board:** the board shows dsh's own chats from dsh's own lists in this window; it adds no chat data of its own. **New task** opens dsh's own new chat, and you write the first message in dsh's composer, so approvals, the sandbox and the chat's model apply as usual. The Host half keeps that chat's first message as the card's prompt and sends it (its first 4,000 characters, nothing else) to that chat's model in one more request, with no tools, for up to 3 tags. The prompt, the tags and the start time of each task are kept in `$DSH_HOME/storages/dsh-composer-plus/board-chats.json` (owner-only file, the newest 2,000), with the ids of the chats that you took off the board with **×** or **Clear all** (the newest 5,000); the switch is in `board-switch.json` next to it. Nothing is written to a project folder. **Answer** sends your answer to dsh's own pending request, the same way the chat's own card does. The old task list of earlier versions (`board.json`) stays on disk as it was and is not read. **Progress on hover** reads the chat's log on this Mac. With **Fast (no AI)** (the default), nothing is sent. With **AI summary**, while a running card's progress box shows (or while Tether's board is open, for up to 8 running cards), the Host half sends that chat's newest part (at most about 6,000 characters: your messages, the agent's text replies, its tool calls and the end of their results; no reasoning, no rolled-back messages) to the chat's model, as one request with no tools. It sends again only after the chat moved on, at most once every 20 seconds per chat. The note is kept only in memory; the setting is in `$DSH_HOME/storages/dsh-composer-plus/board-progress.json` (owner-only file).
200
- - **Assistant:** the assistant chat is an ordinary dsh chat in `~/Assistant`; its model calls go to dsh's default model as in any chat. Its tools read your other chats' logs on this Mac (titles, projects, status, and with chat_read their newest messages) and give them to that model only when it calls a tool. Sending, starting, stopping and archiving a chat each wait for your approval. The chat id is kept in `$DSH_HOME/storages/dsh-composer-plus/assistant.json` and the switch in `assistant-switch.json` (owner-only files). Reminders and automations are dsh's own scheduled tasks. Nothing leaves this Mac except the model requests and the web searches that the chat makes.
204
+ - **Assistant:** the assistant chat is an ordinary dsh chat in `~/Assistant`; its model calls go to dsh's default model as in any chat. Its tools read your other chats' logs on this Mac (titles, projects, status, and with chat_read their newest messages) and give them to that model only when it calls a tool. Sending, starting, stopping and archiving a chat each wait for your approval. The chat id is kept in `$DSH_HOME/storages/dsh-composer-plus/assistant.json` and the switch in `assistant-switch.json` (owner-only files). Reminders and automations are dsh's own scheduled tasks. Nothing leaves this Mac except the model requests and the web searches that the chat makes. The assistant-as-a-bot switches keep their state in `assistant-free.json` and `assistant-notify.json` (owner-only files). **Assistant news from chats** puts a short line about another chat (its title, project and at most 300 characters of its last reply or error) into the assistant chat, so that text goes to the assistant's model too; the news waits in memory only.
201
205
  - **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.
202
206
  - **Blocked commands:** the rules and the switch are in `$DSH_HOME/storages/dsh-composer-plus/blocked-commands.json` (owner-only file). The check reads only the command text of each `bash` and `pwsh` call; it runs nothing and sends nothing.
203
207
  - **Secret input:** the value goes from the card (or from Tether, through the gateway, which does not log request bodies) to the Host only in the answer request. The Host writes it to `$DSH_HOME/storages/dsh-composer-plus/secrets/<random name>` (folder 0700, file 0600); nothing goes into the project, the chat log or the tool result. The Host keeps the value in memory to replace it with `[secret]` in later tool results of that chat. The file and that copy go when the chat's turn ends and at dsh start. The switch is in `secrets.json` next to it. A command that the agent runs with the file can send the value where that command sends it: that is the purpose.
@@ -224,7 +228,7 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
224
228
  - **No branch pill on a chat row:** the sidebar is not in “In one list” (in “WorkSpace” and “Workspace Tree”, no chat row shows a pill), the chat had no turn since you installed this version, its folder is not a git repository, or **Git branch on chat rows** is off. After an update, restart dsh (the Host half records the branch).
225
229
  - **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.
226
230
  - **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).
227
- - **Install fails right after a release:** add the version (`dsh-composer-plus@1.24.0`), see the install note above.
231
+ - **Install fails right after a release:** add the version (`dsh-composer-plus@1.25.0`), see the install note above.
228
232
  - **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.
229
233
  - **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.
230
234
  - **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.
@@ -258,7 +262,7 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
258
262
  - **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.
259
263
  - **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.
260
264
  - **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). With an APNs key in `apns.json` (see `tether/README.md`), the Mac sends the notifications through Apple's push service, so they come also while Tether is closed; the Mac must be awake with dsh open. Without the key, the phone gets them only while Tether is open or just went to the background. Tether sends them only after you switch on **Settings → Notifications → Send notifications** in Tether. Tether keeps this switch and its hours separately for each paired Mac. The switch is off by default for each Mac, 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. Each notification shows the Mac and the chat's project (`Studio Mac · recipe-box`), the chat's title and the text: Turn finished shows the agent's last reply. With the APNs key, this text goes through Apple's push service. 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.
261
- - **Remote computers** needs Tailscale on both Macs, and Composer Plus with this feature on the Mac that you open. That Mac must be awake with dsh running. The picker shows only while the left sidebar is open (not in its icon rail). When the other Mac's page has no picker of its own (Composer Plus older than 1.23.0 there), this Mac's picker shows over that page in the same place. With 1.23.0 there, the picker shows that Mac's name: pick **This Mac** in its menu to come back. Each computer that you opened keeps its page in memory until you switch the feature off or restart dsh. On the desktop app, the other Mac's page is an embedded page: dsh's own keyboard shortcuts (for example a new chat) do not work in it, and file downloads, microphone and notifications do not work there either. It uses port 19392 (only one dsh on each Mac can let other computers in). From another Mac's page, the picker switches only among the computers of this Mac: you cannot open a third Mac through the other Mac.
265
+ - **Remote computers** needs Tailscale on both Macs, and Composer Plus with this feature on the Mac that you open. That Mac must be awake with dsh running. The picker shows only while the left sidebar is open (not in its icon rail). When the other Mac's page has no picker of its own (Composer Plus older than 1.23.0 there), this Mac's picker shows over that page in the same place. With 1.23.0 there, the picker shows that Mac's name: pick **This Mac** in its menu to come back. Each computer that you opened keeps its page in memory until you switch the feature off or restart dsh. When the computer did not answer (it was asleep or Tailscale was off), its page is not kept: pick it again and it loads again. On the desktop app, the other Mac's page is an embedded page: dsh's own keyboard shortcuts (for example a new chat) do not work in it, and file downloads, microphone and notifications do not work there either. It uses port 19392 (only one dsh on each Mac can let other computers in). From another Mac's page, the picker switches only among the computers of this Mac: you cannot open a third Mac through the other Mac. The one-click switch counts only computers that are paired and reachable (a computer that must pair again does not count); with one such computer, **Add a computer…** is behind a right-click (on a touch screen: press and hold) or in **Settings → Composer Plus → Remote computers**.
262
266
  - 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.
263
267
  - **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.
264
268
  - **Edit queued message in place** does not change a message that started to send meanwhile, and it does not overwrite a message that changed meanwhile (for example in Tether on the iPhone): a notice tells you. A new image needs a model that takes images (dsh's own image limits apply), and a new file must finish its upload before you can save. Only your own queued messages can be edited: a goal round or a question reply in the queue cannot. After a plugin update, only text-only edits work at once: restart dsh before you save a message with images or files (the Host half loads at start).
@@ -294,7 +298,8 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
294
298
  - **Turkish skill pack** installs a third-party skill: its rules come from the author's GitHub repository, not from Composer Plus, and a new version is used from the next daily check without a review by us. The check proves that the files are the ones GitHub lists for that commit, not that the rules are good. The model decides when to load the skill (the user can also call it by name); the rules apply to Turkish texts only. The Host uses the language that a browser reported last: when two browsers use different languages, the newest one wins. GitHub allows 60 API calls per hour without a login; a refused check keeps the installed copy and shows the reason in Settings.
295
299
  - **Untangle codebase** ships a fixed copy of the skill (caldoai/skills, commit f3cf477): a change upstream comes only with a new Composer Plus version. The skill runs a long goal that can change many files, and its subagents and checks use many tokens. Where the project has no tests, it can change behavior without notice: start it on a branch and read the diff before you merge. A skill with the same name in the project, in a custom skill folder or in `~/.dsh/skills` replaces it. While the switch is off, `/untangle-codebase` goes to the model as plain text.
296
300
  - **Task board** shows the chats that dsh lists in this window: a chat outside a project shows only in **All projects**, and a Branch per chat folder (`<project>/.worktrees/<name>`) counts as its project. A card's column is the chat's live state, so cards cannot be dragged: a chat goes to **Done** when its turn ends, also after an error or a stop, and back to **Doing** when it runs again. The green dot is dsh's own done dot, which dsh keeps only in this window: after a reload, finished chats show without it. **Done** shows the newest 50 chats (**Show N older** shows the rest). **Search projects** finds a project by its name only, not by its folder path. **Active in the last 2 hours** hides a project when each of its chats is older than 2 hours, idle and read; the board still shows the project that you picked. **New task** remembers only the newest new chat of this window: when you open another chat before the first message, that chat stays at the top of **Doing** as **New task** until you write in it, but the board comes back by itself only for the newest one. After a reload, a new chat without a message is not on the board (dsh keeps it as its empty New session). The tags come from one model call per task, from its first message: they can be wrong, and a chat that you did not start on the board has none. The title is dsh's own chat title (dsh's title service, with the chat's model); until it comes, the card shows the first line of the first message. **×** and **Clear all** take cards off the board only: no chat is deleted. **Undo** shows for 8 seconds only, in this window; later, **Removed (N)** → **Put back** brings a card back, and a chat that runs again comes back by itself. **Clear all** asks first and takes the read finished cards of the shown project (all projects with **All projects**), also the ones behind **Show N older**; an unread (green) card stays. dsh keeps its green dot only in this window, so after a reload Clear all can take a card whose answer you did not read. The list is kept on this Mac for every window and for Tether; when it has 5,000 chats, the oldest come back. **Answer** answers only the newest request of the chat: when the chat answered it elsewhere (another window, Tether, Auto Review) or asks something new, the panel says so and sends nothing. Earlier versions had a task list with comments and agent tools; they are gone, and the old `board.json` is not shown. The idea and the look come from [Kanzo](https://github.com/emanuele-em/kanzo) by emanuele-em (AGPL-3.0); Composer Plus uses no code from it. `Cmd+Shift+K` is a dsh shortcut: in a browser on Linux it has no default key (set one on dsh's Keyboard shortcuts page), and a browser extension or another app can take it first. A card leaves **Done** when dsh's own green dot goes (you opened the chat) or, for a chat that finished behind the board while it was the open chat, when that chat shows with no panel over it. This read state lives only in this dsh window, as dsh's own dots: after a reload or in another window every finished chat is read, so it is in **Recently finished**.
297
- - **Assistant** has one chat for all windows of this Mac. It runs with the workspace-write permission mode: it writes files only in `~/Assistant`, and a command outside it asks first. When you switch the chat to a mode without approvals (Full access), dsh rejects each approval, so the assistant cannot send, start, stop or archive a chat. The approval card guards the six tools only: a shell command of the assistant can still reach the network, as in any chat with that mode. On dsh 0.2.0 and 0.2.1, dsh's schedule tools see only the reminders of the assistant chat itself, not the automations of other chats; from dsh 0.2.2, they list and change every scheduled task. chats_list leaves out archived, blank and subagent chats, and the assistant chat itself; "waiting for you" means an open approval, question or plan review in a running chat. chat_read gives the user's messages and the agent's replies (no tool output), at most 50 messages and about 24,000 characters. chat_archive refuses a chat that still runs or has active reminders. A model can still be misled by text that it reads: the approval card is the last check, so read it before you click **Allow once**.
301
+ - **Assistant** has one chat for all windows of this Mac. It runs with the workspace-write permission mode: it writes files only in `~/Assistant`, and a command outside it asks first. When you switch the chat to a mode without approvals (Full access), dsh rejects each approval, so the assistant cannot send, start, stop or archive a chat. The approval card guards the six tools only: a shell command of the assistant can still reach the network, as in any chat with that mode. On dsh 0.2.0 and 0.2.1, dsh's schedule tools see only the reminders of the assistant chat itself, not the automations of other chats; from dsh 0.2.2, they list and change every scheduled task. chats_list leaves out archived, blank and subagent chats, and the assistant chat itself; "waiting for you" means an open approval, question or plan review in a running chat. chat_read gives the user's messages and the agent's replies (no tool output), at most 50 messages and about 24,000 characters. chat_archive refuses a chat that still runs or has active reminders. A model can still be misled by text that it reads: the approval card is the last check, so read it before you click **Allow once**. Parallel topics use dsh's subagent tool: a profile or permission mode without it keeps the old way (one topic at a time, the next message waits in the queue or steers the running turn). The model decides what counts as a long task, so a short question can still take a turn. Each topic's subagent runs with its own tokens; when dsh restarts, a running topic stops (its result does not come back). A result comes back as a new turn of the assistant chat, so it waits while you type in the middle of a turn.
302
+ - **Assistant apart from chats** and **Assistant messages only** hide dsh's own rows with a style rule, found by dsh's sidebar and chat markup (`data-row-key`, `data-chat-flow-kind`): when a dsh update changes that markup, the assistant chat shows in the list again, or its work steps show again. The rows are hidden, not removed: dsh's keyboard navigation in the sidebar can still reach a hidden row. **Assistant always free** refuses each tool call of the assistant chat that is not one of its short tools; the model then gives the step to a subagent, but it can try the refused call first, which costs one model step. While an approval card waits for you, the assistant chat still counts as busy. When its newest request has no subagent tool (a permission mode or profile without it), the rule does nothing. **Assistant news from chats** starts a model turn of the assistant chat for each batch of news, so it uses tokens; with **Mobile connect (iPhone)** on, your phone can get two notifications for one finished chat (the chat's own and the assistant's). News that waits is lost when dsh restarts. It sees only chats on this Mac.
298
303
  - **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.
299
304
  - **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.
300
305
  - **Memory version history** keeps the newest 50 versions of each memory (each project and the global memory); older ones go. A version holds the whole memory of that project, not one note. **Restore** puts back every file of that version (topics included) and refuses when the memory changed after you opened the version; the memory before the restore becomes a new version, so you can undo it. While the switch is off, no new version is kept and **Restore** refuses; the kept versions stay. A version from before this feature does not exist: the history starts with the first save after you install it.
@@ -348,7 +353,9 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
348
353
 
349
354
  **Can I see all my chats as a kanban board and start new ones from it?** Yes, with **Task board** (on by default): open it in the left sidebar. Each chat is a card in **Doing**, **Review** (it waits for you) or **Done**. **New task** opens dsh's new chat in the project, and the board comes back when your first message goes; click **Answer** on an orange card to answer it without opening the chat. **Clear all** in **Done** asks first and takes the finished cards that you read off the board; **Undo** and **Removed (N)** bring them back, and the chats stay in dsh.
350
355
 
351
- **Can I have a personal assistant chat that reminds me and manages my other chats?** Yes, with **Assistant** (off by default): switch it on in Settings → Composer Plus, then click **Assistant** in the left sidebar. It sets reminders with dsh's scheduled tasks, searches the web, lists and reads your chats, and sends a message to a chat or starts, stops or archives one only after you approve it. Keep your profile in its project memory, topic "profil".
356
+ **Can I have a personal assistant chat that reminds me and manages my other chats?** Yes, with **Assistant** (on by default): click **Assistant** in the left sidebar. It sets reminders with dsh's scheduled tasks, searches the web, lists and reads your chats, and sends a message to a chat or starts, stops or archives one only after you approve it. Keep your profile in its project memory, topic "profil".
357
+
358
+ **Can the assistant stay out of my chat list and work like a bot?** Yes. **Assistant apart from chats** takes its chat out of the sidebar list and shows its state on the **Assistant** row (orange while it waits for you). **Assistant messages only** hides its work steps. **Assistant always free** makes it give every longer step to a background subagent, so it answers at once. **Assistant news from chats** (off by default, it uses tokens) makes it tell you when another chat finishes, fails or waits for you.
352
359
 
353
360
  **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.
354
361
 
@@ -502,8 +509,10 @@ SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-queue-stop-send.mjs /pat
502
509
  SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-queue-edit.mjs /path/to/dsh/lib/bin.js
503
510
  # Task board: New task opens dsh's new chat and comes back after the first message, AI tags, live columns, Answer on the board, × with Undo, Clear all with its question (unread cards stay), Removed and Put back (kept after a restart), the switch
504
511
  SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-task-board.mjs /path/to/dsh/lib/bin.js
505
- # Assistant: off by default, sidebar row under Task board, one chat in ~/Assistant (workspace-write), a reminder that runs the chat, chats_list, chat_send after its approval card, an injected chat_send rejected, no tools in other chats, automations of other chats (dsh 0.2.2+), switch off
512
+ # Assistant: on by default, sidebar row under Task board, one chat in ~/Assistant (workspace-write), a reminder that runs the chat, chats_list, chat_send after its approval card, an injected chat_send rejected, no tools in other chats, automations of other chats (dsh 0.2.2+), switch off
506
513
  SHOT=1 CHECK_DELAY=20 PLAYWRIGHT=/path/to/playwright node test/browser-assistant.mjs /path/to/dsh/lib/bin.js
514
+ # Assistant welcome card: shows above the input on the first open of the assistant chat, goes with the switch and with the first message, not in other chats
515
+ PLAYWRIGHT=/path/to/playwright node test/browser-assistant-welcome.mjs /path/to/dsh/lib/bin.js
507
516
  ```
508
517
 
509
518
  ```sh