<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Skills on Lesstruct</title><link>https://lesstruct.dev/skills/</link><description>Recent content in Skills on Lesstruct</description><generator>Hugo</generator><language>en</language><copyright>Released under the [MIT License](https://github.com/aristorinjuang/lesstruct/blob/main/LICENSE).</copyright><atom:link href="https://lesstruct.dev/skills/index.xml" rel="self" type="application/rss+xml"/><item><title/><link>https://lesstruct.dev/skills/plugin-development/dev-vs-prod/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lesstruct.dev/skills/plugin-development/dev-vs-prod/</guid><description>&lt;h1 id="development-vs-production-mode"&gt;Development vs Production Mode&lt;a class="anchor" href="#development-vs-production-mode"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Lesstruct&amp;rsquo;s plugin system supports two modes, toggled by the same
&lt;code&gt;DEV_MODE&lt;/code&gt; env var used by the admin SPA.&lt;/p&gt;
&lt;h2 id="production-mode-default"&gt;Production mode (default)&lt;a class="anchor" href="#production-mode-default"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When &lt;code&gt;DEV_MODE&lt;/code&gt; is unset, false, or any value other than the string
&lt;code&gt;&amp;quot;true&amp;quot;&lt;/code&gt; (the runtime uses &lt;code&gt;getEnvBool&lt;/code&gt;, which is permissive about the
exact spelling), the plugin system loads all &lt;code&gt;.wasm&lt;/code&gt; files in
&lt;code&gt;plugins/&lt;/code&gt; once at startup. To apply changes, restart the server.&lt;/p&gt;
&lt;p&gt;This is the recommended mode for any non-development environment.&lt;/p&gt;</description></item><item><title/><link>https://lesstruct.dev/skills/plugin-development/examples/go-content-transform/README/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lesstruct.dev/skills/plugin-development/examples/go-content-transform/README/</guid><description>&lt;h1 id="content-transform-plugin"&gt;Content Transform Plugin&lt;a class="anchor" href="#content-transform-plugin"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;A Lesstruct plugin that transforms content before it is saved by uppercasing the title.&lt;/p&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites&lt;a class="anchor" href="#prerequisites"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tinygo.org/getting-started/install/"&gt;TinyGo&lt;/a&gt; 0.28+&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="build"&gt;Build&lt;a class="anchor" href="#build"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tinygo build -o content-transform.wasm -target&lt;span class="o"&gt;=&lt;/span&gt;wasi main.go&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="install"&gt;Install&lt;a class="anchor" href="#install"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Copy the compiled WASM file to the Lesstruct plugins directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cp content-transform.wasm &amp;lt;lesstruct-project&amp;gt;/plugins/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="expected-behavior"&gt;Expected Behavior&lt;a class="anchor" href="#expected-behavior"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When content is saved, the plugin intercepts the &lt;code&gt;before_save&lt;/code&gt; hook and uppercases the &lt;code&gt;&amp;quot;title&amp;quot;&lt;/code&gt; field value. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Input: &lt;code&gt;{&amp;quot;title&amp;quot;:&amp;quot;my blog post&amp;quot;, &amp;quot;content&amp;quot;:&amp;quot;...&amp;quot;}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Output: &lt;code&gt;{&amp;quot;title&amp;quot;:&amp;quot;MY BLOG POST&amp;quot;, &amp;quot;content&amp;quot;:&amp;quot;...&amp;quot;}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title/><link>https://lesstruct.dev/skills/plugin-development/examples/go-hello-world/README/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lesstruct.dev/skills/plugin-development/examples/go-hello-world/README/</guid><description>&lt;h1 id="hello-world-plugin"&gt;Hello World Plugin&lt;a class="anchor" href="#hello-world-plugin"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;A minimal Lesstruct plugin that responds when loaded by the plugin system.&lt;/p&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites&lt;a class="anchor" href="#prerequisites"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tinygo.org/getting-started/install/"&gt;TinyGo&lt;/a&gt; 0.28+&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="build"&gt;Build&lt;a class="anchor" href="#build"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tinygo build -o hello-world.wasm -target&lt;span class="o"&gt;=&lt;/span&gt;wasi main.go&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="install"&gt;Install&lt;a class="anchor" href="#install"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Copy the compiled WASM file to the Lesstruct plugins directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cp hello-world.wasm &amp;lt;lesstruct-project&amp;gt;/plugins/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="expected-behavior"&gt;Expected Behavior&lt;a class="anchor" href="#expected-behavior"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When Lesstruct starts, it loads the plugin and calls &lt;code&gt;hook_on_plugin_loaded&lt;/code&gt;. The plugin returns a JSON response:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;loaded&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;plugin&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;hello-world&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;input_size&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;...&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title/><link>https://lesstruct.dev/skills/plugin-development/examples/go-validation/README/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lesstruct.dev/skills/plugin-development/examples/go-validation/README/</guid><description>&lt;h1 id="validation-plugin"&gt;Validation Plugin&lt;a class="anchor" href="#validation-plugin"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;A Lesstruct plugin that validates content before it is saved by rejecting empty titles.&lt;/p&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites&lt;a class="anchor" href="#prerequisites"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tinygo.org/getting-started/install/"&gt;TinyGo&lt;/a&gt; 0.28+&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="build"&gt;Build&lt;a class="anchor" href="#build"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tinygo build -o validation.wasm -target&lt;span class="o"&gt;=&lt;/span&gt;wasi main.go&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="install"&gt;Install&lt;a class="anchor" href="#install"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Copy the compiled WASM file to the Lesstruct plugins directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cp validation.wasm &amp;lt;lesstruct-project&amp;gt;/plugins/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="expected-behavior"&gt;Expected Behavior&lt;a class="anchor" href="#expected-behavior"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When content is saved, the plugin intercepts the &lt;code&gt;before_save&lt;/code&gt; hook and checks if the &lt;code&gt;&amp;quot;title&amp;quot;&lt;/code&gt; field is empty.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the title is empty, the plugin returns an error response:
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;validation failed&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;title must not be empty&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;If the title is not empty, the original content passes through unchanged.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title/><link>https://lesstruct.dev/skills/plugin-development/install-paths/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lesstruct.dev/skills/plugin-development/install-paths/</guid><description>&lt;h1 id="install-paths"&gt;Install Paths&lt;a class="anchor" href="#install-paths"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote class='book-hint '&gt;
&lt;p&gt;&lt;strong&gt;Path note.&lt;/strong&gt; The exact skill directory location depends on the agent.
The patterns below are based on common conventions; if your agent uses
a different path, adjust accordingly. The &lt;code&gt;README.md&lt;/code&gt; of this skill is
the canonical install guide; this file is a quick reference.&lt;/p&gt;
&lt;/blockquote&gt;&lt;h2 id="claude-code"&gt;Claude Code&lt;a class="anchor" href="#claude-code"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Copy the skill into Claude Code&amp;#39;s skill directory.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cp -r lesstruct-plugin-development ~/.claude/skills/lesstruct-plugin-development&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Claude Code loads skills from &lt;code&gt;~/.claude/skills/&lt;/code&gt; by default. If you have
configured a custom path, substitute it.&lt;/p&gt;</description></item><item><title/><link>https://lesstruct.dev/skills/plugin-development/plugin-capabilities/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lesstruct.dev/skills/plugin-development/plugin-capabilities/</guid><description>&lt;h1 id="plugin-capabilities"&gt;Plugin Capabilities&lt;a class="anchor" href="#plugin-capabilities"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote class='book-hint '&gt;
&lt;p&gt;&lt;strong&gt;Snapshot notice.&lt;/strong&gt; This is the &lt;strong&gt;user-facing&lt;/strong&gt; snapshot of the Lesstruct
plugin capabilities reference, bundled with the &lt;code&gt;lesstruct-plugin-development&lt;/code&gt;
skill so the skill is self-contained. The canonical, developer-facing
version lives in the Lesstruct repository at &lt;code&gt;docs/plugin-capabilities.md&lt;/code&gt;
and references source-tree paths; this version is rewritten for someone
with a binary Lesstruct install and a &lt;code&gt;plugins/&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;If you have a newer Lesstruct release, re-export this file from the repo to
refresh the snapshot.&lt;/p&gt;</description></item><item><title/><link>https://lesstruct.dev/skills/plugin-development/plugin-checklist/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lesstruct.dev/skills/plugin-development/plugin-checklist/</guid><description>&lt;h1 id="plugin-pre-flight-checklist"&gt;Plugin Pre-Flight Checklist&lt;a class="anchor" href="#plugin-pre-flight-checklist"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Use this checklist to audit a plugin before declaring it ready. Each
item is a hard pass / fail.&lt;/p&gt;
&lt;h2 id="file-layout"&gt;File layout&lt;a class="anchor" href="#file-layout"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Plugin file is &lt;code&gt;&amp;lt;name&amp;gt;.wasm&lt;/code&gt; in &lt;code&gt;plugins/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Optional &lt;code&gt;&amp;lt;name&amp;gt;.manifest&lt;/code&gt; is in the same directory as the &lt;code&gt;.wasm&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Plugin filename (without extension) and the manifest&amp;rsquo;s &lt;code&gt;name&lt;/code&gt; field
match. The host does not enforce this today, but matching them is
good hygiene.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="hooks"&gt;Hooks&lt;a class="anchor" href="#hooks"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Plugin exports at least one of the three currently-invoked hooks:
&lt;code&gt;hook_before_save&lt;/code&gt;, &lt;code&gt;hook_after_create&lt;/code&gt;, &lt;code&gt;hook_after_publish&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Plugin does &lt;strong&gt;not&lt;/strong&gt; rely on &lt;code&gt;hook_on_plugin_loaded&lt;/code&gt; or
&lt;code&gt;hook_before_delete&lt;/code&gt;. Both are defined in the host but not
currently invoked. Plugins that only export one of these will
load but never fire.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Each hook&amp;rsquo;s result is a JSON object containing (at most)
&lt;code&gt;customFields&lt;/code&gt; for mutation. The host reads only &lt;code&gt;customFields&lt;/code&gt;
back; other fields in the result are ignored.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;__hook_result_len&lt;/code&gt; is exported only if the result length differs
from the input length. The export is optional; the host uses
&lt;code&gt;inputLen&lt;/code&gt; as the result length when the export is missing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="manifest"&gt;Manifest&lt;a class="anchor" href="#manifest"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;name&lt;/code&gt; is set and non-empty.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;version&lt;/code&gt; is set and non-empty.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;capabilities.http&lt;/code&gt; is set to a list of URL patterns if the
plugin uses &lt;code&gt;http_get&lt;/code&gt; or &lt;code&gt;http_post&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;capabilities.database&lt;/code&gt; is set to a list of
&lt;code&gt;read|write:content|media|users&lt;/code&gt; permissions if the plugin uses
&lt;code&gt;db_query&lt;/code&gt; or &lt;code&gt;db_exec&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; URL patterns use trailing &lt;code&gt;*&lt;/code&gt; only (no regex, no &lt;code&gt;?&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; URL patterns are ordered so the most specific match comes first
(the first match wins).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="host-function-calls"&gt;Host function calls&lt;a class="anchor" href="#host-function-calls"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; If the plugin uses &lt;code&gt;http_get&lt;/code&gt; or &lt;code&gt;http_post&lt;/code&gt;, the manifest&amp;rsquo;s
&lt;code&gt;http&lt;/code&gt; patterns cover the actual URLs the plugin will request.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; If the plugin uses &lt;code&gt;db_query&lt;/code&gt; or &lt;code&gt;db_exec&lt;/code&gt;, the manifest&amp;rsquo;s
&lt;code&gt;database&lt;/code&gt; permissions cover the actual table names in the
queries (and the actual operation: &lt;code&gt;db_query&lt;/code&gt; is always
&lt;code&gt;read&lt;/code&gt;, &lt;code&gt;db_exec&lt;/code&gt; is always &lt;code&gt;write&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Every SQL query is a single explicit &lt;code&gt;SELECT&lt;/code&gt; / &lt;code&gt;INSERT&lt;/code&gt; /
&lt;code&gt;UPDATE&lt;/code&gt; / &lt;code&gt;DELETE&lt;/code&gt; statement. No CTEs, no subqueries, no
comments, no quoted identifiers, no multi-statement queries.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; The plugin reads each host function&amp;rsquo;s result from offset &lt;code&gt;4096&lt;/code&gt;
before invoking the next host function. All four data host
functions share the same result offset.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="build"&gt;Build&lt;a class="anchor" href="#build"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Compiled with &lt;code&gt;tinygo build -target=wasi&lt;/code&gt; (Go),
&lt;code&gt;cargo build --target wasm32-wasip1&lt;/code&gt; (Rust), or
&lt;code&gt;clang --target=wasm32-wasi&lt;/code&gt; (C/C++).&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Compiled &lt;code&gt;.wasm&lt;/code&gt; is well under 64 MB (typical TinyGo plugin:
&amp;lt; 1 MB).&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; For Go plugins that use host functions, the
&lt;code&gt;//go:wasmimport&lt;/code&gt; block from
&lt;code&gt;references/host-function-imports.go.txt&lt;/code&gt; is copied into the
plugin&amp;rsquo;s &lt;code&gt;main.go&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="deployment"&gt;Deployment&lt;a class="anchor" href="#deployment"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Lesstruct was restarted after the last &lt;code&gt;plugins/&lt;/code&gt; change
(unless &lt;code&gt;DEV_MODE=true&lt;/code&gt; is set; in that case, the watcher
picks up new &lt;code&gt;.wasm&lt;/code&gt; files automatically).&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; The &lt;code&gt;.wasm&lt;/code&gt; is the top-level file in &lt;code&gt;plugins/&lt;/code&gt;. Subdirectories
are not watched.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="smoke-test"&gt;Smoke test&lt;a class="anchor" href="#smoke-test"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Run the smoke test from
&lt;a href="../../SKILL.md#step-8-verify-manual#step-8-verify-manual"&gt;&lt;code&gt;SKILL.md&lt;/code&gt; Step 8&lt;/a&gt; and
confirm the relevant hook fires and any &lt;code&gt;customFields&lt;/code&gt;
modification is reflected in the saved item.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; For host function calls, check the Lesstruct log for
&amp;ldquo;blocked&amp;rdquo; messages. If the call was permitted, no log line is
produced (audit logging is partial); use &lt;code&gt;log_info&lt;/code&gt; from the
plugin to record what it did.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="documentation"&gt;Documentation&lt;a class="anchor" href="#documentation"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; A &lt;code&gt;plugins/&amp;lt;name&amp;gt;.README&lt;/code&gt; records the Lesstruct version the
plugin was authored against, the hooks it uses, and the
capabilities declared in the manifest.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title/><link>https://lesstruct.dev/skills/plugin-development/plugin-development/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lesstruct.dev/skills/plugin-development/plugin-development/</guid><description>&lt;h1 id="plugin-development-guide"&gt;Plugin Development Guide&lt;a class="anchor" href="#plugin-development-guide"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote class='book-hint '&gt;
&lt;p&gt;&lt;strong&gt;Snapshot notice.&lt;/strong&gt; This is the &lt;strong&gt;user-facing&lt;/strong&gt; snapshot of the Lesstruct
plugin development guide, bundled with the &lt;code&gt;lesstruct-plugin-development&lt;/code&gt;
skill so the skill is self-contained. The canonical, developer-facing
version lives in the Lesstruct repository at &lt;code&gt;docs/plugin-development.md&lt;/code&gt;
and references source-tree paths; this version is rewritten for someone
with a binary Lesstruct install and a &lt;code&gt;plugins/&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;If you have a newer Lesstruct release, re-export this file from the repo to
refresh the snapshot.&lt;/p&gt;</description></item><item><title/><link>https://lesstruct.dev/skills/theme-development/install-paths/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lesstruct.dev/skills/theme-development/install-paths/</guid><description>&lt;h1 id="install-paths"&gt;Install Paths&lt;a class="anchor" href="#install-paths"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote class='book-hint '&gt;
&lt;p&gt;&lt;strong&gt;Path note.&lt;/strong&gt; The exact skill directory location depends on the agent. The
patterns below are based on common conventions; if your agent uses a
different path, adjust accordingly. The &lt;code&gt;README.md&lt;/code&gt; of this skill is the
canonical install guide; this file is a quick reference.&lt;/p&gt;
&lt;/blockquote&gt;&lt;h2 id="claude-code"&gt;Claude Code&lt;a class="anchor" href="#claude-code"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Copy the skill into Claude Code&amp;#39;s skill directory.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cp -r lesstruct-theme-development ~/.claude/skills/lesstruct-theme-development&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Claude Code loads skills from &lt;code&gt;~/.claude/skills/&lt;/code&gt; by default. If you have
configured a custom path, substitute it.&lt;/p&gt;</description></item><item><title/><link>https://lesstruct.dev/skills/theme-development/page-render-smoke-test/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lesstruct.dev/skills/theme-development/page-render-smoke-test/</guid><description>&lt;h1 id="page-render-smoke-test"&gt;Page Render Smoke Test&lt;a class="anchor" href="#page-render-smoke-test"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This is a manual smoke test for a Lesstruct theme. Run it after every change
to &lt;code&gt;themes/&amp;lt;name&amp;gt;/&lt;/code&gt; and after every Lesstruct upgrade. The skill does not have
access to the Lesstruct source, so this test must be run by you, against your
running install, in a browser or with &lt;code&gt;curl&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="setup"&gt;Setup&lt;a class="anchor" href="#setup"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Confirm &lt;code&gt;THEME_DIR&lt;/code&gt; is set and Lesstruct is running.&lt;/li&gt;
&lt;li&gt;Confirm at least one post exists (the smoke test uses &lt;code&gt;/&amp;lt;slug&amp;gt;&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Confirm at least one user with author profile exists (for the author page).&lt;/li&gt;
&lt;li&gt;Confirm at least one post has at least one tag (for the tag page).&lt;/li&gt;
&lt;li&gt;Replace &lt;code&gt;&amp;lt;slug&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;username&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;tag&amp;gt;&lt;/code&gt; in the URLs below with values
from your install.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="page-by-page-test"&gt;Page-by-page test&lt;a class="anchor" href="#page-by-page-test"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For each URL: load it in a browser (or &lt;code&gt;curl&lt;/code&gt; it), then check the column on
the right. The &amp;ldquo;Smoke signal&amp;rdquo; column is the smallest signal that the page
rendered and your theme took effect.&lt;/p&gt;</description></item><item><title/><link>https://lesstruct.dev/skills/theme-development/theme-audit-checklist/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lesstruct.dev/skills/theme-development/theme-audit-checklist/</guid><description>&lt;h1 id="theme-audit-checklist"&gt;Theme Audit Checklist&lt;a class="anchor" href="#theme-audit-checklist"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Use this checklist to audit a &lt;code&gt;themes/&amp;lt;name&amp;gt;/&lt;/code&gt; directory before declaring a
theme ready. Each item is a hard pass / fail.&lt;/p&gt;
&lt;h2 id="environment"&gt;Environment&lt;a class="anchor" href="#environment"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;THEME_DIR&lt;/code&gt; is set in &lt;code&gt;.env&lt;/code&gt; or the environment the Lesstruct process
runs in (not only in a shell session that has since closed).&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;THEME_DIR&lt;/code&gt; resolves to an existing directory.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Lesstruct was restarted after the most recent &lt;code&gt;THEME_DIR&lt;/code&gt; change.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; The theme directory has a &lt;code&gt;static/&lt;/code&gt; and a &lt;code&gt;templates/&lt;/code&gt; subdirectory
(even if empty).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="css-staticstylecss"&gt;CSS (&lt;code&gt;static/style.css&lt;/code&gt;)&lt;a class="anchor" href="#css-staticstylecss"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;static/style.css&lt;/code&gt; is valid CSS (run it through a linter).&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;static/style.css&lt;/code&gt; does not reference &lt;code&gt;style.src.css&lt;/code&gt; (the source file
is not served; only the minified &lt;code&gt;style.css&lt;/code&gt; is).&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Every CSS variable the default theme defines is still defined in the
override (or in a parent file the override loads). The full set is in
the &lt;a href="https://lesstruct.dev/skills/theme-development/theme-development/#css-variable-reference"&gt;CSS Variable Reference&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;@import&lt;/code&gt; URLs (fonts, third-party CSS) resolve.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="layout-template-templateslayouthtml"&gt;Layout template (&lt;code&gt;templates/layout.html&lt;/code&gt;)&lt;a class="anchor" href="#layout-template-templateslayouthtml"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; File defines &lt;code&gt;{{define &amp;quot;layout&amp;quot;}}…{{end}}&lt;/code&gt; exactly once.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; The HTML element has &lt;code&gt;lang=&amp;quot;{{.Lang}}&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;&amp;lt;title&amp;gt;{{.PageTitle}}&amp;lt;/title&amp;gt;&lt;/code&gt; is present.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/static/style.css&amp;quot;&amp;gt;&lt;/code&gt; is present.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;&amp;lt;main&amp;gt;…{{template &amp;quot;body&amp;quot; .}}…&amp;lt;/main&amp;gt;&lt;/code&gt; is present.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; The Open Graph &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tags are present (otherwise share previews
break).&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;&amp;lt;script src=&amp;quot;/static/nav-auth.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt; and
&lt;code&gt;&amp;lt;script src=&amp;quot;/static/search.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt; are present (otherwise
the nav login/logout toggle and search dropdown break).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="page-templates-any-templatespagehtml-you-ship"&gt;Page templates (any &lt;code&gt;templates/&amp;lt;page&amp;gt;.html&lt;/code&gt; you ship)&lt;a class="anchor" href="#page-templates-any-templatespagehtml-you-ship"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; The template defines &lt;code&gt;{{define &amp;quot;body&amp;quot;}}…{{end}}&lt;/code&gt; exactly once.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; The template uses the data fields listed in
&lt;a href="https://lesstruct.dev/skills/theme-development/theme-development/#template-data-fields"&gt;Template Data Fields&lt;/a&gt; by
their documented names (&lt;code&gt;.Title&lt;/code&gt;, &lt;code&gt;.PageTitle&lt;/code&gt;, etc.).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="javascript-dom-contract"&gt;JavaScript DOM contract&lt;a class="anchor" href="#javascript-dom-contract"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you override &lt;code&gt;static/comments.js&lt;/code&gt;:&lt;/p&gt;</description></item><item><title/><link>https://lesstruct.dev/skills/theme-development/theme-development/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lesstruct.dev/skills/theme-development/theme-development/</guid><description>&lt;h1 id="theme-development-guide"&gt;Theme Development Guide&lt;a class="anchor" href="#theme-development-guide"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote class='book-hint '&gt;
&lt;p&gt;&lt;strong&gt;Snapshot notice.&lt;/strong&gt; This is the &lt;strong&gt;user-facing&lt;/strong&gt; snapshot of the Lesstruct
theme development guide, bundled with the &lt;code&gt;lesstruct-theme-development&lt;/code&gt; skill
so the skill is self-contained. The canonical, developer-facing version lives
in the Lesstruct repository at &lt;code&gt;docs/theme-development.md&lt;/code&gt; and references
source-tree paths; this version is rewritten for someone with a binary
Lesstruct install and a &lt;code&gt;themes/&amp;lt;name&amp;gt;/&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;If you have a newer Lesstruct release, re-export this file from the repo to
refresh the snapshot.&lt;/p&gt;</description></item></channel></rss>