feat: add managed skills gating
This commit is contained in:
15
skills/agent-tools/SKILL.md
Normal file
15
skills/agent-tools/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: agent-tools
|
||||
description: Utility toolkit for automations and MCP-friendly scripts.
|
||||
metadata: {"clawdis":{"requires":{"bins":["agent-tools"]}}}
|
||||
---
|
||||
|
||||
# agent-tools
|
||||
|
||||
Use `agent-tools` for helper utilities and automations. Start with:
|
||||
|
||||
```bash
|
||||
agent-tools --help
|
||||
```
|
||||
|
||||
Prefer small, composable commands.
|
||||
19
skills/bird/SKILL.md
Normal file
19
skills/bird/SKILL.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
name: bird
|
||||
description: X/Twitter CLI to tweet, reply, read threads, and search.
|
||||
metadata: {"clawdis":{"requires":{"bins":["bird"]}}}
|
||||
---
|
||||
|
||||
# bird
|
||||
|
||||
Use `bird` to interact with X/Twitter.
|
||||
|
||||
- Tweet: `bird tweet "..."`
|
||||
- Reply: `bird reply <tweet-id> "..."`
|
||||
- Read: `bird read <tweet-id>`
|
||||
- Thread: `bird thread <tweet-id>`
|
||||
- Search: `bird search "query"`
|
||||
- Mentions: `bird mentions`
|
||||
- Whoami: `bird whoami`
|
||||
|
||||
Confirm before posting publicly.
|
||||
15
skills/blucli/SKILL.md
Normal file
15
skills/blucli/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: blucli
|
||||
description: Control BluOS players from the CLI.
|
||||
metadata: {"clawdis":{"requires":{"bins":["blucli"]}}}
|
||||
---
|
||||
|
||||
# blucli
|
||||
|
||||
Use `blucli` to control BluOS players. Start with:
|
||||
|
||||
```bash
|
||||
blucli --help
|
||||
```
|
||||
|
||||
Confirm target player before changing playback.
|
||||
15
skills/camsnap/SKILL.md
Normal file
15
skills/camsnap/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: camsnap
|
||||
description: Capture frames or clips from RTSP/ONVIF cameras.
|
||||
metadata: {"clawdis":{"requires":{"bins":["camsnap"]}}}
|
||||
---
|
||||
|
||||
# camsnap
|
||||
|
||||
Use `camsnap` to grab frames or clips from configured cameras. Start with:
|
||||
|
||||
```bash
|
||||
camsnap --help
|
||||
```
|
||||
|
||||
Prefer small test captures before longer clips.
|
||||
18
skills/clawdis-browser/SKILL.md
Normal file
18
skills/clawdis-browser/SKILL.md
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
name: clawdis-browser
|
||||
description: Control clawd's dedicated browser (tabs, snapshots, actions) via the clawdis CLI.
|
||||
metadata: {"clawdis":{"requires":{"config":["browser.enabled"]}}}
|
||||
---
|
||||
|
||||
# Clawdis Browser
|
||||
|
||||
Use the clawd-managed Chrome/Chromium instance through `clawdis browser` commands.
|
||||
|
||||
## Common commands
|
||||
|
||||
- Status/start/stop: `clawdis browser status|start|stop`
|
||||
- Tabs: `clawdis browser tabs|open <url>|focus <id>|close <id>`
|
||||
- Snapshot/screenshot: `clawdis browser snapshot --format ai|aria`, `clawdis browser screenshot [--full-page]`
|
||||
- Actions: `clawdis browser click|type|hover|drag|select|upload|press|wait|navigate|back|evaluate|run`
|
||||
|
||||
If disabled, ask the user to enable `browser.enabled` in `~/.clawdis/clawdis.json`.
|
||||
22
skills/clawdis-canvas/SKILL.md
Normal file
22
skills/clawdis-canvas/SKILL.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
name: clawdis-canvas
|
||||
description: Drive the Clawdis Canvas panel (present, eval, snapshot, A2UI) via the clawdis CLI.
|
||||
metadata: {"clawdis":{"always":true}}
|
||||
---
|
||||
|
||||
# Clawdis Canvas
|
||||
|
||||
Use Canvas to render HTML/JS or A2UI surfaces and capture snapshots.
|
||||
|
||||
## Core commands
|
||||
|
||||
- Show/hide: `clawdis canvas present [--node <id>] [--target <path>]`, `clawdis canvas hide`
|
||||
- JS eval: `clawdis canvas eval --js "..."`
|
||||
- Snapshot: `clawdis canvas snapshot`
|
||||
|
||||
## A2UI
|
||||
|
||||
- Push JSONL: `clawdis canvas a2ui push --jsonl /path/to/file.jsonl`
|
||||
- Reset: `clawdis canvas a2ui reset`
|
||||
|
||||
If targeting remote nodes, use the canvas host (LAN/tailnet) and keep HTML under `~/clawd/canvas`.
|
||||
15
skills/eightctl/SKILL.md
Normal file
15
skills/eightctl/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: eightctl
|
||||
description: Control sleep workflows with eightctl.
|
||||
metadata: {"clawdis":{"requires":{"bins":["eightctl"]}}}
|
||||
---
|
||||
|
||||
# eightctl
|
||||
|
||||
Use `eightctl` for sleep/wake automation. Start with:
|
||||
|
||||
```bash
|
||||
eightctl --help
|
||||
```
|
||||
|
||||
Confirm before scheduling disruptive actions.
|
||||
15
skills/gemini-cli/SKILL.md
Normal file
15
skills/gemini-cli/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: gemini-cli
|
||||
description: Use the Gemini CLI for fast Q&A and generation.
|
||||
metadata: {"clawdis":{"requires":{"bins":["gemini"]}}}
|
||||
---
|
||||
|
||||
# Gemini CLI
|
||||
|
||||
Use `gemini` for quick prompts. Start with:
|
||||
|
||||
```bash
|
||||
gemini --help
|
||||
```
|
||||
|
||||
If auth is required, set the provider's API key in the environment.
|
||||
15
skills/gog/SKILL.md
Normal file
15
skills/gog/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: gog
|
||||
description: Google Suite CLI for Gmail, Calendar, Drive, and Contacts.
|
||||
metadata: {"clawdis":{"requires":{"bins":["gog"]}}}
|
||||
---
|
||||
|
||||
# gog
|
||||
|
||||
Use `gog` for Gmail/Calendar/Drive/Contacts. Start with:
|
||||
|
||||
```bash
|
||||
gog --help
|
||||
```
|
||||
|
||||
Ask for confirmation before sending emails or creating events.
|
||||
15
skills/imsg/SKILL.md
Normal file
15
skills/imsg/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: imsg
|
||||
description: Send or read iMessage/SMS using the imsg CLI.
|
||||
metadata: {"clawdis":{"requires":{"bins":["imsg"]}}}
|
||||
---
|
||||
|
||||
# imsg
|
||||
|
||||
Use `imsg` for iMessage/SMS. Start with:
|
||||
|
||||
```bash
|
||||
imsg --help
|
||||
```
|
||||
|
||||
Confirm recipients and message text before sending.
|
||||
15
skills/mcporter/SKILL.md
Normal file
15
skills/mcporter/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: mcporter
|
||||
description: Manage MCP servers (install, list, sync) with mcporter.
|
||||
metadata: {"clawdis":{"requires":{"bins":["mcporter"]}}}
|
||||
---
|
||||
|
||||
# mcporter
|
||||
|
||||
Use the `mcporter` CLI to install, list, and sync MCP servers. Start with:
|
||||
|
||||
```bash
|
||||
mcporter --help
|
||||
```
|
||||
|
||||
If the tool is missing, ask the user to install it from the Tools tab.
|
||||
42
skills/nano-banana-pro/SKILL.md
Normal file
42
skills/nano-banana-pro/SKILL.md
Normal file
@@ -0,0 +1,42 @@
|
||||
---
|
||||
name: nano-banana-pro
|
||||
description: Generate or edit images via Gemini 3 Pro Image (Nano Banana Pro).
|
||||
metadata: {"clawdis":{"requires":{"env":["GEMINI_API_KEY"]},"primaryEnv":"GEMINI_API_KEY"}}
|
||||
---
|
||||
|
||||
# Nano Banana Pro Image Generation & Editing
|
||||
|
||||
Generate new images or edit existing ones using Google's Nano Banana Pro API.
|
||||
|
||||
## Usage (always run from the current working directory)
|
||||
|
||||
**Generate new image:**
|
||||
```bash
|
||||
uv run {baseDir}/scripts/generate_image.py --prompt "your image description" --filename "output-name.png" [--resolution 1K|2K|4K]
|
||||
```
|
||||
|
||||
**Edit existing image:**
|
||||
```bash
|
||||
uv run {baseDir}/scripts/generate_image.py --prompt "editing instructions" --filename "output-name.png" --input-image "path/to/input.png" [--resolution 1K|2K|4K]
|
||||
```
|
||||
|
||||
## API key
|
||||
|
||||
The script uses:
|
||||
1) `GEMINI_API_KEY` environment variable
|
||||
2) `--api-key` argument (optional)
|
||||
|
||||
If the key is missing, check `skills."nano-banana-pro".apiKey` or `skills."nano-banana-pro".env.GEMINI_API_KEY` in `~/.clawdis/clawdis.json`, or ask the user to provide one.
|
||||
|
||||
## Resolution
|
||||
|
||||
- `1K` (default), `2K`, `4K`
|
||||
- Map user intent: low/1080 → `1K`, medium/2K → `2K`, high/ultra/4K → `4K`
|
||||
|
||||
## Filename
|
||||
|
||||
Use `{timestamp}-{short-name}.png` (yyyy-mm-dd-hh-mm-ss, lowercase, hyphens).
|
||||
|
||||
## Output
|
||||
|
||||
Do **not** read the image back; just report the saved path.
|
||||
167
skills/nano-banana-pro/scripts/generate_image.py
Executable file
167
skills/nano-banana-pro/scripts/generate_image.py
Executable file
@@ -0,0 +1,167 @@
|
||||
#!/usr/bin/env python3
|
||||
# /// script
|
||||
# requires-python = ">=3.10"
|
||||
# dependencies = [
|
||||
# "google-genai>=1.0.0",
|
||||
# "pillow>=10.0.0",
|
||||
# ]
|
||||
# ///
|
||||
"""
|
||||
Generate images using Google's Nano Banana Pro (Gemini 3 Pro Image) API.
|
||||
|
||||
Usage:
|
||||
uv run generate_image.py --prompt "your image description" --filename "output.png" [--resolution 1K|2K|4K] [--api-key KEY]
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def get_api_key(provided_key: str | None) -> str | None:
|
||||
"""Get API key from argument first, then environment."""
|
||||
if provided_key:
|
||||
return provided_key
|
||||
return os.environ.get("GEMINI_API_KEY")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate images using Nano Banana Pro (Gemini 3 Pro Image)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--prompt", "-p",
|
||||
required=True,
|
||||
help="Image description/prompt"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--filename", "-f",
|
||||
required=True,
|
||||
help="Output filename (e.g., sunset-mountains.png)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--input-image", "-i",
|
||||
help="Optional input image path for editing/modification"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--resolution", "-r",
|
||||
choices=["1K", "2K", "4K"],
|
||||
default="1K",
|
||||
help="Output resolution: 1K (default), 2K, or 4K"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--api-key", "-k",
|
||||
help="Gemini API key (overrides GEMINI_API_KEY env var)"
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Get API key
|
||||
api_key = get_api_key(args.api_key)
|
||||
if not api_key:
|
||||
print("Error: No API key provided.", file=sys.stderr)
|
||||
print("Please either:", file=sys.stderr)
|
||||
print(" 1. Provide --api-key argument", file=sys.stderr)
|
||||
print(" 2. Set GEMINI_API_KEY environment variable", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Import here after checking API key to avoid slow import on error
|
||||
from google import genai
|
||||
from google.genai import types
|
||||
from PIL import Image as PILImage
|
||||
|
||||
# Initialise client
|
||||
client = genai.Client(api_key=api_key)
|
||||
|
||||
# Set up output path
|
||||
output_path = Path(args.filename)
|
||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Load input image if provided
|
||||
input_image = None
|
||||
output_resolution = args.resolution
|
||||
if args.input_image:
|
||||
try:
|
||||
input_image = PILImage.open(args.input_image)
|
||||
print(f"Loaded input image: {args.input_image}")
|
||||
|
||||
# Auto-detect resolution if not explicitly set by user
|
||||
if args.resolution == "1K": # Default value
|
||||
# Map input image size to resolution
|
||||
width, height = input_image.size
|
||||
max_dim = max(width, height)
|
||||
if max_dim >= 3000:
|
||||
output_resolution = "4K"
|
||||
elif max_dim >= 1500:
|
||||
output_resolution = "2K"
|
||||
else:
|
||||
output_resolution = "1K"
|
||||
print(f"Auto-detected resolution: {output_resolution} (from input {width}x{height})")
|
||||
except Exception as e:
|
||||
print(f"Error loading input image: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Build contents (image first if editing, prompt only if generating)
|
||||
if input_image:
|
||||
contents = [input_image, args.prompt]
|
||||
print(f"Editing image with resolution {output_resolution}...")
|
||||
else:
|
||||
contents = args.prompt
|
||||
print(f"Generating image with resolution {output_resolution}...")
|
||||
|
||||
try:
|
||||
response = client.models.generate_content(
|
||||
model="gemini-3-pro-image-preview",
|
||||
contents=contents,
|
||||
config=types.GenerateContentConfig(
|
||||
response_modalities=["TEXT", "IMAGE"],
|
||||
image_config=types.ImageConfig(
|
||||
image_size=output_resolution
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
# Process response and convert to PNG
|
||||
image_saved = False
|
||||
for part in response.parts:
|
||||
if part.text is not None:
|
||||
print(f"Model response: {part.text}")
|
||||
elif part.inline_data is not None:
|
||||
# Convert inline data to PIL Image and save as PNG
|
||||
from io import BytesIO
|
||||
|
||||
# inline_data.data is already bytes, not base64
|
||||
image_data = part.inline_data.data
|
||||
if isinstance(image_data, str):
|
||||
# If it's a string, it might be base64
|
||||
import base64
|
||||
image_data = base64.b64decode(image_data)
|
||||
|
||||
image = PILImage.open(BytesIO(image_data))
|
||||
|
||||
# Ensure RGB mode for PNG (convert RGBA to RGB with white background if needed)
|
||||
if image.mode == 'RGBA':
|
||||
rgb_image = PILImage.new('RGB', image.size, (255, 255, 255))
|
||||
rgb_image.paste(image, mask=image.split()[3])
|
||||
rgb_image.save(str(output_path), 'PNG')
|
||||
elif image.mode == 'RGB':
|
||||
image.save(str(output_path), 'PNG')
|
||||
else:
|
||||
image.convert('RGB').save(str(output_path), 'PNG')
|
||||
image_saved = True
|
||||
|
||||
if image_saved:
|
||||
full_path = output_path.resolve()
|
||||
print(f"\nImage saved: {full_path}")
|
||||
else:
|
||||
print("Error: No image was generated in the response.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error generating image: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
15
skills/openai-whisper/SKILL.md
Normal file
15
skills/openai-whisper/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: openai-whisper
|
||||
description: Local speech-to-text using OpenAI Whisper CLI.
|
||||
metadata: {"clawdis":{"requires":{"bins":["whisper"]}}}
|
||||
---
|
||||
|
||||
# OpenAI Whisper (CLI)
|
||||
|
||||
Use `whisper` for local speech-to-text. Start with:
|
||||
|
||||
```bash
|
||||
whisper --help
|
||||
```
|
||||
|
||||
Prefer small files first; keep outputs in the current working directory.
|
||||
15
skills/openhue/SKILL.md
Normal file
15
skills/openhue/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: openhue
|
||||
description: Control Philips Hue lights and scenes via CLI.
|
||||
metadata: {"clawdis":{"requires":{"bins":["openhue"]}}}
|
||||
---
|
||||
|
||||
# OpenHue CLI
|
||||
|
||||
Use `openhue` to control Hue lights/scenes. Start with:
|
||||
|
||||
```bash
|
||||
openhue --help
|
||||
```
|
||||
|
||||
Prefer listing lights/scenes before toggling.
|
||||
15
skills/oracle/SKILL.md
Normal file
15
skills/oracle/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: oracle
|
||||
description: Run a second-model review or debug session with the oracle CLI.
|
||||
metadata: {"clawdis":{"requires":{"bins":["oracle"]}}}
|
||||
---
|
||||
|
||||
# oracle
|
||||
|
||||
Use `oracle` to run a second-model review or debugging pass.
|
||||
|
||||
```bash
|
||||
oracle --help
|
||||
```
|
||||
|
||||
If the binary is missing, use `npx -y @steipete/oracle --help`.
|
||||
20
skills/peekaboo/SKILL.md
Normal file
20
skills/peekaboo/SKILL.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: peekaboo
|
||||
description: Capture and inspect macOS UI via the Peekaboo CLI.
|
||||
metadata: {"clawdis":{"requires":{"bins":["peekaboo"]}}}
|
||||
---
|
||||
|
||||
# Peekaboo
|
||||
|
||||
Fast UI capture and inspection.
|
||||
|
||||
## Common commands
|
||||
|
||||
- Capture: `peekaboo capture`
|
||||
- Inspect: `peekaboo see`
|
||||
- Click: `peekaboo click`
|
||||
- List windows: `peekaboo list`
|
||||
- Tool info: `peekaboo tools`
|
||||
- Permissions: `peekaboo permissions status`
|
||||
|
||||
Requires Screen Recording + Accessibility permissions.
|
||||
15
skills/qmd/SKILL.md
Normal file
15
skills/qmd/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: qmd
|
||||
description: Search notes/content with qmd (BM25 + vectors + rerank).
|
||||
metadata: {"clawdis":{"requires":{"bins":["qmd"]}}}
|
||||
---
|
||||
|
||||
# qmd
|
||||
|
||||
Use `qmd` to search local content. Start with:
|
||||
|
||||
```bash
|
||||
qmd --help
|
||||
```
|
||||
|
||||
Use concise queries and refine with filters if available.
|
||||
15
skills/sag/SKILL.md
Normal file
15
skills/sag/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: sag
|
||||
description: ElevenLabs text-to-speech with mac-style say UX.
|
||||
metadata: {"clawdis":{"requires":{"bins":["sag"]}}}
|
||||
---
|
||||
|
||||
# sag
|
||||
|
||||
Use `sag` to speak or stream text to speakers. Start with:
|
||||
|
||||
```bash
|
||||
sag --help
|
||||
```
|
||||
|
||||
Confirm the voice/speaker before long output.
|
||||
17
skills/sonoscli/SKILL.md
Normal file
17
skills/sonoscli/SKILL.md
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
name: sonoscli
|
||||
description: Control Sonos speakers (discover/status/play/volume/group).
|
||||
metadata: {"clawdis":{"requires":{"bins":["sonos"]}}}
|
||||
---
|
||||
|
||||
# Sonos CLI
|
||||
|
||||
Use `sonos` to control Sonos speakers.
|
||||
|
||||
- Discover: `sonos discover`
|
||||
- Status: `sonos status`
|
||||
- Playback: `sonos play|pause|stop`
|
||||
- Volume: `sonos volume set <0-100>`
|
||||
- Group: `sonos group <leader> <member>`
|
||||
|
||||
If SSDP fails, specify `--ip <speaker-ip>`.
|
||||
15
skills/spotify-player/SKILL.md
Normal file
15
skills/spotify-player/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: spotify-player
|
||||
description: Control Spotify playback from the terminal.
|
||||
metadata: {"clawdis":{"requires":{"bins":["spotify-player"]}}}
|
||||
---
|
||||
|
||||
# spotify-player
|
||||
|
||||
Use `spotify-player` to search, queue, and control playback.
|
||||
|
||||
```bash
|
||||
spotify-player --help
|
||||
```
|
||||
|
||||
Confirm the device/target if multiple are available.
|
||||
15
skills/wacli/SKILL.md
Normal file
15
skills/wacli/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: wacli
|
||||
description: WhatsApp CLI for syncing, searching, and sending messages.
|
||||
metadata: {"clawdis":{"requires":{"bins":["wacli"]}}}
|
||||
---
|
||||
|
||||
# wacli
|
||||
|
||||
Use `wacli` to sync/search/send WhatsApp messages. Start with:
|
||||
|
||||
```bash
|
||||
wacli --help
|
||||
```
|
||||
|
||||
Confirm before sending messages.
|
||||
Reference in New Issue
Block a user