letscode 0.1.0__tar.gz → 0.5.0__tar.gz

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 (261) hide show
  1. letscode-0.5.0/.builds/alpine.yml +25 -0
  2. letscode-0.5.0/.builds/ubuntu-2404.yml +38 -0
  3. letscode-0.5.0/.cache/.gitignore +1 -0
  4. letscode-0.5.0/.cache/10318616000990552681 +4 -0
  5. letscode-0.5.0/.cache/10493891611479424259 +4 -0
  6. letscode-0.5.0/.cache/10702343394967673498 +4 -0
  7. letscode-0.5.0/.cache/11010100411556762066 +4 -0
  8. letscode-0.5.0/.cache/11154141664771110464 +4 -0
  9. letscode-0.5.0/.cache/11168941369259313220 +80 -0
  10. letscode-0.5.0/.cache/11992942182152933888 +144 -0
  11. letscode-0.5.0/.cache/12059922036673638020 +4 -0
  12. letscode-0.5.0/.cache/1249039435107563575 +161 -0
  13. letscode-0.5.0/.cache/12576105843982642077 +4 -0
  14. letscode-0.5.0/.cache/14203930344178090297 +4 -0
  15. letscode-0.5.0/.cache/1563633362711557789 +4 -0
  16. letscode-0.5.0/.cache/15661711846603463071 +207 -0
  17. letscode-0.5.0/.cache/15908712471909210796 +178 -0
  18. letscode-0.5.0/.cache/16912669318574488615 +80 -0
  19. letscode-0.5.0/.cache/16988395898165525092 +419 -0
  20. letscode-0.5.0/.cache/17150484726184191142 +128 -0
  21. letscode-0.5.0/.cache/17419555459594506489 +4 -0
  22. letscode-0.5.0/.cache/2041198230313398573 +4 -0
  23. letscode-0.5.0/.cache/3072703261793992529 +4 -0
  24. letscode-0.5.0/.cache/3151054395951844290 +4 -0
  25. letscode-0.5.0/.cache/3226154870166803660 +4 -0
  26. letscode-0.5.0/.cache/3476900567878811119 +4 -0
  27. letscode-0.5.0/.cache/3510264687931475889 +160 -0
  28. letscode-0.5.0/.cache/3520474981437140632 +112 -0
  29. letscode-0.5.0/.cache/3541202890535126406 +96 -0
  30. letscode-0.5.0/.cache/3728666290973476153 +80 -0
  31. letscode-0.5.0/.cache/4780842327402266928 +64 -0
  32. letscode-0.5.0/.cache/5187878047780114009 +161 -0
  33. letscode-0.5.0/.cache/6069231736669146243 +4 -0
  34. letscode-0.5.0/.cache/6463951297718265957 +31 -0
  35. letscode-0.5.0/.cache/6479415784420637704 +4 -0
  36. letscode-0.5.0/.cache/6764327636681606151 +4 -0
  37. letscode-0.5.0/.cache/6789241458458765738 +354 -0
  38. letscode-0.5.0/.cache/8444450551902475297 +113 -0
  39. letscode-0.5.0/.cache/8863633364771264685 +112 -0
  40. letscode-0.5.0/.cache/9378231046984033364 +177 -0
  41. letscode-0.5.0/.cache/9810942886417102030 +4 -0
  42. letscode-0.5.0/.github/workflows/ci.yml +36 -0
  43. letscode-0.5.0/.github/workflows/docs.yml +29 -0
  44. letscode-0.5.0/.gitignore +20 -0
  45. letscode-0.5.0/.pre-commit-config.yaml +33 -0
  46. letscode-0.5.0/CHANGES.md +123 -0
  47. letscode-0.5.0/CLAUDE.md +85 -0
  48. letscode-0.5.0/Makefile +50 -0
  49. letscode-0.5.0/PKG-INFO +283 -0
  50. letscode-0.5.0/README.md +265 -0
  51. letscode-0.5.0/docs/about/changelog.md +39 -0
  52. letscode-0.5.0/docs/about/index.md +54 -0
  53. letscode-0.5.0/docs/about/lessons-learned.md +56 -0
  54. letscode-0.5.0/docs/about/related-projects.md +69 -0
  55. letscode-0.5.0/docs/about/roadmap.md +98 -0
  56. letscode-0.5.0/docs/architecture/agent-loop.md +97 -0
  57. letscode-0.5.0/docs/architecture/extension-model.md +194 -0
  58. letscode-0.5.0/docs/architecture/index.md +69 -0
  59. letscode-0.5.0/docs/getting-started.md +136 -0
  60. letscode-0.5.0/docs/index.md +113 -0
  61. letscode-0.5.0/docs/plugins/authoring.md +542 -0
  62. letscode-0.5.0/docs/plugins/index.md +85 -0
  63. letscode-0.5.0/docs/plugins/memory.md +79 -0
  64. letscode-0.5.0/docs/user-guide/configuration.md +108 -0
  65. letscode-0.5.0/docs/user-guide/index.md +36 -0
  66. letscode-0.5.0/docs/user-guide/sessions.md +55 -0
  67. letscode-0.5.0/docs/user-guide/skills.md +130 -0
  68. letscode-0.5.0/docs/user-guide/slash-commands.md +87 -0
  69. letscode-0.5.0/local-notes/playbooks/litestar-dishka/CHECKLISTS.md +131 -0
  70. letscode-0.5.0/local-notes/playbooks/litestar-dishka/COMMON-GOTCHAS.md +296 -0
  71. letscode-0.5.0/local-notes/playbooks/litestar-dishka/INDEX.md +90 -0
  72. letscode-0.5.0/local-notes/playbooks/litestar-dishka/advanced-alchemy.md +1558 -0
  73. letscode-0.5.0/local-notes/playbooks/litestar-dishka/configuration.md +858 -0
  74. letscode-0.5.0/local-notes/playbooks/litestar-dishka/dishka.md +244 -0
  75. letscode-0.5.0/local-notes/playbooks/litestar-dishka/integration.md +135 -0
  76. letscode-0.5.0/local-notes/playbooks/litestar-dishka/litestar-views.md +322 -0
  77. letscode-0.5.0/local-notes/playbooks/litestar-dishka/litestar.md +408 -0
  78. letscode-0.5.0/local-notes/playbooks/litestar-dishka/stack-guide.md +1060 -0
  79. letscode-0.5.0/local-notes/playbooks/litestar-dishka/testing.md +1308 -0
  80. letscode-0.5.0/local-notes/playbooks/litestar-dishka/workflows.md +707 -0
  81. letscode-0.5.0/local-notes/playbooks/python/4-rules-design.md +159 -0
  82. letscode-0.5.0/local-notes/playbooks/python/CHECKLISTS.md +171 -0
  83. letscode-0.5.0/local-notes/playbooks/python/INDEX.md +72 -0
  84. letscode-0.5.0/local-notes/playbooks/python/coding-guidelines.md +301 -0
  85. letscode-0.5.0/local-notes/playbooks/python/design-patterns.md +101 -0
  86. letscode-0.5.0/local-notes/playbooks/python/error-messages.md +197 -0
  87. letscode-0.5.0/local-notes/playbooks/python/monorepo.md +513 -0
  88. letscode-0.5.0/local-notes/playbooks/python/nouns-and-verbs.md +125 -0
  89. letscode-0.5.0/local-notes/playbooks/python/testing.md +434 -0
  90. letscode-0.5.0/local-notes/playbooks/webdev/CHECKLISTS.md +175 -0
  91. letscode-0.5.0/local-notes/playbooks/webdev/INDEX.md +74 -0
  92. letscode-0.5.0/local-notes/playbooks/webdev/api-design.md +405 -0
  93. letscode-0.5.0/local-notes/playbooks/webdev/deployment.md +499 -0
  94. letscode-0.5.0/local-notes/playbooks/webdev/hybrid-ui.md +194 -0
  95. letscode-0.5.0/local-notes/playbooks/webdev/production-patterns.md +577 -0
  96. letscode-0.5.0/local-notes/playbooks/webdev/security.md +480 -0
  97. letscode-0.5.0/notes/01-vision.md +323 -0
  98. letscode-0.5.0/notes/02-design.md +1143 -0
  99. letscode-0.5.0/notes/03-plan.md +383 -0
  100. letscode-0.5.0/notes/04-lessons-learned.md +274 -0
  101. letscode-0.5.0/notes/05-gap-vs-pi.md +284 -0
  102. letscode-0.5.0/notes/06-v0.2-plan.md +183 -0
  103. letscode-0.5.0/notes/07-v0.3-plan.md +204 -0
  104. letscode-0.5.0/notes/08-extension-model.md +228 -0
  105. letscode-0.5.0/notes/09-ergonomics-punchlist.md +96 -0
  106. letscode-0.5.0/notes/10-v0.4-plan.md +250 -0
  107. letscode-0.5.0/notes/11-plugin-contract-v0.4-findings.md +110 -0
  108. letscode-0.5.0/notes/12-textual-frontend.md +339 -0
  109. letscode-0.5.0/notes/13-textual-test-drive.md +105 -0
  110. letscode-0.5.0/notes/14-vs-anthropic-playbook.md +65 -0
  111. letscode-0.5.0/notes/15-prompt-caching.md +57 -0
  112. letscode-0.5.0/notes/16-config-schema.md +96 -0
  113. letscode-0.5.0/notes/17-rpc-protocol.md +135 -0
  114. letscode-0.5.0/notes/18-v0.5-plan.md +147 -0
  115. letscode-0.5.0/notes/19-release-runbook.md +23 -0
  116. letscode-0.5.0/notes/plans/2026-W21.md +46 -0
  117. letscode-0.5.0/notes/plans/textual-tui.md +69 -0
  118. letscode-0.5.0/notes/playbooks/INDEX.md +129 -0
  119. letscode-0.5.0/notes/playbooks/generic-python/4-rules-design.md +159 -0
  120. letscode-0.5.0/notes/playbooks/generic-python/CHECKLISTS.md +173 -0
  121. letscode-0.5.0/notes/playbooks/generic-python/INDEX.md +72 -0
  122. letscode-0.5.0/notes/playbooks/generic-python/coding-guidelines.md +301 -0
  123. letscode-0.5.0/notes/playbooks/generic-python/design-patterns.md +101 -0
  124. letscode-0.5.0/notes/playbooks/generic-python/error-messages.md +197 -0
  125. letscode-0.5.0/notes/playbooks/generic-python/monorepo.md +513 -0
  126. letscode-0.5.0/notes/playbooks/generic-python/nouns-and-verbs.md +125 -0
  127. letscode-0.5.0/notes/playbooks/generic-python/testing.md +434 -0
  128. letscode-0.5.0/notes/playbooks/pluggy/CHECKLISTS.md +126 -0
  129. letscode-0.5.0/notes/playbooks/pluggy/COMMON-GOTCHAS.md +155 -0
  130. letscode-0.5.0/notes/playbooks/pluggy/INDEX.md +88 -0
  131. letscode-0.5.0/notes/playbooks/pluggy/plugin-system.md +870 -0
  132. letscode-0.5.0/notes/plugins-guide.md +554 -0
  133. letscode-0.5.0/notes/test-drive.md +116 -0
  134. letscode-0.5.0/notes/weekly/00readme.md +104 -0
  135. letscode-0.5.0/notes/weekly/2026-W20.md +96 -0
  136. letscode-0.5.0/noxfile.py +27 -0
  137. letscode-0.5.0/plugins/letscode-goal/README.md +67 -0
  138. letscode-0.5.0/plugins/letscode-goal/pyproject.toml +43 -0
  139. letscode-0.5.0/plugins/letscode-goal/src/letscode_goal/__init__.py +12 -0
  140. letscode-0.5.0/plugins/letscode-goal/src/letscode_goal/plugin.py +168 -0
  141. letscode-0.5.0/plugins/letscode-goal/src/letscode_goal/state.py +237 -0
  142. letscode-0.5.0/plugins/letscode-goal/tests/test_plugin.py +330 -0
  143. letscode-0.5.0/plugins/letscode-goal/uv.lock +618 -0
  144. letscode-0.5.0/plugins/letscode-memory/README.md +51 -0
  145. letscode-0.5.0/plugins/letscode-memory/pyproject.toml +42 -0
  146. letscode-0.5.0/plugins/letscode-memory/src/letscode_memory/__init__.py +13 -0
  147. letscode-0.5.0/plugins/letscode-memory/src/letscode_memory/plugin.py +337 -0
  148. letscode-0.5.0/plugins/letscode-memory/src/letscode_memory/store.py +105 -0
  149. letscode-0.5.0/plugins/letscode-memory/tests/test_plugin.py +524 -0
  150. letscode-0.5.0/plugins/letscode-memory/uv.lock +616 -0
  151. letscode-0.5.0/plugins/letscode-textual/README.md +49 -0
  152. letscode-0.5.0/plugins/letscode-textual/pyproject.toml +43 -0
  153. letscode-0.5.0/plugins/letscode-textual/src/letscode_textual/__init__.py +12 -0
  154. letscode-0.5.0/plugins/letscode-textual/src/letscode_textual/app.py +307 -0
  155. letscode-0.5.0/plugins/letscode-textual/src/letscode_textual/frontend.py +104 -0
  156. letscode-0.5.0/plugins/letscode-textual/src/letscode_textual/plugin.py +32 -0
  157. letscode-0.5.0/plugins/letscode-textual/tests/test_plugin.py +517 -0
  158. letscode-0.5.0/plugins/letscode-textual/uv.lock +682 -0
  159. letscode-0.5.0/pyproject.toml +127 -0
  160. letscode-0.5.0/ruff.toml +53 -0
  161. letscode-0.5.0/scripts/verify_plugin.py +93 -0
  162. letscode-0.5.0/scripts/verify_wheel.py +143 -0
  163. letscode-0.5.0/src/letscode/__main__.py +13 -0
  164. letscode-0.5.0/src/letscode/agent/agent.py +181 -0
  165. letscode-0.5.0/src/letscode/agent/compaction.py +273 -0
  166. letscode-0.5.0/src/letscode/agent/events.py +163 -0
  167. letscode-0.5.0/src/letscode/agent/execution_env.py +360 -0
  168. letscode-0.5.0/src/letscode/agent/hooks.py +39 -0
  169. letscode-0.5.0/src/letscode/agent/hookspecs.py +226 -0
  170. letscode-0.5.0/src/letscode/agent/loop.py +684 -0
  171. letscode-0.5.0/src/letscode/agent/messages.py +100 -0
  172. letscode-0.5.0/src/letscode/agent/state.py +49 -0
  173. letscode-0.5.0/src/letscode/agent/tools.py +245 -0
  174. letscode-0.5.0/src/letscode/cli/app.py +653 -0
  175. letscode-0.5.0/src/letscode/cli/rpc.py +312 -0
  176. letscode-0.5.0/src/letscode/commands/__init__.py +0 -0
  177. letscode-0.5.0/src/letscode/commands/builtin.py +330 -0
  178. letscode-0.5.0/src/letscode/commands/dispatch.py +121 -0
  179. letscode-0.5.0/src/letscode/config/__init__.py +7 -0
  180. letscode-0.5.0/src/letscode/config/loader.py +187 -0
  181. letscode-0.5.0/src/letscode/context/__init__.py +11 -0
  182. letscode-0.5.0/src/letscode/context/files.py +113 -0
  183. letscode-0.5.0/src/letscode/frontends/__init__.py +0 -0
  184. letscode-0.5.0/src/letscode/frontends/basic/__init__.py +0 -0
  185. letscode-0.5.0/src/letscode/frontends/basic/footer.py +105 -0
  186. letscode-0.5.0/src/letscode/frontends/basic/tui.py +1121 -0
  187. letscode-0.5.0/src/letscode/frontends/protocol.py +46 -0
  188. letscode-0.5.0/src/letscode/llm/__init__.py +0 -0
  189. letscode-0.5.0/src/letscode/llm/client.py +272 -0
  190. letscode-0.5.0/src/letscode/llm/errors.py +22 -0
  191. letscode-0.5.0/src/letscode/llm/models.py +57 -0
  192. letscode-0.5.0/src/letscode/llm/stream.py +134 -0
  193. letscode-0.5.0/src/letscode/llm/types.py +54 -0
  194. letscode-0.5.0/src/letscode/plugins/__init__.py +0 -0
  195. letscode-0.5.0/src/letscode/plugins/builtin.py +122 -0
  196. letscode-0.5.0/src/letscode/plugins/manager.py +76 -0
  197. letscode-0.5.0/src/letscode/plugins/registries.py +242 -0
  198. letscode-0.5.0/src/letscode/session/__init__.py +0 -0
  199. letscode-0.5.0/src/letscode/session/format.py +80 -0
  200. letscode-0.5.0/src/letscode/session/store.py +194 -0
  201. letscode-0.5.0/src/letscode/skills/__init__.py +0 -0
  202. letscode-0.5.0/src/letscode/skills/discovery.py +106 -0
  203. letscode-0.5.0/src/letscode/skills/loader.py +100 -0
  204. letscode-0.5.0/src/letscode/skills/synth.py +121 -0
  205. letscode-0.5.0/src/letscode/tools/__init__.py +0 -0
  206. letscode-0.5.0/src/letscode/tools/bash.py +67 -0
  207. letscode-0.5.0/src/letscode/tools/builtin.py +26 -0
  208. letscode-0.5.0/src/letscode/tools/edit.py +130 -0
  209. letscode-0.5.0/src/letscode/tools/read.py +98 -0
  210. letscode-0.5.0/src/letscode/tools/write.py +79 -0
  211. letscode-0.5.0/tests/__init__.py +0 -0
  212. letscode-0.5.0/tests/_helpers.py +170 -0
  213. letscode-0.5.0/tests/a_unit/__init__.py +0 -0
  214. letscode-0.5.0/tests/a_unit/test_builtin_commands.py +602 -0
  215. letscode-0.5.0/tests/a_unit/test_builtin_plugin.py +164 -0
  216. letscode-0.5.0/tests/a_unit/test_cli.py +845 -0
  217. letscode-0.5.0/tests/a_unit/test_command_dispatch.py +274 -0
  218. letscode-0.5.0/tests/a_unit/test_compaction.py +545 -0
  219. letscode-0.5.0/tests/a_unit/test_config.py +285 -0
  220. letscode-0.5.0/tests/a_unit/test_context_files.py +172 -0
  221. letscode-0.5.0/tests/a_unit/test_execution_env.py +199 -0
  222. letscode-0.5.0/tests/a_unit/test_fake_llm.py +84 -0
  223. letscode-0.5.0/tests/a_unit/test_footer.py +139 -0
  224. letscode-0.5.0/tests/a_unit/test_hooks.py +211 -0
  225. letscode-0.5.0/tests/a_unit/test_hookspecs.py +125 -0
  226. letscode-0.5.0/tests/a_unit/test_llm_client.py +574 -0
  227. letscode-0.5.0/tests/a_unit/test_plugin_manager.py +464 -0
  228. letscode-0.5.0/tests/a_unit/test_session.py +413 -0
  229. letscode-0.5.0/tests/a_unit/test_skill_discovery.py +154 -0
  230. letscode-0.5.0/tests/a_unit/test_skill_loader.py +192 -0
  231. letscode-0.5.0/tests/a_unit/test_skill_synth.py +246 -0
  232. letscode-0.5.0/tests/a_unit/test_smoke.py +30 -0
  233. letscode-0.5.0/tests/a_unit/test_stream.py +138 -0
  234. letscode-0.5.0/tests/a_unit/test_tool_bash.py +183 -0
  235. letscode-0.5.0/tests/a_unit/test_tool_edit.py +231 -0
  236. letscode-0.5.0/tests/a_unit/test_tool_read.py +164 -0
  237. letscode-0.5.0/tests/a_unit/test_tool_write.py +164 -0
  238. letscode-0.5.0/tests/a_unit/test_tools.py +287 -0
  239. letscode-0.5.0/tests/a_unit/test_types.py +235 -0
  240. letscode-0.5.0/tests/b_integration/__init__.py +0 -0
  241. letscode-0.5.0/tests/b_integration/test_agent.py +787 -0
  242. letscode-0.5.0/tests/b_integration/test_agent_loop.py +440 -0
  243. letscode-0.5.0/tests/b_integration/test_agent_loop_tools.py +473 -0
  244. letscode-0.5.0/tests/b_integration/test_basic_frontend.py +2361 -0
  245. letscode-0.5.0/tests/b_integration/test_lifecycle_hooks.py +857 -0
  246. letscode-0.5.0/tests/b_integration/test_rpc_mode.py +351 -0
  247. letscode-0.5.0/tests/b_integration/test_rpc_subprocess.py +219 -0
  248. letscode-0.5.0/tests/c_e2e/__init__.py +0 -0
  249. letscode-0.5.0/tests/c_e2e/test_smoke.py +246 -0
  250. letscode-0.5.0/tests/conftest.py +79 -0
  251. letscode-0.5.0/tests/fixtures/config/sample.toml +11 -0
  252. letscode-0.5.0/tests/fixtures/llm/README.md +47 -0
  253. letscode-0.5.0/tests/fixtures/llm/hello-tool.jsonl +5 -0
  254. letscode-0.5.0/tests/fixtures/llm/hello.jsonl +5 -0
  255. letscode-0.5.0/uv.lock +1326 -0
  256. letscode-0.5.0/zensical.toml +161 -0
  257. letscode-0.1.0/PKG-INFO +0 -9
  258. letscode-0.1.0/pyproject.toml +0 -17
  259. letscode-0.1.0/src/letscode/__init__.py +0 -2
  260. /letscode-0.1.0/README.md → /letscode-0.5.0/src/letscode/agent/__init__.py +0 -0
  261. /letscode-0.1.0/src/letscode/COMMING_SOON.py → /letscode-0.5.0/src/letscode/cli/__init__.py +0 -0
@@ -0,0 +1,25 @@
1
+ image: alpine/latest
2
+ packages:
3
+ - uv
4
+ # - gcc
5
+ - python3-dev
6
+
7
+ secrets:
8
+ - b88a4c2c-944c-42a6-9fbb-7483049c458a
9
+
10
+ tasks:
11
+ - install: |
12
+ ln -sf letscode-private letscode
13
+ cd letscode
14
+ uv sync
15
+ - test: |
16
+ cd letscode
17
+ uv run pytest -q --tb=short
18
+ - lint: |
19
+ cd letscode
20
+ uv run ruff check
21
+ uv run ty check src
22
+ - nox: |
23
+ cd letscode
24
+ uvx nox
25
+
@@ -0,0 +1,38 @@
1
+ # Copyright (c) 2024, Abilian SAS
2
+ #
3
+ # SPDX-License-Identifier: BSD-3-Clause
4
+
5
+ image: ubuntu/24.04
6
+
7
+ secrets:
8
+ - b88a4c2c-944c-42a6-9fbb-7483049c458a
9
+
10
+ packages:
11
+ # Build tools
12
+ - software-properties-common
13
+ - build-essential
14
+ # Python is 3.12
15
+ - python3-dev
16
+ - python3-pip
17
+ # Extra
18
+ # - nodejs
19
+
20
+ tasks:
21
+ - setup: |
22
+ echo "Building on Ubuntu 2404"
23
+ sudo pip install --break-system-packages -U uv nox
24
+ ln -sf letscode-private letscode
25
+ cd letscode
26
+ uv sync
27
+
28
+ - test: |
29
+ cd letscode
30
+ uv run pytest -q --tb=short
31
+ - lint: |
32
+ cd letscode
33
+ uv run ruff check
34
+ # uv run ty check src
35
+ - nox: |
36
+ cd letscode
37
+ uvx nox
38
+
@@ -0,0 +1 @@
1
+ *
@@ -0,0 +1,4 @@
1
+ {
2
+ "data": "\n<!doctype html>\n<html lang=\"en\" class=\"no-js\">\n <head>\n \n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n \n <meta name=\"description\" content=\"Every `/command` shipping in core, what it does, when to use it.\">\n \n \n <meta name=\"author\" content=\"Stefane Fermigier\">\n \n \n <link rel=\"canonical\" href=\"https://letscode.dev/user-guide/slash-commands/\">\n \n \n <link rel=\"prev\" href=\"../configuration/\">\n \n \n <link rel=\"next\" href=\"../skills/\">\n \n \n \n \n \n <link rel=\"icon\" href=\"../../assets/images/favicon.png\">\n <meta name=\"generator\" content=\"zensical-0.0.43\">\n \n \n \n <title>Slash commands - letscode</title>\n \n \n \n \n \n \n <link rel=\"stylesheet\" href=\"../../assets/stylesheets/modern/main.fba56155.min.css\">\n \n \n \n \n <link rel=\"stylesheet\" href=\"../../assets/stylesheets/modern/palette.dfe2e883.min.css\">\n \n \n\n\n \n \n \n \n \n \n \n \n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n <link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Inter:300,300i,400,400i,500,500i,700,700i%7CJetBrains+Mono:400,400i,700,700i&amp;display=fallback\">\n <style>:root{--md-text-font:\"Inter\";--md-code-font:\"JetBrains Mono\"}</style>\n \n \n \n <script>__md_scope=new URL(\"../..\",location),__md_scope.pathname.endsWith(\"/\")||(__md_scope=new URL(__md_scope.pathname+\"/\",location)),__md_hash=e=>[...e].reduce(((e,t)=>(e<<5)-e+t.charCodeAt(0)),0),__md_get=(e,t=localStorage,_=__md_scope)=>JSON.parse(t.getItem(_.pathname+\".\"+e)),__md_set=(e,t,_=localStorage,a=__md_scope)=>{try{_.setItem(a.pathname+\".\"+e,JSON.stringify(t))}catch(e){}},document.documentElement.setAttribute(\"data-platform\",navigator.platform)</script>\n \n \n\n \n \n </head>\n \n \n \n \n \n \n \n \n \n <body dir=\"ltr\" data-md-color-scheme=\"default\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\">\n \n \n <input class=\"md-toggle\" data-md-toggle=\"drawer\" type=\"checkbox\" id=\"__drawer\" autocomplete=\"off\">\n <input class=\"md-toggle\" data-md-toggle=\"search\" type=\"checkbox\" id=\"__search\" autocomplete=\"off\">\n <label class=\"md-overlay\" for=\"__drawer\" aria-label=\"Navigation\"></label>\n <div data-md-component=\"skip\">\n \n \n <a href=\"#slash-commands\" class=\"md-skip\">\n Skip to content\n </a>\n \n </div>\n <div data-md-component=\"announce\">\n \n </div>\n \n \n \n\n<header class=\"md-header\" data-md-component=\"header\">\n <nav class=\"md-header__inner md-grid\" aria-label=\"Header\">\n <a href=\"../..\" title=\"letscode\" class=\"md-header__button md-logo\" aria-label=\"letscode\" data-md-component=\"logo\">\n \n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-book-open\" viewBox=\"0 0 24 24\"><path d=\"M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z\"/></svg>\n\n </a>\n <label class=\"md-header__button md-icon\" for=\"__drawer\" aria-label=\"Navigation\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-menu\" viewBox=\"0 0 24 24\"><path d=\"M4 5h16M4 12h16M4 19h16\"/></svg>\n </label>\n <div class=\"md-header__title\" data-md-component=\"header-title\">\n <div class=\"md-header__ellipsis\">\n <div class=\"md-header__topic\">\n <span class=\"md-ellipsis\">\n letscode\n </span>\n </div>\n <div class=\"md-header__topic\" data-md-component=\"header-topic\">\n <span class=\"md-ellipsis\">\n \n Slash commands\n \n </span>\n </div>\n </div>\n </div>\n \n \n <form class=\"md-header__option\" data-md-component=\"palette\">\n \n \n \n \n <input class=\"md-option\" data-md-color-media=\"(prefers-color-scheme)\" data-md-color-scheme=\"default\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\" aria-label=\"Switch to light mode\" type=\"radio\" name=\"__palette\" id=\"__palette_0\">\n \n <label class=\"md-header__button md-icon\" title=\"Switch to light mode\" for=\"__palette_1\" hidden>\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-sun-moon\" viewBox=\"0 0 24 24\"><path d=\"M12 2v2M14.837 16.385a6 6 0 1 1-7.223-7.222c.624-.147.97.66.715 1.248a4 4 0 0 0 5.26 5.259c.589-.255 1.396.09 1.248.715M16 12a4 4 0 0 0-4-4M19 5l-1.256 1.256M20 12h2\"/></svg>\n </label>\n \n \n \n \n \n <input class=\"md-option\" data-md-color-media=\"(prefers-color-scheme: light)\" data-md-color-scheme=\"default\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\" aria-label=\"Switch to dark mode\" type=\"radio\" name=\"__palette\" id=\"__palette_1\">\n \n <label class=\"md-header__button md-icon\" title=\"Switch to dark mode\" for=\"__palette_2\" hidden>\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-sun\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\"/></svg>\n </label>\n \n \n \n \n \n <input class=\"md-option\" data-md-color-media=\"(prefers-color-scheme: dark)\" data-md-color-scheme=\"slate\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\" aria-label=\"Switch to system preference\" type=\"radio\" name=\"__palette\" id=\"__palette_2\">\n \n <label class=\"md-header__button md-icon\" title=\"Switch to system preference\" for=\"__palette_0\" hidden>\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-moon\" viewBox=\"0 0 24 24\"><path d=\"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401\"/></svg>\n </label>\n \n \n</form>\n \n \n \n <script>var palette=__md_get(\"__palette\");if(palette&&palette.color){if(\"(prefers-color-scheme)\"===palette.color.media){var media=matchMedia(\"(prefers-color-scheme: light)\"),input=document.querySelector(media.matches?\"[data-md-color-media='(prefers-color-scheme: light)']\":\"[data-md-color-media='(prefers-color-scheme: dark)']\");palette.color.media=input.getAttribute(\"data-md-color-media\"),palette.color.scheme=input.getAttribute(\"data-md-color-scheme\"),palette.color.primary=input.getAttribute(\"data-md-color-primary\"),palette.color.accent=input.getAttribute(\"data-md-color-accent\")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute(\"data-md-color-\"+key,value)}</script>\n \n \n \n \n \n <label class=\"md-header__button md-icon\" for=\"__search\" aria-label=\"Search\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-search\" viewBox=\"0 0 24 24\"><path d=\"m21 21-4.34-4.34\"/><circle cx=\"11\" cy=\"11\" r=\"8\"/></svg>\n </label>\n <div class=\"md-search\" data-md-component=\"search\" role=\"dialog\" aria-label=\"Search\">\n <button type=\"button\" class=\"md-search__button\">\n Search\n </button>\n</div>\n \n \n <div class=\"md-header__source\">\n \n </div>\n </nav>\n \n</header>\n \n <div class=\"md-container\" data-md-component=\"container\">\n \n \n \n \n \n<nav class=\"md-tabs\" aria-label=\"Tabs\" data-md-component=\"tabs\">\n <div class=\"md-grid\">\n <ul class=\"md-tabs__list\">\n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../..\" class=\"md-tabs__link\">\n \n \n Home\n\n </a>\n </li>\n \n\n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../getting-started/\" class=\"md-tabs__link\">\n \n \n Getting started\n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item md-tabs__item--active\">\n <a href=\"../\" class=\"md-tabs__link\">\n \n \n User guide\n\n </a>\n </li>\n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../plugins/\" class=\"md-tabs__link\">\n \n \n Plugins\n\n </a>\n </li>\n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../architecture/\" class=\"md-tabs__link\">\n \n \n Architecture\n\n </a>\n </li>\n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../about/\" class=\"md-tabs__link\">\n \n \n About\n\n </a>\n </li>\n \n \n\n \n </ul>\n </div>\n</nav>\n \n \n \n <main class=\"md-main\" data-md-component=\"main\">\n <div class=\"md-main__inner md-grid\">\n \n \n \n <div class=\"md-sidebar md-sidebar--primary\" data-md-component=\"sidebar\" data-md-type=\"navigation\" >\n <div class=\"md-sidebar__scrollwrap\">\n <div class=\"md-sidebar__inner\">\n \n\n\n \n\n\n<nav class=\"md-nav md-nav--primary md-nav--lifted\" aria-label=\"Navigation\" data-md-level=\"0\">\n <label class=\"md-nav__title\" for=\"__drawer\">\n <a href=\"../..\" title=\"letscode\" class=\"md-nav__button md-logo\" aria-label=\"letscode\" data-md-component=\"logo\">\n \n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-book-open\" viewBox=\"0 0 24 24\"><path d=\"M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z\"/></svg>\n\n </a>\n letscode\n </label>\n \n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../..\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Home\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../getting-started/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Getting started\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested\">\n \n \n \n <input class=\"md-nav__toggle md-toggle \" type=\"checkbox\" id=\"__nav_3\" checked>\n \n \n <div class=\"md-nav__link md-nav__container\">\n <a href=\"../\" class=\"md-nav__link \">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n User guide\n\n \n </span>\n \n \n\n </a>\n \n \n <label class=\"md-nav__link \" for=\"__nav_3\" id=\"__nav_3_label\" tabindex=\"\">\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n </div>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_3_label\" aria-expanded=\"true\">\n <label class=\"md-nav__title\" for=\"__nav_3\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n User guide\n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../configuration/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Configuration\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--active\">\n \n \n \n \n \n \n \n <label class=\"md-nav__link md-nav__link--active\" for=\"__toc\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Slash commands\n\n \n </span>\n \n \n\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n <a href=\"././\" class=\"md-nav__link md-nav__link--active\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Slash commands\n\n \n </span>\n \n \n\n </a>\n \n \n\n\n<nav class=\"md-nav md-nav--secondary\" aria-label=\"On this page\">\n \n \n \n \n \n \n <label class=\"md-nav__title\" for=\"__toc\">\n <span class=\"md-nav__icon md-icon\"></span>\n On this page\n </label>\n <ul class=\"md-nav__list\" data-md-component=\"toc\" data-md-scrollfix>\n \n <li class=\"md-nav__item\">\n <a href=\"#basics\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Basics\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#inspection\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Inspection\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#sessions-since-v04\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Sessions (since v0.4)\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#skills\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Skills\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#steering-and-follow-up\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Steering and follow-up\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#compaction\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Compaction\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#ui-toggles\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n UI toggles\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#plugin-commands\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Plugin commands\n </span>\n </span>\n </a>\n \n</li>\n \n </ul>\n \n</nav>\n \n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../skills/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Skills\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../sessions/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Sessions\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--nested\">\n \n \n \n <input class=\"md-nav__toggle md-toggle \" type=\"checkbox\" id=\"__nav_4\" >\n \n \n <div class=\"md-nav__link md-nav__container\">\n <a href=\"../../plugins/\" class=\"md-nav__link \">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Plugins\n\n \n </span>\n \n \n\n </a>\n \n \n <label class=\"md-nav__link \" for=\"__nav_4\" id=\"__nav_4_label\" tabindex=\"0\">\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n </div>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_4_label\" aria-expanded=\"false\">\n <label class=\"md-nav__title\" for=\"__nav_4\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n Plugins\n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../plugins/authoring/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Authoring guide\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../plugins/memory/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Reference plugin\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--nested\">\n \n \n \n <input class=\"md-nav__toggle md-toggle \" type=\"checkbox\" id=\"__nav_5\" >\n \n \n <div class=\"md-nav__link md-nav__container\">\n <a href=\"../../architecture/\" class=\"md-nav__link \">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Architecture\n\n \n </span>\n \n \n\n </a>\n \n \n <label class=\"md-nav__link \" for=\"__nav_5\" id=\"__nav_5_label\" tabindex=\"0\">\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n </div>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_5_label\" aria-expanded=\"false\">\n <label class=\"md-nav__title\" for=\"__nav_5\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n Architecture\n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../architecture/extension-model/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Extension model\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../architecture/agent-loop/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Agent loop\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--nested\">\n \n \n \n <input class=\"md-nav__toggle md-toggle \" type=\"checkbox\" id=\"__nav_6\" >\n \n \n <div class=\"md-nav__link md-nav__container\">\n <a href=\"../../about/\" class=\"md-nav__link \">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n About\n\n \n </span>\n \n \n\n </a>\n \n \n <label class=\"md-nav__link \" for=\"__nav_6\" id=\"__nav_6_label\" tabindex=\"0\">\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n </div>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_6_label\" aria-expanded=\"false\">\n <label class=\"md-nav__title\" for=\"__nav_6\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n About\n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../about/changelog/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Changelog\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../about/roadmap/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Roadmap\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../about/lessons-learned/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Lessons learned\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../about/related-projects/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Related projects\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n </ul>\n</nav>\n </div>\n </div>\n </div>\n \n \n \n <div class=\"md-sidebar md-sidebar--secondary\" data-md-component=\"sidebar\" data-md-type=\"toc\" >\n <div class=\"md-sidebar__scrollwrap\">\n \n \n \n \n \n \n \n <input class=\"md-nav__toggle md-toggle\" type=\"checkbox\" id=\"__toc\">\n <div class=\"md-sidebar-button__wrapper\">\n <label class=\"md-sidebar-button\" for=\"__toc\"></label>\n </div>\n \n \n <div class=\"md-sidebar__inner\">\n \n\n\n<nav class=\"md-nav md-nav--secondary\" aria-label=\"On this page\">\n \n \n \n \n \n \n <label class=\"md-nav__title\" for=\"__toc\">\n <span class=\"md-nav__icon md-icon\"></span>\n On this page\n </label>\n <ul class=\"md-nav__list\" data-md-component=\"toc\" data-md-scrollfix>\n \n <li class=\"md-nav__item\">\n <a href=\"#basics\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Basics\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#inspection\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Inspection\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#sessions-since-v04\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Sessions (since v0.4)\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#skills\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Skills\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#steering-and-follow-up\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Steering and follow-up\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#compaction\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Compaction\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#ui-toggles\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n UI toggles\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#plugin-commands\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Plugin commands\n </span>\n </span>\n </a>\n \n</li>\n \n </ul>\n \n</nav>\n </div>\n </div>\n </div>\n \n \n \n <div class=\"md-content\" data-md-component=\"content\">\n \n \n\n\n\n \n\n\n <nav class=\"md-path\" aria-label=\"Navigation\" >\n <ol class=\"md-path__list\">\n \n \n \n \n <li class=\"md-path__item\">\n <a href=\"../..\" class=\"md-path__link\">\n \n \n <span class=\"md-ellipsis\">\n Home\n </span>\n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-path__item\">\n <a href=\"../\" class=\"md-path__link\">\n \n \n <span class=\"md-ellipsis\">\n User guide\n </span>\n\n </a>\n </li>\n \n \n\n \n </ol>\n </nav>\n\n \n <article class=\"md-content__inner md-typeset\">\n \n \n\n<h1 id=\"slash-commands\">Slash commands<a class=\"headerlink\" href=\"#slash-commands\" title=\"Permanent link\">&para;</a></h1>\n<p>Type <code>/help</code> at the prompt to see this list at runtime.</p>\n<h2 id=\"basics\">Basics<a class=\"headerlink\" href=\"#basics\" title=\"Permanent link\">&para;</a></h2>\n<table>\n<thead>\n<tr>\n<th>Command</th>\n<th>Effect</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>/help</code></td>\n<td>List every registered command (built-in + plugin).</td>\n</tr>\n<tr>\n<td><code>/quit</code></td>\n<td>Exit <code>letscode</code>.</td>\n</tr>\n<tr>\n<td><code>/reset</code></td>\n<td>Clear the conversation history (system prompt stays).</td>\n</tr>\n<tr>\n<td><code>/model [NAME]</code></td>\n<td>Show the current model; with an arg, switch to it.</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"inspection\">Inspection<a class=\"headerlink\" href=\"#inspection\" title=\"Permanent link\">&para;</a></h2>\n<table>\n<thead>\n<tr>\n<th>Command</th>\n<th>Effect</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>/tools</code></td>\n<td>List active tools.</td>\n</tr>\n<tr>\n<td><code>/skills</code></td>\n<td>List discovered skills.</td>\n</tr>\n<tr>\n<td><code>/plugins</code></td>\n<td>List loaded plugins (built-in + entry-point) with version.</td>\n</tr>\n<tr>\n<td><code>/reload</code></td>\n<td>Reload skills from disk and re-read TOML config (since v0.4); honours launch-pinned flags.</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"sessions-since-v04\">Sessions (since v0.4)<a class=\"headerlink\" href=\"#sessions-since-v04\" title=\"Permanent link\">&para;</a></h2>\n<table>\n<thead>\n<tr>\n<th>Command</th>\n<th>Effect</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>/tree</code></td>\n<td>Show the session as a numbered entry chain.</td>\n</tr>\n<tr>\n<td><code>/fork [n]</code></td>\n<td>Branch a new session at entry <code>n</code> (default: all); switch to it, original untouched.</td>\n</tr>\n<tr>\n<td><code>/clone</code></td>\n<td>Duplicate the whole session into a new file and continue on the copy.</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"skills\">Skills<a class=\"headerlink\" href=\"#skills\" title=\"Permanent link\">&para;</a></h2>\n<p><code>/skill:&lt;name&gt; [message]</code> — splices a skill body into the next user message.</p>\n<div class=\"language-text highlight\"><pre><span></span><code><span id=\"__span-0-1\"><a id=\"__codelineno-0-1\" name=\"__codelineno-0-1\" href=\"#__codelineno-0-1\"></a>&gt; /skill:write-a-prd a todo-list manager with Flask and htmx\n</span></code></pre></div>\n<p>Equivalent to typing the skill body followed by your message. The model also has the skill exposed as a tool named <code>skill_&lt;normalised-name&gt;</code> (auto-wrapping), so it can invoke skills natively via tool-calling without needing the slash form.</p>\n<p><a href=\"../skills/\">Skills</a> covers the format and discovery paths.</p>\n<h2 id=\"steering-and-follow-up\">Steering and follow-up<a class=\"headerlink\" href=\"#steering-and-follow-up\" title=\"Permanent link\">&para;</a></h2>\n<p>These mid-flight UX commands let you queue work without aborting the current turn.</p>\n<table>\n<thead>\n<tr>\n<th>Command</th>\n<th>Effect</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>/steer &lt;text&gt;</code></td>\n<td>Queue a steering message. Delivered at the next tool-batch boundary.</td>\n</tr>\n<tr>\n<td><code>/follow-up &lt;text&gt;</code></td>\n<td>Queue a follow-up. Delivered after the agent would otherwise emit <code>agent_end</code>.</td>\n</tr>\n<tr>\n<td><code>/queue</code></td>\n<td>Show pending steering and follow-up messages.</td>\n</tr>\n</tbody>\n</table>\n<div class=\"admonition note\">\n<p class=\"admonition-title\">Streaming-time steering</p>\n<p>Since v0.4 you can type while the model is working: <strong>Enter</strong> stops the run; <strong>type then Enter</strong> stops and redirects it to the new instruction (interrupt-and-redirect). <code>/steer</code> and <code>/follow-up</code> remain the explicit queue commands and back the RPC <code>steer</code>/<code>follow_up</code> mechanism.</p>\n</div>\n<h2 id=\"compaction\">Compaction<a class=\"headerlink\" href=\"#compaction\" title=\"Permanent link\">&para;</a></h2>\n<p><code>/compact [bias]</code> — manually compact older history into a summary.</p>\n<p>When the context window is approached, the agent auto-compacts. Manual compaction is for taking the bias parameter:</p>\n<div class=\"language-text highlight\"><pre><span></span><code><span id=\"__span-1-1\"><a id=\"__codelineno-1-1\" name=\"__codelineno-1-1\" href=\"#__codelineno-1-1\"></a>&gt; /compact focus on the auth refactor decisions\n</span></code></pre></div>\n<p>Without a bias, the default summariser prompt runs.</p>\n<h2 id=\"ui-toggles\">UI toggles<a class=\"headerlink\" href=\"#ui-toggles\" title=\"Permanent link\">&para;</a></h2>\n<p>These are <strong>frontend-owned commands</strong> — they're registered by <code>BasicFrontend.__init__</code>, not via the standard <code>letscode_register_commands</code> hook, because they toggle frontend-private state.</p>\n<table>\n<thead>\n<tr>\n<th>Command</th>\n<th>Effect</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>/verbose</code></td>\n<td>Toggle full vs. truncated tool-result panels and tool-call args. Default: truncated.</td>\n</tr>\n<tr>\n<td><code>/footer</code></td>\n<td>Toggle the per-turn model/cost/ctx footer. Default: on.</td>\n</tr>\n</tbody>\n</table>\n<p>In default mode, the <code>read</code> tool's result panel is <strong>suppressed entirely</strong> — only the call line <code>&gt; read({\"path\":\"X\"})</code> shows. <code>/verbose</code> restores the full Syntax-highlighted body.</p>\n<h2 id=\"plugin-commands\">Plugin commands<a class=\"headerlink\" href=\"#plugin-commands\" title=\"Permanent link\">&para;</a></h2>\n<p>Slash commands from installed plugins appear in <code>/help</code> alongside the built-ins. See the <a href=\"../../plugins/memory/\">reference plugin</a> for <code>/remember</code>, <code>/memories</code>, and <code>/forget &lt;id&gt;</code> (from <code>letscode-memory</code>).</p>\n\n\n\n\n\n\n\n\n\n \n \n\n\n\n\n\n\n \n </article>\n </div>\n \n \n <script>var tabs=__md_get(\"__tabs\");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(\".tabbed-set\")){var labels=set.querySelector(\".tabbed-labels\");for(var tab of tabs)for(var label of labels.getElementsByTagName(\"label\"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script>\n\n<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith(\"__tabbed_\"))</script>\n </div>\n \n <button type=\"button\" class=\"md-top md-icon\" data-md-component=\"top\" hidden>\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-circle-arrow-up\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m16 12-4-4-4 4M12 16V8\"/></svg>\n Back to top\n</button>\n \n </main>\n \n <footer class=\"md-footer\">\n \n \n \n <nav class=\"md-footer__inner md-grid\" aria-label=\"Footer\" >\n \n \n <a href=\"../configuration/\" class=\"md-footer__link md-footer__link--prev\" aria-label=\"Previous: Configuration\">\n <div class=\"md-footer__button md-icon\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-arrow-left\" viewBox=\"0 0 24 24\"><path d=\"m12 19-7-7 7-7M19 12H5\"/></svg>\n </div>\n <div class=\"md-footer__title\">\n <span class=\"md-footer__direction\">\n Previous\n </span>\n <div class=\"md-ellipsis\">\n Configuration\n </div>\n </div>\n </a>\n \n \n \n <a href=\"../skills/\" class=\"md-footer__link md-footer__link--next\" aria-label=\"Next: Skills\">\n <div class=\"md-footer__title\">\n <span class=\"md-footer__direction\">\n Next\n </span>\n <div class=\"md-ellipsis\">\n Skills\n </div>\n </div>\n <div class=\"md-footer__button md-icon\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-arrow-right\" viewBox=\"0 0 24 24\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg>\n </div>\n </a>\n \n </nav>\n \n \n <div class=\"md-footer-meta md-typeset\">\n <div class=\"md-footer-meta__inner md-grid\">\n <div class=\"md-copyright\">\n \n <div class=\"md-copyright__highlight\">\n Copyright &copy; 2026 Stefane Fermigier &mdash; released under the MIT license.\n\n </div>\n \n \n Made with\n <a href=\"https://zensical.org/\" target=\"_blank\" rel=\"noopener\">\n Zensical\n </a>\n \n</div>\n \n \n<div class=\"md-social\">\n \n \n \n \n \n <a href=\"https://github.com/abilian/letscode\" target=\"_blank\" rel=\"noopener\" title=\"letscode on GitHub\" class=\"md-social__link\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><!--! Font Awesome Free 7.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2026 Fonticons, Inc.--><path fill=\"currentColor\" d=\"M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8M105.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2\"/></svg>\n </a>\n \n</div>\n \n </div>\n </div>\n</footer>\n \n </div>\n <div class=\"md-dialog\" data-md-component=\"dialog\">\n <div class=\"md-dialog__inner md-typeset\"></div>\n </div>\n \n \n \n \n \n <script id=\"__config\" type=\"application/json\">{\"annotate\":null,\"base\":\"../..\",\"features\":[\"announce.dismiss\",\"content.code.annotate\",\"content.code.copy\",\"content.code.select\",\"content.footnote.tooltips\",\"content.tabs.link\",\"content.tooltips\",\"navigation.footer\",\"navigation.indexes\",\"navigation.instant\",\"navigation.instant.prefetch\",\"navigation.path\",\"navigation.sections\",\"navigation.tabs\",\"navigation.top\",\"navigation.tracking\",\"search.highlight\",\"search.share\",\"search.suggest\"],\"search\":\"../../assets/javascripts/workers/search.e2d2d235.min.js\",\"tags\":null,\"translations\":{\"clipboard.copied\":\"Copied to clipboard\",\"clipboard.copy\":\"Copy to clipboard\",\"search.result.more.one\":\"1 more on this page\",\"search.result.more.other\":\"# more on this page\",\"search.result.none\":\"No matching documents\",\"search.result.one\":\"1 matching document\",\"search.result.other\":\"# matching documents\",\"search.result.placeholder\":\"Type to start searching\",\"search.result.term.missing\":\"Missing\",\"select.version\":\"Select version\"},\"version\":null}</script>\n \n \n <script src=\"../../assets/javascripts/bundle.6e5f0216.min.js\"></script>\n \n \n </body>\n</html>",
3
+ "hash": 17166931202801081034
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "data": "\n<!doctype html>\n<html lang=\"en\" class=\"no-js\">\n <head>\n \n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n \n <meta name=\"description\" content=\"Per-version notes on what shipped.\">\n \n \n <meta name=\"author\" content=\"Stefane Fermigier\">\n \n \n <link rel=\"canonical\" href=\"https://letscode.dev/about/changelog/\">\n \n \n <link rel=\"prev\" href=\"../\">\n \n \n <link rel=\"next\" href=\"../roadmap/\">\n \n \n \n \n \n <link rel=\"icon\" href=\"../../assets/images/favicon.png\">\n <meta name=\"generator\" content=\"zensical-0.0.43\">\n \n \n \n <title>Changes - letscode</title>\n \n \n \n \n \n \n <link rel=\"stylesheet\" href=\"../../assets/stylesheets/modern/main.fba56155.min.css\">\n \n \n \n \n <link rel=\"stylesheet\" href=\"../../assets/stylesheets/modern/palette.dfe2e883.min.css\">\n \n \n\n\n \n \n \n \n \n \n \n \n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n <link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Inter:300,300i,400,400i,500,500i,700,700i%7CJetBrains+Mono:400,400i,700,700i&amp;display=fallback\">\n <style>:root{--md-text-font:\"Inter\";--md-code-font:\"JetBrains Mono\"}</style>\n \n \n \n <script>__md_scope=new URL(\"../..\",location),__md_scope.pathname.endsWith(\"/\")||(__md_scope=new URL(__md_scope.pathname+\"/\",location)),__md_hash=e=>[...e].reduce(((e,t)=>(e<<5)-e+t.charCodeAt(0)),0),__md_get=(e,t=localStorage,_=__md_scope)=>JSON.parse(t.getItem(_.pathname+\".\"+e)),__md_set=(e,t,_=localStorage,a=__md_scope)=>{try{_.setItem(a.pathname+\".\"+e,JSON.stringify(t))}catch(e){}},document.documentElement.setAttribute(\"data-platform\",navigator.platform)</script>\n \n \n\n \n \n </head>\n \n \n \n \n \n \n \n \n \n <body dir=\"ltr\" data-md-color-scheme=\"default\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\">\n \n \n <input class=\"md-toggle\" data-md-toggle=\"drawer\" type=\"checkbox\" id=\"__drawer\" autocomplete=\"off\">\n <input class=\"md-toggle\" data-md-toggle=\"search\" type=\"checkbox\" id=\"__search\" autocomplete=\"off\">\n <label class=\"md-overlay\" for=\"__drawer\" aria-label=\"Navigation\"></label>\n <div data-md-component=\"skip\">\n \n \n <a href=\"#changes\" class=\"md-skip\">\n Skip to content\n </a>\n \n </div>\n <div data-md-component=\"announce\">\n \n </div>\n \n \n \n\n<header class=\"md-header\" data-md-component=\"header\">\n <nav class=\"md-header__inner md-grid\" aria-label=\"Header\">\n <a href=\"../..\" title=\"letscode\" class=\"md-header__button md-logo\" aria-label=\"letscode\" data-md-component=\"logo\">\n \n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-book-open\" viewBox=\"0 0 24 24\"><path d=\"M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z\"/></svg>\n\n </a>\n <label class=\"md-header__button md-icon\" for=\"__drawer\" aria-label=\"Navigation\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-menu\" viewBox=\"0 0 24 24\"><path d=\"M4 5h16M4 12h16M4 19h16\"/></svg>\n </label>\n <div class=\"md-header__title\" data-md-component=\"header-title\">\n <div class=\"md-header__ellipsis\">\n <div class=\"md-header__topic\">\n <span class=\"md-ellipsis\">\n letscode\n </span>\n </div>\n <div class=\"md-header__topic\" data-md-component=\"header-topic\">\n <span class=\"md-ellipsis\">\n \n Changes\n \n </span>\n </div>\n </div>\n </div>\n \n \n <form class=\"md-header__option\" data-md-component=\"palette\">\n \n \n \n \n <input class=\"md-option\" data-md-color-media=\"(prefers-color-scheme)\" data-md-color-scheme=\"default\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\" aria-label=\"Switch to light mode\" type=\"radio\" name=\"__palette\" id=\"__palette_0\">\n \n <label class=\"md-header__button md-icon\" title=\"Switch to light mode\" for=\"__palette_1\" hidden>\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-sun-moon\" viewBox=\"0 0 24 24\"><path d=\"M12 2v2M14.837 16.385a6 6 0 1 1-7.223-7.222c.624-.147.97.66.715 1.248a4 4 0 0 0 5.26 5.259c.589-.255 1.396.09 1.248.715M16 12a4 4 0 0 0-4-4M19 5l-1.256 1.256M20 12h2\"/></svg>\n </label>\n \n \n \n \n \n <input class=\"md-option\" data-md-color-media=\"(prefers-color-scheme: light)\" data-md-color-scheme=\"default\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\" aria-label=\"Switch to dark mode\" type=\"radio\" name=\"__palette\" id=\"__palette_1\">\n \n <label class=\"md-header__button md-icon\" title=\"Switch to dark mode\" for=\"__palette_2\" hidden>\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-sun\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\"/></svg>\n </label>\n \n \n \n \n \n <input class=\"md-option\" data-md-color-media=\"(prefers-color-scheme: dark)\" data-md-color-scheme=\"slate\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\" aria-label=\"Switch to system preference\" type=\"radio\" name=\"__palette\" id=\"__palette_2\">\n \n <label class=\"md-header__button md-icon\" title=\"Switch to system preference\" for=\"__palette_0\" hidden>\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-moon\" viewBox=\"0 0 24 24\"><path d=\"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401\"/></svg>\n </label>\n \n \n</form>\n \n \n \n <script>var palette=__md_get(\"__palette\");if(palette&&palette.color){if(\"(prefers-color-scheme)\"===palette.color.media){var media=matchMedia(\"(prefers-color-scheme: light)\"),input=document.querySelector(media.matches?\"[data-md-color-media='(prefers-color-scheme: light)']\":\"[data-md-color-media='(prefers-color-scheme: dark)']\");palette.color.media=input.getAttribute(\"data-md-color-media\"),palette.color.scheme=input.getAttribute(\"data-md-color-scheme\"),palette.color.primary=input.getAttribute(\"data-md-color-primary\"),palette.color.accent=input.getAttribute(\"data-md-color-accent\")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute(\"data-md-color-\"+key,value)}</script>\n \n \n \n \n \n <label class=\"md-header__button md-icon\" for=\"__search\" aria-label=\"Search\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-search\" viewBox=\"0 0 24 24\"><path d=\"m21 21-4.34-4.34\"/><circle cx=\"11\" cy=\"11\" r=\"8\"/></svg>\n </label>\n <div class=\"md-search\" data-md-component=\"search\" role=\"dialog\" aria-label=\"Search\">\n <button type=\"button\" class=\"md-search__button\">\n Search\n </button>\n</div>\n \n \n <div class=\"md-header__source\">\n \n </div>\n </nav>\n \n</header>\n \n <div class=\"md-container\" data-md-component=\"container\">\n \n \n \n \n \n<nav class=\"md-tabs\" aria-label=\"Tabs\" data-md-component=\"tabs\">\n <div class=\"md-grid\">\n <ul class=\"md-tabs__list\">\n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../..\" class=\"md-tabs__link\">\n \n \n Home\n\n </a>\n </li>\n \n\n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../getting-started/\" class=\"md-tabs__link\">\n \n \n Getting started\n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../user-guide/\" class=\"md-tabs__link\">\n \n \n User guide\n\n </a>\n </li>\n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../plugins/\" class=\"md-tabs__link\">\n \n \n Plugins\n\n </a>\n </li>\n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../architecture/\" class=\"md-tabs__link\">\n \n \n Architecture\n\n </a>\n </li>\n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item md-tabs__item--active\">\n <a href=\"../\" class=\"md-tabs__link\">\n \n \n About\n\n </a>\n </li>\n \n \n\n \n </ul>\n </div>\n</nav>\n \n \n \n <main class=\"md-main\" data-md-component=\"main\">\n <div class=\"md-main__inner md-grid\">\n \n \n \n <div class=\"md-sidebar md-sidebar--primary\" data-md-component=\"sidebar\" data-md-type=\"navigation\" >\n <div class=\"md-sidebar__scrollwrap\">\n <div class=\"md-sidebar__inner\">\n \n\n\n \n\n\n<nav class=\"md-nav md-nav--primary md-nav--lifted\" aria-label=\"Navigation\" data-md-level=\"0\">\n <label class=\"md-nav__title\" for=\"__drawer\">\n <a href=\"../..\" title=\"letscode\" class=\"md-nav__button md-logo\" aria-label=\"letscode\" data-md-component=\"logo\">\n \n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-book-open\" viewBox=\"0 0 24 24\"><path d=\"M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z\"/></svg>\n\n </a>\n letscode\n </label>\n \n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../..\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Home\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../getting-started/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Getting started\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--nested\">\n \n \n \n <input class=\"md-nav__toggle md-toggle \" type=\"checkbox\" id=\"__nav_3\" >\n \n \n <div class=\"md-nav__link md-nav__container\">\n <a href=\"../../user-guide/\" class=\"md-nav__link \">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n User guide\n\n \n </span>\n \n \n\n </a>\n \n \n <label class=\"md-nav__link \" for=\"__nav_3\" id=\"__nav_3_label\" tabindex=\"0\">\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n </div>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_3_label\" aria-expanded=\"false\">\n <label class=\"md-nav__title\" for=\"__nav_3\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n User guide\n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../user-guide/configuration/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Configuration\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../user-guide/slash-commands/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Slash commands\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../user-guide/skills/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Skills\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../user-guide/sessions/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Sessions\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--nested\">\n \n \n \n <input class=\"md-nav__toggle md-toggle \" type=\"checkbox\" id=\"__nav_4\" >\n \n \n <div class=\"md-nav__link md-nav__container\">\n <a href=\"../../plugins/\" class=\"md-nav__link \">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Plugins\n\n \n </span>\n \n \n\n </a>\n \n \n <label class=\"md-nav__link \" for=\"__nav_4\" id=\"__nav_4_label\" tabindex=\"0\">\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n </div>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_4_label\" aria-expanded=\"false\">\n <label class=\"md-nav__title\" for=\"__nav_4\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n Plugins\n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../plugins/authoring/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Authoring guide\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../plugins/memory/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Reference plugin\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--nested\">\n \n \n \n <input class=\"md-nav__toggle md-toggle \" type=\"checkbox\" id=\"__nav_5\" >\n \n \n <div class=\"md-nav__link md-nav__container\">\n <a href=\"../../architecture/\" class=\"md-nav__link \">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Architecture\n\n \n </span>\n \n \n\n </a>\n \n \n <label class=\"md-nav__link \" for=\"__nav_5\" id=\"__nav_5_label\" tabindex=\"0\">\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n </div>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_5_label\" aria-expanded=\"false\">\n <label class=\"md-nav__title\" for=\"__nav_5\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n Architecture\n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../architecture/extension-model/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Extension model\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../architecture/agent-loop/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Agent loop\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested\">\n \n \n \n <input class=\"md-nav__toggle md-toggle \" type=\"checkbox\" id=\"__nav_6\" checked>\n \n \n <div class=\"md-nav__link md-nav__container\">\n <a href=\"../\" class=\"md-nav__link \">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n About\n\n \n </span>\n \n \n\n </a>\n \n \n <label class=\"md-nav__link \" for=\"__nav_6\" id=\"__nav_6_label\" tabindex=\"\">\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n </div>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_6_label\" aria-expanded=\"true\">\n <label class=\"md-nav__title\" for=\"__nav_6\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n About\n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--active\">\n \n \n \n \n \n \n \n <label class=\"md-nav__link md-nav__link--active\" for=\"__toc\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Changelog\n\n \n </span>\n \n \n\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n <a href=\"././\" class=\"md-nav__link md-nav__link--active\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Changelog\n\n \n </span>\n \n \n\n </a>\n \n \n\n\n<nav class=\"md-nav md-nav--secondary\" aria-label=\"On this page\">\n \n \n \n \n \n \n <label class=\"md-nav__title\" for=\"__toc\">\n <span class=\"md-nav__icon md-icon\"></span>\n On this page\n </label>\n <ul class=\"md-nav__list\" data-md-component=\"toc\" data-md-scrollfix>\n \n <li class=\"md-nav__item\">\n <a href=\"#v050-2026-05-19\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n v0.5.0 — 2026-05-19\n </span>\n </span>\n </a>\n \n <nav class=\"md-nav\" aria-label=\"v0.5.0 — 2026-05-19\">\n <ul class=\"md-nav__list\">\n \n <li class=\"md-nav__item\">\n <a href=\"#added\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Added\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#changed\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Changed\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#fixed\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Fixed\n </span>\n </span>\n </a>\n \n</li>\n \n </ul>\n </nav>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#earlier-releases\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Earlier releases\n </span>\n </span>\n </a>\n \n</li>\n \n </ul>\n \n</nav>\n \n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../roadmap/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Roadmap\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../lessons-learned/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Lessons learned\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../related-projects/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Related projects\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n </ul>\n</nav>\n </div>\n </div>\n </div>\n \n \n \n <div class=\"md-sidebar md-sidebar--secondary\" data-md-component=\"sidebar\" data-md-type=\"toc\" >\n <div class=\"md-sidebar__scrollwrap\">\n \n \n \n \n \n \n \n <input class=\"md-nav__toggle md-toggle\" type=\"checkbox\" id=\"__toc\">\n <div class=\"md-sidebar-button__wrapper\">\n <label class=\"md-sidebar-button\" for=\"__toc\"></label>\n </div>\n \n \n <div class=\"md-sidebar__inner\">\n \n\n\n<nav class=\"md-nav md-nav--secondary\" aria-label=\"On this page\">\n \n \n \n \n \n \n <label class=\"md-nav__title\" for=\"__toc\">\n <span class=\"md-nav__icon md-icon\"></span>\n On this page\n </label>\n <ul class=\"md-nav__list\" data-md-component=\"toc\" data-md-scrollfix>\n \n <li class=\"md-nav__item\">\n <a href=\"#v050-2026-05-19\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n v0.5.0 — 2026-05-19\n </span>\n </span>\n </a>\n \n <nav class=\"md-nav\" aria-label=\"v0.5.0 — 2026-05-19\">\n <ul class=\"md-nav__list\">\n \n <li class=\"md-nav__item\">\n <a href=\"#added\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Added\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#changed\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Changed\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#fixed\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Fixed\n </span>\n </span>\n </a>\n \n</li>\n \n </ul>\n </nav>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#earlier-releases\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Earlier releases\n </span>\n </span>\n </a>\n \n</li>\n \n </ul>\n \n</nav>\n </div>\n </div>\n </div>\n \n \n \n <div class=\"md-content\" data-md-component=\"content\">\n \n \n\n\n\n \n\n\n <nav class=\"md-path\" aria-label=\"Navigation\" >\n <ol class=\"md-path__list\">\n \n \n \n \n <li class=\"md-path__item\">\n <a href=\"../..\" class=\"md-path__link\">\n \n \n <span class=\"md-ellipsis\">\n Home\n </span>\n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-path__item\">\n <a href=\"../\" class=\"md-path__link\">\n \n \n <span class=\"md-ellipsis\">\n About\n </span>\n\n </a>\n </li>\n \n \n\n \n </ol>\n </nav>\n\n \n <article class=\"md-content__inner md-typeset\">\n \n \n\n<h1 id=\"changes\">Changes<a class=\"headerlink\" href=\"#changes\" title=\"Permanent link\">&para;</a></h1>\n<p>The canonical, current change log lives at the repo root: <a href=\"https://github.com/abilian/letscode/blob/main/CHANGES.md\"><code>CHANGES.md</code></a>. The summary below covers the most recent release; click through for earlier versions.</p>\n<h2 id=\"v050-2026-05-19\">v0.5.0 — 2026-05-19<a class=\"headerlink\" href=\"#v050-2026-05-19\" title=\"Permanent link\">&para;</a></h2>\n<p>Distribution &amp; usability — make letscode installable and survivable on first contact. (No public PyPI release yet: the name is reserved; publishing is a held maintainer decision.)</p>\n<h3 id=\"added\">Added<a class=\"headerlink\" href=\"#added\" title=\"Permanent link\">&para;</a></h3>\n<ul>\n<li><code>letscode --version</code> and <code>letscode --init</code> (scaffold a commented <code>~/.letscode/config.toml</code>); both work with no API key.</li>\n<li>Actionable no-API-key message (names the env var, <code>--api-key</code>, <code>--init</code>, the config path).</li>\n<li>Per-turn footer shows provider prompt-cache hits when present.</li>\n<li>Release-readiness gates: <code>make verify-dist</code> (drive the built wheel from a clean venv) and <code>make verify-plugin</code> (entry-point discovery from a non-editable install).</li>\n</ul>\n<h3 id=\"changed\">Changed<a class=\"headerlink\" href=\"#changed\" title=\"Permanent link\">&para;</a></h3>\n<ul>\n<li><strong>CLI migrated from typer/click to <a href=\"https://cyclopts.readthedocs.io\">cyclopts</a></strong> — behaviour-preserving (same flags, env vars, exit codes).</li>\n<li>Input typed at the <code>&gt;</code> prompt no longer echoes twice.</li>\n<li>Docs corrected: not on PyPI yet → install from source / built wheel.</li>\n</ul>\n<h3 id=\"fixed\">Fixed<a class=\"headerlink\" href=\"#fixed\" title=\"Permanent link\">&para;</a></h3>\n<ul>\n<li>A malformed config file degrades to defaults with a one-line warning instead of a traceback.</li>\n<li>Options after the prompt are no longer swallowed into it (<code>letscode \"p\" --model x</code> honours <code>--model</code>).</li>\n</ul>\n<h2 id=\"earlier-releases\">Earlier releases<a class=\"headerlink\" href=\"#earlier-releases\" title=\"Permanent link\">&para;</a></h2>\n<ul>\n<li><a href=\"https://github.com/abilian/letscode/blob/main/CHANGES.md#040--2026-05-19\">v0.4.0 — 2026-05-19</a> — Plugin &amp; integration: RPC mode (<code>--mode rpc</code>), tree sessions (<code>/tree</code>/<code>/fork</code>/<code>/clone</code>), memory recall + <code>/forget</code>, <code>/reload</code>, interrupt-and-redirect streaming input, config sections, external Textual frontend.</li>\n<li><a href=\"https://github.com/abilian/letscode/blob/main/CHANGES.md#030--2026-05-13\">v0.3.0 — 2026-05-13</a> — Extension model + ergonomics: <code>render_custom_message</code> hook, <code>Frontend</code> Protocol, skill-to-tool synthesis, <code>letscode-memory</code>, docs site, Markdown rendering.</li>\n<li><a href=\"https://github.com/abilian/letscode/blob/main/CHANGES.md#020--2026-05-12\">v0.2.0 — 2026-05-12</a> — Two-tier message model, <code>ExecutionEnv</code>, <code>parent_id</code> sessions, compaction, steering / follow-up queues, TOML config.</li>\n<li><a href=\"https://github.com/abilian/letscode/blob/main/CHANGES.md#010--2026-05-09\">v0.1.0 — 2026-05-09</a> — Initial release: agent loop, four built-in tools, skill discovery, slash commands, sessions, basic TUI, plugin system.</li>\n</ul>\n<p>For the full per-version breakdown, see <a href=\"https://github.com/abilian/letscode/blob/main/CHANGES.md\"><code>CHANGES.md</code></a>.</p>\n\n\n\n\n\n\n\n\n\n \n \n\n\n\n\n\n\n \n </article>\n </div>\n \n \n <script>var tabs=__md_get(\"__tabs\");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(\".tabbed-set\")){var labels=set.querySelector(\".tabbed-labels\");for(var tab of tabs)for(var label of labels.getElementsByTagName(\"label\"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script>\n\n<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith(\"__tabbed_\"))</script>\n </div>\n \n <button type=\"button\" class=\"md-top md-icon\" data-md-component=\"top\" hidden>\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-circle-arrow-up\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m16 12-4-4-4 4M12 16V8\"/></svg>\n Back to top\n</button>\n \n </main>\n \n <footer class=\"md-footer\">\n \n \n \n <nav class=\"md-footer__inner md-grid\" aria-label=\"Footer\" >\n \n \n <a href=\"../\" class=\"md-footer__link md-footer__link--prev\" aria-label=\"Previous: Overview\">\n <div class=\"md-footer__button md-icon\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-arrow-left\" viewBox=\"0 0 24 24\"><path d=\"m12 19-7-7 7-7M19 12H5\"/></svg>\n </div>\n <div class=\"md-footer__title\">\n <span class=\"md-footer__direction\">\n Previous\n </span>\n <div class=\"md-ellipsis\">\n Overview\n </div>\n </div>\n </a>\n \n \n \n <a href=\"../roadmap/\" class=\"md-footer__link md-footer__link--next\" aria-label=\"Next: Roadmap\">\n <div class=\"md-footer__title\">\n <span class=\"md-footer__direction\">\n Next\n </span>\n <div class=\"md-ellipsis\">\n Roadmap\n </div>\n </div>\n <div class=\"md-footer__button md-icon\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-arrow-right\" viewBox=\"0 0 24 24\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg>\n </div>\n </a>\n \n </nav>\n \n \n <div class=\"md-footer-meta md-typeset\">\n <div class=\"md-footer-meta__inner md-grid\">\n <div class=\"md-copyright\">\n \n <div class=\"md-copyright__highlight\">\n Copyright &copy; 2026 Stefane Fermigier &mdash; released under the MIT license.\n\n </div>\n \n \n Made with\n <a href=\"https://zensical.org/\" target=\"_blank\" rel=\"noopener\">\n Zensical\n </a>\n \n</div>\n \n \n<div class=\"md-social\">\n \n \n \n \n \n <a href=\"https://github.com/abilian/letscode\" target=\"_blank\" rel=\"noopener\" title=\"letscode on GitHub\" class=\"md-social__link\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><!--! Font Awesome Free 7.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2026 Fonticons, Inc.--><path fill=\"currentColor\" d=\"M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8M105.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2\"/></svg>\n </a>\n \n</div>\n \n </div>\n </div>\n</footer>\n \n </div>\n <div class=\"md-dialog\" data-md-component=\"dialog\">\n <div class=\"md-dialog__inner md-typeset\"></div>\n </div>\n \n \n \n \n \n <script id=\"__config\" type=\"application/json\">{\"annotate\":null,\"base\":\"../..\",\"features\":[\"announce.dismiss\",\"content.code.annotate\",\"content.code.copy\",\"content.code.select\",\"content.footnote.tooltips\",\"content.tabs.link\",\"content.tooltips\",\"navigation.footer\",\"navigation.indexes\",\"navigation.instant\",\"navigation.instant.prefetch\",\"navigation.path\",\"navigation.sections\",\"navigation.tabs\",\"navigation.top\",\"navigation.tracking\",\"search.highlight\",\"search.share\",\"search.suggest\"],\"search\":\"../../assets/javascripts/workers/search.e2d2d235.min.js\",\"tags\":null,\"translations\":{\"clipboard.copied\":\"Copied to clipboard\",\"clipboard.copy\":\"Copy to clipboard\",\"search.result.more.one\":\"1 more on this page\",\"search.result.more.other\":\"# more on this page\",\"search.result.none\":\"No matching documents\",\"search.result.one\":\"1 matching document\",\"search.result.other\":\"# matching documents\",\"search.result.placeholder\":\"Type to start searching\",\"search.result.term.missing\":\"Missing\",\"select.version\":\"Select version\"},\"version\":null}</script>\n \n \n <script src=\"../../assets/javascripts/bundle.6e5f0216.min.js\"></script>\n \n \n </body>\n</html>",
3
+ "hash": 2404931562954233819
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "data": "\n<!doctype html>\n<html lang=\"en\" class=\"no-js\">\n <head>\n \n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n \n <meta name=\"description\" content=\"Persistence, continuation, and the JSONL file format.\">\n \n \n <meta name=\"author\" content=\"Stefane Fermigier\">\n \n \n <link rel=\"canonical\" href=\"https://letscode.dev/user-guide/sessions/\">\n \n \n <link rel=\"prev\" href=\"../skills/\">\n \n \n <link rel=\"next\" href=\"../../plugins/\">\n \n \n \n \n \n <link rel=\"icon\" href=\"../../assets/images/favicon.png\">\n <meta name=\"generator\" content=\"zensical-0.0.43\">\n \n \n \n <title>Sessions - letscode</title>\n \n \n \n \n \n \n <link rel=\"stylesheet\" href=\"../../assets/stylesheets/modern/main.fba56155.min.css\">\n \n \n \n \n <link rel=\"stylesheet\" href=\"../../assets/stylesheets/modern/palette.dfe2e883.min.css\">\n \n \n\n\n \n \n \n \n \n \n \n \n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n <link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Inter:300,300i,400,400i,500,500i,700,700i%7CJetBrains+Mono:400,400i,700,700i&amp;display=fallback\">\n <style>:root{--md-text-font:\"Inter\";--md-code-font:\"JetBrains Mono\"}</style>\n \n \n \n <script>__md_scope=new URL(\"../..\",location),__md_scope.pathname.endsWith(\"/\")||(__md_scope=new URL(__md_scope.pathname+\"/\",location)),__md_hash=e=>[...e].reduce(((e,t)=>(e<<5)-e+t.charCodeAt(0)),0),__md_get=(e,t=localStorage,_=__md_scope)=>JSON.parse(t.getItem(_.pathname+\".\"+e)),__md_set=(e,t,_=localStorage,a=__md_scope)=>{try{_.setItem(a.pathname+\".\"+e,JSON.stringify(t))}catch(e){}},document.documentElement.setAttribute(\"data-platform\",navigator.platform)</script>\n \n \n\n \n \n </head>\n \n \n \n \n \n \n \n \n \n <body dir=\"ltr\" data-md-color-scheme=\"default\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\">\n \n \n <input class=\"md-toggle\" data-md-toggle=\"drawer\" type=\"checkbox\" id=\"__drawer\" autocomplete=\"off\">\n <input class=\"md-toggle\" data-md-toggle=\"search\" type=\"checkbox\" id=\"__search\" autocomplete=\"off\">\n <label class=\"md-overlay\" for=\"__drawer\" aria-label=\"Navigation\"></label>\n <div data-md-component=\"skip\">\n \n \n <a href=\"#sessions\" class=\"md-skip\">\n Skip to content\n </a>\n \n </div>\n <div data-md-component=\"announce\">\n \n </div>\n \n \n \n\n<header class=\"md-header\" data-md-component=\"header\">\n <nav class=\"md-header__inner md-grid\" aria-label=\"Header\">\n <a href=\"../..\" title=\"letscode\" class=\"md-header__button md-logo\" aria-label=\"letscode\" data-md-component=\"logo\">\n \n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-book-open\" viewBox=\"0 0 24 24\"><path d=\"M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z\"/></svg>\n\n </a>\n <label class=\"md-header__button md-icon\" for=\"__drawer\" aria-label=\"Navigation\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-menu\" viewBox=\"0 0 24 24\"><path d=\"M4 5h16M4 12h16M4 19h16\"/></svg>\n </label>\n <div class=\"md-header__title\" data-md-component=\"header-title\">\n <div class=\"md-header__ellipsis\">\n <div class=\"md-header__topic\">\n <span class=\"md-ellipsis\">\n letscode\n </span>\n </div>\n <div class=\"md-header__topic\" data-md-component=\"header-topic\">\n <span class=\"md-ellipsis\">\n \n Sessions\n \n </span>\n </div>\n </div>\n </div>\n \n \n <form class=\"md-header__option\" data-md-component=\"palette\">\n \n \n \n \n <input class=\"md-option\" data-md-color-media=\"(prefers-color-scheme)\" data-md-color-scheme=\"default\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\" aria-label=\"Switch to light mode\" type=\"radio\" name=\"__palette\" id=\"__palette_0\">\n \n <label class=\"md-header__button md-icon\" title=\"Switch to light mode\" for=\"__palette_1\" hidden>\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-sun-moon\" viewBox=\"0 0 24 24\"><path d=\"M12 2v2M14.837 16.385a6 6 0 1 1-7.223-7.222c.624-.147.97.66.715 1.248a4 4 0 0 0 5.26 5.259c.589-.255 1.396.09 1.248.715M16 12a4 4 0 0 0-4-4M19 5l-1.256 1.256M20 12h2\"/></svg>\n </label>\n \n \n \n \n \n <input class=\"md-option\" data-md-color-media=\"(prefers-color-scheme: light)\" data-md-color-scheme=\"default\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\" aria-label=\"Switch to dark mode\" type=\"radio\" name=\"__palette\" id=\"__palette_1\">\n \n <label class=\"md-header__button md-icon\" title=\"Switch to dark mode\" for=\"__palette_2\" hidden>\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-sun\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\"/></svg>\n </label>\n \n \n \n \n \n <input class=\"md-option\" data-md-color-media=\"(prefers-color-scheme: dark)\" data-md-color-scheme=\"slate\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\" aria-label=\"Switch to system preference\" type=\"radio\" name=\"__palette\" id=\"__palette_2\">\n \n <label class=\"md-header__button md-icon\" title=\"Switch to system preference\" for=\"__palette_0\" hidden>\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-moon\" viewBox=\"0 0 24 24\"><path d=\"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401\"/></svg>\n </label>\n \n \n</form>\n \n \n \n <script>var palette=__md_get(\"__palette\");if(palette&&palette.color){if(\"(prefers-color-scheme)\"===palette.color.media){var media=matchMedia(\"(prefers-color-scheme: light)\"),input=document.querySelector(media.matches?\"[data-md-color-media='(prefers-color-scheme: light)']\":\"[data-md-color-media='(prefers-color-scheme: dark)']\");palette.color.media=input.getAttribute(\"data-md-color-media\"),palette.color.scheme=input.getAttribute(\"data-md-color-scheme\"),palette.color.primary=input.getAttribute(\"data-md-color-primary\"),palette.color.accent=input.getAttribute(\"data-md-color-accent\")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute(\"data-md-color-\"+key,value)}</script>\n \n \n \n \n \n <label class=\"md-header__button md-icon\" for=\"__search\" aria-label=\"Search\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-search\" viewBox=\"0 0 24 24\"><path d=\"m21 21-4.34-4.34\"/><circle cx=\"11\" cy=\"11\" r=\"8\"/></svg>\n </label>\n <div class=\"md-search\" data-md-component=\"search\" role=\"dialog\" aria-label=\"Search\">\n <button type=\"button\" class=\"md-search__button\">\n Search\n </button>\n</div>\n \n \n <div class=\"md-header__source\">\n \n </div>\n </nav>\n \n</header>\n \n <div class=\"md-container\" data-md-component=\"container\">\n \n \n \n \n \n<nav class=\"md-tabs\" aria-label=\"Tabs\" data-md-component=\"tabs\">\n <div class=\"md-grid\">\n <ul class=\"md-tabs__list\">\n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../..\" class=\"md-tabs__link\">\n \n \n Home\n\n </a>\n </li>\n \n\n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../getting-started/\" class=\"md-tabs__link\">\n \n \n Getting started\n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item md-tabs__item--active\">\n <a href=\"../\" class=\"md-tabs__link\">\n \n \n User guide\n\n </a>\n </li>\n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../plugins/\" class=\"md-tabs__link\">\n \n \n Plugins\n\n </a>\n </li>\n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../architecture/\" class=\"md-tabs__link\">\n \n \n Architecture\n\n </a>\n </li>\n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../about/\" class=\"md-tabs__link\">\n \n \n About\n\n </a>\n </li>\n \n \n\n \n </ul>\n </div>\n</nav>\n \n \n \n <main class=\"md-main\" data-md-component=\"main\">\n <div class=\"md-main__inner md-grid\">\n \n \n \n <div class=\"md-sidebar md-sidebar--primary\" data-md-component=\"sidebar\" data-md-type=\"navigation\" >\n <div class=\"md-sidebar__scrollwrap\">\n <div class=\"md-sidebar__inner\">\n \n\n\n \n\n\n<nav class=\"md-nav md-nav--primary md-nav--lifted\" aria-label=\"Navigation\" data-md-level=\"0\">\n <label class=\"md-nav__title\" for=\"__drawer\">\n <a href=\"../..\" title=\"letscode\" class=\"md-nav__button md-logo\" aria-label=\"letscode\" data-md-component=\"logo\">\n \n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-book-open\" viewBox=\"0 0 24 24\"><path d=\"M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z\"/></svg>\n\n </a>\n letscode\n </label>\n \n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../..\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Home\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../getting-started/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Getting started\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested\">\n \n \n \n <input class=\"md-nav__toggle md-toggle \" type=\"checkbox\" id=\"__nav_3\" checked>\n \n \n <div class=\"md-nav__link md-nav__container\">\n <a href=\"../\" class=\"md-nav__link \">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n User guide\n\n \n </span>\n \n \n\n </a>\n \n \n <label class=\"md-nav__link \" for=\"__nav_3\" id=\"__nav_3_label\" tabindex=\"\">\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n </div>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_3_label\" aria-expanded=\"true\">\n <label class=\"md-nav__title\" for=\"__nav_3\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n User guide\n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../configuration/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Configuration\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../slash-commands/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Slash commands\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../skills/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Skills\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--active\">\n \n \n \n \n \n \n \n <label class=\"md-nav__link md-nav__link--active\" for=\"__toc\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Sessions\n\n \n </span>\n \n \n\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n <a href=\"././\" class=\"md-nav__link md-nav__link--active\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Sessions\n\n \n </span>\n \n \n\n </a>\n \n \n\n\n<nav class=\"md-nav md-nav--secondary\" aria-label=\"On this page\">\n \n \n \n \n \n \n <label class=\"md-nav__title\" for=\"__toc\">\n <span class=\"md-nav__icon md-icon\"></span>\n On this page\n </label>\n <ul class=\"md-nav__list\" data-md-component=\"toc\" data-md-scrollfix>\n \n <li class=\"md-nav__item\">\n <a href=\"#continuation\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Continuation\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#ephemeral-runs\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Ephemeral runs\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#file-format\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n File format\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#custom-messages\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Custom messages\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#locations\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Locations\n </span>\n </span>\n </a>\n \n</li>\n \n </ul>\n \n</nav>\n \n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--nested\">\n \n \n \n <input class=\"md-nav__toggle md-toggle \" type=\"checkbox\" id=\"__nav_4\" >\n \n \n <div class=\"md-nav__link md-nav__container\">\n <a href=\"../../plugins/\" class=\"md-nav__link \">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Plugins\n\n \n </span>\n \n \n\n </a>\n \n \n <label class=\"md-nav__link \" for=\"__nav_4\" id=\"__nav_4_label\" tabindex=\"0\">\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n </div>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_4_label\" aria-expanded=\"false\">\n <label class=\"md-nav__title\" for=\"__nav_4\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n Plugins\n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../plugins/authoring/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Authoring guide\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../plugins/memory/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Reference plugin\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--nested\">\n \n \n \n <input class=\"md-nav__toggle md-toggle \" type=\"checkbox\" id=\"__nav_5\" >\n \n \n <div class=\"md-nav__link md-nav__container\">\n <a href=\"../../architecture/\" class=\"md-nav__link \">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Architecture\n\n \n </span>\n \n \n\n </a>\n \n \n <label class=\"md-nav__link \" for=\"__nav_5\" id=\"__nav_5_label\" tabindex=\"0\">\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n </div>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_5_label\" aria-expanded=\"false\">\n <label class=\"md-nav__title\" for=\"__nav_5\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n Architecture\n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../architecture/extension-model/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Extension model\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../architecture/agent-loop/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Agent loop\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--nested\">\n \n \n \n <input class=\"md-nav__toggle md-toggle \" type=\"checkbox\" id=\"__nav_6\" >\n \n \n <div class=\"md-nav__link md-nav__container\">\n <a href=\"../../about/\" class=\"md-nav__link \">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n About\n\n \n </span>\n \n \n\n </a>\n \n \n <label class=\"md-nav__link \" for=\"__nav_6\" id=\"__nav_6_label\" tabindex=\"0\">\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n </div>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_6_label\" aria-expanded=\"false\">\n <label class=\"md-nav__title\" for=\"__nav_6\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n About\n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../about/changelog/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Changelog\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../about/roadmap/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Roadmap\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../about/lessons-learned/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Lessons learned\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../about/related-projects/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Related projects\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n </ul>\n</nav>\n </div>\n </div>\n </div>\n \n \n \n <div class=\"md-sidebar md-sidebar--secondary\" data-md-component=\"sidebar\" data-md-type=\"toc\" >\n <div class=\"md-sidebar__scrollwrap\">\n \n \n \n \n \n \n \n <input class=\"md-nav__toggle md-toggle\" type=\"checkbox\" id=\"__toc\">\n <div class=\"md-sidebar-button__wrapper\">\n <label class=\"md-sidebar-button\" for=\"__toc\"></label>\n </div>\n \n \n <div class=\"md-sidebar__inner\">\n \n\n\n<nav class=\"md-nav md-nav--secondary\" aria-label=\"On this page\">\n \n \n \n \n \n \n <label class=\"md-nav__title\" for=\"__toc\">\n <span class=\"md-nav__icon md-icon\"></span>\n On this page\n </label>\n <ul class=\"md-nav__list\" data-md-component=\"toc\" data-md-scrollfix>\n \n <li class=\"md-nav__item\">\n <a href=\"#continuation\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Continuation\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#ephemeral-runs\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Ephemeral runs\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#file-format\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n File format\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#custom-messages\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Custom messages\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#locations\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Locations\n </span>\n </span>\n </a>\n \n</li>\n \n </ul>\n \n</nav>\n </div>\n </div>\n </div>\n \n \n \n <div class=\"md-content\" data-md-component=\"content\">\n \n \n\n\n\n \n\n\n <nav class=\"md-path\" aria-label=\"Navigation\" >\n <ol class=\"md-path__list\">\n \n \n \n \n <li class=\"md-path__item\">\n <a href=\"../..\" class=\"md-path__link\">\n \n \n <span class=\"md-ellipsis\">\n Home\n </span>\n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-path__item\">\n <a href=\"../\" class=\"md-path__link\">\n \n \n <span class=\"md-ellipsis\">\n User guide\n </span>\n\n </a>\n </li>\n \n \n\n \n </ol>\n </nav>\n\n \n <article class=\"md-content__inner md-typeset\">\n \n \n\n<h1 id=\"sessions\">Sessions<a class=\"headerlink\" href=\"#sessions\" title=\"Permanent link\">&para;</a></h1>\n<p>Every interactive run is persisted as a JSONL file under <code>~/.letscode/sessions/&lt;cwd-hash&gt;/&lt;uuid&gt;.jsonl</code>. One JSON object per line, one line per <code>MessageEnd</code> event.</p>\n<h2 id=\"continuation\">Continuation<a class=\"headerlink\" href=\"#continuation\" title=\"Permanent link\">&para;</a></h2>\n<div class=\"language-bash highlight\"><pre><span></span><code><span id=\"__span-0-1\"><a id=\"__codelineno-0-1\" name=\"__codelineno-0-1\" href=\"#__codelineno-0-1\"></a>letscode<span class=\"w\"> </span>-c\n</span></code></pre></div>\n<p>Continues the <strong>most recent</strong> session for the current working directory. The conversation history is reloaded, the system prompt is recomputed (so newly added skills / tools are visible), and the agent picks up where it left off.</p>\n<h2 id=\"ephemeral-runs\">Ephemeral runs<a class=\"headerlink\" href=\"#ephemeral-runs\" title=\"Permanent link\">&para;</a></h2>\n<div class=\"language-bash highlight\"><pre><span></span><code><span id=\"__span-1-1\"><a id=\"__codelineno-1-1\" name=\"__codelineno-1-1\" href=\"#__codelineno-1-1\"></a>letscode<span class=\"w\"> </span>--no-session<span class=\"w\"> </span><span class=\"s2\">&quot;one-off question&quot;</span>\n</span></code></pre></div>\n<p>Skips persistence entirely. Use for piped pipelines, CI checks, or anything you don't want in the session history.</p>\n<h2 id=\"file-format\">File format<a class=\"headerlink\" href=\"#file-format\" title=\"Permanent link\">&para;</a></h2>\n<p>The JSONL envelope:</p>\n<div class=\"language-text highlight\"><pre><span></span><code><span id=\"__span-2-1\"><a id=\"__codelineno-2-1\" name=\"__codelineno-2-1\" href=\"#__codelineno-2-1\"></a>{ &quot;_v&quot;: 2, &quot;msg&quot;: { &quot;role&quot;: &quot;user&quot;, &quot;id&quot;: &quot;...&quot;, &quot;content&quot;: [...], &quot;timestamp&quot;: ... } }\n</span><span id=\"__span-2-2\"><a id=\"__codelineno-2-2\" name=\"__codelineno-2-2\" href=\"#__codelineno-2-2\"></a>{ &quot;_v&quot;: 2, &quot;msg&quot;: { &quot;role&quot;: &quot;assistant&quot;, &quot;id&quot;: &quot;...&quot;, &quot;content&quot;: [...], &quot;tool_calls&quot;: [...], ... } }\n</span><span id=\"__span-2-3\"><a id=\"__codelineno-2-3\" name=\"__codelineno-2-3\" href=\"#__codelineno-2-3\"></a>{ &quot;_v&quot;: 2, &quot;msg&quot;: { &quot;role&quot;: &quot;tool&quot;, &quot;id&quot;: &quot;...&quot;, &quot;tool_call_id&quot;: &quot;...&quot;, &quot;content&quot;: [...], ... } }\n</span><span id=\"__span-2-4\"><a id=\"__codelineno-2-4\" name=\"__codelineno-2-4\" href=\"#__codelineno-2-4\"></a>{ &quot;_v&quot;: 2, &quot;msg&quot;: { &quot;role&quot;: &quot;custom&quot;, &quot;kind&quot;: &quot;compaction&quot;, &quot;payload&quot;: {...}, ... } }\n</span></code></pre></div>\n<ul>\n<li><code>_v: 2</code> is the format version. v1 files still load (entries get a synthesized <code>parent_id</code> chain).</li>\n<li><code>parent_id</code> lives on the envelope (not shown above for brevity) — entries form a tree, not a flat list, even though the default UX is linear. Tree navigation shipped in v0.4: <code>/tree</code> (numbered chain), <code>/fork [n]</code> (branch a new session at entry n), <code>/clone</code> (duplicate and continue on the copy).</li>\n</ul>\n<h2 id=\"custom-messages\">Custom messages<a class=\"headerlink\" href=\"#custom-messages\" title=\"Permanent link\">&para;</a></h2>\n<p>The <code>role: \"custom\"</code> entries are letscode-specific. They live in the transcript but are <em>not</em> sent to the LLM by default. The most common kind is <code>compaction</code> — when the context window is approached, the agent collapses older turns into a single summary <code>CustomMessage(kind=\"compaction\")</code> and the built-in plugin renders it as a synthetic assistant message at LLM-call time.</p>\n<p>Plugins can define their own <code>CustomMessage.kind</code> values and render them via the <code>letscode_render_custom_message</code> hook. See <a href=\"../../architecture/extension-model/\">Extension model</a> for the contract.</p>\n<h2 id=\"locations\">Locations<a class=\"headerlink\" href=\"#locations\" title=\"Permanent link\">&para;</a></h2>\n<table>\n<thead>\n<tr>\n<th>Path</th>\n<th>Purpose</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>~/.letscode/sessions/&lt;cwd-hash&gt;/&lt;uuid&gt;.jsonl</code></td>\n<td>Default session storage.</td>\n</tr>\n<tr>\n<td><code>~/.letscode/history</code></td>\n<td><code>prompt_toolkit</code> input history.</td>\n</tr>\n<tr>\n<td><code>~/.letscode/config.toml</code></td>\n<td>User configuration.</td>\n</tr>\n<tr>\n<td><code>~/.letscode/skills/</code></td>\n<td>User-global skills directory.</td>\n</tr>\n</tbody>\n</table>\n<p>The <code>&lt;cwd-hash&gt;</code> is a stable hash of the working directory's absolute path — sessions are scoped per project location, so <code>-c</code> continues the right conversation regardless of which repo you're in.</p>\n\n\n\n\n\n\n\n\n\n \n \n\n\n\n\n\n\n \n </article>\n </div>\n \n \n <script>var tabs=__md_get(\"__tabs\");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(\".tabbed-set\")){var labels=set.querySelector(\".tabbed-labels\");for(var tab of tabs)for(var label of labels.getElementsByTagName(\"label\"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script>\n\n<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith(\"__tabbed_\"))</script>\n </div>\n \n <button type=\"button\" class=\"md-top md-icon\" data-md-component=\"top\" hidden>\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-circle-arrow-up\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m16 12-4-4-4 4M12 16V8\"/></svg>\n Back to top\n</button>\n \n </main>\n \n <footer class=\"md-footer\">\n \n \n \n <nav class=\"md-footer__inner md-grid\" aria-label=\"Footer\" >\n \n \n <a href=\"../skills/\" class=\"md-footer__link md-footer__link--prev\" aria-label=\"Previous: Skills\">\n <div class=\"md-footer__button md-icon\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-arrow-left\" viewBox=\"0 0 24 24\"><path d=\"m12 19-7-7 7-7M19 12H5\"/></svg>\n </div>\n <div class=\"md-footer__title\">\n <span class=\"md-footer__direction\">\n Previous\n </span>\n <div class=\"md-ellipsis\">\n Skills\n </div>\n </div>\n </a>\n \n \n \n <a href=\"../../plugins/\" class=\"md-footer__link md-footer__link--next\" aria-label=\"Next: Overview\">\n <div class=\"md-footer__title\">\n <span class=\"md-footer__direction\">\n Next\n </span>\n <div class=\"md-ellipsis\">\n Overview\n </div>\n </div>\n <div class=\"md-footer__button md-icon\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-arrow-right\" viewBox=\"0 0 24 24\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg>\n </div>\n </a>\n \n </nav>\n \n \n <div class=\"md-footer-meta md-typeset\">\n <div class=\"md-footer-meta__inner md-grid\">\n <div class=\"md-copyright\">\n \n <div class=\"md-copyright__highlight\">\n Copyright &copy; 2026 Stefane Fermigier &mdash; released under the MIT license.\n\n </div>\n \n \n Made with\n <a href=\"https://zensical.org/\" target=\"_blank\" rel=\"noopener\">\n Zensical\n </a>\n \n</div>\n \n \n<div class=\"md-social\">\n \n \n \n \n \n <a href=\"https://github.com/abilian/letscode\" target=\"_blank\" rel=\"noopener\" title=\"letscode on GitHub\" class=\"md-social__link\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><!--! Font Awesome Free 7.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2026 Fonticons, Inc.--><path fill=\"currentColor\" d=\"M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8M105.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2\"/></svg>\n </a>\n \n</div>\n \n </div>\n </div>\n</footer>\n \n </div>\n <div class=\"md-dialog\" data-md-component=\"dialog\">\n <div class=\"md-dialog__inner md-typeset\"></div>\n </div>\n \n \n \n \n \n <script id=\"__config\" type=\"application/json\">{\"annotate\":null,\"base\":\"../..\",\"features\":[\"announce.dismiss\",\"content.code.annotate\",\"content.code.copy\",\"content.code.select\",\"content.footnote.tooltips\",\"content.tabs.link\",\"content.tooltips\",\"navigation.footer\",\"navigation.indexes\",\"navigation.instant\",\"navigation.instant.prefetch\",\"navigation.path\",\"navigation.sections\",\"navigation.tabs\",\"navigation.top\",\"navigation.tracking\",\"search.highlight\",\"search.share\",\"search.suggest\"],\"search\":\"../../assets/javascripts/workers/search.e2d2d235.min.js\",\"tags\":null,\"translations\":{\"clipboard.copied\":\"Copied to clipboard\",\"clipboard.copy\":\"Copy to clipboard\",\"search.result.more.one\":\"1 more on this page\",\"search.result.more.other\":\"# more on this page\",\"search.result.none\":\"No matching documents\",\"search.result.one\":\"1 matching document\",\"search.result.other\":\"# matching documents\",\"search.result.placeholder\":\"Type to start searching\",\"search.result.term.missing\":\"Missing\",\"select.version\":\"Select version\"},\"version\":null}</script>\n \n \n <script src=\"../../assets/javascripts/bundle.6e5f0216.min.js\"></script>\n \n \n </body>\n</html>",
3
+ "hash": 2080764135429424961
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "data": "\n<!doctype html>\n<html lang=\"en\" class=\"no-js\">\n <head>\n \n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n \n <meta name=\"description\" content=\"Cross-session memory as a worked example of the extension model.\">\n \n \n <meta name=\"author\" content=\"Stefane Fermigier\">\n \n \n <link rel=\"canonical\" href=\"https://letscode.dev/plugins/memory/\">\n \n \n <link rel=\"prev\" href=\"../authoring/\">\n \n \n <link rel=\"next\" href=\"../../architecture/\">\n \n \n \n \n \n <link rel=\"icon\" href=\"../../assets/images/favicon.png\">\n <meta name=\"generator\" content=\"zensical-0.0.43\">\n \n \n \n <title>letscode-memory: reference plugin - letscode</title>\n \n \n \n \n \n \n <link rel=\"stylesheet\" href=\"../../assets/stylesheets/modern/main.fba56155.min.css\">\n \n \n \n \n <link rel=\"stylesheet\" href=\"../../assets/stylesheets/modern/palette.dfe2e883.min.css\">\n \n \n\n\n \n \n \n \n \n \n \n \n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n <link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Inter:300,300i,400,400i,500,500i,700,700i%7CJetBrains+Mono:400,400i,700,700i&amp;display=fallback\">\n <style>:root{--md-text-font:\"Inter\";--md-code-font:\"JetBrains Mono\"}</style>\n \n \n \n <script>__md_scope=new URL(\"../..\",location),__md_scope.pathname.endsWith(\"/\")||(__md_scope=new URL(__md_scope.pathname+\"/\",location)),__md_hash=e=>[...e].reduce(((e,t)=>(e<<5)-e+t.charCodeAt(0)),0),__md_get=(e,t=localStorage,_=__md_scope)=>JSON.parse(t.getItem(_.pathname+\".\"+e)),__md_set=(e,t,_=localStorage,a=__md_scope)=>{try{_.setItem(a.pathname+\".\"+e,JSON.stringify(t))}catch(e){}},document.documentElement.setAttribute(\"data-platform\",navigator.platform)</script>\n \n \n\n \n \n </head>\n \n \n \n \n \n \n \n \n \n <body dir=\"ltr\" data-md-color-scheme=\"default\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\">\n \n \n <input class=\"md-toggle\" data-md-toggle=\"drawer\" type=\"checkbox\" id=\"__drawer\" autocomplete=\"off\">\n <input class=\"md-toggle\" data-md-toggle=\"search\" type=\"checkbox\" id=\"__search\" autocomplete=\"off\">\n <label class=\"md-overlay\" for=\"__drawer\" aria-label=\"Navigation\"></label>\n <div data-md-component=\"skip\">\n \n \n <a href=\"#letscode-memory\" class=\"md-skip\">\n Skip to content\n </a>\n \n </div>\n <div data-md-component=\"announce\">\n \n </div>\n \n \n \n\n<header class=\"md-header\" data-md-component=\"header\">\n <nav class=\"md-header__inner md-grid\" aria-label=\"Header\">\n <a href=\"../..\" title=\"letscode\" class=\"md-header__button md-logo\" aria-label=\"letscode\" data-md-component=\"logo\">\n \n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-book-open\" viewBox=\"0 0 24 24\"><path d=\"M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z\"/></svg>\n\n </a>\n <label class=\"md-header__button md-icon\" for=\"__drawer\" aria-label=\"Navigation\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-menu\" viewBox=\"0 0 24 24\"><path d=\"M4 5h16M4 12h16M4 19h16\"/></svg>\n </label>\n <div class=\"md-header__title\" data-md-component=\"header-title\">\n <div class=\"md-header__ellipsis\">\n <div class=\"md-header__topic\">\n <span class=\"md-ellipsis\">\n letscode\n </span>\n </div>\n <div class=\"md-header__topic\" data-md-component=\"header-topic\">\n <span class=\"md-ellipsis\">\n \n letscode-memory: reference plugin\n \n </span>\n </div>\n </div>\n </div>\n \n \n <form class=\"md-header__option\" data-md-component=\"palette\">\n \n \n \n \n <input class=\"md-option\" data-md-color-media=\"(prefers-color-scheme)\" data-md-color-scheme=\"default\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\" aria-label=\"Switch to light mode\" type=\"radio\" name=\"__palette\" id=\"__palette_0\">\n \n <label class=\"md-header__button md-icon\" title=\"Switch to light mode\" for=\"__palette_1\" hidden>\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-sun-moon\" viewBox=\"0 0 24 24\"><path d=\"M12 2v2M14.837 16.385a6 6 0 1 1-7.223-7.222c.624-.147.97.66.715 1.248a4 4 0 0 0 5.26 5.259c.589-.255 1.396.09 1.248.715M16 12a4 4 0 0 0-4-4M19 5l-1.256 1.256M20 12h2\"/></svg>\n </label>\n \n \n \n \n \n <input class=\"md-option\" data-md-color-media=\"(prefers-color-scheme: light)\" data-md-color-scheme=\"default\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\" aria-label=\"Switch to dark mode\" type=\"radio\" name=\"__palette\" id=\"__palette_1\">\n \n <label class=\"md-header__button md-icon\" title=\"Switch to dark mode\" for=\"__palette_2\" hidden>\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-sun\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\"/></svg>\n </label>\n \n \n \n \n \n <input class=\"md-option\" data-md-color-media=\"(prefers-color-scheme: dark)\" data-md-color-scheme=\"slate\" data-md-color-primary=\"indigo\" data-md-color-accent=\"indigo\" aria-label=\"Switch to system preference\" type=\"radio\" name=\"__palette\" id=\"__palette_2\">\n \n <label class=\"md-header__button md-icon\" title=\"Switch to system preference\" for=\"__palette_0\" hidden>\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-moon\" viewBox=\"0 0 24 24\"><path d=\"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401\"/></svg>\n </label>\n \n \n</form>\n \n \n \n <script>var palette=__md_get(\"__palette\");if(palette&&palette.color){if(\"(prefers-color-scheme)\"===palette.color.media){var media=matchMedia(\"(prefers-color-scheme: light)\"),input=document.querySelector(media.matches?\"[data-md-color-media='(prefers-color-scheme: light)']\":\"[data-md-color-media='(prefers-color-scheme: dark)']\");palette.color.media=input.getAttribute(\"data-md-color-media\"),palette.color.scheme=input.getAttribute(\"data-md-color-scheme\"),palette.color.primary=input.getAttribute(\"data-md-color-primary\"),palette.color.accent=input.getAttribute(\"data-md-color-accent\")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute(\"data-md-color-\"+key,value)}</script>\n \n \n \n \n \n <label class=\"md-header__button md-icon\" for=\"__search\" aria-label=\"Search\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-search\" viewBox=\"0 0 24 24\"><path d=\"m21 21-4.34-4.34\"/><circle cx=\"11\" cy=\"11\" r=\"8\"/></svg>\n </label>\n <div class=\"md-search\" data-md-component=\"search\" role=\"dialog\" aria-label=\"Search\">\n <button type=\"button\" class=\"md-search__button\">\n Search\n </button>\n</div>\n \n \n <div class=\"md-header__source\">\n \n </div>\n </nav>\n \n</header>\n \n <div class=\"md-container\" data-md-component=\"container\">\n \n \n \n \n \n<nav class=\"md-tabs\" aria-label=\"Tabs\" data-md-component=\"tabs\">\n <div class=\"md-grid\">\n <ul class=\"md-tabs__list\">\n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../..\" class=\"md-tabs__link\">\n \n \n Home\n\n </a>\n </li>\n \n\n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../getting-started/\" class=\"md-tabs__link\">\n \n \n Getting started\n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../user-guide/\" class=\"md-tabs__link\">\n \n \n User guide\n\n </a>\n </li>\n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item md-tabs__item--active\">\n <a href=\"../\" class=\"md-tabs__link\">\n \n \n Plugins\n\n </a>\n </li>\n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../architecture/\" class=\"md-tabs__link\">\n \n \n Architecture\n\n </a>\n </li>\n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-tabs__item\">\n <a href=\"../../about/\" class=\"md-tabs__link\">\n \n \n About\n\n </a>\n </li>\n \n \n\n \n </ul>\n </div>\n</nav>\n \n \n \n <main class=\"md-main\" data-md-component=\"main\">\n <div class=\"md-main__inner md-grid\">\n \n \n \n <div class=\"md-sidebar md-sidebar--primary\" data-md-component=\"sidebar\" data-md-type=\"navigation\" >\n <div class=\"md-sidebar__scrollwrap\">\n <div class=\"md-sidebar__inner\">\n \n\n\n \n\n\n<nav class=\"md-nav md-nav--primary md-nav--lifted\" aria-label=\"Navigation\" data-md-level=\"0\">\n <label class=\"md-nav__title\" for=\"__drawer\">\n <a href=\"../..\" title=\"letscode\" class=\"md-nav__button md-logo\" aria-label=\"letscode\" data-md-component=\"logo\">\n \n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-book-open\" viewBox=\"0 0 24 24\"><path d=\"M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z\"/></svg>\n\n </a>\n letscode\n </label>\n \n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../..\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Home\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../getting-started/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Getting started\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--nested\">\n \n \n \n <input class=\"md-nav__toggle md-toggle \" type=\"checkbox\" id=\"__nav_3\" >\n \n \n <div class=\"md-nav__link md-nav__container\">\n <a href=\"../../user-guide/\" class=\"md-nav__link \">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n User guide\n\n \n </span>\n \n \n\n </a>\n \n \n <label class=\"md-nav__link \" for=\"__nav_3\" id=\"__nav_3_label\" tabindex=\"0\">\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n </div>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_3_label\" aria-expanded=\"false\">\n <label class=\"md-nav__title\" for=\"__nav_3\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n User guide\n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../user-guide/configuration/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Configuration\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../user-guide/slash-commands/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Slash commands\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../user-guide/skills/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Skills\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../user-guide/sessions/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Sessions\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested\">\n \n \n \n <input class=\"md-nav__toggle md-toggle \" type=\"checkbox\" id=\"__nav_4\" checked>\n \n \n <div class=\"md-nav__link md-nav__container\">\n <a href=\"../\" class=\"md-nav__link \">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Plugins\n\n \n </span>\n \n \n\n </a>\n \n \n <label class=\"md-nav__link \" for=\"__nav_4\" id=\"__nav_4_label\" tabindex=\"\">\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n </div>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_4_label\" aria-expanded=\"true\">\n <label class=\"md-nav__title\" for=\"__nav_4\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n Plugins\n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../authoring/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Authoring guide\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--active\">\n \n \n \n \n \n \n \n <label class=\"md-nav__link md-nav__link--active\" for=\"__toc\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Reference plugin\n\n \n </span>\n \n \n\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n <a href=\"././\" class=\"md-nav__link md-nav__link--active\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Reference plugin\n\n \n </span>\n \n \n\n </a>\n \n \n\n\n<nav class=\"md-nav md-nav--secondary\" aria-label=\"On this page\">\n \n \n \n \n \n \n <label class=\"md-nav__title\" for=\"__toc\">\n <span class=\"md-nav__icon md-icon\"></span>\n On this page\n </label>\n <ul class=\"md-nav__list\" data-md-component=\"toc\" data-md-scrollfix>\n \n <li class=\"md-nav__item\">\n <a href=\"#install\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Install\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#use\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Use\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#how-it-hooks-in\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n How it hooks in\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#why-a-custommessage-and-not-a-usermessage\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Why a CustomMessage and not a UserMessage?\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#source\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Source\n </span>\n </span>\n </a>\n \n</li>\n \n </ul>\n \n</nav>\n \n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--nested\">\n \n \n \n <input class=\"md-nav__toggle md-toggle \" type=\"checkbox\" id=\"__nav_5\" >\n \n \n <div class=\"md-nav__link md-nav__container\">\n <a href=\"../../architecture/\" class=\"md-nav__link \">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Architecture\n\n \n </span>\n \n \n\n </a>\n \n \n <label class=\"md-nav__link \" for=\"__nav_5\" id=\"__nav_5_label\" tabindex=\"0\">\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n </div>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_5_label\" aria-expanded=\"false\">\n <label class=\"md-nav__title\" for=\"__nav_5\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n Architecture\n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../architecture/extension-model/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Extension model\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../architecture/agent-loop/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Agent loop\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item md-nav__item--nested\">\n \n \n \n <input class=\"md-nav__toggle md-toggle \" type=\"checkbox\" id=\"__nav_6\" >\n \n \n <div class=\"md-nav__link md-nav__container\">\n <a href=\"../../about/\" class=\"md-nav__link \">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n About\n\n \n </span>\n \n \n\n </a>\n \n \n <label class=\"md-nav__link \" for=\"__nav_6\" id=\"__nav_6_label\" tabindex=\"0\">\n <span class=\"md-nav__icon md-icon\"></span>\n </label>\n \n </div>\n \n <nav class=\"md-nav\" data-md-level=\"1\" aria-labelledby=\"__nav_6_label\" aria-expanded=\"false\">\n <label class=\"md-nav__title\" for=\"__nav_6\">\n <span class=\"md-nav__icon md-icon\"></span>\n \n \n About\n\n </label>\n <ul class=\"md-nav__list\" data-md-scrollfix>\n \n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../about/changelog/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Changelog\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../about/roadmap/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Roadmap\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../about/lessons-learned/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Lessons learned\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n <li class=\"md-nav__item\">\n <a href=\"../../about/related-projects/\" class=\"md-nav__link\">\n \n \n \n <span class=\"md-ellipsis\">\n \n \n Related projects\n\n \n </span>\n \n \n\n </a>\n </li>\n \n\n \n \n </ul>\n </nav>\n \n </li>\n \n\n \n </ul>\n</nav>\n </div>\n </div>\n </div>\n \n \n \n <div class=\"md-sidebar md-sidebar--secondary\" data-md-component=\"sidebar\" data-md-type=\"toc\" >\n <div class=\"md-sidebar__scrollwrap\">\n \n \n \n \n \n \n \n <input class=\"md-nav__toggle md-toggle\" type=\"checkbox\" id=\"__toc\">\n <div class=\"md-sidebar-button__wrapper\">\n <label class=\"md-sidebar-button\" for=\"__toc\"></label>\n </div>\n \n \n <div class=\"md-sidebar__inner\">\n \n\n\n<nav class=\"md-nav md-nav--secondary\" aria-label=\"On this page\">\n \n \n \n \n \n \n <label class=\"md-nav__title\" for=\"__toc\">\n <span class=\"md-nav__icon md-icon\"></span>\n On this page\n </label>\n <ul class=\"md-nav__list\" data-md-component=\"toc\" data-md-scrollfix>\n \n <li class=\"md-nav__item\">\n <a href=\"#install\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Install\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#use\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Use\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#how-it-hooks-in\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n How it hooks in\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#why-a-custommessage-and-not-a-usermessage\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Why a CustomMessage and not a UserMessage?\n </span>\n </span>\n </a>\n \n</li>\n \n <li class=\"md-nav__item\">\n <a href=\"#source\" class=\"md-nav__link\">\n <span class=\"md-ellipsis\">\n <span class=\"md-typeset\">\n Source\n </span>\n </span>\n </a>\n \n</li>\n \n </ul>\n \n</nav>\n </div>\n </div>\n </div>\n \n \n \n <div class=\"md-content\" data-md-component=\"content\">\n \n \n\n\n\n \n\n\n <nav class=\"md-path\" aria-label=\"Navigation\" >\n <ol class=\"md-path__list\">\n \n \n \n \n <li class=\"md-path__item\">\n <a href=\"../..\" class=\"md-path__link\">\n \n \n <span class=\"md-ellipsis\">\n Home\n </span>\n\n </a>\n </li>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <li class=\"md-path__item\">\n <a href=\"../\" class=\"md-path__link\">\n \n \n <span class=\"md-ellipsis\">\n Plugins\n </span>\n\n </a>\n </li>\n \n \n\n \n </ol>\n </nav>\n\n \n <article class=\"md-content__inner md-typeset\">\n \n \n\n<h1 id=\"letscode-memory\">letscode-memory<a class=\"headerlink\" href=\"#letscode-memory\" title=\"Permanent link\">&para;</a></h1>\n<p>Cross-session memory for letscode, shipped as the canonical reference plugin. Drop markdown files in <code>~/.letscode/memory/</code>; the plugin injects them as background context at the top of every LLM turn.</p>\n<p>The plugin lives at <a href=\"https://github.com/abilian/letscode/tree/main/plugins/letscode-memory\"><code>plugins/letscode-memory/</code></a> in the main repo — outside <code>src/letscode/</code>, in its own package with its own <code>pyproject.toml</code>, validating that the <a href=\"../../architecture/extension-model/\">extension model</a> works for a real third-party-shaped plugin.</p>\n<h2 id=\"install\">Install<a class=\"headerlink\" href=\"#install\" title=\"Permanent link\">&para;</a></h2>\n<p>Install the plugin into the <strong>same environment as letscode</strong>:</p>\n<div class=\"tabbed-set tabbed-alternate\" data-tabs=\"1:2\"><input checked=\"checked\" id=\"__tabbed_1_1\" name=\"__tabbed_1\" type=\"radio\" /><input id=\"__tabbed_1_2\" name=\"__tabbed_1\" type=\"radio\" /><div class=\"tabbed-labels\"><label for=\"__tabbed_1_1\">As a user</label><label for=\"__tabbed_1_2\">For development</label></div>\n<div class=\"tabbed-content\">\n<div class=\"tabbed-block\">\n<div class=\"language-bash highlight\"><pre><span></span><code><span id=\"__span-0-1\"><a id=\"__codelineno-0-1\" name=\"__codelineno-0-1\" href=\"#__codelineno-0-1\"></a>uv<span class=\"w\"> </span>tool<span class=\"w\"> </span>install<span class=\"w\"> </span>letscode<span class=\"w\"> </span>--with<span class=\"w\"> </span>letscode-memory<span class=\"w\"> </span><span class=\"c1\"># once published</span>\n</span><span id=\"__span-0-2\"><a id=\"__codelineno-0-2\" name=\"__codelineno-0-2\" href=\"#__codelineno-0-2\"></a><span class=\"c1\"># or, from a locally built wheel:</span>\n</span><span id=\"__span-0-3\"><a id=\"__codelineno-0-3\" name=\"__codelineno-0-3\" href=\"#__codelineno-0-3\"></a>uv<span class=\"w\"> </span>pip<span class=\"w\"> </span>install<span class=\"w\"> </span>--python<span class=\"w\"> </span>&lt;letscode-env&gt;<span class=\"w\"> </span>letscode_memory-*.whl\n</span></code></pre></div>\n</div>\n<div class=\"tabbed-block\">\n<div class=\"language-bash highlight\"><pre><span></span><code><span id=\"__span-1-1\"><a id=\"__codelineno-1-1\" name=\"__codelineno-1-1\" href=\"#__codelineno-1-1\"></a>uv<span class=\"w\"> </span>pip<span class=\"w\"> </span>install<span class=\"w\"> </span>-e<span class=\"w\"> </span>plugins/letscode-memory/\n</span></code></pre></div>\n</div>\n</div>\n</div>\n<p>Either way, letscode discovers the plugin via its <code>letscode</code> entry point — no further setup. Startup loads <code>/remember</code>, <code>/memories</code>, and <code>/forget</code> and activates the memory transform. Discovery from a clean, non-editable install is gated in CI-style by <code>make verify-plugin</code>.</p>\n<h2 id=\"use\">Use<a class=\"headerlink\" href=\"#use\" title=\"Permanent link\">&para;</a></h2>\n<div class=\"language-text highlight\"><pre><span></span><code><span id=\"__span-2-1\"><a id=\"__codelineno-2-1\" name=\"__codelineno-2-1\" href=\"#__codelineno-2-1\"></a>&gt; /remember Likes terse responses, no preamble.\n</span><span id=\"__span-2-2\"><a id=\"__codelineno-2-2\" name=\"__codelineno-2-2\" href=\"#__codelineno-2-2\"></a>&gt; /remember Prefers Python over JavaScript when both work.\n</span><span id=\"__span-2-3\"><a id=\"__codelineno-2-3\" name=\"__codelineno-2-3\" href=\"#__codelineno-2-3\"></a>&gt; /memories\n</span></code></pre></div>\n<p>Memories are plain markdown files in <code>~/.letscode/memory/</code>. Filename is the UTC ISO timestamp of creation (<code>2026-05-13T103045Z.md</code>); the file's body is the memory itself. Hand-edit freely — the plugin reads them fresh each turn.</p>\n<div class=\"admonition info\">\n<p class=\"admonition-title\">Recall budget</p>\n<p>Up to the <strong>20 most recent</strong> memories are injected per turn. Beyond that the prompt cost is no longer worth the recall value — either prune (<code>rm ~/.letscode/memory/&lt;id&gt;.md</code>) or move long-form context into a <a href=\"../../user-guide/skills/\">skill</a>.</p>\n</div>\n<h2 id=\"how-it-hooks-in\">How it hooks in<a class=\"headerlink\" href=\"#how-it-hooks-in\" title=\"Permanent link\">&para;</a></h2>\n<p>Three hooks:</p>\n<ul>\n<li><code>letscode_register_commands</code> — adds <code>/remember</code> and <code>/memories</code>.</li>\n<li><code>letscode_transform_context</code> — prepends a <code>CustomMessage(kind=\"memory\")</code> to the turn's message list. Returns <code>None</code> (opt out) when there are no memories.</li>\n<li><code>letscode_render_custom_message</code> — renders the memory marker into a <code>UserMessage</code> at LLM-call time. Returns <code>None</code> for any other <code>kind</code>, so other plugins' renderers (including the built-in's compaction handler) keep working.</li>\n</ul>\n<p>That's the entire surface. No tools, no skills, no frontend.</p>\n<p>This is the <strong>composable</strong> pattern: the <code>CustomMessage</code> lives in the persisted transcript (so it survives session save/load), and the per-kind <code>render_custom_message</code> hook lets the memory plugin and the built-in compaction plugin coexist without shadowing each other.</p>\n<h2 id=\"why-a-custommessage-and-not-a-usermessage\">Why a CustomMessage and not a UserMessage?<a class=\"headerlink\" href=\"#why-a-custommessage-and-not-a-usermessage\" title=\"Permanent link\">&para;</a></h2>\n<p>A <code>UserMessage</code> prepended to the message list would also work — but it would also be persisted as a \"user said this\" entry, which is confusing when the user is actually about to type something else. The <code>CustomMessage</code> lives in the transcript with <code>kind=\"memory\"</code> and is <em>rendered</em> into a <code>UserMessage</code>-shaped LLMMessage just for the model. The transcript stays clean.</p>\n<p>Earlier in v0.3 the plugin used a <code>UserMessage</code> directly because the <code>letscode_convert_to_llm</code> hook didn't compose across plugins. That gap was resolved later in v0.3 by introducing <code>letscode_render_custom_message</code> (per-<code>CustomMessage</code>-kind dispatch, <code>firstresult=True</code>). The plugin migrated to the cleaner path; see the <a href=\"../../architecture/extension-model/\">extension model doc</a> §5.11 for the design rationale.</p>\n<h2 id=\"source\">Source<a class=\"headerlink\" href=\"#source\" title=\"Permanent link\">&para;</a></h2>\n<p>The full source is in <a href=\"https://github.com/abilian/letscode/tree/main/plugins/letscode-memory\"><code>plugins/letscode-memory/</code></a>:</p>\n<div class=\"language-text highlight\"><pre><span></span><code><span id=\"__span-3-1\"><a id=\"__codelineno-3-1\" name=\"__codelineno-3-1\" href=\"#__codelineno-3-1\"></a>plugins/letscode-memory/\n</span><span id=\"__span-3-2\"><a id=\"__codelineno-3-2\" name=\"__codelineno-3-2\" href=\"#__codelineno-3-2\"></a>├── pyproject.toml # entry point + dev-only [tool.uv.sources]\n</span><span id=\"__span-3-3\"><a id=\"__codelineno-3-3\" name=\"__codelineno-3-3\" href=\"#__codelineno-3-3\"></a>├── README.md\n</span><span id=\"__span-3-4\"><a id=\"__codelineno-3-4\" name=\"__codelineno-3-4\" href=\"#__codelineno-3-4\"></a>├── src/letscode_memory/\n</span><span id=\"__span-3-5\"><a id=\"__codelineno-3-5\" name=\"__codelineno-3-5\" href=\"#__codelineno-3-5\"></a>│ ├── __init__.py\n</span><span id=\"__span-3-6\"><a id=\"__codelineno-3-6\" name=\"__codelineno-3-6\" href=\"#__codelineno-3-6\"></a>│ ├── plugin.py # @hookimpl declarations (~120 lines)\n</span><span id=\"__span-3-7\"><a id=\"__codelineno-3-7\" name=\"__codelineno-3-7\" href=\"#__codelineno-3-7\"></a>│ └── store.py # filesystem-backed memory list (~80 lines)\n</span><span id=\"__span-3-8\"><a id=\"__codelineno-3-8\" name=\"__codelineno-3-8\" href=\"#__codelineno-3-8\"></a>└── tests/test_plugin.py # 20 tests, imports only from stable surface\n</span></code></pre></div>\n<p>Total: ~200 lines of source plus tests. The shape any external plugin author can copy.</p>\n\n\n\n\n\n\n\n\n\n \n \n\n\n\n\n\n\n \n </article>\n </div>\n \n \n <script>var tabs=__md_get(\"__tabs\");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(\".tabbed-set\")){var labels=set.querySelector(\".tabbed-labels\");for(var tab of tabs)for(var label of labels.getElementsByTagName(\"label\"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script>\n\n<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith(\"__tabbed_\"))</script>\n </div>\n \n <button type=\"button\" class=\"md-top md-icon\" data-md-component=\"top\" hidden>\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-circle-arrow-up\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m16 12-4-4-4 4M12 16V8\"/></svg>\n Back to top\n</button>\n \n </main>\n \n <footer class=\"md-footer\">\n \n \n \n <nav class=\"md-footer__inner md-grid\" aria-label=\"Footer\" >\n \n \n <a href=\"../authoring/\" class=\"md-footer__link md-footer__link--prev\" aria-label=\"Previous: Authoring guide\">\n <div class=\"md-footer__button md-icon\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-arrow-left\" viewBox=\"0 0 24 24\"><path d=\"m12 19-7-7 7-7M19 12H5\"/></svg>\n </div>\n <div class=\"md-footer__title\">\n <span class=\"md-footer__direction\">\n Previous\n </span>\n <div class=\"md-ellipsis\">\n Authoring guide\n </div>\n </div>\n </a>\n \n \n \n <a href=\"../../architecture/\" class=\"md-footer__link md-footer__link--next\" aria-label=\"Next: Overview\">\n <div class=\"md-footer__title\">\n <span class=\"md-footer__direction\">\n Next\n </span>\n <div class=\"md-ellipsis\">\n Overview\n </div>\n </div>\n <div class=\"md-footer__button md-icon\">\n \n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" class=\"lucide lucide-arrow-right\" viewBox=\"0 0 24 24\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg>\n </div>\n </a>\n \n </nav>\n \n \n <div class=\"md-footer-meta md-typeset\">\n <div class=\"md-footer-meta__inner md-grid\">\n <div class=\"md-copyright\">\n \n <div class=\"md-copyright__highlight\">\n Copyright &copy; 2026 Stefane Fermigier &mdash; released under the MIT license.\n\n </div>\n \n \n Made with\n <a href=\"https://zensical.org/\" target=\"_blank\" rel=\"noopener\">\n Zensical\n </a>\n \n</div>\n \n \n<div class=\"md-social\">\n \n \n \n \n \n <a href=\"https://github.com/abilian/letscode\" target=\"_blank\" rel=\"noopener\" title=\"letscode on GitHub\" class=\"md-social__link\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><!--! Font Awesome Free 7.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2026 Fonticons, Inc.--><path fill=\"currentColor\" d=\"M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8M105.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2\"/></svg>\n </a>\n \n</div>\n \n </div>\n </div>\n</footer>\n \n </div>\n <div class=\"md-dialog\" data-md-component=\"dialog\">\n <div class=\"md-dialog__inner md-typeset\"></div>\n </div>\n \n \n \n \n \n <script id=\"__config\" type=\"application/json\">{\"annotate\":null,\"base\":\"../..\",\"features\":[\"announce.dismiss\",\"content.code.annotate\",\"content.code.copy\",\"content.code.select\",\"content.footnote.tooltips\",\"content.tabs.link\",\"content.tooltips\",\"navigation.footer\",\"navigation.indexes\",\"navigation.instant\",\"navigation.instant.prefetch\",\"navigation.path\",\"navigation.sections\",\"navigation.tabs\",\"navigation.top\",\"navigation.tracking\",\"search.highlight\",\"search.share\",\"search.suggest\"],\"search\":\"../../assets/javascripts/workers/search.e2d2d235.min.js\",\"tags\":null,\"translations\":{\"clipboard.copied\":\"Copied to clipboard\",\"clipboard.copy\":\"Copy to clipboard\",\"search.result.more.one\":\"1 more on this page\",\"search.result.more.other\":\"# more on this page\",\"search.result.none\":\"No matching documents\",\"search.result.one\":\"1 matching document\",\"search.result.other\":\"# matching documents\",\"search.result.placeholder\":\"Type to start searching\",\"search.result.term.missing\":\"Missing\",\"select.version\":\"Select version\"},\"version\":null}</script>\n \n \n <script src=\"../../assets/javascripts/bundle.6e5f0216.min.js\"></script>\n \n \n </body>\n</html>",
3
+ "hash": 6964273037549609280
4
+ }