examples/extensions/scratchpad: real .ts (not .js) extension, no
build step, no SDK. Runs via `npx --yes tsx index.ts` so authors
can use TypeScript without forcing a global install. Demonstrates:
/note <text> slash command (typed CommandResponse)
/notes slash command (display action)
/clear-notes slash command
read_notes LLM-callable tool (typed ToolResult)
Plus a typed wire-format subset inline so the file shows what the
protocol actually looks like from the consumer side. Pure node +
tsx, zero npm deps beyond tsx itself (~5 MB cached on first call).
Manager fix: extension exec paths are now resolved by shape:
absolute used as-is
starts with ./ or ../ joined to ext.Dir
contains a separator joined to ext.Dir (other relative form)
bare name (no sep) left as-is so $PATH lookup works
Before this, "exec": "npx" was being looked up at
extensions/scratchpad/npx and failing with a "no such file or
directory" error. With the fix, "node", "npx", "python3", "tsx",
etc. resolve via $PATH like users intuitively expect.
Bumped WaitForReady grace from 500ms to 3s so slow runtimes
(npx tsx cold-start ≈ 1.4s) get their register_tool frames
in before the agent's tool registry is built. Extensions that
send ready quickly still release the wait immediately; the
extra grace only applies to laggards.
Verified end-to-end live against anthropic:
prompt: "Use the read_notes tool now and tell me what's in the
scratchpad"
-> [tool_call] read_notes({})
-> [tool_result] (scratchpad is empty)
-> "The scratchpad is empty."
|
||
|---|---|---|
| .. | ||
| extension.json | ||
| index.ts | ||
| README.md | ||
scratchpad — TypeScript extension example
Real .ts (not .js), no build step, no SDK. Runs via npx tsx,
which downloads itself into the npm cache on first invocation and
runs from cache on every subsequent call.
Demonstrates:
- registering slash commands (
/note,/notes,/clear-notes) - registering an LLM-callable tool (
read_notes) - the wire protocol from a typed TypeScript perspective
- running TypeScript via
npx tsxfromextension.json
Requirements
Node 18+. The first time you use it, npx will quietly fetch tsx
into the npm cache (~5 MB, one-shot). If you'd rather pre-install
globally:
npm install -g tsx
…and change extension.json's exec to "tsx" and args to
["index.ts"] if you want.
Install
From this directory:
zot ext install .
Use
In zot:
/note remind me to update the changelog— appends to the scratchpad/notes— shows everything stored/clear-notes— wipes the scratchpad
The model also has a read_notes tool. Ask it:
"What did I tell you to remember?"
…and it will call the tool and tell you. The scratchpad is
process-local: it lives only as long as the extension subprocess
(i.e. the duration of one zot session).
Why TypeScript here
The extension protocol is small enough that you can hand-write it in
any language. JS works fine; TS adds type safety on the frame shapes
without any infrastructure beyond tsx. If you want richer ergonomics
(decorators, schema-from-types), publish your own SDK on top.
See also
examples/extensions/clock— JS sibling (no tsx required)examples/extensions/hello— Go SDKexamples/extensions/weather— Go SDK, exposes one toolexamples/extensions/guard— Go SDK, demonstrates interceptsdocs/extensions.md— full protocol reference