CLAUDE.md
CLAUDE.mdCLAUDE.mdroot
Quality
73/100
Scores the file, not the repository.Length
6,506 words
51 headings · 3 code blocksRepository
91
— · pushed 61 days agoLast changed
2 days ago
First indexed 2 days ago.1# CLAUDE.md23Instructions for any AI coding session working *on* the open-forge plugin (not running it). Different audience from `plugins/open-forge/skills/open-forge/SKILL.md`, which is what an end-user's agent reads to *use* the plugin.45> **Also accessible as [`AGENTS.md`](AGENTS.md)** per the [agents.md](https://agents.md) convention. AGENTS.md is a thin landing page that points here; this file is the canonical reference. Tools that look for either filename find their way in.6>7> **For *system shape* (actors, data flow, state stores, quality gates, cadence) see [`ARCHITECTURE.md`](ARCHITECTURE.md).** This file is the *policy* (what's in scope, strict-doc rules, sanitization principles, processing workflow); ARCHITECTURE.md is how the policy is operationalized as a maintenance system.8>9> **For *intent* — why the project exists, who it's for, what success looks like, what we're explicitly not building — see [`BRD.md`](BRD.md).** When a strategic decision feels off (or when a recipe-authoring choice has policy ambiguity), check BRD.md before re-litigating.1011## What is open-forge1213A Claude Code plugin/skill that turns "read a README, copy-paste 30 lines of bash, debug for hours" into a guided chat where Claude executes everything via the user's local CLI tools and the user only makes choices.1415## Architecture — 3 layers, asked in 3 questions1617A deployment is a tuple of three independent axes, asked in this order:1819| # | Question | Layer | Examples |20|---|---|---|---|21| 1 | **What** to host? | software | OpenClaw, Ghost, Mastodon, Vaultwarden, Nextcloud |22| 2 | **Where** to host? | infra (cloud or local) | AWS / Hetzner / DigitalOcean / GCP / Azure / bring-your-own-VPS / **localhost** |23| 3 | **How** to host (within that cloud)? | infra-service + runtime | AWS: Lightsail blueprint, Lightsail Ubuntu + Docker, EC2 + native, EKS, ECS Fargate. Hetzner: Cloud CX + Docker, Cloud CX + native. localhost: Docker Desktop, native. |2425The third question is *dynamically generated* from (software, cloud) — different clouds expose different compute services, and some software has vendor-bundled blueprints on specific clouds.2627**Some infra services bundle the runtime** — EKS → Kubernetes, Lightsail OpenClaw blueprint → vendor's pre-baked install. In those cases the "runtime" question is not asked separately. **Other services give runtime choice** — EC2, plain VPS, localhost — there we ask Docker vs native vs k3s.2829**Reusability is the test.** "Install Docker + run docker-compose" is the same on Lightsail Ubuntu, Hetzner CX-line, a DO droplet, and a localhost — write it once in the runtime layer, reference from every project. "Install k3s" is the same across clouds — write it once. Project recipes should be 80% software-specific concerns and contain *no* per-runtime install commands beyond a one-line link.3031### File layout for the 3 layers3233```34references/35├── projects/<sw>.md # software layer (thin)36├── infra/37│ ├── aws/38│ │ ├── lightsail-blueprint.md # vendor-bundled, software-specific39│ │ ├── lightsail-ubuntu.md # Lightsail as a plain VM40│ │ ├── ec2.md41│ │ ├── eks.md42│ │ └── ecs-fargate.md43│ ├── hetzner/cloud-cx.md44│ ├── digitalocean/droplet.md45│ ├── gcp/compute-engine.md46│ ├── byo-vps.md # user provides any Linux VPS, Claude SSH-es in47│ └── localhost.md # user's own machine, Claude runs commands directly48├── runtimes/49│ ├── docker.md # reusable wherever Docker works50│ ├── native.md # native installer (curl/apt)51│ └── kubernetes.md # reusable across EKS/GKE/AKS/k3s52└── modules/ # cross-cutting (preflight, dns, tls, smtp providers, inbound forwarders, tunnels, backups, monitoring)53```5455`localhost.md` is a first-class infra — for many projects (especially OpenClaw), running locally is the default upstream path. Same conversational UX as a cloud deploy; differences are: no SSH (Claude runs commands directly), no provisioning, public reach via tunnel (`references/modules/tunnels.md`).5657### A fourth orchestration layer — bundles5859Above software / infra / runtime sits an optional **bundle** layer (`references/bundles/`). A bundle is a *recipe-of-recipes* — it pairs commonly-co-deployed software for goal-shaped user requests (*"set up an AI homelab"*) and ships the cross-software wiring (env vars / DNS / ports between constituents). Bundles don't replace single-recipe routing; they're an additional entry point for goal-shaped intents.6061Per *Tier 2 → Tier 1 graduation criteria* below, bundles aren't speculative authoring — they orchestrate **existing Tier 1 recipes** only. If a constituent recipe gets demoted, the bundle goes with it. New bundles get added when 3+ users (or one repeat user) ask for the same combination. Current bundles: `bundles/ai-homelab.md` (Ollama + Open WebUI + AnythingLLM + Aider) and `bundles/privacy-stack.md` (Pi-hole + Vaultwarden + Headscale OR wg-easy).6263## Is this software in scope?6465open-forge is for **deployable self-hosted services**. Use these criteria when deciding whether a piece of software belongs as a Tier 1 recipe (see *Two-tier coverage model* below).6667### Inclusion criteria — recipe is in scope when ALL are true68691. **Software runs as a deployed service or is served from a host the user owns**: long-running daemon, scheduled job, web service, API, CLI agent, or static asset published to a host.702. **Source code or binaries are user-installable on infrastructure they control**: cloud VM, VPS, k3s cluster, or localhost. Paid AMIs / vendor stacks (Bitnami, Dify Premium, etc.) count — closed-source SaaS-only does not.713. **At least one upstream-documented install method or canonical install artifact in-repo** exists, so the strict-doc-policy below has something to verify against.7273### Exclusion criteria — out of scope7475- **Pure libraries / SDKs / packages** that you `import` or call (Unsloth, requests, lodash). No deployment surface.76- **Desktop / mobile end-user apps** with no self-hosted server side (Slack desktop, VS Code, Discord client).77- **SaaS / managed-only products** with no self-host distribution (Notion, Linear, Figma).78- **Dev-only tooling that runs ephemerally on a developer machine** and is never deployed (Storybook *dev* mode, Vite dev server, REPLs).7980### Edge cases — borderline classes8182| Class | Verdict | Recipe shape |83|---|---|---|84| **Static-site generators** (Hugo, Jekyll, Docusaurus, Storybook in production-preview mode) | ✅ in scope | Thin: `<sg> build` → static dir → deploy via a static-host module (nginx / S3+CDN / Pages). The SG-specific bit is build config, theme path, content tree. |85| **CLI agents** (Aider, OpenClaw, Hermes-Agent) | ✅ in scope | Install on a host, run as daemon or interactive CLI. Standard recipe shape. |86| **AI inference servers** (vLLM, Ollama, TGI) | ✅ in scope | Deployed services exposing HTTP APIs. Standard recipe shape. |87| **AI training libraries** (Unsloth, axolotl, transformers) | ❌ out of scope | Libraries called from training scripts, not deployed services. If a "training environments" track ever exists, it's a separate category — not project recipes under `references/projects/`. |88| **CI runners** (GitHub Actions self-hosted, Buildkite agent) | ✅ in scope | Long-running daemon attached to a control plane. Standard recipe shape. |89| **Standalone databases** (Postgres, ClickHouse, Redis) | ⚠️ borderline | Useful but usually a dependency of another recipe rather than a deployment goal. Document as a supporting service inside the consuming recipe; only write a standalone recipe when there's clear demand. |90| **Storage backends** (MinIO, SeaweedFS, Garage) | ✅ in scope | Self-hostable services with HTTP APIs. Standard recipe shape. |9192### When in doubt9394Ask: *"Would the user need open-forge to walk them through provisioning + DNS + TLS + ongoing lifecycle for this?"* If yes, write a recipe. If no (e.g. they'd just `pip install` it inside their own scripts), it's out of scope — or fall back to Tier 2 (below) for one-off requests.9596## Operating principles97981. **Do more, ask less. Non-tech-friendly.** Default to autonomous execution. Only prompt the user for things only they can decide or provide: credentials, opinionated choices, things that touch their accounts at other companies. Hide everything Claude can figure out from the recipe.992. **Towards production-ready architecture.** Even single-node hobby deploys should be on a path to backups, monitoring, TLS, key rotation, OS updates, and least-privilege firewalls. Don't write recipes that "work" but leave the system one outage away from data loss.1003. **Security in mind.** Treat tokens/keys as toxic — never log them, rotate after chat exposure, prefer fragment URLs over query strings. Default firewalls to closed; open ports explicitly. Default to SSH key auth; never password. Let's Encrypt for any public endpoint. Sandbox agent tool execution where the runtime supports it.1014. **One question at a time.** Use `AskUserQuestion` for structured choices. Reserve free-text for credentials and identifiers (domain names, emails). No upfront questionnaires.1025. **Auto-install with confirmation, never silently.** If `jq` or `aws` is missing, propose the install command, get one-line approval, then run.1036. **Reference upstream docs; don't replace them.** Recipes condense and translate upstream documentation into Claude-actionable steps — they aren't the source of truth for the product itself. Always link the upstream pages we summarized (e.g. `docs.openclaw.ai/install/docker`, AWS Lightsail user guide, Bitnami docs). Reasons: (a) users can verify what we condensed, (b) when upstream drifts our recipe goes stale fast and the link is the recovery path, (c) credit where due. **See *Strict doc-verification policy* below — every install method documented by upstream must have its own recipe section, verified against upstream before being written.**1047. **Don't invent — interface.** open-forge is a chat-friendly interface to existing tools. Claude is the orchestrator; the user's existing software stack (AWS CLI, Docker, openclaw, ssh, gh, registrar UIs) is the substrate. **Do not** build custom DSLs, YAML schemas, CLI tools, deployment managers, or wrappers around upstream tools. **Do not** reimplement what an upstream tool already does (e.g. don't rebuild `openclaw onboard`'s prompts in chat — call the command). The state file is a thin orchestration helper for resume, nothing more. *Caveat:* "don't invent" applies to **fabricating a deployment path the upstream doesn't support** (e.g. authoring a Helm chart for a project that has no chart). It does **not** mean "no tooling." If upstream supports Docker / k8s / Helm / Terraform, lean on every skill and MCP that helps you orchestrate those paths well — see *Companion skills & MCPs* below.105106## Credential handling (expanded from Operating Principle #3)107108Pasting raw credentials into Claude Code is risky — secrets enter session history, may be relayed via MCP servers, and could appear in shared transcripts. The skill must offer safer alternatives **first** and only fall back to direct paste with explicit risk acknowledgement.109110### The five patterns (priority order)111112| # | Pattern | When to suggest |113|---|---|---|114| 1 | **Local file path** — user gives skill a path; skill `cat`s it | Personal-use API keys; user already has a `.env` or `.secrets` file |115| 2 | **Env var name** — user pre-exports the secret; skill reads `$<NAME>` | Shell users with secrets in `.envrc` / `.bashrc` |116| 3 | **Cloud-CLI session** — user runs `<provider> login` ahead of time; skill uses the resulting profile / session | Default for AWS, GCP, Azure, GitHub, DigitalOcean, Hetzner, Cloudflare |117| 4 | **Secrets-manager reference** — user gives skill a `op://` / `bw://` / `vault://` reference; skill calls the matching CLI just-in-time | Users with proper secret management (1Password, Bitwarden, Vault, AWS Secrets Manager, GCP Secret Manager, `pass`) |118| 5 | **Direct chat paste** — last resort, requires risk acknowledgement | When patterns 1-4 don't apply; user explicitly opts in |119120### Hard rules121122- **Always offer the five patterns** when asking for any sensitive input. Don't silently accept a paste; don't assume Claude Code is a vault.123- **Surface the risk** before accepting a direct paste: *"the key will live in this session's history; rotate after deploy completes."*124- **Never accept SSH key contents.** Always ask for the key file *path* (skill uses `ssh -i <path>`); never the key material itself in chat.125- **Validate before proceeding**: `test -r <path>` for file paths; `test -n "$<VAR>"` for env vars; smoke-command for cloud-CLI sessions and secrets-manager refs.126- **Refuse files with permissions wider than 600**; offer to `chmod 600` first.127- **Detect accidental pastes** (regex for `re_*`, `sk-*`, `AKIA*`, etc. in a prompt that expected a path) and stop the user before the secret commits to chat.128- **End-of-deploy rotation reminder** if the user pasted any secret directly during the deploy: list each pasted credential + the provider's dashboard URL; recommend rotating now that the deploy is done.129130The full pattern catalog with skill prompt templates, per-credential-class recommendations, and failure-mode handling lives in [`plugins/open-forge/skills/open-forge/references/modules/credentials.md`](plugins/open-forge/skills/open-forge/references/modules/credentials.md).131132## Strict doc-verification policy (mandatory before writing any recipe)133134Recipes are condensations of upstream docs; condensing what we haven't read is speculation. Past failures (the v0.7.0 Helm chart claim sourced from a search snippet, the v0.6.0 OpenClaw "every blessed path" claim that was 4 of 17 because we trusted the README's enumeration) traced back to this. The policy:135136### Before writing or expanding any project / infra recipe1371381. **Read the upstream README verbatim.** Not summarized — the actual README. Note: the README is necessary but **not sufficient** — many projects' READMEs are deliberately minimal and point at a separate docs site for install methods.1392. **Locate the upstream install-method index.** Typically:140 - The project's docs site (`docs.PROJECT.ai`, `PROJECT.com/docs`, `PROJECT.github.io`, etc.).141 - The repo's `docs/install/` or `website/docs/getting-started/` tree.142 - The repo's wiki (often a separate `<repo>.wiki.git` clone).1433. **Enumerate every method documented under that index.** Include:144 - First-party install scripts (`install.sh`, `install.ps1`, vendor blueprints).145 - First-party Docker / Compose / Kubernetes / Helm support.146 - First-party package-manager support (Homebrew, Nix, Pacman, etc.).147 - First-party PaaS templates (`fly.toml`, `render.yaml`, Railway / Zeabur / Sealos one-click buttons published by upstream).148 - First-party cloud templates (Terraform / CDK / Computing Nest published by upstream).1494. **Read the canonical install artifacts in the repo:** `docker-compose.yml`, `Dockerfile`, `flake.nix`, the project's primary config-file example. These often surface details the docs gloss over (service inventory, env-var matrix).1505. **Write one section per documented method.** No merging, no skipping. Each section's first line cites the upstream URL it's derived from.151152### What counts as "official"153154| Source | Official? |155|---|---|156| Upstream's own README | ✅ |157| Upstream's own docs site (linked from README) | ✅ |158| Upstream's repo `docs/` or `website/` tree | ✅ |159| Upstream's repo wiki | ✅ |160| Upstream-published PaaS deploy buttons (Railway/Render/Fly/etc.) where the manifest lives in the upstream repo | ✅ |161| Community-maintained Docker images / Helm charts when upstream ships none | ⚠️ Allowed but **must be flagged** as "community-maintained, verify source"; recipe lists multiple options (most-active first), doesn't pick a winner |162| Anything else (third-party blogs, search snippets, my training data) | ❌ Not allowed as the basis for a section. If upstream ships no path for X, do not invent one. |163164### When upstream-doc fetch fails165166- WebFetch rate-limited / 403 / 404 → try `raw.githubusercontent.com/<org>/<repo>/<branch>/<path>` for repo content.167- Wiki page WebFetch fails → `git clone https://github.com/<org>/<repo>.wiki.git` and read locally.168- All fetch paths fail → **stop**. Do not write speculative content. Either: (a) ask the user to paste relevant doc text, (b) wait until access is restored, or (c) write only the sections for methods we *did* read and note in the recipe's TODO that the rest is pending verification.169170### Community-maintained methods — flagging requirements171172When a recipe documents a method upstream doesn't ship (e.g. A1111 + ComfyUI Docker, Helm charts for many projects), the section MUST:1731741. Open with an explicit "community-maintained" note in a blockquote.1752. List **multiple** options when they exist (most-active first; reference upstream README's pointer if upstream lists them).1763. Frame commands as "illustrative — verify the README at the version you pull"; never present community-chart `--set` values as authoritative.1774. Document the gap in the recipe's TODO section: "Verify which community option is most actively maintained at first-deploy time."178179### Retroactive application180181When this policy is added (or strengthened), every existing recipe must be re-verified against its upstream docs index. If the verification surfaces a missing method, file it in that recipe's TODO, write the missing section, and bump the plugin version.182183### When in doubt184185Ask the user whether to pause for verification or accept the README's enumeration. Don't silently downgrade thoroughness.186187---188189## Two-tier coverage model190191open-forge ships a finite catalogue of verified recipes (Tier 1) plus a documented fallback for everything else (Tier 2). Both tiers obey the strict-doc-policy above; the difference is *when* the verification happens.192193### Tier 1 — verified recipes (the catalogue)194195The current set under `references/projects/`. Authored ahead of time, audited against upstream docs, kept current via the first-run discipline + version bumps. **Quality bar:**196197- Every install method has a `> **Source:** <upstream URL>` line at the top of its section.198- Community-maintained methods open with the required ⚠️ blockquote per *Community-maintained methods — flagging requirements*.199- Gotchas captured from real deploys; TODOs track unresolved verifications.200- Plugin version bumped on each user-visible change.201202### Tier 2 — derived live from upstream docs203204When a user asks for software that has no Tier 1 recipe, the skill **falls back** instead of refusing:2052061. **Announce the fallback in one sentence**: *"This software isn't in our verified recipe set — I'll fetch upstream docs live and reuse the runtime / infra modules. Treat my output as best-effort, not authoritative."*2072. **Apply the strict-doc-policy on the fly** — same rules as Tier 1:208 - Read upstream README via `WebFetch`. If 403/404, fall back to `raw.githubusercontent.com` paths and/or `git clone` the docs repo locally.209 - Locate the upstream install-method index (docs site, repo `docs/install/` tree, wiki).210 - Enumerate methods from upstream — **do not invent**. If fetches fail, stop and tell the user; never speculate to fill a gap.211 - Read canonical install artifacts (`Dockerfile`, `docker-compose.yml`, `helm/`, `flake.nix`).2123. **Reuse runtime + infra + cross-cutting modules** under `references/runtimes/`, `references/infra/`, `references/modules/` for all the reusable parts (Docker install, k8s prereqs, VM provisioning, DNS, TLS, SMTP). Tier 2 is mostly *software-specific* on top of those — same shape as Tier 1, just authored at request time.2134. **Cite every upstream URL** the same way Tier 1 does.2145. **Offer to capture the result** as a new Tier 1 recipe when the deploy succeeds — that's how the catalogue grows. The captured recipe must still go through first-run discipline before claiming Tier 1 status.215216### Routing217218The skill checks Tier 1 first by name match against `references/projects/*.md`. If no match, fall back to Tier 2 with the announcement above. **Never silently mix tiers** — the user should always know which tier they're in, since the verification depth differs.219220### Quality boundary221222Tier 2 output is **best-effort, not authoritative.** It will hallucinate at the edges of upstream docs we couldn't fetch; it skips the iterative refinement that Tier 1 recipes get from real deploys. Tell the user this. They're trading verification depth for coverage breadth.223224### Tier 2 → Tier 1 graduation criteria225226The catalogue grows demand-driven, not by guess. Promote a Tier 2 deploy to a Tier 1 recipe when ANY of:2272281. **3+ feedback issues** for the same software (demand signal — see *Issue-driven contribution model*).2292. **Same user has deployed it 3+ times** and asks for first-run discipline applied.2303. **A Tier 2 deploy surfaced a non-obvious gotcha** that's likely to bite the next person — capture the gotcha as a recipe even if demand is small (one-shot promotion is allowed when the value is in the captured knowledge).2314. **A maintainer chooses to deploy the software themselves** (sunk cost is acceptable).232233Don't author Tier 1 recipes speculatively from a "popular self-host" list — without a real demand signal, the compounding effect can't kick in and the upfront cost goes to waste.234235---236237## Issue-driven contribution model238239The catalogue evolves through GitHub issues, not direct human PRs. AI coding sessions (whether triggered by a maintainer running this skill, by a scheduled job, or by a webhook) read incoming issues, verify them against upstream docs per *Strict doc-verification policy*, and author patches.240241### Three input channels242243GitHub issue templates under `.github/ISSUE_TEMPLATE/` define the structured input:244245| Template | When to use | Filed by |246|---|---|---|247| `recipe-feedback.yml` | A user deployed via the skill and wants to suggest recipe edits (gotchas captured, install steps that surprised them, sections that were wrong/outdated). The skill drafts these automatically at the end of a deploy. | End user (skill-assisted) |248| `software-nomination.yml` | A user wants software added to the Tier 1 catalogue. Must include rationale + upstream URL + the user's intended deploy combo. | End user |249| `method-proposal.yml` | A user knows an upstream-supported install method that an existing recipe doesn't cover. Must include the upstream URL where the method is documented. | End user |250251A blank-issue / off-template issue is treated as a request for routing — close politely with a pointer to the templates.252253### Why issues, not PRs254255- **Sanitization happens at submission time.** The skill (or a careful manual filer) redacts identifiers before posting; the issue templates encode the structure. PRs from random users could include credentials in commit history that can't be cleanly removed.256- **Verification happens centrally.** Every change is re-verified against upstream by the AI session that processes the issue, not trusted because someone filed a PR.257- **Demand signal lives in the issue stream.** Issues with the most thumbs-up / cross-linking / repeat filings are the demand signal that drives Tier 2 → Tier 1 graduation.258259### Direct human PRs260261Discouraged. If a maintainer writes a PR by hand, it's still subject to the strict-doc-policy and recipe-structure rules — the issue model is the documented contribution path.262263---264265## Sanitization principles266267User-shared content (deployment logs, gotchas, error output) routinely contains identifiers that **must not** end up in the public repo. Both the skill (when drafting issue content) and any session reviewing user-supplied content (when accepting a PR sourced from an issue) must apply these rules.268269### Always strip270271| Class | Replace with |272|---|---|273| Domain names (apex / canonical / admin) | `${CANONICAL_HOST}` / `${APEX}` / `${ADMIN_DOMAIN}` |274| IP addresses (public + private + IPv6) | `${PUBLIC_IP}` / `${PRIVATE_IP}` |275| SSH key paths and contents | `${KEY_PATH}` / `<REDACTED-SSH-KEY>` |276| API keys and bearer tokens (regex: `re_[A-Za-z0-9_]+`, `SG\.[A-Za-z0-9._-]+`, `sk-[A-Za-z0-9]+`, `xox[bp]-[A-Za-z0-9-]+`, `ghp_[A-Za-z0-9]+`, AWS access keys `AKIA[0-9A-Z]{16}` + secret `[A-Za-z0-9/+=]{40}`, GCP service-account JSON, generic `Bearer [A-Za-z0-9._-]{20,}`) | `<REDACTED>` |277| AWS account IDs (12 consecutive digits in AWS context) | `${AWS_ACCOUNT}` |278| AWS profile names | `${AWS_PROFILE}` |279| Email addresses (LE email, SMTP from-address, user identity) | `${EMAIL}` |280| State-file contents from `~/.open-forge/deployments/<name>.yaml` | Reference the file by name only, never paste contents |281| Hostnames embedded in URLs that include the user's domain | `https://${CANONICAL_HOST}/path` |282| Anything from the user's clipboard / env vars they pasted into chat | `<REDACTED>` |283284### Multi-step consent (no auto-post, ever)285286The skill flow when posting feedback to GitHub:2872881. **Opt-in prompt** — *"Want to share what you learned?"* User must explicitly opt in.2892. **Show the redacted draft in chat** — full text, before any submission attempt.2903. **Confirm post?** — explicit "yes" required.2914. **If user edits the draft**, re-show + re-confirm before submitting.2925. **Standing reminder text** in the prompt: *"GitHub issues are public and permanent. Once posted, this can't be unposted. Review every line; edit if anything looks identifiable."*2936. **Liability notice in the issue body**: *"Submitter grants a non-revocable license to use this content in the open-forge recipe; the project bears no liability for the submitter's choice to share."*294295### When reviewing PRs sourced from issues296297Issue-processing sessions must re-scan PR diffs against the same strip-list before merging. If any identifier slipped through, redact in the PR before merge — never merge content with live identifiers.298299---300301## Processing incoming issues302303When an AI coding session is asked to process incoming issues (whether by a maintainer prompt, a scheduled job, or a webhook), apply this workflow:304305> **Catalog-growth sources** beyond GitHub issues — public lists / feeds the bot pulls from in priority order — are documented in [`progress/sources.md`](progress/sources.md). The current queue is **selfh.st** (in progress) → **awesome-selfhosted-data** (queued) → **Self-Host Weekly newsletter** (continuous) → **GitHub issues** (continuous). When the active source completes or a new source is added, update `progress/sources.md` to reflect the change.306307### 1. Triage308309For each open issue without an `applied` / `out-of-scope` / `needs-info` label:310311- Identify the template type from the issue body's structured fields. If the issue doesn't follow a template, comment with a pointer to the templates and label `needs-info`.312- Validate that the issue is in scope per *Is this software in scope?*. Out-of-scope → comment + `out-of-scope` label + close.313- Otherwise, label `triaged` and proceed to validation.314315### 2. Validate against upstream316317Apply *Strict doc-verification policy* to every change:318319- For `recipe-feedback`: re-fetch the recipe's cited upstream URLs; verify the user's proposed change is consistent with current upstream content. If upstream has drifted in a way that conflicts with the user's report, prefer upstream and explain the discrepancy in the PR.320- For `software-nomination`: confirm the software passes inclusion criteria; locate upstream's install-method index; do **not** start authoring a recipe until the index is reachable.321- For `method-proposal`: confirm the cited upstream URL documents the method; if it's community-maintained, it must be flagged per *Community-maintained methods — flagging requirements*.322323If validation fails (upstream URL 404s, software is out of scope, methodology is unverifiable), comment on the issue explaining + label `needs-info` or `out-of-scope` as appropriate. Do not author a patch.324325### 3. Author the patch326327- Apply the change per *Recipe structure (must-have sections)*.328- Cite the upstream URL at the top of every section per *Strict doc-verification policy*.329- Flag community-maintained methods with the required ⚠️ blockquote.330- Re-scan against the *Sanitization principles* strip-list — if any identifier slipped through user-supplied content, redact before drafting.331- **If your patch touches `CLAUDE.md`, `plugins/open-forge/skills/open-forge/SKILL.md`, or any file under `plugins/open-forge/skills/open-forge/references/`, regenerate the multi-platform distribution bundles**: `./scripts/build-dist.sh all`. Include the regenerated `dist/` files in the same PR. The bundles concatenate canonical sources for non-Claude-Code platforms (Codex / Cursor / Aider / Continue / generic); they drift if not regenerated, which silently breaks those platforms. CI enforces this — see `.github/workflows/dist-bundles.yml`.332- Bump `plugin.json` `version` per *Versioning + publish flow*.333- If multiple feedback issues for the same recipe are pending, batch them into a single PR.334335### 4. Open the PR336337- **Branch naming**: `bot/issue-<N>-<short-slug>` (where `<N>` is the originating issue number).338- **Commit author**: `Qi Zhang <zhangqi444@gmail.com>` per *Author convention*.339- **PR body** must cite (a) the originating issue number(s), (b) every upstream URL re-verified, (c) the version bump rationale.340- After opening, label the issue `in-progress`. After merge, relabel `applied`.341342### 5. State-machine via labels343344| Label | Meaning |345|---|---|346| (none) | New issue, not yet triaged |347| `triaged` | Identified template type + scope-checked; ready to validate |348| `in-progress` | A PR is open against this issue |349| `applied` | PR merged; issue resolved |350| `needs-info` | Author needs to provide more before processing can continue |351| `out-of-scope` | Software / request doesn't meet inclusion criteria; closed |352353Optionally also: `recipe:<name>`, `tier:1`, `tier:2`, `infra:<cloud>`, `runtime:<runtime>` for filtering.354355### 6. Conflicts and ambiguity356357- **Contradicting suggestions across issues**: prefer upstream-doc-verified content; cite the upstream URL in the PR explaining which suggestion was chosen and why.358- **Ambiguous suggestion**: if the issue is unclear about what should change, comment asking for clarification with a deadline (e.g. *"reply within 14 days or this issue will be auto-closed"*) and label `needs-info`.359- **Idempotency**: never re-process an issue already labeled `applied`. If the same recipe issue resurfaces under a new issue number, treat it as a fresh demand signal (counts toward Tier 2 → Tier 1 graduation per *Two-tier coverage model*).360361---362363## Companion skills & MCPs364365open-forge orchestrates *upstream-blessed* deployment paths. To do that well, recipes are encouraged to depend on companion skills/MCPs as soft dependencies — declared in prose, not enforced. The filter is one question:366367> Does this tool help me **drive** an upstream-supported deploy path more reliably?368369| Shape | Stance | Examples |370|---|---|---|371| **Operators** — read state, query docs, drive existing CLIs more accurately | ✅ Embrace | `awsdocs` MCP, `gcp-docs` MCP, `cloudflare` MCP, GitHub MCP (fetch upstream `docker-compose.yml` / `charts/`), k8s state-query MCPs |372| **Generators** — author config from scratch | ❌ Avoid by default | `dockerfile-generator`, `k8s-yaml-generator`, `helm-generator`, `terraform-generator`. Only justified when upstream genuinely ships nothing and we deliberately wrap. |373| **Plain CLIs** | ✅ Default substrate | `docker`, `kubectl`, `helm`, `aws`, `gcloud`, `az`, `gh`, `ssh`, `terraform` |374375How to reference companion tooling — **fallback hierarchy**, in order of preference:3763771. **Companion skill/MCP**, if available. Name it in SKILL.md / recipe body in prose: *"If the k8s state MCP is available, use it to confirm pod readiness; otherwise parse `kubectl get pods -o json`."* Claude uses it when present, falls back gracefully when not.3782. **Captured docs in `references/`**, if no skill/MCP exists. Distill the relevant upstream pages (Helm chart values, k8s CRD schema, AWS CLI flags for the specific service) into a focused reference under `references/modules/<topic>.md` or alongside the recipe. Cite the upstream URL as the source of truth — captured docs are a lossy snapshot, the link is the recovery path (principle #6).3793. **Inline upstream-doc links** as a last resort, when even capture is overkill — let Claude WebFetch them on demand.380381Where to declare companion tooling:382383- **In recipe frontmatter**, optionally list `companion-skills:` / `companion-mcps:` as documentation (not enforced — no formal deps mechanism in plugin manifests yet).384- **In `plugins/open-forge/.mcp.json`**, register MCPs the recipes depend on heavily so they install transparently with the plugin. Reserve this for read-only docs/state MCPs; never wrap deployment commands.385- **For dev work on open-forge itself** (CI, settings audit, plugin packaging): use whatever skills help your local workflow (`gh-fix-ci`, `claude-settings-audit`) — these don't need to ship with the plugin.386387### Recommended companion: `garrytan/gstack`388389[`garrytan/gstack`](https://github.com/garrytan/gstack) is a Claude Code skill bundle (Garry Tan, MIT) that ships ~30 SDLC slash commands for AI-assisted engineering: `/office-hours` (product interrogation before coding), `/plan-eng-review` (architecture review), `/review` (code review for production bugs), `/qa` (test + regression-suite generation), `/ship` (sync + test + audit + push PR), `/cso` (OWASP Top 10 + STRIDE security audit), `/learn` (persistent project learnings), `/retro` (engineering retrospective), and others.390391**Install** (one-shot in any Claude Code session):392393```bash394git clone --single-branch --depth 1 https://github.com/garrytan/gstack.git ~/.claude/skills/gstack \395 && cd ~/.claude/skills/gstack && ./setup396```397398**How its commands map to open-forge work**:399400| gstack command | When to use on open-forge |401|---|---|402| `/office-hours` | Before authoring a new module (backups, monitoring) or a bundle — interrogate the design before writing code. |403| `/plan-eng-review` | Before merging a major architectural addition (e.g. multi-platform support, agent-platform support) — catches the kind of cross-cutting issues that slipped past on PR #44 (in-bundle reference paths). |404| `/review` | On any PR that touches `references/projects/*.md`, `SKILL.md`, or `CLAUDE.md` — production-bug-flavored code review. |405| `/qa` | After authoring a new recipe — would force first-run-discipline-style verification before claiming Tier 1. |406| `/ship` | The PR-creation flow this session has been doing manually (sync main → regenerate dist → push → open PR with structured body). |407| `/cso` | Periodic security audit — credential handling module is the obvious target. |408| `/learn` | Capture session-level learnings (e.g. *"the bot polls newsletters — check origin/main before authoring duplicate work"*) into a persistent store the next AI session can read. |409| `/document-release` | Update README + CLAUDE.md + ARCHITECTURE.md to match shipped code — ran manually as PR #45 did. |410411Optional but recommended for AI sessions and maintainers working on this repo. Not required — the catalog has been maintained without it. But the workflow patterns it encodes line up cleanly with how PR-authoring actually happens here.412413When a recipe is exercised end-to-end and a companion skill/MCP proved necessary — or a captured doc was added to `references/` — record it in the recipe's *Compatible runtimes* or a new *Companion tooling* note alongside upstream doc links. Same first-run discipline applies.414415## Recipe structure (must-have sections)416417Every `references/projects/<software>.md` should have:418419| Section | Purpose |420|---|---|421| **Frontmatter** (name + description) | Loaded into context whenever the skill triggers. Keep concise; this is for Claude, not the user. |422| **Inputs to collect** (table keyed by phase) | Exact prompts, structured-choice options, defaults. So the same recipe is consistent across runs. |423| **Compatible runtimes** | Which runtime modules this software supports + recommended default |424| **Phase applicability** | Which of preflight/provision/dns/tls/smtp/inbound/hardening apply or skip |425| **Per-phase content** | Project-specific commands, config patches, verification checks |426| **Gotchas (consolidated)** | One-line summaries of every non-obvious thing learned in production. Single source of truth. |427| **TODO — verify on subsequent deployments** | Open questions to resolve on the next real deploy. Empty = recipe is fully validated. |428429`references/runtimes/<name>.md` and `references/infra/<name>.md` mirror this with their own scope (no `Inputs to collect` for infra usually — preflight handles AWS profile/region; infra adds bundle/region-specific bits).430431## First-run discipline432433When a recipe is exercised end-to-end against a real deployment for the first time:4344351. Capture every gotcha that surprised us into the recipe's *Gotchas* section.4362. Resolve / delete TODO items as they're answered.4373. Update the deployment state file's phase notes.4384. Bump `plugin.json` `version` (see *Versioning* below).4395. Commit.440441This is how the recipe stops being a guess and becomes a known-working deployment template. Don't skip it.442443The dominant path for first-run discipline is now **user-submitted feedback issues** processed per *Processing incoming issues* — the skill drafts a sanitized issue at the end of each deploy and the user opts in to share. Maintainer-driven deploys (where the maintainer is also the recipe author) still apply for new recipes. Either way, the same five-step capture applies.444445## File layout446447```448open-forge/449├── CLAUDE.md ← you are reading450├── AGENTS.md ← agents.md-standard landing page; thin pointer to CLAUDE.md451├── ARCHITECTURE.md ← system shape (actors, data flow, state stores, quality gates) — complement to this file452├── BRD.md ← project intent (why / who / success / non-goals) — strategic clarity453├── README.md ← user-facing, lives on GitHub454├── CHANGELOG.md ← user-visible changes per version (Keep-a-Changelog format; required on every version bump)455├── LICENSE ← MIT456├── .claude-plugin/marketplace.json ← marketplace manifest457├── .github/458│ ├── ISSUE_TEMPLATE/ ← three issue channels (recipe-feedback, software-nomination, method-proposal)459│ └── workflows/460│ ├── dist-bundles.yml ← CI: fail PRs whose dist/ bundles are stale vs canonical sources461│ └── release.yml ← auto-creates GitHub Release on plugin.json version bump462├── docs/platforms/ ← per-platform usage guides (Codex / Cursor / Aider / Continue / OpenClaw / Hermes / generic)463├── dist/ ← regenerated multi-platform distribution bundles (see scripts/build-dist.sh)464├── progress/ ← bot's state files: selfhst-progress.json + selfhst-software.json + issues-log.json (bot-owned) + sources.md (maintainer-curated source queue)465├── assets/ ← icon.svg + social-preview.svg466├── scripts/467│ └── build-dist.sh ← regenerates dist/ from canonical sources; run when CLAUDE.md / SKILL.md / modules change468└── plugins/open-forge/469 ├── .claude-plugin/plugin.json ← plugin manifest (version!)470 └── skills/open-forge/471 ├── SKILL.md ← end-user-Claude entrypoint472 ├── references/473 │ ├── projects/<name>.md ← software layer (2,200+ Tier 1 verified recipes)474 │ ├── runtimes/<name>.md ← runtime layer (docker.md, podman.md, native.md, kubernetes.md)475 │ ├── infra/<name>.md ← infra layer (aws/, azure/, hetzner/, digitalocean/, gcp/, oracle/, paas/, hostinger.md, raspberry-pi.md, macos-vm.md, byo-vps.md, localhost.md)476 │ ├── modules/<name>.md ← cross-cutting (preflight, dns, tls, smtp providers, inbound forwarders, tunnels, credentials, feedback, backups, monitoring)477 │ └── bundles/<name>.md ← curated multi-software bundles (recipe-of-recipes; ai-homelab, privacy-stack)478 └── scripts/ ← deployment-time operational scripts (per-recipe); empty by default479```480481The skill-side `plugins/open-forge/skills/open-forge/scripts/` (deployment-time) stays empty unless something is reused 3+ times across deployments — inline commands in recipes are clearer for one-off use. Distinct from the top-level `scripts/` (build-time tooling for dist/ bundles).482483For the **system architecture** (how the catalog grows, who maintains what, how an issue becomes a recipe edit, where state lives), see [`ARCHITECTURE.md`](ARCHITECTURE.md). This file is *policy*; ARCHITECTURE.md is *system shape*.484485## Versioning + publish flow486487`plugin.json` `version` controls what the Claude Code marketplace fetches.488489- **Bump on**: skill description change, new project/runtime/infra, major recipe rewrite, anything that changes user-visible behavior.490- **Don't bump on**: typo fixes, internal comment cleanups, lint-only changes.491492Publish flow (typical path: AI session processing an issue per *Issue-driven contribution model*):4934941. Add a `CHANGELOG.md` entry in user-visible terms (Keep-a-Changelog format) under `## [Unreleased]` → move to `## [<version>]` on bump.4952. Bump `plugin.json` `version`.4963. Commit and push to `main` (typically as a PR).4974. `.github/workflows/release.yml` auto-creates a GitHub Release tagged `v<version>` with notes pulled from the matching `CHANGELOG.md` section.4985. Users run `/plugin marketplace update` in their Claude Code session to pick up the new version.499500Maintainer manual edits follow the same flow but skip the issue-tracking labels.501502## Author convention503504Commits authored as `Qi Zhang <zhangqi444@gmail.com>` — set inline via env vars (`GIT_AUTHOR_NAME`, `GIT_AUTHOR_EMAIL`, `GIT_COMMITTER_NAME`, `GIT_COMMITTER_EMAIL`), **don't write to git config**.505506## Refactor (started 2026-04-24, completed 2026-04-26)507508Initial state collapsed three axes into linear "Path A/B/C" inside `openclaw.md`, which hid valid combos and biased preflight toward AWS even for non-AWS deployments. Migrated to the 3-layer file layout above. Order:5095101. ✅ CLAUDE.md model locked in (this section).5112. ✅ Preflight refactor — branch on infra choice; only require AWS CLI when infra ∈ AWS.5123. ✅ Skeleton infra adapters: `infra/aws/lightsail.md` (Bitnami + OpenClaw blueprints share this; the blueprint-vs-Ubuntu split is a project-recipe concern, not a separate adapter), `infra/aws/ec2.md`, `infra/azure/vm.md`, `infra/hetzner/cloud-cx.md`, `infra/digitalocean/droplet.md`, `infra/gcp/compute-engine.md`, `infra/oracle/free-tier-arm.md`, `infra/hostinger.md`, `infra/raspberry-pi.md`, `infra/macos-vm.md`, `infra/byo-vps.md`, `infra/localhost.md`, plus a PaaS family under `infra/paas/`: `fly.md`, `render.md`, `railway.md`, `northflank.md`, `exe-dev.md`.5134. ✅ Runtime modules: `runtimes/docker.md`, `runtimes/podman.md`, `runtimes/native.md`, `runtimes/kubernetes.md`. Docker + native extracted from openclaw.md Paths B and C; kubernetes added when openclaw upstream's Kustomize-based path was wired in; podman added in v0.8.0.5145. ✅ Slim down `projects/openclaw.md` — software-layer concerns only; reference runtimes + infra modules for everything else. v0.8.0: corrected the Kubernetes section to be Kustomize-first (matches upstream `scripts/k8s/deploy.sh`); added Podman, ClawDock, Ansible, Nix, and Bun (experimental) sections; combo table now enumerates every upstream-blessed install method documented under `docs.openclaw.ai/install/*`.5156. ✅ Add `modules/tunnels.md` for localhost public-reach (Cloudflare Tunnel / Tailscale / ngrok).5167. ✅ Update SKILL.md, README.md support tables and prompts. Bump plugin version (→ 0.8.0).517518Path A/B/C terminology retired. Future work tracked in each adapter's *TODO — verify on subsequent deployments* section, not here. Cluster-provisioning adapters (EKS / GKE / AKS / DOKS) are intentionally not in scope — open-forge orchestrates an existing cluster; users own cluster create/delete in their cloud's k8s UI. Cloud-VM adapters and PaaS adapters added in v0.8.0 are documented from upstream docs only — none has been exercised end-to-end yet; first-run discipline (CLAUDE.md § *First-run discipline*) applies as those deployments happen.519520## Behavioral guidelines (echoes of bota CLAUDE.md, kept here for autonomy)521522- **Think before coding.** State assumptions; ask when uncertain; surface tradeoffs.523- **Simplicity first.** Minimum recipe content that works; no speculative abstractions.524- **Surgical changes.** When updating a recipe after a deploy, change only what the deploy taught us. Don't "improve" adjacent sections.525- **Goal-driven execution.** A recipe edit is "done" when the next deploy can use it without manual fixes.526- **Documentation updates** (the recipes themselves) are a deliverable of every deployment, not a follow-up.527
Also in zhangqi444/open-forge
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| zhangqi444/open-forgeAGENTS.md · 91 | AGENTS.md | buildtestlint-formatsecurity+1 | 81/100 | 2 days ago |
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| Adit-Jain-srm/NightmareNetCLAUDE.md · 45 | CLAUDE.md | buildtestlint-formatstyle+6 | 100/100 | 3 days ago | |
| nimbalyst/nimbalystpackages/android/CLAUDE.md · 1.4k | CLAUDE.md | setupbuildstylearch+2 | 100/100 | 3 days ago | |
| stacklok/toolhiveCLAUDE.md · 2.0k | CLAUDE.md | buildteststylearch+4 | 100/100 | 3 days ago | |
| dotCMS/corecore-web/CLAUDE.md · 949 | CLAUDE.md | teststylearchtesting-strategy+3 | 100/100 | 3 days ago | |
| microsoft/playwrightCLAUDE.md · 94k | CLAUDE.md | buildtestlint-formatstyle+7 | 100/100 | 3 days ago | |
| filamentphp/filamentCLAUDE.md · 32k | CLAUDE.md | buildtestlint-formatstyle+7 | 100/100 | 3 days ago | |
| livewire/livewireCLAUDE.md · 24k | CLAUDE.md | setupbuildteststyle+4 | 100/100 | 3 days ago | |
| bagisto/bagistoCLAUDE.md · 28k | CLAUDE.md | setupbuildteststyle+5 | 100/100 | 3 days ago |
