This file defines the working rules for the entire repository. Use it as the default context for future changes. Follow a direct user instruction when it conflicts with this file. Communicate with the maintainer in German unless they request another language. Keep source code, interface copy, and public project documentation in English.
Omarchy Plugins is an independent community marketplace at omarchyplugins.com. It helps people discover, inspect, and install plugins for Omarchy. It is not affiliated with Omarchy or 37signals.
Preserve these product qualities:
- Minimal, precise, technical, and aesthetically restrained
- Command-first, with source and trust information visible
- Fast, static, accessible, and usable without an application server
- Curated, while stating clearly that listing is not a security review
Do not introduce accounts, a database, a backend, a frontend framework, or a new dependency unless the maintainer explicitly approves that architectural change. The approved exception is the credential-free engagement feature under worker/: a narrowly scoped Cloudflare Worker and D1 database may store anonymous aggregate plugin detail views, successful command-copy actions, and hearts guarded by local browser storage. Hearts are anonymous reactions, not unique or verified votes. Do not expand it into identity, profiling, comments, scored ratings, installation telemetry, or general analytics without separate approval.
site/index.htmlcontains the marketplace and catalog interfacesite/plugin.htmlcontains the plugin detail shellsite/publish.htmlcontains the publishing guidesite/assets/css/style.cssis the shared visual systemsite/assets/js/shared.jscontains shared browser behaviorsite/assets/js/engagement.jscontains the credential-free engagement API clientsite/assets/js/app.js,plugin.js,publish.js, andsearch.jscontain page-specific behaviorregistry.jsonis the curated registry and the source of marketplace metadata- Upstream plugin
manifest.jsonfiles are the source of plugin-owned metadata scripts/build-catalog.mjscombines registry and upstream datasite/catalog.jsonandsite/assets/img/plugins/are generated build outputssharpis the build-only image dependency; source previews are normalized into card and detail WebP variantspackage.jsondefines the Node.js engine, project commands, and direct development dependenciespackage-lock.jsonpins the complete transitive npm dependency graph and integrity hashes used bynpm ciSECURITY.mdis the unified security policy: it defines private vulnerability reporting, public reporting boundaries, high-level scope, and the deterministic scanner policy, limits, outcomes, enforcement, exact-SHA rules, and contributor requirementsVERIFICATION.mddefines the public meaning, request flow, publication safeguards, and display contract forVerifiedandUnverifiedSUBMISSION.mddefines the public command-line and AI-assisted submission contractworker/src/index.js,worker/migrations/, andworker/wrangler.example.jsoncdefine the approved engagement service, D1 schema, and credential-free deployment templatePLAN.mdis the living implementation and security roadmap; current code, tests, workflows, and focused policy documents remain authoritative for implemented behavior
Do not manually edit generated catalog data or preview assets. Change their source or build logic, then regenerate them. Do not include unrelated catalog drift in a UI-only change.
Use npm ci for reproducible installs and CI. Do not hand-edit package-lock.json. When an explicitly approved dependency or other lockfile-represented field changes, update package.json and regenerate and review package-lock.json together. Script or metadata-only package.json changes may legitimately leave the lockfile unchanged. Do not commit a dependency change without its corresponding lockfile update, or a lockfile change that cannot be explained by the manifest.
- Run
git status --short --branchbefore editing - Read the relevant source, tests, and nearby patterns
- Make the smallest coherent change that solves the request
- Preserve unrelated user changes in a dirty worktree
- Verify the change according to its risk
- Report changed behavior, verification, and remaining limitations
Avoid broad cleanup, formatting passes, renamed files, and dependency updates during a focused change. Ask before expanding the task into a redesign or architectural change.
When asked to inspect, audit, diagnose, or verify, do not edit files, regenerate outputs, commit, amend, or push unless explicitly requested. Read-only commands, tests, temporary local servers, and screenshots under /tmp are allowed when needed for verification. Stop temporary processes after the review.
Use the existing HTML, CSS, and JavaScript patterns. Reuse design tokens and existing components before adding new ones.
Preserve the visual language:
- Monospace typography for navigation, commands, identifiers, and technical metadata
- Black and neutral surfaces with restrained orange accents
- Thin borders, square controls, clear spacing, and no decorative clutter
- Strong information hierarchy without oversized promotional elements
- Existing dark and light themes
Keep interface copy short and functional. Match nearby capitalization and terminology. Do not translate the English interface unless the maintainer requests it.
The Ko-fi support action uses https://ko-fi.com/hancore. Keep it directly before Browse plugins in the desktop header. It uses the same dimensions and typography as the other navigation links, an orange status dot, and the established orange hover treatment. Keep Browse plugins visually primary; utility links may use the muted text color. Support is a desktop-header action; do not add it to the mobile bottom navigation unless the maintainer requests it.
External links that open a new tab must use target="_blank" and rel="noreferrer". Add an accessible name when the visible label does not fully describe the destination.
The header uses three intentional states:
0–760 px: hide desktop navigation links and use the mobile bottom navigation761–879 px: keep desktop navigation on one line and hide thePLUGIN MARKETPLACEbrand suffix880 pxand wider: show the full brand and desktop navigation
Do not let navigation labels wrap. Keep arrows attached to their labels. Adding or renaming a navigation item requires a fresh width review.
For header or layout changes, render at least these widths:
320,375, and760 px761,800,850,879, and880 px1024and1440 px
Check these invariants:
- No horizontal page scroll
- No overlap, clipping, or unexpected two-line controls
- No isolated arrows or detached icons
- Stable header and mobile navigation heights
- Visible hover and keyboard-focus states
- Usable dark and light themes
- Motion respects
prefers-reduced-motion
Run npm run dev for local runtime review. The server listens on http://127.0.0.1:4173. Stop the server after the review unless the maintainer asks to keep it running.
Use semantic HTML and native controls. Preserve the skip link, landmark structure, visible focus indicators, keyboard navigation, accessible names, live status messages, and reduced-motion behavior.
Do not encode meaning through color alone. Decorative icons and dots need aria-hidden="true". Dynamic controls must expose their current state to assistive technology.
Verify hover, focus, active, empty, loading, error, and disabled states when a change affects them. Copy actions must keep visible and screen-reader-readable feedback.
Static assets use a ?v=YYYYMMDD-NN query string. Bump the version after the final asset change, not after each edit.
When CSS changes, update every HTML reference to style.css so all pages use the same version. When JavaScript changes, update every HTML or module import that references the changed file. Keep one version for coupled JavaScript changes.
Find all current references with:
rg -n '\?v=' site/*.html site/assets/js/*.jsDo not leave different cache versions for the same asset across pages.
Plugins run as unsandboxed upstream code. Never describe marketplace validation or maintainer approval as a security review. Keep the existing disclaimer visible wherever installation trust is discussed.
Treat registry, catalog, submission, and upstream manifest values as untrusted input. Escape every dynamic value inserted into HTML with the existing escapeHtml helper. Encode URL path segments with encodeURIComponent, build query strings with URLSearchParams, and reject unsupported URL protocols. Never render raw HTML supplied by a plugin repository.
New automated submissions use one public GitHub repository per plugin, with manifest.json, README, and license files at the repository root. Preserve the exact submission headings, checklist, controlled categories, and tags defined in SUBMISSION.md.
The Automated Security Baseline statically scans the exact validated commit without executing plugin code. The Automated Security Baseline section in SECURITY.md is the public policy for all contributors; keep implementation, reports, tests, and contributor documentation aligned with it. Preserve deterministic outcomes (passed, review-required, and needs-fixes), evidence templates, exact-SHA binding, and the required disclaimer. Do not use AI to determine outcomes, enforcement, labels, or approval. Selective enforcement determines verified-publication label disposition: every new listing must be published through approved-and-verified, a current passed result is automatic, a complete review-required disposition for capabilities or non-selectively-blocking findings requires exact authorized maintainer attestation, and selectively blocking findings or scan failures block publication until resolved. Existing-snapshot maintainer-verified remains capability-only. Treat executable binaries as review capabilities, narrowly scoped root-owned helpers as review cases rather than automatic blockers, and execution sourced only from the submitted repository as self-installation requiring review rather than as external mutable-code rejection.
Security module boundaries are deliberate. security-baseline-policy.mjs is the single owner of policy version, marker protocol, finding/capability catalogs, outcome, enforcement, and label disposition. security-baseline-record.mjs is the only stored-record and marker converter, while verification-review.mjs exclusively validates maintainer-review attestations against canonical records. security-github-snapshot.mjs encapsulates bounded GitHub transport, security-baseline-scope.mjs owns deterministic file selection, security-baseline-analysis.mjs owns static findings and capabilities, and security-baseline-scanner.mjs only orchestrates scope plus analysis. security-baseline.mjs is the compatible CLI/facade. verification-subject.mjs resolves exact source-wide scan plans by configured plugin ID, and catalog-verification.mjs is the only catalog status projection. Manifest paths from mutable catalog refreshes are hints only. Catalog projection must require the exact registry plugin set for a source and fail closed on stale extra entries. Domain modules must not import filesystem APIs, sharp, workflows, or build-catalog.mjs. Approval and verification must persist identical canonical baseline records.
The registry stores automated baseline facts, including record schema, repository, affected plugin IDs, finding IDs, and capability IDs. Keep authorized maintainer verification separate as a canonical maintainerVerificationReview attestation bound to the exact bot-authored pre-label report, baseline repository, plugin IDs, commit, policy version, enforcement mode, prior and current scan times, outcome, accepted finding set, accepted capability set, and exact label-event identity and request time. Initial submissions and plugin updates use approved-and-verified and may attest complete selective review dispositions; existing-snapshot verification uses maintainer-verified and remains capability-only. All actions must reuse the same attestation validator and exact-evidence rules. Store the reviewer and review time for auditability, but never add a freely editable verified flag. Failed scans, stale evidence, mismatches, and selectively blocking findings have no review bypass. The baseline applies only to the current exact marketplace snapshot. Scheduled catalog refreshes still inspect upstream branch HEAD for compatibility and do not refresh the stored baseline. A different observed commit must display as Update unverified, while the old verified evidence remains attached to its snapshot. One public verification Issue form routes the recorded-snapshot and newer-upstream actions to separate internal workflows. Only the newer-upstream action may enter the guarded update workflow and promote a new commit; it preserves superseded evidence in listingValidationHistory. Derive snapshot verification from either a current-version passed baseline with empty finding and capability sets or an exact eligible maintainer-review attestation. Both paths describe only the exact listed commit, never trust or later upstream code. After a valid listing, update, or verification path succeeds, the responsible workflow automatically tests and publishes the canonical registry/catalog update and deploys the tested Pages artifact.
Root community plugins default to the generated standard Omarchy install command. Current Omarchy install and update commands obtain mutable upstream HEAD and do not accept an exact marketplace SHA, so UI copy must identify them as current-upstream and not verification-bound. Never imply that the command installs the verified snapshot. Use a manual installation override only when that command cannot produce a functioning plugin, such as when a required native binary is absent or a mandatory build must run before enablement. Optional feature setup, credentials, API configuration, data sources, bar placement, and layout customization do not make an otherwise functioning plugin manual. A curated plugins.<id>.installation override in registry.json must contain exactly mode: "manual" and a non-empty user-facing note. Manual overrides must not publish arbitrary installer commands, apply only to root plugin repositories, and must keep installation disabled and the curated note intact across passed, failed, and unreachable upstream checks. During automated listing review, apply manual-setup before approved-and-verified; approval maps that maintainer decision to the registry override. approved-for-listing is a legacy audit label and must not publish new submissions.
The catalog build performs live GitHub requests and may change generated files when upstream repositories change. Run npm run build for catalog, registry, validation, or generation changes. Do not run it for a UI-only change unless the UI change depends on new generated output.
Approval builds refresh only the exact approved repository and preserve all unrelated catalog and preview state. Scheduled refreshes remain the only full-source catalog scan. Each workflow must build and test once, upload that exact site/ tree as an immutable Pages artifact, and deploy without rebuilding. Keep dependency installation and repository code out of write-token jobs. Never rebase generated changes after tests: if main moved, fail and rebuild from the new base. GitHub API rate-limit exhaustion and forbidden API access are fatal build errors; they must not degrade sources to repository-unreachable or produce a catalog artifact. Submission validation consumes pre-provisioned labels and must not rewrite repository label metadata on every run; use the maintainer-only provision-labels.yml workflow to create or repair the required labels. Validation, approval publication, verification, and scheduled refresh workflows share the plugin-catalog-writes concurrency group so mutable issue state cannot be analyzed in parallel with publication. route-issue-automation.yml is the only workflow with a direct issues trigger. It selects one reusable issue workflow for supported events, but it is not an authorization boundary: every called workflow must independently preserve its existing event, actor, issue-state, evidence, replay, and permission checks.
Optional source previews may use root preview.png, preview.jpg, preview.jpeg, preview.webp, or preview.avif. The build enforces a 50 MB and 40 megapixel input limit, strips metadata, and generates separate card and detail WebP files. Do not optimize source screenshots manually or preserve unreferenced generated previews.
Never commit credentials, GitHub tokens, temporary issue bodies, downloaded audit data, or local screenshots.
Run the test suite for every code or content change:
npm testRun every whitespace check that matches the current Git state:
- New untracked file:
git diff --no-index --check /dev/null path/to/file; inspect the output because status1also means the files differ - Uncommitted changes:
git diff --check - Staged changes:
git diff --cached --check - Unpublished committed changes:
git diff --check origin/main..HEAD - Single amended commit:
git diff --check HEAD^ HEAD
Also run the relevant checks:
- UI or CSS: runtime review at the affected viewport matrix
- Catalog or registry:
npm run build, then inspect generated changes and rerun tests - Submission workflow: validate successful and rejected input paths
- GitHub Actions: preserve least-privilege permissions, pinned action commits, timeouts, and concurrency controls
Structural tests that match HTML, CSS, or JavaScript source do not replace runtime browser verification for visual or responsive changes.
Do not claim a check passed unless you ran it after the final change.
Do not commit, amend, push, open an issue, or create a pull request without explicit maintainer approval. Approval for one action does not authorize later actions.
Use concise imperative commit subjects. Stage only files that belong to the requested change. Do not amend a published commit or force-push main.
The scheduled catalog workflow can add commits to main at any time. Before every push:
- Run
git fetch origin main - Inspect
git status --short --branchand the local/remote graph - Rebase the unpublished local commit onto
origin/mainwhen the histories diverge - Resolve conflicts without discarding remote catalog updates
- Rerun tests and every applicable whitespace check
- Push normally, never with force
- Confirm that
git rev-list --left-right --count origin/main...mainreports0 0
A push to main triggers the GitHub Pages build, tests, and production deployment. Treat the push as a production change and report the final commit hash.
A change is complete when:
- The requested behavior works in the relevant states and viewports
- Accessibility and existing visual conventions remain intact
- Cache-busting references match changed assets
- Tests and every applicable whitespace check pass
- Generated changes are intentional and reviewed
- The worktree contains no unintended files
- Commit, push, and deployment status are reported accurately
Update this file when a durable architecture, design, workflow, or maintainer decision changes.