This is a starter template for publishing your own static site using ShadowClaw as the build engine.
- You write your content as markdown (
.md) or HTML (.html) files underpages/main/. - You can add Agent Skills under
.agents/skills/main/. Each skill is a directory containing a standardSKILL.md; these skills are available to the main ShadowClaw conversation. - You can add Declarative Tools under
.agents/tools/main/as JSON files to declare custom executable tools for your site. - When you push to
main, the included GitHub Actions workflow:- Checks out ShadowClaw's source as a build dependency (not redistributed).
- Copies your
pages/and.agents/into the build root. - Runs
npm run build:prodwith your repo's GitHub Pages URL injected automatically. - Deploys
dist/public/to GitHub Pages viaactions/deploy-pages.
No ShadowClaw source lives in this repo — only your content and the workflow.
To run or build your template site locally, use the shadow-claw CLI:
# Preview and run live dev server on http://127.0.0.1:8888
npx shadow-claw dev
# Or build the static distribution locally into ./dist/public
npx shadow-claw build- Click Use this template on GitHub (or fork/clone).
- In your new repo, go to Settings → Pages → Source and select GitHub Actions.
- Optionally drop your markdown files into
pages/main/. A repository with nopages/directory still builds with ShadowClaw's default Pages content. - Optionally add skills under
.agents/skills/main/; a repository without that directory simply has no bundled skills. - Optionally add tools under
.agents/tools/main/; a repository without that directory has no bundled custom tools. - Optionally configure
shadow-claw.config.json(repo root) for site branding, sidebar navigation visibility, initial tool enablement (enabledTools), and page sort order. - Optionally edit
pages/resources/routes.jsonto add pretty-path URLs. - Push to
main— the workflow builds and deploys automatically.
shadow-claw.config.json ← declarative site branding, sidebar, enabled tools, and sorting config
pages/
main/
index.html ← your home page
~/content/
about.md ← any other pages
resources/ ← root level files & resources (routes.json, 404.html, manifest.json, sitemap.xml / sitemap.txt, favicon.svg, assets/)
.agents/
skills/
main/
toast-random-number/
SKILL.md ← optional Agent Skills for the main conversation
tools/
main/
generate_random_number.json ← optional executable tool definition
scripts/
main/
starter-tools.js ← portable ESM logic with zero DOM dependencies
.well-known/
agent-skills/
index.json ← standard skills discovery index (RFC v0.2.0)
.github/
workflows/
deploy-pages.yml ← the build + deploy workflow (no changes needed)External AI agents and peer ShadowClaw instances discover and consume your skills headlessly over HTTPS per the Agent Skills Discovery RFC via:
/.well-known/agent-skills/index.json
Generate or refresh this index anytime using the ShadowClaw CLI:
npx shadow-claw skills:indexTo make your tools reusable across both headless worker threads and on-page UI components:
- Portable Scripts (
.agents/scripts/main/<name>.js): Pure ESM containing business logic, computations, and parameter normalization. Zero DOM or browser dependencies. - Presentation Adapters (
pages/main/<name>-adapter.js): Imports portable scripts to synchronize custom elements, render UI controls, and bridgeBroadcastChannelevents.
Agent Skills follow the open Agent Skills format. Place skills in .agents/skills/main/<skill-name>/SKILL.md.
- Required fields:
name: 1–64 characters using lowercase letters, digits, and single hyphens.description: Up to 1,024 characters describing what the skill does.
- Optional standard fields:
license,compatibility,user-invocable,disable-model-invocation,argument-hint.metadata: Key-value map for skill metadata. Tool allowlists belong undermetadata.allowed-tools(e.g.allowed-tools: javascript show_toast generate_random_number).execution: Defines deterministic execution tool chains.
Skills with user-invocable: true (or where user-invocable is omitted) can be invoked directly by users in chat using slash commands matching the skill name (for example /toast-random-number or /skill-creator).
Skills can define deterministic, sequential tool pipelines in frontmatter. When triggered via slash command or agent invocation, tool chains execute directly via executeToolChain on the worker thread without scheduling LLM prompts or calling model endpoints.
---
name: toast-random-number
description: Generate a random integer from 1 to 1000000 and display it in a toast notification silently.
user-invocable: true
metadata:
allowed-tools: javascript show_toast generate_random_number
execution:
type: tools
suppressToast: true
suppressOutput: true
tools:
- name: generate_random_number
input:
min: 1
max: 1000000
- name: show_toast
input:
title: Random Number
message:
$pipe: prev
---- Output Pipelining (
$pipe): Pass outputs between steps using:{ "$pipe": "prev" }— output of the immediately preceding step.{ "$pipe": 0 }— output of step index 0.{ "$pipe": "generate_random_number" }— output of the step executinggenerate_random_number.
- Notification & Output Suppression:
suppressToast: true— suppresses step-by-step progress toasts ("Running skill tool...").suppressOutput: true— suppresses raw step output blocks from cluttering the chat thread.- Setting suppression at the top-level
executionblock automatically cascades down to all steps in the chain.
- Auto-returning JavaScript Evaluation: Single expressions in
javascripttool steps (e.g.,Math.floor(Math.random() * 100) + 1) evaluate and return automatically without requiring explicitreturnstatements.
Skills are seeded into the main conversation's OPFS workspace (.agents/skills/main/) on initial boot. They do not become host filesystem commands and are scoped to the main workspace.
Add executable tools under .agents/tools/main/ as JSON files. Each file defines a standard tool schema and an explicit execution object.
{
"name": "generate_random_number",
"description": "Generate a random integer within a specified range.",
"input_schema": {
"type": "object",
"properties": {
"min": { "type": "integer", "description": "Minimum value (inclusive)" },
"max": { "type": "integer", "description": "Maximum value (inclusive)" }
},
"required": ["min", "max"]
},
"execution": {
"type": "javascript",
"code": "const input = typeof data === 'string' ? JSON.parse(data) : data; const min = Number(input?.min ?? 1); const max = Number(input?.max ?? 100); return Math.floor(Math.random() * (max - min + 1)) + min;"
}
}javascript: Runs inside ShadowClaw's sandboxed JavaScript worker. The parsed arguments are available viadata. Single expressions evaluate and return automatically.bash: Runs through the sandboxed JS shell / WebVM. Arguments are passed as serialized JSON viastdin.tool: Delegates to another allowlisted ShadowClaw tool with optional pre-configured input parameter merging.
- Tool names must match
^[a-z][a-z0-9_]{0,63}$. - Built-in tool names cannot be shadowed.
- Declarative tool delegation is capped at eight levels to prevent recursion loops.
- Loaded declarative tools automatically register with the browser's WebMCP Model Context API (
document.modelContext/navigator.modelContext) for native model execution.
Configure your site metadata, branding, navigation visibility, tool defaults, and sorting declaratively without touching source code:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"site": {
"title": "My Site",
"description": "Published with ShadowClaw",
"themeColor": "#121212",
"lang": "en"
},
"branding": {
"titleText": "My Project",
"siteUrl": "https://example.com",
"repoUrl": "https://github.com/my-user/my-project"
},
"sidebar": {
"pagesHidden": false,
"chatHidden": false,
"tasksHidden": true,
"filesHidden": false,
"defaultPage": "pages"
},
"pages": {
"sortOrder": "desc"
},
"enabledTools": [
"bash",
"javascript",
"read_file",
"write_file",
"generate_random_number"
],
"customElements": {
"allowedElements": ["block-garden", "block-garden-select", "x-pwgen"],
"allowedDomains": ["kherrick.github.io", "xt-ml.github.io"],
"scripts": [
"https://kherrick.github.io/block-garden/block-garden-bundle-min.mjs"
]
}
}enabledTools specifies the initial active tool profile applied on first run for the main conversation. When omitted, ShadowClaw uses its standard default tool profile. User modifications made later in the UI are preserved.
ShadowClaw builds via npx --yes shadow-claw@latest build --prod. To pin to a specific npm release (e.g. 1.23.3), specify the version in .github/workflows/deploy-pages.yml or supply shadowclaw_version when triggering the GitHub Actions workflow manually.
To reset bundled skills on a later deployment, add a Markdown file under .agents/skills/main/ with this frontmatter, updating purge-id for each reset:
---
slug: shadow-claw--purge-skills
purge-id: skills-build-002
---The purge marker is removed from the catalog before seeding, and the main conversation's .agents/skills/main/ OPFS directory is cleared and re-seeded with current published skills. Page purge markers (slug: shadow-claw--purge-pages) operate independently.
You can hide or show individual sidebar navigation items (pagesHidden, chatHidden, tasksHidden, filesHidden) and set the default landing section (defaultPage: "pages" | "chat" | "tasks" | "files"). When hidden, the corresponding section is hidden from the sidebar at build time and on first boot.
ShadowClaw enforces a deny-by-default security stance on custom elements and external scripts rendered within articles and pages. Site authors can declare approved elements and trusted host domains in customElements:
allowedElements: List of custom element tag names permitted in page markup and HTML sanitization (e.g.["block-garden", "block-garden-select"]). Unapproved custom elements are blocked from registration and stripped from the DOM.allowedDomains: List of approved domains or wildcard patterns (e.g.["kherrick.github.io", "*.github.io"]) permitted to load scripts or custom element bundles.scripts: Array of approved script URLs (or objects{ "src": "...", "type": "module" }) to preload at build time and on boot.
Map source files to clean URLs:
{
"routes": {
"/pages/main/index.html": { "prettyPath": "/main" },
"/pages/main/~/content/about.md": { "prettyPath": "/main/about" },
"/pages/main/MEMORY.md": { "prettyPath": "/main/memory" }
}
}The prerender pipeline generates a physical index.html for every mapped path so direct links and page refreshes work correctly on GitHub Pages without any server-side rewrites.
Reserved path prefixes — the following first-path-segments are owned by ShadowClaw's router and must not be used as pretty path prefixes:
/,/chat,/files,/tasks,/pages,/settings,/tools,/channels. Additionally,/(root) is reserved as the default pinned page and is unreachable as a pretty path. Use a safe namespace like/main/,/articles/,/docs/, or any other prefix that doesn't conflict with the above list.
When a visitor loads the root URL (/) of your published site, ShadowClaw automatically displays the default pinned page.
- Both the static site build pipeline (
prerender-dsd-shell) and runtime page store (orchestratorStore) collect all files inpages/main/. MEMORY.mdis always sorted to the bottom of the list.- All other pages are sorted by
pages.sortOrderfromshadow-claw.config.json("desc"by default, natural numeric, or"asc"). - The first file in this sorted list (
pages[0]) becomes the default page pre-rendered into the DSD shell at/.
If you use a custom apex domain (e.g. example.com), override the two URL env vars in the workflow:
env:
PAGES_ORIGIN: "https://example.com/"
PAGES_BASE_PATH: "/"You can drive publishing from inside the ShadowClaw app itself using a type: "tools" task chain — no LLM calls required:
{
"type": "tools",
"tools": [
{
"name": "write_file",
"input": {
"path": "repos/my-site/pages/main/post.md",
"content": "# Hello\n\nContent."
}
},
{
"name": "git_add",
"input": { "repo": "my-site", "files": ["pages/main/post.md"] }
},
{
"name": "git_commit",
"input": { "repo": "my-site", "message": "publish: new post" }
},
{ "name": "git_push", "input": { "repo": "my-site" } }
]
}Pushing triggers the workflow, which builds and publishes the site automatically.