Doc Author
InsForge/InsForge
Write, edit, and maintain documentation. An agent skill from InsForge/InsForge.
Create, update, and manage Glance dashboard widgets. An agent skill from LeoYeAI/openclaw-master-skills.
$ npx skills add LeoYeAI/openclaw-master-skills --skill glance -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills glance --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/glance .claude/skills/glance && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "glance" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/glance into .claude/skills/glance/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "glance", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/glanceType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add LeoYeAI/openclaw-master-skills --skill glance -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills glance --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/glance .agents/skills/glance && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "glance" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/glance into .agents/skills/glance/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "glance", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LeoYeAI/openclaw-master-skills --skill glance -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills glance --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/glance .cursor/skills/glance && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "glance" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/glance into .cursor/skills/glance/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "glance", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/LeoYeAI/openclaw-master-skills.git --path skills/glance--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add LeoYeAI/openclaw-master-skills --skill glance -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills glance --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/glance .gemini/skills/glance && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "glance" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/glance into .gemini/skills/glance/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "glance", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install LeoYeAI/openclaw-master-skills glanceInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add LeoYeAI/openclaw-master-skills --skill glance -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/glance .github/skills/glance && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "glance" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/glance into .github/skills/glance/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "glance", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LeoYeAI/openclaw-master-skills --skill glance -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills glance --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/glance .opencode/skills/glance && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "glance" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/glance into .opencode/skills/glance/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "glance", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
glanceCreate, update, and manage Glance dashboard widgets. An agent skill from LeoYeAI/openclaw-master-skills.
Glance is an agent skill from LeoYeAI/openclaw-master-skills. Create, update, and manage Glance dashboard widgets. Use when user wants to: add something to their dashboard, create a widget, track data visually, show metrics/stats, display API data, or monitor usage.
Its SKILL.md is about 7.3k tokens, which your agent loads only when the skill is triggered. The skill folder holds 4 other files (for example `README.md`, `_meta.json` and `dashboard-api.md`).
It sits in AI & LLM Engineering. The repository describes itself as: 🧠 Curated collection of 1209+ best OpenClaw skills — weekly updated by MyClaw.ai. The licence is MIT.
4 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit e5199b5. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
npmcurlgitjqsqlite3claudeFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
github.comapple.comapi.github.combrew.shFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
OPENCLAW_TOKENAUTH_TOKENGLANCE_TOKENFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Glance loads about 7.3k tokens when it runs. Until then it costs about 53 tokens; SKILL.md has 1,772 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
cp .env.example .env.local# Edit .env.local with your settingsEdit `.env.local`:**Environment variables** (add to `.env.local`):Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from LeoYeAI/openclaw-master-skills at commit e5199b5, republished under its MIT licence (© LeoYeAI). 1,772 words, ~7,293 tokens.
.claude/skills/glance/SKILL.md (or your agent's skills folder). This skill also uses 4 other files; get the full folder from GitHub.AI-extensible personal dashboard. Create custom widgets with natural language — the AI handles data collection.
# Navigate to skill directory (if installed via ClawHub)
cd "$(clawhub list | grep glance | awk '{print $2}')"
# Or clone directly
git clone https://github.com/acfranzen/glance ~/.glance
cd ~/.glance
# Install dependencies
npm install
# Configure environment
cp .env.example .env.local
# Edit .env.local with your settings
# Start development server
npm run dev
# Or build and start production
npm run build && npm startDashboard runs at http://localhost:3333
Edit .env.local:
# Server
PORT=3333
AUTH_TOKEN=your-secret-token # Optional: Bearer token auth
# OpenClaw Integration (for instant widget refresh)
OPENCLAW_GATEWAY_URL=https://localhost:18789
OPENCLAW_TOKEN=your-gateway-token
# Database
DATABASE_PATH=./data/glance.db # SQLite database location# Create launchd plist
cat > ~/Library/LaunchAgents/com.glance.dashboard.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.glance.dashboard</string>
<key>ProgramArguments</key>
<array>
<string>/opt/homebrew/bin/npm</string>
<string>run</string>
<string>dev</string>
</array>
<key>WorkingDirectory</key>
<string>~/.glance</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>~/.glance/logs/stdout.log</string>
<key>StandardErrorPath</key>
<string>~/.glance/logs/stderr.log</string>
</dict>
</plist>
EOF
# Load service
mkdir -p ~/.glance/logs
launchctl load ~/Library/LaunchAgents/com.glance.dashboard.plist
# Service commands
launchctl start com.glance.dashboard
launchctl stop com.glance.dashboard
launchctl unload ~/Library/LaunchAgents/com.glance.dashboard.plist| Variable | Description | Default |
|---|---|---|
PORT | Server port | 3333 |
AUTH_TOKEN | Bearer token for API auth | — |
DATABASE_PATH | SQLite database path | ./data/glance.db |
OPENCLAW_GATEWAY_URL | OpenClaw gateway for webhooks | — |
OPENCLAW_TOKEN | OpenClaw auth token | — |
Create and manage dashboard widgets. Most widgets use agent_refresh — you collect the data.
# Check Glance is running (list widgets)
curl -s -H "Origin: $GLANCE_URL" "$GLANCE_URL/api/widgets" | jq '.custom_widgets[].slug'
# Auth note: Local requests with Origin header bypass Bearer token auth
# For external access, use: -H "Authorization: Bearer $GLANCE_TOKEN"
# Refresh a widget (look up instructions, collect data, POST to cache)
sqlite3 $GLANCE_DATA/glance.db "SELECT json_extract(fetch, '$.instructions') FROM custom_widgets WHERE slug = 'my-widget'"
# Follow the instructions, then:
curl -X POST "$GLANCE_URL/api/widgets/my-widget/cache" \
-H "Content-Type: application/json" \
-H "Origin: $GLANCE_URL" \
-d '{"data": {"value": 42, "fetchedAt": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}}'
# Verify in browser
browser action:open targetUrl:"$GLANCE_URL"When generating widget definitions, use the JSON Schema at docs/schemas/widget-schema.json with your AI model's structured output mode:
tool_use with the schemaresponse_format: { type: "json_schema", schema }The schema enforces all required fields at generation time — malformed widgets cannot be produced.
Every widget MUST have these fields (the schema enforces them):
| Field | Type | Notes |
|---|---|---|
name | string | Non-empty, human-readable |
slug | string | Lowercase kebab-case (my-widget) |
source_code | string | Valid JSX with Widget function |
default_size | { w: 1-12, h: 1-20 } | Grid units |
min_size | { w: 1-12, h: 1-20 } | Cannot resize smaller |
fetch.type | enum | "server_code" | "webhook" | "agent_refresh" |
fetch.instructions | string | REQUIRED if type is agent_refresh |
fetch.schedule | string | REQUIRED if type is agent_refresh (cron) |
data_schema.type | "object" | Always object |
data_schema.properties | object | Define each field |
data_schema.required | array | MUST include "fetchedAt" |
credentials | array | Use [] if none needed |
{
"name": "My Widget",
"slug": "my-widget",
"source_code": "function Widget({ serverData }) { return <div>{serverData?.value}</div>; }",
"default_size": { "w": 2, "h": 2 },
"min_size": { "w": 1, "h": 1 },
"fetch": {
"type": "agent_refresh",
"schedule": "*/15 * * * *",
"instructions": "## Data Collection\nCollect the data...\n\n## Cache Update\nPOST to /api/widgets/my-widget/cache"
},
"data_schema": {
"type": "object",
"properties": {
"value": { "type": "number" },
"fetchedAt": { "type": "string", "format": "date-time" }
},
"required": ["value", "fetchedAt"]
},
"credentials": []
}Every widget must complete ALL steps before being considered done:
□ Step 1: Create widget definition (POST /api/widgets)
- source_code with Widget function
- data_schema (REQUIRED for validation)
- fetch config (type + instructions for agent_refresh)
□ Step 2: Add to dashboard (POST /api/widgets/instances)
- custom_widget_id matches definition
- title and config set
□ Step 3: Populate cache (for agent_refresh widgets)
- Data matches data_schema exactly
- Includes fetchedAt timestamp
□ Step 4: Set up cron job (for agent_refresh widgets)
- Simple message: "⚡ WIDGET REFRESH: {slug}"
- Appropriate schedule (*/15 or */30 typically)
□ Step 5: BROWSER VERIFICATION (MANDATORY)
- Open http://localhost:3333
- Widget is visible on dashboard
- Shows actual data (not loading spinner)
- Data values match what was cached
- No errors or broken layouts
⛔ DO NOT report widget as complete until Step 5 passes!docs/widget-sdk.md in the Glance repoWidget Package
├── meta (name, slug, description, author, version)
├── widget (source_code, default_size, min_size)
├── fetch (server_code | webhook | agent_refresh)
├── dataSchema? (JSON Schema for cached data - validates on POST)
├── cache (ttl, staleness, fallback)
├── credentials[] (API keys, local software requirements)
├── config_schema? (user options)
└── error? (retry, fallback, timeout)Is data available via API that the widget can call?
├── YES → Use server_code
└── NO → Does an external service push data?
├── YES → Use webhook
└── NO → Use agent_refresh (YOU collect it)| Scenario | Fetch Type | Who Collects Data? |
|---|---|---|
| Public/authenticated API | server_code | Widget calls API at render |
| External service pushes data | webhook | External service POSTs to cache |
| Local CLI tools | agent_refresh | YOU (the agent) via PTY/exec |
| Interactive terminals | agent_refresh | YOU (the agent) via PTY |
| Computed/aggregated data | agent_refresh | YOU (the agent) on a schedule |
⚠️ agent_refresh means YOU are the data source. You set up a cron to remind yourself, then YOU collect the data using your tools (exec, PTY, browser, etc.) and POST it to the cache.
| Method | Endpoint | Description |
|---|---|---|
POST | /api/widgets | Create widget definition |
GET | /api/widgets | List all definitions |
GET | /api/widgets/:slug | Get single definition |
PATCH | /api/widgets/:slug | Update definition |
DELETE | /api/widgets/:slug | Delete definition |
| Method | Endpoint | Description |
|---|---|---|
POST | /api/widgets/instances | Add widget to dashboard |
GET | /api/widgets/instances | List dashboard widgets |
PATCH | /api/widgets/instances/:id | Update instance (config, position) |
DELETE | /api/widgets/instances/:id | Remove from dashboard |
| Method | Endpoint | Description |
|---|---|---|
GET | /api/credentials | List credentials + status |
POST | /api/credentials | Store credential |
DELETE | /api/credentials/:id | Delete credential |
{
"name": "GitHub PRs",
"slug": "github-prs",
"description": "Shows open pull requests",
"source_code": "function Widget({ serverData }) { ... }",
"default_size": { "w": 2, "h": 2 },
"min_size": { "w": 1, "h": 1 },
"refresh_interval": 300,
"credentials": [
{
"id": "github",
"type": "api_key",
"name": "GitHub Personal Access Token",
"description": "Token with repo scope",
"obtain_url": "https://github.com/settings/tokens"
}
],
"fetch": {
"type": "agent_refresh",
"schedule": "*/5 * * * *",
"instructions": "Fetch open PRs from GitHub API and POST to cache endpoint",
"expected_freshness_seconds": 300,
"max_staleness_seconds": 900
},
"cache": {
"ttl_seconds": 300,
"max_staleness_seconds": 900,
"storage": "sqlite",
"on_error": "use_stale"
},
"setup": {
"description": "Configure GitHub token",
"agent_skill": "Store GitHub PAT via /api/credentials",
"verification": {
"type": "cache_populated",
"target": "github-prs"
},
"idempotent": true
}
}| Type | When to Use | Data Flow |
|---|---|---|
server_code | Widget can call API directly | Widget → server_code → API |
agent_refresh | Agent must fetch/compute data | Agent → POST /cache → Widget reads |
webhook | External service pushes data | External → POST /cache → Widget reads |
Most widgets should use agent_refresh — the agent fetches data on a schedule and pushes to the cache endpoint.
POST /api/widgets
Content-Type: application/json
{
"name": "GitHub PRs",
"slug": "github-prs",
"description": "Shows open pull requests",
"source_code": "function Widget({ serverData }) { ... }",
"default_size": { "w": 2, "h": 2 },
"credentials": [...],
"fetch": { "type": "agent_refresh", "schedule": "*/5 * * * *", ... },
"data_schema": {
"type": "object",
"properties": {
"prs": { "type": "array", "description": "List of PR objects" },
"fetchedAt": { "type": "string", "format": "date-time" }
},
"required": ["prs", "fetchedAt"]
},
"cache": { "ttl_seconds": 300, ... }
}data_schema (REQUIRED) defines the data contract between the fetcher and the widget. Cache POSTs are validated against it — malformed data returns 400.
⚠️ Always include
data_schemawhen creating widgets. This ensures:
- Data validation on cache POSTs (400 on schema mismatch)
- Clear documentation of expected data structure
- AI agents know the exact format to produce
POST /api/widgets/instances
Content-Type: application/json
{
"type": "custom",
"title": "GitHub PRs",
"custom_widget_id": "cw_abc123",
"config": { "owner": "acfranzen", "repo": "libra" }
}POST /api/widgets/github-prs/cache
Content-Type: application/json
{
"data": {
"prs": [...],
"fetchedAt": "2026-02-03T14:00:00Z"
}
}⚠️ If the widget has a dataSchema, the cache endpoint validates your data against it. Bad data returns 400 with details. Always check the widget's schema before POSTing:
GET /api/widgets/github-prs
# Response includes dataSchema showing required fields and types⚠️ MANDATORY: Every widget creation and refresh MUST end with browser verification.
Never consider a widget "done" until you've visually confirmed it renders correctly on the dashboard.
// REQUIRED: Open dashboard and verify widget renders
browser({
action: 'open',
targetUrl: 'http://localhost:3333',
profile: 'openclaw'
});
// Take a snapshot and check the widget
browser({ action: 'snapshot' });
// Look for:
// 1. Widget is visible on the dashboard
// 2. Shows actual data, NOT "Waiting for data..." or loading spinner
// 3. Data values match what was pushed to cache
// 4. No error messages displayed
// 5. Layout looks correct (not broken/overlapping)Verification checklist (must ALL be true):
Common issues and fixes:
| Symptom | Cause | Fix |
|---|---|---|
| "Waiting for data..." | Cache empty | POST data to /api/widgets/{slug}/cache |
| Widget not visible | Not added to dashboard | POST /api/widgets/instances |
| Wrong/old data | Slug mismatch | Check slug matches between definition and cache POST |
| Broken layout | Bad JSX in source_code | Check widget code for syntax errors |
| "No data" after POST | Schema validation failed | Check data matches data_schema |
If verification fails, fix the issue before reporting success.
For agent_refresh widgets, use serverData prop (NOT useData hook):
function Widget({ serverData }) {
const data = serverData;
const loading = !serverData;
const error = serverData?.error;
if (loading) return <Loading message="Waiting for data..." />;
if (error) return <ErrorDisplay message={error} />;
// NOTE: Do NOT wrap in <Card> - the framework wrapper (CustomWidgetWrapper)
// already provides the outer card with title, refresh button, and footer.
// Just render your content directly.
return (
<div className="space-y-3">
<List items={data.prs?.map(pr => ({
title: pr.title,
subtitle: `#${pr.number} by ${pr.author}`,
badge: pr.state
})) || []} />
</div>
);
}Important: The widget wrapper (CustomWidgetWrapper) provides:
<Card> container with header (widget title)Your widget code should just render the content — no Card, no CardHeader, no footer.
Key difference: agent_refresh widgets receive data via serverData prop, NOT by calling useData(). The agent pushes data to /api/widgets/{slug}/cache.
Prefer agent_refresh over server_code. Only use server_code when the widget MUST execute code at render time (rare).
// Only for fetch.type = "server_code" widgets
const token = await getCredential('github');
const response = await fetch('https://api.github.com/repos/owner/repo/pulls', {
headers: { 'Authorization': `Bearer ${token}` }
});
return await response.json();Available: fetch, getCredential(provider), params, console
Blocked: require, eval, fs, process, global
⚠️ CRITICAL: For agent_refresh widgets, YOU (the OpenClaw agent) are the data collector.
This is NOT an external API or service. YOU must:
┌─────────────────────────────────────────────────────────────┐
│ Cron fires → Agent wakes up → Agent collects data → │
│ Agent POSTs to /cache → Widget displays fresh data │
└─────────────────────────────────────────────────────────────┘fetch.type = "agent_refresh" and detailed fetch.instructionscron.add({
name: "Widget: My Data Refresh",
schedule: { kind: "cron", expr: "*/15 * * * *" },
payload: {
kind: "systemEvent",
text: "⚡ WIDGET REFRESH: my-widget" // Just the slug!
},
sessionTarget: "main" // Reminds YOU, not an isolated session
})fetch.instructions from the DB and spawn a subagent:// Parse slug from message
const slug = message.replace('⚡ WIDGET REFRESH:', '').trim();
// Query widget's fetch.instructions
const widget = db.query('SELECT fetch FROM custom_widgets WHERE slug = ?', slug);
// Spawn subagent with the instructions
sessions_spawn({ task: widget.fetch.instructions, model: 'haiku' });exec for shell commandsclaude /status)browser for web scrapingweb_fetchPOST /api/widgets/{slug}/cache
Content-Type: application/json
{
"data": {
"myValue": 42,
"fetchedAt": "2026-02-03T18:30:00.000Z"
}
}The fetch.instructions field is the single source of truth for how to collect widget data. Write them clearly so any subagent can follow them.
Required sections:
## Data Collection
Exact commands to run with full paths and flags.
Include PTY requirements if interactive.
## Data Transformation
Exact JSON structure expected.
Include field descriptions and examples.
## Cache Update
Full URL, required headers, body format.
## Browser Verification
Confirm the widget renders correctly.Good example:
## Data Collection
```bash
gog gmail search "in:inbox" --jsonTake first 5-8 emails, generate AI summary (3-5 words) for each:
{
"emails": [{"id": "...", "from": "...", "subject": "...", "summary": "AI summary here", "unread": true}],
"fetchedAt": "ISO timestamp"
}POST to: http://localhost:3333/api/widgets/recent-emails/cache
Header: Origin: http://localhost:3333
Body: { "data": <object above> }
Open http://localhost:3333 and confirm widget shows emails with AI summaries.
**Bad example (too vague):**Get emails and post to cache.
### Real Example: Claude Max Usage Widget
This widget shows Claude CLI usage stats. The data comes from running `claude` in a PTY and navigating to `/status → Usage`.
**The agent's job every 15 minutes:**
**This is YOUR responsibility as the agent.** The widget just displays whatever data is in the cache.
### Subagent Task Template for Refreshes
When spawning subagents for widget refreshes, always include browser verification:
```javascript
sessions_spawn({
task: `${fetchInstructions}
## REQUIRED: Browser Verification
After posting to cache, verify the widget renders correctly:
1. Open http://localhost:3333 in browser
2. Find the widget on the dashboard
3. Confirm it shows the data you just posted
4. Report any rendering issues
Do NOT report success until browser verification passes.`,
model: 'haiku',
label: `${slug}-refresh`
});POST /api/widgets/{slug}/cache
Content-Type: application/json
{
"data": {
"packages": 142,
"fetchedAt": "2026-02-03T18:30:00.000Z"
}
}For agent_refresh widgets, users can trigger immediate refreshes via the UI refresh button.
When configured with OPENCLAW_GATEWAY_URL and OPENCLAW_TOKEN environment variables, clicking the refresh button will:
/api/sessions/wakeThis eliminates the delay of waiting for the next heartbeat poll.
Environment variables (add to .env.local):
OPENCLAW_GATEWAY_URL=http://localhost:18789
OPENCLAW_TOKEN=your-gateway-tokenHow it works:
/api/widgets/{slug}/refresh⚡ WIDGET REFRESH: Refresh the "{slug}" widget now and POST to cacheResponse includes webhook status:
{
"status": "refresh_requested",
"webhook_sent": true,
"fallback_queued": true
}If webhook fails or isn't configured, the DB fallback ensures the next heartbeat/poll will pick it up.
fetchedAt timestamp
## Credential Requirements Format
### Credential Types
| Type | Storage | Description | Use For |
|------|---------|-------------|---------|
| `api_key` | Glance DB (encrypted) | API tokens stored in Glance | GitHub PAT, OpenWeather key |
| `local_software` | Agent's machine | Software that must be installed | Homebrew, Docker |
| `agent` | Agent environment | Auth that lives on the agent | `gh` CLI auth, `gcloud` auth |
| `oauth` | Glance DB | OAuth tokens (future) | Google Calendar |
### Examples
```json
{
"credentials": [
{
"id": "github",
"type": "api_key",
"name": "GitHub Personal Access Token",
"description": "Token with repo scope",
"obtain_url": "https://github.com/settings/tokens",
"obtain_instructions": "Create token with 'repo' scope"
},
{
"id": "homebrew",
"type": "local_software",
"name": "Homebrew",
"check_command": "which brew",
"install_url": "https://brew.sh"
},
{
"id": "github_cli",
"type": "agent",
"name": "GitHub CLI",
"description": "Agent needs gh CLI authenticated to GitHub",
"agent_tool": "gh",
"agent_auth_check": "gh auth status",
"agent_auth_instructions": "Run `gh auth login` on the machine running OpenClaw"
}
]
}When to use agent type: Use for agent_refresh widgets where the agent collects data using CLI tools that have their own auth (like gh, gcloud, aws). These credentials aren't stored in Glance — they exist in the agent's environment.
| Provider | ID | Description |
|---|---|---|
| GitHub | github | GitHub API (PAT with repo scope) |
| Anthropic | anthropic | Claude API (Admin key for usage) |
| OpenAI | openai | GPT API (Admin key for usage) |
| OpenWeather | openweather | Weather data API |
| Linear | linear | Linear API |
| Notion | notion | Notion API |
GET /api/widgets/{slug}/exportReturns: { "package": "!GW1!eJxVj8EKwj..." }
POST /api/widgets/import
Content-Type: application/json
{
"package": "!GW1!eJxVj8EKwj...",
"dry_run": false,
"auto_add_to_dashboard": true
}The !GW1! prefix indicates Glance Widget v1 format (compressed base64 JSON).
{
"valid": true,
"widget": { "id": "cw_abc", "slug": "homebrew-status" },
"cronSchedule": {
"expression": "*/15 * * * *",
"instructions": "Run brew list...",
"slug": "homebrew-status"
}
}When cronSchedule is returned, OpenClaw should register a cron job.
| Component | Use For |
|---|---|
Card | Widget container (always use className="h-full") |
List | Items with title/subtitle/badge |
Stat | Single metric with trend indicator |
Progress | Progress bars with variants |
Badge | Status labels (success/warning/error) |
Stack | Flexbox layout (row/column) |
Grid | CSS Grid layout |
Loading | Loading spinner |
ErrorDisplay | Error with retry button |
See references/components.md for full props.
// Fetch data (BOTH args required!)
const { data, loading, error, refresh } = useData('github', {});
const { data } = useData('github', { endpoint: '/pulls', params: { state: 'open' } });
// Get widget config
const config = useConfig();
// Widget-local state
const { state, setState } = useWidgetState('counter', 0);⚠️ useData requires both arguments. Pass empty {} if no query needed.
if (error?.code === 'CREDENTIAL_MISSING') {
return <Card><CardContent>
<Icons.Lock className="h-8 w-8" />
<p>GitHub token required</p>
</CardContent></Card>;
}Error codes: CREDENTIAL_MISSING, RATE_LIMITED, NETWORK_ERROR, API_ERROR
github-prs-libra not widget-1To summarize dashboard for user:
1. GET /api/widgets/instances → list instances
2. For each: POST /api/widgets/:slug/execute
3. Combine into natural language summarydocs/schemas/widget-schema.json enforces all required fields[] if no credentials neededDELETE /api/widgets/{slug}/refresh after handling| Variable | Description | Example |
|---|---|---|
GLANCE_URL | Glance server URL | http://localhost:3333 |
GLANCE_DATA | Path to SQLite database | /tmp/glance-test/data |
OPENCLAW_GATEWAY_URL | For webhook refresh notifications | https://localhost:18789 |
OPENCLAW_TOKEN | Gateway auth token | d551fe97... |
⚡ WIDGET REFRESH: {slug}, agent looks up instructionsgog calendar doesn't work for iCloud, use /opt/homebrew/bin/icalBuddywttr.in/City?format=j1© LeoYeAI, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 4 other files in skills/glance of LeoYeAI/openclaw-master-skills.
Open the folder on GitHubat commit e5199b5
Glance next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Glance this skillLeoYeAI/openclaw-master-skills | 2.2k | — | ~7.3k | Automated safety check: Notes | MIT | |
| Doc AuthorInsForge/InsForge | 13k | — | ~3.7k | Automated safety check: Pass | MIT | |
| Add AI Chat Toolryokun6/ryos | 1.3k | — | ~2.2k | Automated safety check: Pass | AGPL-3.0 | |
| Benchmarksamchon/typia | 5.9k | — | ~1.2k | Automated safety check: Pass | MIT | |
| Agent Interface DesignNeeeophytee/finding-unknowns-skills | 343 | — | ~650 | Automated safety check: Pass | MIT | |
| Search Benchmarkagentic-community/mcp-gateway-registry | 967 | — | ~1.9k | Automated safety check: Pass | Apache-2.0 |
InsForge/InsForge
Write, edit, and maintain documentation. An agent skill from InsForge/InsForge.
ryokun6/ryos
Add or modify an AI chat tool ("Ask Ryo" capability) in ryOS.
samchon/typia
Defines typia benchmark fixture integrity, result reporting, and publication safeguards.
Neeeophytee/finding-unknowns-skills
Design tools, scripts, and CLIs that an agent will call, so the interface teaches its own use instead of a wall of prose and examples.
agentic-community/mcp-gateway-registry
Generate a search quality benchmark for the AI Registry. An agent skill from agentic-community/mcp-gateway-registry.
ljxpython/ai-agent-platform
AI 在项目文档(docs/projects/{YYYYMMDD}-{项目名}/)已存在时,实现任务过程中自动调用(不需要用户手动触发),记录改动细节到 implementation/ 目录。跳过条件:单项目改动的小改动不需要创建实现记录。
LeoYeAI/openclaw-master-skills
Manages pipelines on a DevOps quality and efficiency platform through its OpenAPI: list workspaces and templates, create, update, run and cancel pipelines, and read run records.
LeoYeAI/openclaw-master-skills
Patches OpenClaw's Feishu extension so an edited document triggers an isolated agent session that reads the doc and replies inline, turning it into a live chat space.
LeoYeAI/openclaw-master-skills
Multi-context memory management system for OpenClaw agents with group-isolated storage, global shared memory, workspace organization, and group-specific skills isolation.
LeoYeAI/openclaw-master-skills
Runs a brand's AI-search visibility work end to end: diagnosing how AI platforms represent it, repositioning it, producing AI-optimized content and monitoring ongoing mentions.
LeoYeAI/openclaw-master-skills
Installs and authenticates the gws CLI, then automates Gmail, Drive, Sheets, Calendar, Docs, Chat and Tasks with ready-made recipes, persona bundles and security audits.
LeoYeAI/openclaw-master-skills
Runs four advisor roles, a fitness coach, nutritionist, data analyst and TCM practitioner, to build a health profile and track workouts, diet and wellness over time.
Categories
Create, update, and manage Glance dashboard widgets. An agent skill from LeoYeAI/openclaw-master-skills. Glance is an agent skill from LeoYeAI/openclaw-master-skills. Create, update, and manage Glance dashboard widgets.
Glance fits situations like: user wants to: add something to their dashboard; create a widget; track data visually; show metrics/stats.
Run `npx skills add LeoYeAI/openclaw-master-skills --skill glance -a claude-code`. Or copy the skill folder (skills/glance in LeoYeAI/openclaw-master-skills) into .claude/skills/glance in your project. Claude Code loads it when a task matches its description.
Run `npx skills add LeoYeAI/openclaw-master-skills --skill glance -a codex`. Or copy the skill folder (skills/glance in LeoYeAI/openclaw-master-skills) into .agents/skills/glance in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add LeoYeAI/openclaw-master-skills --skill glance -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/glance, .gemini/skills/glance, .github/skills/glance and .opencode/skills/glance in your project.
Going by SKILL.md and its folder, Glance needs the command-line tools its instructions call (npm, curl, git, jq, sqlite3 and claude) and credentials named OPENCLAW_TOKEN, AUTH_TOKEN and GLANCE_TOKEN. Our summary lists: Node.js; A credential in AUTH_TOKEN; A credential in OPENCLAW_TOKEN.
SKILL.md names 4 domains. In commands or code: github.com, apple.com, api.github.com and brew.sh; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.
Glance is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 7.3k tokens (SKILL.md is roughly 29k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Glance: Doc Author (InsForge/InsForge, 13k stars), Add AI Chat Tool (ryokun6/ryos, 1.3k stars), Benchmark (samchon/typia, 5.9k stars) and Agent Interface Design (Neeeophytee/finding-unknowns-skills, 343 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
LeoYeAI (a GitHub user) maintains it in LeoYeAI/openclaw-master-skills, which has 2,160 GitHub stars. The repository holds 1,235 skills in this directory. The repository was last updated on July 20, 2026.
Source: LeoYeAI/openclaw-master-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.