core/willow-seed/SKILL.md
# Willow Seed — SAFE App Scaffold Skill **Version 1.0.0** ## What This Is The Willow Seed skill lets you bootstrap a SAFE-compliant app using Claude directly. No bat files. No unknown repos to clone. Claude generates the scaffold inline, in your conversation, and you copy it where you need it. SAFE apps are local-first apps that use session-based consent: the app asks permission each time it opens, and that permission expires when you close it. Your data stays on your machine. --- ## When
npx skillsauth add rudi193-cmd/aionic-claude-skills core/willow-seedInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Version 1.0.0
The Willow Seed skill lets you bootstrap a SAFE-compliant app using Claude directly. No bat files. No unknown repos to clone. Claude generates the scaffold inline, in your conversation, and you copy it where you need it.
SAFE apps are local-first apps that use session-based consent: the app asks permission each time it opens, and that permission expires when you close it. Your data stays on your machine.
Activate when a user asks to:
Ask the user:
safe-app-{name})Generate safe-app-manifest.json using this exact structure:
{
"app_id": "{slug}",
"name": "{App Name}",
"version": "0.1.0",
"safe_version": ">=2.0.0",
"description": "{one sentence description}",
"author": "{user's name or 'Community'}",
"data_streams": [
{
"id": "{stream_id}",
"purpose": "{what this data is used for}",
"retention": "{session|permanent}",
"description": "{what happens to it — deleted on session end, or kept until user deletes}"
}
],
"permissions": [
"local_llm",
"{other_permissions}"
],
"privacy_tier": "{client_only|mixed}",
"local_processing": 0.96,
"entry_point": "{module.main:app}",
"license": "MIT",
"repository": "https://github.com/{username}/safe-app-{slug}"
}
Retention rules:
session — data is deleted when the app closes (good for: queries, temp analysis, uploads)permanent — data persists until the user explicitly deletes it (good for: saved notes, preferences, learned patterns)Permission options:
local_llm — uses a local AI modelfile_read — reads files from the user's machinefile_write — writes files to the user's machinenetwork_read — fetches from the internet (read-only)image_ocr — processes imagesknowledge_graph — reads/writes to the Willow knowledge graphbinder_write — deposits findings into The Binder (requires Binder consent separately)Privacy tier:
client_only — nothing leaves the machinemixed — some network reads (specify what and why)Generate safe_integration.py using this template, customized for the app's data streams:
"""
SAFE Framework Integration — {App Name}
=========================================
{One sentence about what the app does and what data it touches.}
"""
from typing import Dict
from datetime import datetime
APP_STREAMS = [
# One entry per data_stream from the manifest
{
"stream_id": "{id}",
"purpose": "{purpose}",
"retention": "{session|permanent}",
"required": {True|False},
"prompt": "May I {brief action} this session?"
}
]
class SAFESession:
def __init__(self, session_id: str):
self.session_id = session_id
self.started_at = datetime.now()
self.consents = {}
self.active = True
def on_session_start(self) -> Dict:
return {
"session_id": self.session_id,
"authorization_requests": APP_STREAMS
}
def on_consent_granted(self, stream_id: str, granted: bool) -> Dict:
self.consents[stream_id] = {
"granted": granted,
"timestamp": datetime.now().isoformat()
}
required = next((s for s in APP_STREAMS if s["stream_id"] == stream_id and s.get("required")), None)
if not granted and required:
return {"status": "consent_required", "message": f"This app requires consent for {stream_id}."}
return {"status": "ok"}
def can_access_stream(self, stream_id: str) -> bool:
return self.consents.get(stream_id, {}).get("granted", False)
def on_session_end(self) -> Dict:
self.active = False
actions = []
for stream in APP_STREAMS:
sid = stream["stream_id"]
if self.can_access_stream(sid):
retention = stream.get("retention", "session")
actions.append({
"action": "retain" if retention == "permanent" else "delete",
"stream": sid,
"reason": "permanent_consent" if retention == "permanent" else "session_ended"
})
return {
"session_id": self.session_id,
"ended_at": datetime.now().isoformat(),
"duration_seconds": (datetime.now() - self.started_at).total_seconds(),
"cleanup_actions": actions
}
def on_revoke(self, stream_id: str) -> Dict:
if stream_id in self.consents:
self.consents[stream_id]["granted"] = False
self.consents[stream_id]["revoked_at"] = datetime.now().isoformat()
return {"status": "revoked", "stream": stream_id, "action": "data_deleted"}
After generating the files, give the user this checklist:
Your SAFE app scaffold is ready. Here's what to do next:
[ ] Create your app directory: mkdir safe-app-{name}
[ ] Save safe-app-manifest.json into that directory
[ ] Save safe_integration.py into that directory
[ ] Build your app code — entry point: {entry_point}
[ ] If you have a Willow node running (http://localhost:8420):
POST /api/opauth/register with your manifest to register the app
[ ] When ready to share: push to GitHub as safe-app-{name}
SAFE principles to keep in mind:
- Ask consent every session. Never assume it carries over.
- Store only what you declared in the manifest.
- Session-retention data must be deleted on close. No exceptions.
- The user can revoke at any time — handle on_revoke() gracefully.
Part of the Willow / Aionic ecosystem. ΔΣ=42
development
Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.
tools
Suggests manual context compaction at logical intervals to preserve context through task phases rather than arbitrary auto-compaction.
tools
System status — atoms, edges, ratio, boot health, unpushed work, open threads
tools
Manual session startup — when boot hooks are degraded, run the bridge-open sequence manually