mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-08 02:14:37 +00:00
feat(templates): promote examples/ to templates/<author>/<name>/ catalog layout
Set up the catalog directory structure this branch will fill with community templates. The existing site-status-checker example moves from examples/templates/ to templates/awizemann/site-status-checker/ (tracked by git as a rename so history is preserved). The examples/ directory is removed. New top-level docs: - templates/README.md — landing for folks browsing the catalog on github.com. Lists the current templates and points at the live site. - templates/CONTRIBUTING.md — author-facing submission walkthrough. Requires AGENTS.md, pre-flight with tools/build-catalog.py --check (added in the next commit), one template per PR, don't edit catalog.json (maintainer regenerates it post-merge). ProjectTemplateExampleTemplateTests.locateExample updated to search templates/<author>/<name>/ instead of examples/templates/ — the test still walks up from #filePath to find the repo root so it works in both xcodebuild and Xcode IDE test runs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,37 +0,0 @@
|
||||
# Example Templates
|
||||
|
||||
This directory holds reference `.scarftemplate` bundles shipped in the Scarf repo. Each subdirectory is one template, laid out as:
|
||||
|
||||
```
|
||||
<template-name>/
|
||||
├── staging/ Source tree — the exact layout of the bundle
|
||||
│ ├── template.json
|
||||
│ ├── README.md
|
||||
│ ├── AGENTS.md
|
||||
│ ├── dashboard.json
|
||||
│ ├── cron/jobs.json (optional)
|
||||
│ ├── skills/<name>/… (optional)
|
||||
│ ├── instructions/… (optional)
|
||||
│ └── memory/append.md (optional)
|
||||
└── <template-name>.scarftemplate Built bundle (zipped staging dir)
|
||||
```
|
||||
|
||||
## Available templates
|
||||
|
||||
- **[site-status-checker](site-status-checker/)** — daily HTTP uptime check for a user-editable list of URLs. Dashboard + cron + AGENTS.md. The simplest example that exercises the full format.
|
||||
|
||||
## Rebuilding a bundle after editing
|
||||
|
||||
```bash
|
||||
cd <template-name>/staging
|
||||
zip -qq -r ../<template-name>.scarftemplate .
|
||||
```
|
||||
|
||||
The Scarf test suite (`ProjectTemplateExampleTemplateTests`) validates each shipped `.scarftemplate` on every build, so a bundle that fails to round-trip through `inspect → buildPlan` will fail CI.
|
||||
|
||||
## Authoring conventions
|
||||
|
||||
- **Always ship `AGENTS.md`.** It's the Linux Foundation cross-agent standard ([agents.md](https://agents.md/)) and every supported agent reads it. Agent-specific shims (`CLAUDE.md`, `GEMINI.md`, `.cursorrules`, `.github/copilot-instructions.md`) go under `instructions/` and only when there's a real per-agent behavior the author needs.
|
||||
- **Cron jobs ship paused.** Don't assume the user wants your job running on install. Write the prompt so running it manually from chat (`"run the X job"`) also works — the cron is just a schedule wrapper.
|
||||
- **Dashboard values that change at runtime should be placeholders.** The agent (not the installer) keeps them fresh. Start with sensible zeros / "never" / "unknown" so an uninstalled, inactive project still renders cleanly.
|
||||
- **Don't claim in the manifest what you don't ship.** The `contents` block is cross-checked against the unpacked files — a mismatch makes the installer refuse the bundle.
|
||||
@@ -490,7 +490,7 @@ import Foundation
|
||||
@Suite struct ProjectTemplateExampleTemplateTests {
|
||||
|
||||
@Test func siteStatusCheckerParsesAndPlans() throws {
|
||||
let bundle = try Self.locateExample(name: "site-status-checker")
|
||||
let bundle = try Self.locateExample(author: "awizemann", name: "site-status-checker")
|
||||
|
||||
let service = ProjectTemplateService(context: .local)
|
||||
let inspection = try service.inspect(zipPath: bundle)
|
||||
@@ -547,17 +547,19 @@ import Foundation
|
||||
/// Resolve the example bundle path robustly. Unit-test working dirs
|
||||
/// differ between `xcodebuild test` (project root) and an Xcode IDE
|
||||
/// run (build-output dir), so we walk up from this source file until
|
||||
/// we find the repo root.
|
||||
nonisolated private static func locateExample(name: String) throws -> String {
|
||||
/// we find the repo root. Templates live at
|
||||
/// `templates/<author>/<name>/<name>.scarftemplate` per the catalog
|
||||
/// layout (see `templates/README.md`).
|
||||
nonisolated private static func locateExample(author: String, name: String) throws -> String {
|
||||
var dir = URL(fileURLWithPath: #filePath).deletingLastPathComponent()
|
||||
for _ in 0..<6 {
|
||||
let candidate = dir.appendingPathComponent("examples/templates/\(name)/\(name).scarftemplate")
|
||||
let candidate = dir.appendingPathComponent("templates/\(author)/\(name)/\(name).scarftemplate")
|
||||
if FileManager.default.fileExists(atPath: candidate.path) {
|
||||
return candidate.path
|
||||
}
|
||||
dir = dir.deletingLastPathComponent()
|
||||
}
|
||||
throw ProjectTemplateError.requiredFileMissing("examples/templates/\(name)/\(name).scarftemplate")
|
||||
throw ProjectTemplateError.requiredFileMissing("templates/\(author)/\(name)/\(name).scarftemplate")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
# Contributing a template to Scarf
|
||||
|
||||
Thanks for packaging something up for other Scarf users. This guide walks you through the full submission flow end-to-end.
|
||||
|
||||
## Before you start
|
||||
|
||||
- You need Scarf 2.2 or later installed to build + test your template.
|
||||
- Your template must ship a cross-agent **`AGENTS.md`** — that's the Linux Foundation open standard ([agents.md](https://agents.md/)) every major coding agent reads. Templates without one are rejected; Scarf specifically supports agent-portable projects.
|
||||
- Templates are free and MIT-licensed implicitly by submission. Don't submit anything you don't have rights to.
|
||||
|
||||
## What makes a good template
|
||||
|
||||
- **Scoped.** One purpose per template. A "does-everything" template is harder to maintain than three focused ones.
|
||||
- **Agent-first.** The `AGENTS.md` tells any agent how to interact with your project. Spell out the project layout, what each file is for, and what the agent should do when the user asks common questions ("run the X job", "add a Y").
|
||||
- **Self-contained prompts.** Cron jobs + skills should not assume state the template doesn't ship. If you need a `sites.txt`, have `AGENTS.md` tell the agent to bootstrap it on first run (see `awizemann/site-status-checker` for the pattern).
|
||||
- **Paused by default.** Every cron job ships disabled — Scarf pauses new jobs on install. Write prompts that work whether fired by cron or invoked directly in chat.
|
||||
- **No secrets.** No API keys, no hostnames, no paths specific to your machine. The catalog's CI secret-scan will block obvious cases but this is on you.
|
||||
- **No config writes.** Templates must not modify `~/.hermes/config.yaml`, `auth.json`, or any credential path. The installer refuses v1 bundles that claim to. If you need integration with, say, a specific MCP server, document the prerequisite in your README instead of trying to install it.
|
||||
|
||||
## Step-by-step submission
|
||||
|
||||
### 1. Fork + clone
|
||||
|
||||
```bash
|
||||
gh repo fork awizemann/scarf --clone && cd scarf
|
||||
```
|
||||
|
||||
### 2. Create your template directory
|
||||
|
||||
```bash
|
||||
mkdir -p templates/<your-github-handle>/<your-template-name>/staging
|
||||
cd templates/<your-github-handle>/<your-template-name>/staging
|
||||
```
|
||||
|
||||
Directory names are lowercase, hyphenated, stable: people will type them.
|
||||
|
||||
### 3. Author the bundle
|
||||
|
||||
Minimum required files under `staging/`:
|
||||
|
||||
- **`template.json`** — manifest. Schema:
|
||||
```json
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "<your-handle>/<your-template-name>",
|
||||
"name": "Your Template Name",
|
||||
"version": "1.0.0",
|
||||
"minScarfVersion": "2.2.0",
|
||||
"minHermesVersion": "0.9.0",
|
||||
"author": { "name": "Your Name", "url": "https://…" },
|
||||
"description": "One-line pitch shown in the catalog.",
|
||||
"category": "monitoring",
|
||||
"tags": ["short", "list"],
|
||||
"contents": {
|
||||
"dashboard": true,
|
||||
"agentsMd": true,
|
||||
"cron": 0,
|
||||
"instructions": null,
|
||||
"skills": null,
|
||||
"memory": null
|
||||
}
|
||||
}
|
||||
```
|
||||
The `contents` claim must exactly match what's in `staging/` — the validator cross-checks and rejects mismatches.
|
||||
|
||||
- **`README.md`** — shown on the catalog detail page. Include: what the project does, what the user has to do after install, how to customize, how to uninstall.
|
||||
|
||||
- **`AGENTS.md`** — the cross-agent spec. Include: project layout, first-run bootstrap (if any), what each cron job expects to happen, and answers to common user prompts (`"what's the status"`, `"add a X"`, etc.).
|
||||
|
||||
- **`dashboard.json`** — the Scarf dashboard that renders on the catalog detail page and after install. See [awizemann/site-status-checker/staging/dashboard.json](awizemann/site-status-checker/staging/dashboard.json) for the schema in action.
|
||||
|
||||
Optional:
|
||||
|
||||
- `instructions/CLAUDE.md`, `instructions/GEMINI.md`, `instructions/.cursorrules`, `instructions/.github/copilot-instructions.md` — agent-specific shims beyond `AGENTS.md`.
|
||||
- `skills/<skill-name>/SKILL.md` — shipped skills, installed into `~/.hermes/skills/templates/<slug>/` on the user's side.
|
||||
- `cron/jobs.json` — an array of cron job specs. Each has `name`, `schedule` (e.g. `0 9 * * *` or `every 2h`), `prompt`, optional `deliver`, `skills[]`, `repeat`.
|
||||
- `memory/append.md` — markdown appended to the user's `MEMORY.md` between template-specific markers. Use sparingly — most templates don't need this.
|
||||
|
||||
### 4. Build the bundle
|
||||
|
||||
From the `staging/` directory:
|
||||
|
||||
```bash
|
||||
cd ..
|
||||
zip -qq -r <your-template-name>.scarftemplate staging/
|
||||
mv <your-template-name>.scarftemplate . # end up alongside staging/
|
||||
```
|
||||
|
||||
Or equivalently:
|
||||
|
||||
```bash
|
||||
cd staging && zip -qq -r ../<your-template-name>.scarftemplate . && cd ..
|
||||
```
|
||||
|
||||
### 5. Test locally in Scarf
|
||||
|
||||
1. Open Scarf → Projects → Templates → **Install from File…** → select your `.scarftemplate`.
|
||||
2. Walk through the preview sheet. Make sure every file, cron job, and memory block shown is something you meant to ship.
|
||||
3. Install into a scratch parent dir. Verify the dashboard renders. Enable the cron job(s) if any and trigger them manually to confirm your `AGENTS.md` drives the right behavior.
|
||||
4. Right-click the project → **Uninstall Template…** → verify nothing unexpected remains.
|
||||
|
||||
### 6. Validate
|
||||
|
||||
Before opening the PR, run the catalog validator locally:
|
||||
|
||||
```bash
|
||||
python3 tools/build-catalog.py --check
|
||||
```
|
||||
|
||||
This checks every template in the repo (including yours), verifies the manifest matches the bundle contents, refuses bundles >5 MB, and flags common secret patterns. If it fails, fix the reported issues before pushing.
|
||||
|
||||
### 7. Open the PR
|
||||
|
||||
```bash
|
||||
git checkout -b add-<your-template-name>
|
||||
git add templates/<your-handle>/<your-template-name>
|
||||
git commit -m "feat(templates): add <your-template-name>"
|
||||
git push origin add-<your-template-name>
|
||||
gh pr create
|
||||
```
|
||||
|
||||
**Do not modify `templates/catalog.json`** — the maintainer regenerates it after merge to keep PR diffs small.
|
||||
|
||||
GitHub Actions runs the validator on your PR. A green check means the bundle structure is sound; it doesn't mean the content is approved. Expect a maintainer pass for content quality (is the `AGENTS.md` clear, does the prompt do what you describe, is the scope reasonable).
|
||||
|
||||
### 8. Iterate + ship
|
||||
|
||||
Respond to review feedback. Common requests:
|
||||
|
||||
- Sharpen the `README.md` so install/uninstall steps are copy-pasteable.
|
||||
- Split ambitious cron prompts into smaller, clearly-scoped ones.
|
||||
- Remove things the template doesn't need (an empty `skills/` dir, an unused `deliver` target, etc.).
|
||||
|
||||
Once merged, your template shows up at `https://awizemann.github.io/scarf/templates/<your-handle>-<your-name>/` within a few minutes (the maintainer pushes the site regeneration by hand).
|
||||
|
||||
## Updating an existing template
|
||||
|
||||
Bump `version` in `template.json`, rebuild the `.scarftemplate`, commit, PR. The Install button on the catalog always points at the latest `main` version — there's no per-version pinning in v1. Users who already installed get no automatic update; they'd have to uninstall + reinstall for v2.
|
||||
|
||||
## Questions?
|
||||
|
||||
Open a [GitHub Discussion](https://github.com/awizemann/scarf/discussions) — the tag `templates` is watched.
|
||||
@@ -0,0 +1,52 @@
|
||||
# Scarf Templates
|
||||
|
||||
The community template catalog for [Scarf](https://github.com/awizemann/scarf) — a macOS GUI for the Hermes AI agent. Each subdirectory here is one installable project template. Browse the live catalog with live dashboard previews at **<https://awizemann.github.io/scarf/templates/>**.
|
||||
|
||||
## What's a template?
|
||||
|
||||
A `.scarftemplate` bundle ships:
|
||||
|
||||
- A pre-configured project **dashboard** (widgets for stats, lists, text, charts).
|
||||
- A cross-agent **`AGENTS.md`** ([agents.md standard](https://agents.md/)) that tells Claude Code, Cursor, Codex, Aider, Jules, Copilot, Zed, etc. how to work with the project.
|
||||
- Optional **skills**, **cron jobs**, optional per-agent instruction shims (`CLAUDE.md`, `GEMINI.md`, `.cursorrules`, `.github/copilot-instructions.md`), and an optional **memory appendix**.
|
||||
|
||||
Users install with one click from the catalog site or by opening a `.scarftemplate` file in Scarf.
|
||||
|
||||
## Layout
|
||||
|
||||
Each template lives at `templates/<github-handle>/<template-name>/` with:
|
||||
|
||||
```
|
||||
templates/<github-handle>/<template-name>/
|
||||
├── staging/ source tree
|
||||
│ ├── template.json manifest (id, name, version, contents claim)
|
||||
│ ├── README.md shown on catalog detail page
|
||||
│ ├── AGENTS.md required cross-agent instructions
|
||||
│ ├── dashboard.json rendered as a live preview on the catalog site
|
||||
│ ├── instructions/… optional per-agent shims
|
||||
│ ├── skills/… optional namespaced skills
|
||||
│ ├── cron/jobs.json optional cron job definitions
|
||||
│ └── memory/append.md optional memory appendix
|
||||
├── <template-name>.scarftemplate built bundle (zipped staging/), committed as-is
|
||||
└── screenshots/ optional PNGs for the detail page
|
||||
```
|
||||
|
||||
The built `.scarftemplate` is served directly from `raw.githubusercontent.com` — the catalog's Install button links at:
|
||||
|
||||
```
|
||||
scarf://install?url=https://raw.githubusercontent.com/awizemann/scarf/main/templates/<author>/<name>/<name>.scarftemplate
|
||||
```
|
||||
|
||||
## Contributing a template
|
||||
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md) for the full submission walkthrough. tl;dr: fork, drop a template under `templates/<your-handle>/<your-name>/`, open a PR. A CI check validates the bundle; a maintainer reviews the content.
|
||||
|
||||
## Catalog metadata
|
||||
|
||||
`catalog.json` at this directory is the aggregate index that the website reads. It's regenerated by the maintainer on merge — **do not modify it in your PR**, the build script will take care of it.
|
||||
|
||||
## Current templates
|
||||
|
||||
| Template | Author | Description |
|
||||
|---|---|---|
|
||||
| [site-status-checker](awizemann/site-status-checker/) | awizemann | Daily HTTP uptime check for a user-editable list of URLs. Dashboard + cron + AGENTS.md. |
|
||||
Reference in New Issue
Block a user