sanook-cli 0.5.0 → 0.5.2

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.
Files changed (146) hide show
  1. package/.env.example +161 -3
  2. package/CHANGELOG.md +83 -5
  3. package/README.md +240 -23
  4. package/README.th.md +87 -6
  5. package/dist/approval.js +6 -0
  6. package/dist/bin.js +3045 -210
  7. package/dist/brain-context.js +223 -0
  8. package/dist/brain-doctor.js +318 -0
  9. package/dist/brain-eval.js +186 -0
  10. package/dist/brain-final.js +371 -0
  11. package/dist/brain-review.js +382 -0
  12. package/dist/brain.js +12 -1
  13. package/dist/brand.js +1 -1
  14. package/dist/cli-args.js +152 -0
  15. package/dist/cli-option-values.js +16 -0
  16. package/dist/commands.js +172 -13
  17. package/dist/compaction.js +96 -11
  18. package/dist/config.js +118 -28
  19. package/dist/context-compression.js +191 -0
  20. package/dist/cost.js +49 -15
  21. package/dist/first-run.js +21 -0
  22. package/dist/gateway/auth.js +37 -8
  23. package/dist/gateway/bluebubbles.js +205 -0
  24. package/dist/gateway/config.js +929 -0
  25. package/dist/gateway/deliver.js +357 -0
  26. package/dist/gateway/discord.js +124 -0
  27. package/dist/gateway/email.js +472 -0
  28. package/dist/gateway/googlechat.js +207 -0
  29. package/dist/gateway/homeassistant.js +256 -0
  30. package/dist/gateway/ledger.js +18 -0
  31. package/dist/gateway/line.js +171 -0
  32. package/dist/gateway/lock.js +3 -1
  33. package/dist/gateway/matrix.js +366 -0
  34. package/dist/gateway/mattermost.js +322 -0
  35. package/dist/gateway/ntfy.js +218 -0
  36. package/dist/gateway/schedule.js +31 -4
  37. package/dist/gateway/serve.js +267 -7
  38. package/dist/gateway/server.js +253 -19
  39. package/dist/gateway/service.js +224 -0
  40. package/dist/gateway/session.js +343 -0
  41. package/dist/gateway/signal.js +351 -0
  42. package/dist/gateway/slack.js +124 -0
  43. package/dist/gateway/sms.js +169 -0
  44. package/dist/gateway/targets.js +576 -0
  45. package/dist/gateway/teams.js +106 -0
  46. package/dist/gateway/telegram.js +38 -15
  47. package/dist/gateway/webhooks.js +220 -0
  48. package/dist/gateway/whatsapp.js +230 -0
  49. package/dist/hooks.js +13 -2
  50. package/dist/insights-args.js +35 -0
  51. package/dist/insights.js +86 -0
  52. package/dist/loop.js +123 -24
  53. package/dist/lsp/index.js +23 -5
  54. package/dist/mcp-registry.js +350 -0
  55. package/dist/mcp-server.js +1 -1
  56. package/dist/mcp.js +44 -6
  57. package/dist/memory.js +100 -33
  58. package/dist/orchestrate.js +49 -19
  59. package/dist/personality.js +58 -0
  60. package/dist/providers/codex.js +86 -38
  61. package/dist/providers/keys.js +1 -1
  62. package/dist/providers/models.js +22 -6
  63. package/dist/providers/registry.js +38 -49
  64. package/dist/search/chunk.js +7 -8
  65. package/dist/search/cli.js +75 -0
  66. package/dist/search/embed-store.js +3 -0
  67. package/dist/search/indexer.js +44 -1
  68. package/dist/search/store.js +23 -1
  69. package/dist/session.js +93 -7
  70. package/dist/skill-install.js +29 -12
  71. package/dist/support-dump.js +175 -0
  72. package/dist/tools/edit.js +45 -15
  73. package/dist/tools/git.js +10 -5
  74. package/dist/tools/homeassistant.js +106 -0
  75. package/dist/tools/index.js +5 -0
  76. package/dist/tools/list.js +19 -6
  77. package/dist/tools/permission.js +923 -9
  78. package/dist/tools/read.js +16 -4
  79. package/dist/tools/schedule.js +19 -3
  80. package/dist/tools/search.js +217 -13
  81. package/dist/tools/task.js +18 -7
  82. package/dist/tools/timeout.js +21 -3
  83. package/dist/trust.js +11 -1
  84. package/dist/ui/app.js +57 -11
  85. package/dist/ui/brain-wizard.js +2 -2
  86. package/dist/ui/history.js +37 -5
  87. package/dist/ui/mentions.js +3 -2
  88. package/dist/ui/render.js +55 -15
  89. package/dist/ui/setup.js +107 -10
  90. package/dist/update.js +24 -11
  91. package/dist/worktree.js +175 -4
  92. package/package.json +4 -4
  93. package/second-brain/AGENTS.md +6 -4
  94. package/second-brain/CLAUDE.md +7 -1
  95. package/second-brain/Evals/_Index.md +10 -2
  96. package/second-brain/Evals/quality-ledger.md +9 -1
  97. package/second-brain/Evals/second-brain-benchmarks.md +62 -0
  98. package/second-brain/GEMINI.md +5 -4
  99. package/second-brain/Home.md +1 -1
  100. package/second-brain/Projects/_Index.md +3 -1
  101. package/second-brain/Projects/sanook-cli/_Index.md +26 -0
  102. package/second-brain/Projects/sanook-cli/second-brain-feature-roadmap.md +156 -0
  103. package/second-brain/README.md +1 -1
  104. package/second-brain/Research/2026-06-17-ai-second-brain-method-experiment.md +108 -0
  105. package/second-brain/Research/2026-06-18-ai-token-reduction-frameworks.md +55 -0
  106. package/second-brain/Research/2026-06-18-hermes-cli-second-brain-expansion-research.md +160 -0
  107. package/second-brain/Research/2026-06-18-sanook-mcp-ecosystem-and-ux-roadmap.md +181 -0
  108. package/second-brain/Research/_Index.md +6 -1
  109. package/second-brain/Reviews/2026-06-18-auto-improve-maintenance.md +54 -0
  110. package/second-brain/Reviews/_Index.md +1 -1
  111. package/second-brain/Runbooks/_Index.md +6 -1
  112. package/second-brain/Runbooks/ai-second-brain-operating-sequence.md +108 -0
  113. package/second-brain/SANOOK.md +45 -0
  114. package/second-brain/Sessions/2026-06-17-ai-framework-additional-zones.md +68 -0
  115. package/second-brain/Sessions/2026-06-17-ai-second-brain-sequence-experiment.md +63 -0
  116. package/second-brain/Sessions/2026-06-18-cli-args-release-readiness.md +59 -0
  117. package/second-brain/Sessions/2026-06-18-final-gate-template-final.md +192 -0
  118. package/second-brain/Sessions/2026-06-18-final-gate-template.md +71 -0
  119. package/second-brain/Sessions/2026-06-18-framework-dogfood-permission-and-memory.md +58 -0
  120. package/second-brain/Sessions/2026-06-18-hermes-second-brain-expansion-research.md +52 -0
  121. package/second-brain/Sessions/2026-06-18-mcp-ecosystem-and-sanook-ux-scan.md +81 -0
  122. package/second-brain/Sessions/2026-06-18-sanook-brain-cli-p0-implementation.md +86 -0
  123. package/second-brain/Sessions/2026-06-18-sanook-brain-final-cli-final.md +246 -0
  124. package/second-brain/Sessions/2026-06-18-sanook-brain-final-cli.md +78 -0
  125. package/second-brain/Sessions/2026-06-18-sanook-cli-second-brain-roadmap-correction.md +54 -0
  126. package/second-brain/Sessions/2026-06-18-token-reduction-framework-integration.md +69 -0
  127. package/second-brain/Sessions/_Index.md +15 -1
  128. package/second-brain/Shared/AI-Context-Index.md +22 -0
  129. package/second-brain/Shared/Context-Packs/_Index.md +9 -1
  130. package/second-brain/Shared/Context-Packs/coding-release.md +51 -0
  131. package/second-brain/Shared/Context-Packs/research-to-framework.md +51 -0
  132. package/second-brain/Shared/Context-Packs/second-brain-maintenance.md +41 -0
  133. package/second-brain/Shared/Operating-State/current-state.md +22 -3
  134. package/second-brain/Shared/Scripts/_Index.md +3 -1
  135. package/second-brain/Shared/Scripts/ai-second-brain-method-eval.mjs +198 -0
  136. package/second-brain/Shared/Tech-Standards/_Index.md +4 -1
  137. package/second-brain/Shared/Tech-Standards/mcp-integration-roadmap.md +86 -0
  138. package/second-brain/Shared/Tech-Standards/verification-standard.md +24 -0
  139. package/second-brain/Shared/User-Memory/_Index.md +4 -1
  140. package/second-brain/Shared/User-Memory/response-examples.md +98 -0
  141. package/second-brain/Shared/User-Memory/user-preferences.md +1 -0
  142. package/second-brain/Templates/_Index.md +9 -0
  143. package/second-brain/Templates/final-lite.md +111 -0
  144. package/second-brain/Templates/final.md +231 -0
  145. package/second-brain/Vault Structure Map.md +2 -1
  146. package/skills/structured-output-llm/SKILL.md +1 -1
package/.env.example CHANGED
@@ -8,12 +8,9 @@ GOOGLE_GENERATIVE_AI_API_KEY=AIzaxxx # aistudio.google.com/apikey (restrict
8
8
 
9
9
  # ── Cloud BYOK ──
10
10
  OPENAI_API_KEY=sk-xxx # platform.openai.com (รวม Codex: model gpt-5-codex)
11
- DEEPSEEK_API_KEY=sk-xxx # platform.deepseek.com
12
11
  XAI_API_KEY=xai-xxx # console.x.ai
13
12
  MISTRAL_API_KEY=xxx # console.mistral.ai
14
13
  GROQ_API_KEY=gsk_xxx # console.groq.com
15
- MINIMAX_API_KEY=xxx # platform.minimax.io (MINIMAX_BASE_URL สลับ region)
16
- ZHIPU_API_KEY=xxx # z.ai / open.bigmodel.cn (GLM — GLM_BASE_URL สลับ region)
17
14
 
18
15
  # ── Local (ไม่ต้อง key — ตั้ง baseURL ถ้าไม่ใช่ default) ──
19
16
  # OLLAMA_BASE_URL=http://localhost:11434/v1
@@ -40,3 +37,164 @@ SANOOK_MODEL=sonnet
40
37
  # SANOOK_DISABLE_PERSISTENCE=1 # ไม่บันทึก sessions/memory
41
38
  # SANOOK_DISABLE_WORKLOG=1 # ไม่เขียน worklog เข้า second-brain
42
39
  # SANOOK_TRUST_PROJECT=1 # trust project .sanook mcp/hooks/skills/commands ชั่วคราว
40
+
41
+ # ── Messaging gateway (optional; ใช้กับ sanook gateway / sanook send) ──
42
+ # Telegram
43
+ # TELEGRAM_BOT_TOKEN=123:abc
44
+ # TELEGRAM_ALLOWED_CHATS=5222385839
45
+
46
+ # Discord
47
+ # DISCORD_BOT_TOKEN=xxx
48
+ # DISCORD_DEFAULT_CHANNEL=123456789012345678
49
+ # DISCORD_ALLOWED_CHANNELS=123456789012345678
50
+
51
+ # Slack
52
+ # SLACK_BOT_TOKEN=xoxb-xxx
53
+ # SLACK_APP_TOKEN=xapp-xxx # ต้องมีถ้าจะรับข้อความผ่าน Socket Mode
54
+ # SLACK_DEFAULT_CHANNEL=C01ABCDEF
55
+ # SLACK_ALLOWED_CHANNELS=C01ABCDEF
56
+
57
+ # Email
58
+ # EMAIL_ADDRESS=bot@example.com
59
+ # EMAIL_PASSWORD=app-password
60
+ # EMAIL_IMAP_HOST=imap.example.com
61
+ # EMAIL_SMTP_HOST=smtp.example.com
62
+ # EMAIL_HOME_ADDRESS=you@example.com
63
+
64
+ # LINE Messaging API (webhook inbound + Push/send + cron delivery)
65
+ # LINE_CHANNEL_ACCESS_TOKEN=xxx
66
+ # LINE_CHANNEL_SECRET=xxx # ใช้ verify x-line-signature ของ webhook
67
+ # LINE_HOME_CHANNEL=U1234567890abcdef # U=user, C=group, R=room
68
+ # LINE_ALLOWED_USERS=U1234567890abcdef
69
+ # LINE_ALLOWED_GROUPS=C1234567890abcdef
70
+ # LINE_ALLOWED_ROOMS=R1234567890abcdef
71
+ # LINE_PUBLIC_URL=https://your-tunnel.example.com
72
+
73
+ # SMS / Twilio (webhook inbound + REST send + cron delivery)
74
+ # TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
75
+ # TWILIO_AUTH_TOKEN=xxx # ใช้ส่ง SMS และ verify x-twilio-signature
76
+ # TWILIO_PHONE_NUMBER=+15550000000
77
+ # SMS_HOME_CHANNEL=+15551234567
78
+ # SMS_ALLOWED_USERS=+15551234567,+15557654321
79
+ # SMS_WEBHOOK_URL=https://your-tunnel.example.com/sms/webhook
80
+ # SMS_INSECURE_NO_SIGNATURE=false # local dev only; production ควร false/ไม่ตั้ง
81
+
82
+ # ntfy (HTTP push + JSON stream subscribe)
83
+ # NTFY_TOPIC=sanook-yourname-2026
84
+ # NTFY_SERVER_URL=https://ntfy.sh
85
+ # NTFY_TOKEN=tk_xxx # optional; หรือ user:pass สำหรับ Basic auth
86
+ # NTFY_PUBLISH_TOPIC=sanook-yourname-2026
87
+ # NTFY_ALLOWED_USERS=sanook-yourname-2026
88
+ # NTFY_HOME_CHANNEL=sanook-yourname-2026
89
+ # NTFY_HOME_CHANNEL_NAME=Owner phone
90
+ # NTFY_MARKDOWN=true
91
+
92
+ # Mattermost REST API v4 + WebSocket inbound
93
+ # MATTERMOST_URL=https://mm.example.com
94
+ # MATTERMOST_TOKEN=xxx # token ของ bot/dedicated account
95
+ # MATTERMOST_HOME_CHANNEL=chan_home_id
96
+ # MATTERMOST_HOME_CHANNEL_NAME=Owner Mattermost
97
+ # MATTERMOST_ALLOWED_USERS=user_id_1,user_id_2 # fail-closed; ใช้ Mattermost user IDs
98
+ # MATTERMOST_ALLOWED_CHANNELS=chan_home_id,chan_ops_id
99
+ # MATTERMOST_FREE_RESPONSE_CHANNELS=chan_dm_like_id
100
+ # MATTERMOST_REQUIRE_MENTION=true # public/private channels ต้อง @mention; DM ตอบทุกข้อความ
101
+ # MATTERMOST_GROUP_SESSIONS_PER_USER=true
102
+ # MATTERMOST_REPLY_MODE=thread # off|thread
103
+ # MATTERMOST_ALLOW_ALL_USERS=false # production ควร false/ไม่ตั้ง
104
+
105
+ # Home Assistant (state_changed WebSocket inbound + persistent_notification send)
106
+ # HASS_URL=http://homeassistant.local:8123
107
+ # HASS_TOKEN=xxx # Long-Lived Access Token
108
+ # HASS_HOME_CHANNEL=sanook_agent # persistent_notification notification_id
109
+ # HASS_HOME_CHANNEL_NAME=Owner Home Assistant
110
+ # HASS_WATCH_DOMAINS=light,binary_sensor,climate
111
+ # HASS_WATCH_ENTITIES=sensor.temp,alarm_control_panel.home
112
+ # HASS_IGNORE_ENTITIES=sensor.noisy
113
+ # HASS_WATCH_ALL=false # production ควร false/ไม่ตั้ง
114
+ # HASS_COOLDOWN_SECONDS=30
115
+
116
+ # Signal via signal-cli daemon --http (JSON-RPC send + SSE inbound)
117
+ # SIGNAL_HTTP_URL=http://127.0.0.1:8080
118
+ # SIGNAL_ACCOUNT=+15550000000
119
+ # SIGNAL_HOME_CHANNEL=+15551234567
120
+ # SIGNAL_HOME_CHANNEL_NAME=Owner Signal
121
+ # SIGNAL_ALLOWED_USERS=+15551234567,+15557654321
122
+ # SIGNAL_GROUP_ALLOWED_USERS=groupIdBase64 # หรือ * เพื่อเปิดทุกกลุ่มโดยตั้งใจ
123
+ # SIGNAL_REQUIRE_MENTION=false # true = group ต้อง mention เบอร์ account
124
+
125
+ # WhatsApp Cloud API (Meta webhook inbound + Graph Messages API send)
126
+ # WHATSAPP_CLOUD_PHONE_NUMBER_ID=123456789012345
127
+ # WHATSAPP_CLOUD_ACCESS_TOKEN=EAA...
128
+ # WHATSAPP_CLOUD_APP_SECRET=xxx # ใช้ verify x-hub-signature-256 ของ webhook
129
+ # WHATSAPP_CLOUD_VERIFY_TOKEN=choose-a-long-random-token
130
+ # WHATSAPP_CLOUD_HOME_CHANNEL=15551234567 # wa_id digits, ไม่ต้องมี +
131
+ # WHATSAPP_CLOUD_HOME_CHANNEL_NAME=Owner WhatsApp
132
+ # WHATSAPP_CLOUD_ALLOWED_USERS=15551234567,15557654321
133
+ # WHATSAPP_CLOUD_PUBLIC_URL=https://your-tunnel.example.com
134
+ # WHATSAPP_CLOUD_API_VERSION=v20.0
135
+ # WHATSAPP_CLOUD_ALLOW_ALL_USERS=false # production ควร false/ไม่ตั้ง
136
+
137
+ # Matrix Client-Server API (sync inbound + room send)
138
+ # MATRIX_HOMESERVER=https://matrix.example.org
139
+ # MATRIX_ACCESS_TOKEN=syt_xxx # แนะนำ: token ของ bot account
140
+ # MATRIX_USER_ID=@sanook:matrix.example.org # optional ถ้าใช้ access token; required ถ้าใช้ password login
141
+ # MATRIX_PASSWORD=xxx # fallback แทน access token
142
+ # MATRIX_HOME_ROOM=!abc123:matrix.example.org
143
+ # MATRIX_HOME_ROOM_NAME=Owner Matrix
144
+ # MATRIX_ALLOWED_USERS=@alice:matrix.org,@bob:matrix.org
145
+ # MATRIX_ALLOWED_ROOMS=!abc123:matrix.example.org,!ops:matrix.example.org
146
+ # MATRIX_FREE_RESPONSE_ROOMS=!free:matrix.example.org
147
+ # MATRIX_REQUIRE_MENTION=true # shared rooms ต้อง mention bot; DM ตอบทุกข้อความ
148
+ # MATRIX_GROUP_SESSIONS_PER_USER=true
149
+ # MATRIX_AUTO_JOIN=true
150
+ # MATRIX_POLL_TIMEOUT_MS=30000
151
+
152
+ # Google Chat (Chat REST API outbound; Pub/Sub config saved for future inbound)
153
+ # GOOGLE_CHAT_PROJECT_ID=my-chat-bot-123
154
+ # GOOGLE_CHAT_SUBSCRIPTION_NAME=projects/my-chat-bot-123/subscriptions/sanook-chat-events-sub
155
+ # GOOGLE_CHAT_SERVICE_ACCOUNT_JSON=/home/you/.sanook/google-chat-sa.json
156
+ # GOOGLE_CHAT_API_BASE_URL=https://chat.googleapis.com
157
+ # GOOGLE_CHAT_HOME_CHANNEL=spaces/AAAA # use googlechat:spaces/AAAA/threads/thread-id for thread replies
158
+ # GOOGLE_CHAT_HOME_CHANNEL_NAME=Owner Google Chat
159
+ # GOOGLE_CHAT_ALLOWED_USERS=you@yourdomain.com,coworker@yourdomain.com
160
+ # GOOGLE_CHAT_ALLOWED_SPACES=spaces/AAAA,spaces/BBBB # explicit proactive send targets; home channel is allowed by default
161
+ # GOOGLE_CHAT_FREE_RESPONSE_SPACES=spaces/FREE
162
+ # GOOGLE_CHAT_MAX_MESSAGES=1
163
+ # GOOGLE_CHAT_MAX_BYTES=16777216
164
+ # GOOGLE_CHAT_ALLOW_ALL_USERS=false
165
+ # GOOGLE_CHAT_ALLOW_ALL_SPACES=false
166
+ # GOOGLE_CHAT_INCOMING_WEBHOOK_URL=https://chat.googleapis.com/v1/spaces/AAAA/messages?key=xxx&token=xxx
167
+
168
+ # BlueBubbles / iMessage (REST outbound now; webhook config saved for inbound parity)
169
+ # BLUEBUBBLES_SERVER_URL=http://localhost:1234
170
+ # BLUEBUBBLES_PASSWORD=xxx
171
+ # BLUEBUBBLES_WEBHOOK_HOST=127.0.0.1
172
+ # BLUEBUBBLES_WEBHOOK_PORT=8645
173
+ # BLUEBUBBLES_WEBHOOK_PATH=/bluebubbles-webhook
174
+ # BLUEBUBBLES_HOME_CHANNEL=user@example.com # chat GUID, email, or +E.164 phone; raw GUID like iMessage;-;user@example.com also works
175
+ # BLUEBUBBLES_HOME_CHANNEL_NAME=Owner iMessage
176
+ # BLUEBUBBLES_ALLOWED_USERS=user@example.com,+15551234567
177
+ # BLUEBUBBLES_ALLOW_ALL_USERS=false # production ควร false/ไม่ตั้ง
178
+ # BLUEBUBBLES_REQUIRE_MENTION=false # group chat inbound gate for future gateway run parity
179
+ # BLUEBUBBLES_MENTION_PATTERNS=["(?<![\\w@])@?sanook\\b[,:\\-]?"]
180
+
181
+ # Microsoft Teams (Incoming Webhook delivery now; Graph delivery for chat/channel targets)
182
+ # TEAMS_DELIVERY_MODE=incoming_webhook # incoming_webhook|graph
183
+ # TEAMS_INCOMING_WEBHOOK_URL=https://...
184
+ # TEAMS_GRAPH_ACCESS_TOKEN=xxx # Graph mode: delegated/application token with ChatMessage.Send/ChannelMessage.Send
185
+ # TEAMS_CHAT_ID=19:...
186
+ # TEAMS_TEAM_ID=team-id
187
+ # TEAMS_CHANNEL_ID=channel-id
188
+ # TEAMS_HOME_CHANNEL=19:... # หรือ team/<team-id>/channel/<channel-id>
189
+ # TEAMS_HOME_CHANNEL_NAME=Owner Teams
190
+ # TEAMS_CLIENT_ID=app-client-id # สำหรับ future Bot Framework inbound parity
191
+ # TEAMS_CLIENT_SECRET=xxx
192
+ # TEAMS_TENANT_ID=tenant-id
193
+ # TEAMS_ALLOWED_USERS=alice@example.com,bob@example.com
194
+ # TEAMS_PORT=3978
195
+
196
+ # Generic Webhooks (GitHub/GitLab/Jira/Stripe/etc. inbound events)
197
+ # WEBHOOK_ENABLED=true
198
+ # WEBHOOK_SECRET=xxx # global fallback HMAC secret
199
+ # WEBHOOK_PUBLIC_URL=https://your-tunnel.example.com
200
+ # WEBHOOK_RATE_LIMIT_PER_MINUTE=30
package/CHANGELOG.md CHANGED
@@ -1,6 +1,85 @@
1
1
  # Changelog
2
2
 
3
- ## Unreleased
3
+ ## 0.5.2
4
+
5
+ ### Token reduction — selective context compression for stale tool output
6
+
7
+ - **`contextCompression: "selective" | "headroom" | "off"`** (env `SANOOK_CONTEXT_COMPRESSION`) — default `"selective"` is a zero-LLM, per-step compressor inspired by Selective Context, LongLLMLingua-style query awareness, and Headroom-style context pruning. It keeps the latest tool results full, but compresses older huge tool outputs with recency-aware budgets and preserves anchors plus high-information lines (current-query matches, errors, paths, diffs, code structure, rare terms) before the next model request. `"headroom"` optionally wraps the Vercel AI SDK model with the `headroom-ai` GitHub/npm framework when a Headroom proxy/cloud setup is available; `"off"` disables compression.
8
+
9
+ ### MCP registry UX — discover, install, and diagnose servers
10
+
11
+ - **`sanook mcp search/info/install`** — browse the official MCP registry, inspect transports/packages/secret requirements, and write a ready-to-use stdio or Streamable-HTTP config into `~/.sanook/mcp.json` (or trusted project config with `--project`).
12
+ - **`sanook mcp test` / `sanook mcp doctor` / `sanook mcp list --tools`** — probe configured MCP servers, show advertised tools, and fail clearly when a server is missing credentials, unreachable, or misconfigured.
13
+ - **`sanook mcp preset`** — curated starter bundles (`dev`, `research`, `pm`, `ops`) for common Sanook workflows.
14
+
15
+ ### Second-brain CLI tooling — doctor, context, eval
16
+
17
+ - **`sanook brain context [--task "..."]`** — shows the exact `<brain_vault>` context Sanook injects from `Shared/AI-Context-Index.md`, `current-state.md`, and Memory-Inbox, with source char counts and stale/missing index warnings. With `--task`, it also runs focused retrieval over vault/session/skill hits.
18
+ - **`sanook brain eval`** — turns `Evals/second-brain-benchmarks.md` into a lightweight runner: static vault sanity checks, context-size/missing-source checks, index freshness, and retrieval probes for key rules/ledgers.
19
+ - **`sanook brain review`** — curator-style vault review for Memory-Inbox duplicates/possible contradictions, stale or incomplete context packs, session notes missing from the search manifest, eval freshness after framework changes, and markdown routing hygiene.
20
+ - **`sanook brain final [--task "..."] [--from-diff] [--lite]`** — creates an evidence-backed final gate note in `Sessions/`, optionally prefilled from the current git diff, and links it from `Sessions/_Index.md`. `brain review` now validates final gates for missing evidence/TODO placeholders, while `brain eval` keeps the full and lite templates covered.
21
+ - **Context assembly is inspectable without drift**: `buildBrainContext()` now exposes typed source parts and renders from the same parts used by the agent prompt.
22
+ - **Fresh scaffold discoverability**: generated `Shared/Context-Packs/_Index.md` now links the bundled context packs, so review/search can find them immediately.
23
+
24
+ ### Whole-codebase audit — confirmed bugs fixed across the CLI
25
+
26
+ A multi-agent review swept every subsystem (agent loop, tools, providers, gateway, MCP, search, orchestration) and adversarially verified each finding. The ones fixed here:
27
+
28
+ **High**
29
+ - **`edit_file` silently stripped indentation.** The whitespace-flexible match tier matched an indented block by trimmed lines but spliced the (un-indented) replacement verbatim — de-indenting code and breaking Python/YAML, invisibly. It now re-applies the file's indentation to the replacement.
30
+ - **Codex delegate could never edit files + ran in the wrong directory.** `sanook -m codex` ran with `--sandbox read-only` unconditionally (a "coding agent" that silently couldn't write) and ignored worktree `cwd`. It now uses `workspace-write` in auto mode (read-only under plan/ask), threads `cwd`, and passes prior conversation so REPL turns aren't contextless.
31
+ - **Worktree rollback could lose a renamed file.** The pre-apply snapshot only captured destination paths, so a failed 3-way apply of a rename didn't restore the deleted source. Snapshots now cover both sides of renames/copies (and parse git-quoted paths).
32
+
33
+ **Medium** — git tools now run in the sub-agent's worktree (`git_commit --addAll` no longer commits the main repo); LSP child process no longer leaks on init failure/timeout (+ init timeout, + Windows `.cmd` shell, + Windows-critical env); Codex no longer crashes the CLI on an EPIPE; the model-fallback path no longer duplicates streamed output; MCP server stderr is drained (was hanging when the pipe filled); an untrusted project can no longer disable the budget cap or spoof pricing; the Telegram bot skips its backlog on startup (no replaying old commands); hooks get Windows-critical env.
34
+
35
+ **Low** — `replace_all` reports the real replacement count; the multi-match hint no longer suggests `replace_all` for flex matches (dead-end); a malformed trusted-project `hooks.json` no longer crashes the run; frontmatter-only notes with no trailing newline no longer leak the frontmatter into the indexed body; the gateway returns 400/413 (not 500) for bad/oversized request bodies.
36
+
37
+ **Follow-up medium fixes** — `sanook index` now builds and saves the semantic vector sidecar, so `--mode semantic|hybrid` no longer silently degrades to BM25 after a reindex; subagent fan-out has a global process-wide concurrency cap; `budgetUsd` is shared across the whole agent tree instead of resetting per subagent; isolated write subagents no longer inherit the interactive approval loop inside their temp worktree after the parent approved `task_parallel`; `/v1/chat/completions` now supports OpenAI-style `stream:true` SSE chunks.
38
+
39
+ **Follow-up low fixes** — protected path checks resolve symlink ancestors before allowing writes; search chunk ids use a stronger SHA-256-derived path hash; oversized MCP tool text is capped before entering model context; malformed search manifests are sanitized on load without discarding a valid index; a setup-wizard timing test now waits for the rendered validation frame instead of flaking under full-suite load.
40
+
41
+ ### Fix: couldn't type in the REPL after first-run setup
42
+
43
+ The setup wizard and the REPL were two separate Ink renders (`render(SetupWizard)` → `unmount` → `render(App)`). After the first Ink instance unmounted, stdin raw-mode/keypress handling didn't reattach to the second, so the chat input was dead — you couldn't type anything. Now the wizard, the brain wizard, and the REPL live under **one Ink render** (a `Root` component swaps screens), so stdin stays continuous and input works the moment the REPL appears. (Regression-tested with ink-testing-library: typed characters reach the input box; phase routing verified.)
44
+
45
+ ### Setup/first-run audit — 8 bugs found by adversarial review, all fixed
46
+
47
+ A multi-agent review of the first-run + setup + REPL flow surfaced (and independently verified) eight real, user-facing bugs — now fixed and regression-tested:
48
+
49
+ - **Empty API key silently completed setup.** `@inkjs/ui` PasswordInput fires `onSubmit` on Enter even when empty, so pressing Enter on a blank key advanced the wizard, finished, and saved *no key* — the first message then failed with "no API key" and no way back. The key step now rejects an empty submit (stays put, shows an inline error).
50
+ - **Wizard accepted OAuth/malformed keys it explicitly warned against.** The key step now runs the same `assertDirectApiKey` policy the runtime uses — paste a `sk-ant-oat…` subscription token and it's rejected *at the input* with a clear message, instead of being saved and blowing up later.
51
+ - **No way back from the key/model steps.** Picking the wrong provider dead-ended you into typing a key for the wrong service (Ctrl+C was the only escape). **Esc now returns to provider selection** from any step.
52
+ - **First-run env-detect trusted banned tokens.** An exported OAuth token (`ANTHROPIC_API_KEY=sk-ant-oat…`) made sanook print "✅ ready" and skip the wizard, then error on every message. `detectEnvProvider` now validates the key against policy (new `hasUsableEnvKey`) and falls through to the wizard when it's unusable.
53
+ - **First-run ignored an explicit `-m` flag.** `sanook -m groq` on a machine with only `OPENAI_API_KEY` printed "OpenAI ready" and ran a keyless Groq session. First-run now keys off the `-m` provider when given.
54
+ - **Codex auth step could wedge.** `detectCodex` had no timeout, so a hung `codex` binary left the step with no way forward. Added a 5s timeout (+ Esc always backs out).
55
+ - **Brain wizard name fields were pre-filled with the literal default** (`Owner` / `ผู้ช่วย`), so typing a custom name produced `OwnerPick`. Switched to a placeholder so the field starts empty (Enter still accepts the default).
56
+ - **Banner showed a stale model after `/model`.** It now tracks the live model.
57
+
58
+ ### Fix: duplicate / empty model choices in the setup wizard
59
+
60
+ `mergeModelOptions` only deduped *remote* model ids against the curated list — never the curated list against itself. So aliases pointing at the same id rendered as **two identical-looking choices** (e.g. `haiku — claude-haiku-4-5` and `fast — claude-haiku-4-5`; OpenAI's `smart`/`gpt` both → `gpt-5.5`), which also collided on React keys (`Encountered two children with the same key` → options could duplicate or vanish). It now groups by model id and merges the alias names into one option (`haiku / fast — claude-haiku-4-5`). Separately, the old code dropped the `default` alias entirely, which **emptied the model list for LM Studio** (`{ default: 'local-model' }`) and hid Ollama's default model — those models are now selectable again. Locked in with tests (every provider yields unique option values; LM Studio/Ollama are non-empty).
61
+
62
+ ### CLI audit follow-ups
63
+
64
+ - **`--continue-any` actually works as a resume flag now.** The headless arg parser forgot to consume it, so `sanook --continue-any` became a literal prompt instead of opening the REPL with the latest cross-project session. The parser is now split into a tested module and consumes all resume/headless aliases.
65
+ - **Search flags are validated.** `sanook search q --mode nope` used to silently fall back to FTS, and `--limit -5` could produce odd slice behavior. Search args now reject invalid modes, sources, missing queries, and non-positive limits with a clear usage line.
66
+ - **`sanook serve --port` missing values now report a human-readable error.** Empty or missing port values now surface `ต้องระบุค่า` instead of leaking `"undefined"` into the validation message.
67
+ - **`SANOOK_DISABLE_PERSISTENCE=1` now includes second-brain worklogs.** Sessions, auto-memory, prompt history, and worklogs all honor the global persistence kill switch; `SANOOK_DISABLE_WORKLOG=1` remains available for worklog-only opt-out.
68
+ - **First-run Codex readiness is real.** `sanook -m codex` no longer skips setup just because Codex does not use an API key; it only skips when the official `codex` CLI is installed and logged in.
69
+ - **Existing broken model config now reopens setup instead of entering a dead REPL.** If `~/.sanook/config.json` points at OpenAI without a usable key (or Codex without a logged-in CLI), interactive `sanook` brings back the setup wizard so the recovery hint is actually actionable.
70
+ - **Provider menu env-key labels now use the same key policy as runtime.** Malformed/OAuth env keys show as unusable instead of a misleading ready checkmark.
71
+ - **`/model gpt` no longer leaves the REPL in a raw alias state.** Slash-command model changes now store canonical `provider:model-id` specs (for example `openai:gpt-5.5`), and missing OpenAI-key messages point ChatGPT-plan users to `/model codex` + `codex login`.
72
+ - **The REPL banner no longer redraws after every command on terminals that keep Ink frames in scrollback.** The welcome banner renders only before history exists; the live model stays visible in the footer.
73
+ - **`config set embeddingModel ...` is now supported.** The README documented this semantic-search setting, but the config allowlist/schema did not accept it.
74
+ - **Help/docs cleanup.** The CLI help no longer points at the deprecated OpenAI Codex model id, and the README test badge was refreshed.
75
+
76
+ ### Setup wizard — better provider selection + working OpenAI Codex login
77
+
78
+ - **Provider menu**: each option now shows a one-line hint — `✓ key ใน env ใช้ได้`, `key ใน env ใช้ไม่ได้`, `local · ไม่ต้อง key`, `login ChatGPT · ไม่ใช้ API key`, or `ต้องมี API key` — and the list is ordered (popular cloud → others → local → Codex). The API-key step shows the expected key format.
79
+ - **OpenAI Codex (ChatGPT plan)**: picking Codex used to skip straight past auth. It now runs a dedicated step that detects whether the `codex` CLI is installed and logged in (reads `~/.codex/auth.json` — robust inside sandboxes where `codex login status` can panic), and guides you: `npm i -g @openai/codex` → `codex login` → re-check, then continues automatically once you're signed in. No API key required.
80
+ - **Codex runs**: `codex exec` now runs through the current non-interactive JSON CLI surface, uses the requested sandbox (`read-only` by default, `workspace-write` in auto mode), and removes `OPENAI_API_KEY` from the child env so it can't fight the ChatGPT-plan login (codex #2733/#3286). Verified against the installed Codex CLI surface.
81
+
82
+ ## 0.5.0
4
83
 
5
84
  ### Install UX — `sanook doctor` + post-install guidance (the "`sanook` is not recognized" fix)
6
85
 
@@ -144,20 +223,19 @@ A Node-native search subsystem (`src/search/`) over the second-brain vault **plu
144
223
 
145
224
  - Tests: remote-MCP, sandbox, repo map, prompt-caching/system-preservation, rate-limit classification, tool timeout, checkpoint restore, cost merge, custom commands (≈200 total).
146
225
 
147
- ## 0.4.0 — second brain, GLM Coding Plan, Telegram, hardening
226
+ ## 0.4.0 — second brain, Telegram, hardening
148
227
 
149
228
  - **Second brain**: `sanook brain init` scaffolds a portable Obsidian "second-brain" workspace — full folder taxonomy (each with `_Index.md`), a central `Vault Structure Map.md`, seed memory files, and a portable AI operating constitution (`CLAUDE/GEMINI/AGENTS.md`). Research-backed rules: context-assembly (anti context-rot), intake quarantine + injection-scan, bi-temporal fact validity, provenance tracking, a verification-gated `Skills/` library, sleep-time consolidation. The agent now **loads the vault** into context, and `brain init` **auto-wires a filesystem MCP** to it. First-run wizard offers to create one (personalized).
150
- - **GLM Coding Plan**: GLM routes through the Anthropic-compatible endpoint (`/api/anthropic`), so Coding Plan keys work; curated ids `glm-4.6 / glm-5.1 / glm-4.5-air`.
151
229
  - **Telegram channel**: drive the agent from your phone (long-polling, fail-closed allowlist, private-only). Remote surface defaults to ask-mode (mutations denied) unless `TELEGRAM_ALLOW_WRITE=1`.
152
230
  - **Auto-compaction**: token-aware sliding window keeps long sessions under the limit.
153
231
  - **Interactive approval** (`ask` mode) + capability-based gating — any non-read-only tool (incl. MCP) is confirmed before running.
154
232
  - **REPL resume** (`sanook -c`), **stdin piping** (`git diff | sanook "review"`), gateway multi-turn history, and `sanook config` / `sanook mcp` management commands.
155
- - **Provider audit**: corrected stale model ids (OpenAI `gpt-5.3-codex`, DeepSeek `v4-flash/pro`, xAI `grok-4.3`).
233
+ - **Provider audit**: corrected stale model ids (OpenAI `gpt-5.3-codex`, xAI `grok-4.3`).
156
234
  - **Hardening**: budget cap now actually fires on the default fast model; write paths confined (no `~/.sanook` / shell-rc / ssh backdoors); MCP child processes get a minimal env (no secret leakage); provider errors surface a clean one-line message; versions read from `package.json`. Added tests for the BYOK/redaction core and budget cap.
157
235
 
158
236
  ## 0.3.0 — providers, memory, gateway, MCP, git
159
237
 
160
- - **Providers**: data-driven registry, now 12 providers (added MiniMax, GLM, and OpenAI Codex via the official CLI). Per-provider model picker that fetches the live model list.
238
+ - **Providers**: data-driven registry, now 9 providers (including OpenAI Codex via the official CLI). Per-provider model picker that fetches the live model list.
161
239
  - **Memory**: auto-memory (`remember` / `recall`), session resume (`--continue`), and in-session REPL conversation history.
162
240
  - **Gateway + cron**: `sanook serve` runs a loopback HTTP endpoint (OpenAI-compatible) plus a cron scheduler with natural-language scheduling, backed by a file-locked JSON task ledger.
163
241
  - **Skills**: load `SKILL.md` files on demand; the agent can author its own with `create_skill`.