td-ai-tools 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/agents/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  ## Available Agent Packs
4
4
  - `horizon-component-library/`: Theory Digital Horizon component-library agent rules, with guard script.
5
+ - `component-library-section-blocks/`: Theory Digital component-library agent rules for section-block implementations, with guard script.
5
6
 
6
7
  ## Pack Structure Convention
7
8
  - `<pack-name>/AGENTS.md`
@@ -0,0 +1,176 @@
1
+ # .codex/AGENTS.md — Theory Digital
2
+
3
+ ## Scope
4
+ Default rules for Theory Digital component-library sections built with section blocks.
5
+
6
+ ## Core Principles
7
+ - Prefer isolated TD implementations over vendor patching.
8
+ - Keep responsibilities separated:
9
+ - Liquid derives and normalizes state.
10
+ - Markup renders only the active structure.
11
+ - CSS handles layout and presentation.
12
+ - JavaScript handles behavior only.
13
+ - Build the simplest implementation that satisfies the requirement.
14
+ - Keep DOM, CSS, and JS minimal and maintainable.
15
+ - Every change must be logged in `docs/changes.md`.
16
+
17
+ ## File Conventions
18
+ - Custom code must live in `td-` or `_td-` prefixed files only.
19
+ - Vendor files are READ-ONLY unless wrapped in TD CHANGE delimiters and documented in `docs/hotspots.md`.
20
+ - Custom sections: `sections/td-*.liquid`
21
+ - Custom snippets: `snippets/td-*.liquid`
22
+ - Put generic, reusable styles in `assets/td-base.css`.
23
+ - Use vendor code only when it already solves the requirement as-is.
24
+ - Otherwise, build an isolated TD implementation instead of patching vendor internals.
25
+
26
+ ## Forbidden
27
+ - Never use `{% include %}`. Use `{% render %}` only.
28
+ - Never add inline scripts to `layout/` files.
29
+ - Never import unapproved third-party JavaScript.
30
+ - Never add non-`td`-prefixed custom CSS variables.
31
+ - Never add non-`data-td-*` custom data attributes.
32
+ - Never declare unnecessary Liquid variables for single-use values.
33
+ - Never overload one setting to drive incompatible behaviors.
34
+ - Never emit parallel desktop/mobile or alternate-mode structures unless needed.
35
+ - Never rely on CSS alone to hide unused structural markup when Liquid can resolve it.
36
+ - Never let invalid or legacy state leak into classes, attributes, or CSS variables.
37
+ - Do not add redundant fallback guards or defensive reassignment for schema-backed primitive settings.
38
+ - Avoid unnecessary conditionals, wrappers, and listeners.
39
+
40
+ ## Required Patterns
41
+
42
+ ### JavaScript
43
+ - Author JavaScript via `{% javascript %}` and Web Components.
44
+ - When creating or modifying JavaScript, load and follow the `$td-js-vanilla-rules` skill.
45
+ - If `$td-js-vanilla-rules` is unavailable, enforce the JavaScript baseline rules in this file.
46
+ - Always guard custom element registration:
47
+ - `if (!customElements.get(...))`
48
+ - Always clean up in `disconnectedCallback`:
49
+ - event listeners
50
+ - timers
51
+ - observers
52
+ - external subscriptions
53
+ - Keep JavaScript minimal, event-driven, and component-scoped.
54
+
55
+ ### CSS
56
+ - Author CSS via `{% stylesheet %}` and CSS variables.
57
+ - All custom properties must use the `--td-*` prefix.
58
+ - Use BEM naming for all classes.
59
+ - Use BEM modifier classes for discrete state:
60
+ - mode
61
+ - layout
62
+ - alignment
63
+ - position
64
+ - variant
65
+ - Use CSS variables for dynamic values:
66
+ - sizes
67
+ - spacing
68
+ - offsets
69
+ - dimensions
70
+ - Use inline CSS variables only when truly dynamic.
71
+ - Keep CSS ordered as:
72
+ - shared/base rules
73
+ - mobile-only rules
74
+ - desktop-only rules
75
+
76
+ ### Liquid
77
+ - Derive and normalize state at the top of the file before rendering.
78
+ - Trust schema-backed primitive settings to provide valid values.
79
+ - Normalize only values that are:
80
+ - derived
81
+ - cross-dependent
82
+ - legacy-sensitive
83
+ - conditionally invalid
84
+ - externally sourced
85
+ - For straightforward values, prefer inline Liquid over one-time-use variables.
86
+ - Only introduce variables when they improve reuse, clarity, or state normalization.
87
+ - Use clear breakpoint-specific names when behavior differs by breakpoint.
88
+ - Use `default` only when truly needed.
89
+ - Support deterministic fallbacks:
90
+ - explicit setting
91
+ - product/metafield
92
+ - placeholder
93
+ - Do not output unresolved or invalid state into markup, classes, attributes, or CSS variables.
94
+
95
+ ### Markup
96
+ - Render only the active structure.
97
+ - Keep DOM output minimal.
98
+ - Accessibility baseline:
99
+ - use real buttons/links for interaction
100
+ - keep `aria-expanded` and `aria-controls` synchronized in JS
101
+ - support Escape to close interactive UI
102
+ - respect `prefers-reduced-motion`
103
+
104
+ ## Section Architecture Rules
105
+ - Resolve layout decisions in Liquid whenever possible.
106
+ - If desktop and mobile behavior differ, use separate schema settings.
107
+ - Use `visible_if` to improve settings organization only when the setting type supports it and the dependency is valid under Shopify schema rules.
108
+ - Do not rely on `visible_if` for behavior enforcement, required logic, or unsupported setting relationships.
109
+ - Normalize invalid settings defensively in Liquid.
110
+ - Use BEM modifier classes for discrete state and CSS variables for dynamic values.
111
+
112
+ ## Schema Rules
113
+ - All hardcoded values must be settings or metafields unless they are true implementation constants.
114
+ - Schema labels, options, and headers should use translation keys (`t:*`) whenever possible.
115
+ - Reuse existing `td` translation keys first.
116
+ - New translation keys must be created under the `td` namespace when needed.
117
+ - Keep new keys simple and reusable.
118
+ - Add `info` text only when the setting is not self-explanatory.
119
+ - Use `visible_if` only where supported and only for editor organization, not as a substitute for Liquid validation.
120
+ - Model schema around actual user-facing behavior.
121
+
122
+ ## Global Schema Requirements
123
+ - All sections must include padding settings.
124
+ - All sections must include color scheme picker settings.
125
+
126
+ ## Rendering Rules
127
+ - Image URL width must be 2x the displayed maximum width.
128
+ - Example:
129
+ - displayed max width `80px`
130
+ - `image_url: width: 160`
131
+ - Render only the assets and markup required for the active implementation.
132
+
133
+ ## Performance Rules
134
+ - Keep JavaScript minimal and event-driven.
135
+ - Avoid unnecessary listeners, observers, timers, and DOM work.
136
+ - Prefer solving state once in Liquid instead of repeatedly in CSS or JS.
137
+
138
+ ## Editor Rules
139
+ - Add Shopify editor hooks when needed:
140
+ - `shopify:block:select`
141
+ - `shopify:block:deselect`
142
+ - Interactive UI must work in both storefront and theme editor contexts.
143
+
144
+ ## Hard Output Gate
145
+ - For any edits in `sections/td-*.liquid` or `snippets/td-*.liquid`, run `.claude/agents/component-library-section-blocks/scripts/td-guard.sh` or `.agents/agents/component-library-section-blocks/scripts/td-guard.sh` (whichever exists) before final output.
146
+ - If `td-guard` fails, fix the code and rerun the guard before responding.
147
+
148
+ ## Guard Retry Budget
149
+ - Auto-fix attempts after a failing required guard are capped at 2 retries per task.
150
+ - If the guard still fails after 2 retries, stop and ask the user for direction.
151
+ - Do not continue retrying without new user input.
152
+
153
+ ## Escalation Message Format
154
+ - When retry budget is exhausted, report:
155
+ - failing check name
156
+ - exact failing files and lines
157
+ - fixes attempted
158
+ - one recommended next action
159
+
160
+ ## Pre-Output Checklist
161
+ - Custom code is isolated in TD-prefixed files.
162
+ - Vendor internals were not patched unless allowed and documented.
163
+ - State is derived and normalized at the top of the file.
164
+ - Schema-backed primitive settings are not wrapped in redundant fallback guards.
165
+ - One installed guard path passes when TD Liquid files were changed:
166
+ - `.claude/agents/component-library-section-blocks/scripts/td-guard.sh`
167
+ - `.agents/agents/component-library-section-blocks/scripts/td-guard.sh`
168
+ - Desktop/mobile differences use explicit settings where needed.
169
+ - Invalid or legacy states are normalized defensively.
170
+ - Markup renders only the active structure.
171
+ - CSS uses BEM modifier classes for discrete state and variables for dynamic values.
172
+ - Inline CSS variables are used only when necessary.
173
+ - Accessibility requirements are satisfied.
174
+ - Required assets are rendered where needed.
175
+ - Schema follows translation and visibility rules.
176
+ - All changes are logged in `docs/changes.md`.
@@ -0,0 +1,10 @@
1
+ # Horizon Component Library Agent
2
+
3
+ This folder contains the reusable agent policy and helper script for section-block-based Horizon component-library work.
4
+
5
+ ## Files
6
+ - `AGENTS.md`: Theory Digital agent rules for Horizon component-library section work using section blocks.
7
+ - `scripts/td-guard.sh`: Guard script referenced by the agent rules.
8
+
9
+ ## Related Skill
10
+ - `skills/td-js-vanilla-rules/`: JavaScript standards skill referenced by this agent (`$td-js-vanilla-rules`).
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
+ cd "$ROOT_DIR"
6
+
7
+ if ! command -v rg >/dev/null 2>&1; then
8
+ echo "ERROR: ripgrep (rg) is required for td-guard checks."
9
+ exit 1
10
+ fi
11
+
12
+ changed_files=()
13
+ while IFS= read -r file; do
14
+ changed_files+=("$file")
15
+ done < <(
16
+ {
17
+ git diff --name-only --diff-filter=ACMRTUXB HEAD
18
+ git ls-files --others --exclude-standard
19
+ } | awk 'NF' | awk '!seen[$0]++'
20
+ )
21
+
22
+ td_targets=()
23
+ for file in "${changed_files[@]}"; do
24
+ case "$file" in
25
+ sections/td-*.liquid|blocks/td-*.liquid|blocks/_td-*.liquid|snippets/td-*.liquid)
26
+ if [[ -f "$file" ]]; then
27
+ td_targets+=("$file")
28
+ fi
29
+ ;;
30
+ esac
31
+ done
32
+
33
+ if [[ "${#td_targets[@]}" -eq 0 ]]; then
34
+ echo "td-guard: no changed TD liquid files to validate."
35
+ exit 0
36
+ fi
37
+
38
+ schema_default_pattern='(section|block)\.settings\.[A-Za-z0-9_]+\s*\|\s*default\s*:'
39
+
40
+ schema_default_hits="$(rg -n --pcre2 "$schema_default_pattern" "${td_targets[@]}" || true)"
41
+ if [[ -n "$schema_default_hits" ]]; then
42
+ echo "td-guard: FAIL - redundant schema fallback detected in changed TD files."
43
+ echo "Rule: do not use '| default:' with schema-backed section/block settings."
44
+ echo ""
45
+ echo "$schema_default_hits"
46
+ exit 1
47
+ fi
48
+
49
+ echo "td-guard: PASS"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "td-ai-tools",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "Install agent skills and packs into your project",
5
5
  "scripts": {
6
6
  "smoke:install": "./scripts/smoke-install.sh"
@@ -18,6 +18,12 @@
18
18
  "engines": {
19
19
  "node": ">=16"
20
20
  },
21
- "keywords": ["claude", "agents", "skills", "shopify", "theory-digital"],
21
+ "keywords": [
22
+ "claude",
23
+ "agents",
24
+ "skills",
25
+ "shopify",
26
+ "theory-digital"
27
+ ],
22
28
  "license": "MIT"
23
29
  }
@@ -0,0 +1,99 @@
1
+ ---
2
+ name: forge-cli
3
+ description: Manage Laravel Forge servers, sites, and provisioned resources from the terminal with the Laravel Forge CLI, falling back to the Forge HTTP API (Statamic-relevant endpoints documented here) for anything the CLI does not cover. Use when the user wants to inspect Forge state, switch active servers, deploy sites, update environment variables, view logs, run remote commands, use Tinker, manage services like PHP, Nginx, daemons, and databases, or perform Statamic site setup tasks the CLI lacks a verb for (site/SSL/git/worker/scheduler/backup/recipe/composer-auth management).
4
+ ---
5
+
6
+ # Laravel Forge CLI
7
+
8
+ ## Core Workflow
9
+
10
+ 1. Start with `forge` to confirm the CLI is installed and to inspect available commands.
11
+ 2. Check the active server before making changes:
12
+
13
+ ```bash
14
+ forge server:current
15
+ forge server:list
16
+ forge server:switch staging
17
+ ```
18
+
19
+ 3. If the task needs SSH access, verify connectivity first:
20
+
21
+ ```bash
22
+ forge ssh:test
23
+ forge ssh:configure --key=/path/to/public/key.pub --name=workstation-name
24
+ ```
25
+
26
+ 4. Run the smallest command that answers the question or performs the requested change.
27
+ 5. After environment changes, note that cached Laravel config or queue workers may require a fresh deployment before the new values take effect.
28
+
29
+ ## Common Tasks
30
+
31
+ ### Sites and Deployments
32
+
33
+ ```bash
34
+ forge site:list
35
+ forge deploy
36
+ forge deploy example.com
37
+ forge deploy:logs
38
+ forge deploy:logs 12345
39
+ ```
40
+
41
+ ### Environment Variables
42
+
43
+ Pull, edit locally, then push back:
44
+
45
+ ```bash
46
+ forge env:pull
47
+ forge env:pull example.com .env
48
+ forge env:push
49
+ forge env:push example.com .env
50
+ ```
51
+
52
+ ### Logs, Commands, and Tinker
53
+
54
+ ```bash
55
+ forge site:logs
56
+ forge site:logs example.com --follow
57
+ forge command example.com --command="php artisan about"
58
+ forge tinker example.com
59
+ ```
60
+
61
+ ### SSH and Resource Access
62
+
63
+ ```bash
64
+ forge ssh
65
+ forge ssh server-name
66
+ forge database:status
67
+ forge database:logs
68
+ forge database:shell my-database-name --user=my-user
69
+ forge php:status 8.5
70
+ forge php:restart 8.5
71
+ forge nginx:logs access
72
+ forge daemon:restart
73
+ ```
74
+
75
+ ## Decision Guide
76
+
77
+ - Need server context first: use `server:current`, `server:list`, or `server:switch`.
78
+ - Need site-level work: use `site:list`, `deploy`, `env:*`, `site:logs`, `command`, or `tinker`.
79
+ - Need service health or maintenance: use `{resource}:status`, `{resource}:logs`, `{resource}:restart`, or `{resource}:shell`.
80
+ - Need a secure shell on the box: confirm `ssh:test`, then use `forge ssh`.
81
+ - Need something the CLI does not expose (creating sites, issuing SSL, wiring up workers, the Laravel scheduler, backups, recipes, Composer auth for Statamic Pro, etc.): drop down to the Forge HTTP API — see the API references below.
82
+
83
+ ## When the CLI Is Not Enough
84
+
85
+ The CLI is intentionally narrow. For Statamic site tasks it does not cover, call the Forge HTTP API directly. Authentication, IDs, and error handling are documented in [references/api-overview.md](references/api-overview.md); start there before reaching for an endpoint table.
86
+
87
+ Picking the right reference:
88
+
89
+ - Creating or reconfiguring a site, wiring a Git repo, editing the deployment script or Nginx, viewing deployment history, registering webhooks → [references/api-sites.md](references/api-sites.md).
90
+ - Queue workers, generic daemons, scheduled jobs, the Laravel scheduler integration, maintenance mode → [references/api-workers-and-scheduler.md](references/api-workers-and-scheduler.md).
91
+ - MySQL/Postgres databases, database users, scheduled backups, restores → [references/api-databases-and-backups.md](references/api-databases-and-backups.md).
92
+ - Let's Encrypt or imported certificates, HTTP basic auth security rules (e.g. locking down `/cp`) → [references/api-ssl-and-security.md](references/api-ssl-and-security.md).
93
+ - Installing/patching PHP, OPCache toggles, service start/stop/restart, server log files, saved Recipes, Composer auth for `composer.statamic.com` and other private repos → [references/api-php-services-recipes.md](references/api-php-services-recipes.md).
94
+
95
+ Operations not relevant to Statamic (WordPress installs, Horizon/Octane/Reverb/Pulse/Inertia SSR daemons, server provisioning, load balancers, deprecated MySQL endpoints) are deliberately omitted — fall back to the [official API docs](https://forge.laravel.com/api-documentation) if one of those comes up.
96
+
97
+ ## Reference
98
+
99
+ Read [references/command-reference.md](references/command-reference.md) when you need the fuller CLI command set, examples, or reminders about how the active server affects command behavior.
@@ -0,0 +1,48 @@
1
+ # Forge API — Databases, Database Users, Backups
2
+
3
+ Endpoint paths are relative to `https://forge.laravel.com/api/v1`.
4
+
5
+ Statamic context: many Statamic sites are flat-file and need none of this. Use these endpoints when the project uses Statamic Eloquent, search drivers like MySQL, runs Laravel auth tables, or simply needs MySQL/Postgres for app-level data.
6
+
7
+ ## Databases
8
+
9
+ | Operation | Method | Path | Body |
10
+ | --------------- | ------ | ----------------------------------------------------- | --------------------------------- |
11
+ | List | GET | `/servers/{serverId}/databases` | — |
12
+ | Create | POST | `/servers/{serverId}/databases` | required: `name`; optional: `user`, `password` (creates a user in one shot) |
13
+ | Get | GET | `/servers/{serverId}/databases/{databaseId}` | — |
14
+ | Delete | DELETE | `/servers/{serverId}/databases/{databaseId}` | Destructive — data is gone |
15
+ | Sync | POST | `/servers/{serverId}/databases/sync` | Reconcile Forge state with what's actually on the server (use if databases were created outside Forge) |
16
+
17
+ ## Database Users
18
+
19
+ | Operation | Method | Path | Body |
20
+ | --------------- | ------ | ------------------------------------------------------------- | ----------------------------------------------------------------- |
21
+ | List | GET | `/servers/{serverId}/database-users` | — |
22
+ | Create | POST | `/servers/{serverId}/database-users` | required: `name`, `password`, `databases[]` (array of DB IDs) |
23
+ | Get | GET | `/servers/{serverId}/database-users/{userId}` | — |
24
+ | Update | PUT | `/servers/{serverId}/database-users/{userId}` | optional: `databases[]` — replaces the access set |
25
+ | Delete | DELETE | `/servers/{serverId}/database-users/{userId}` | — |
26
+
27
+ To grant an existing user access to a new database, PUT the full list of database IDs you want it to have, not just the addition.
28
+
29
+ ## Backup Configurations
30
+
31
+ Forge can run scheduled mysqldump/pg_dump to S3, DigitalOcean Spaces, or any S3-compatible store. For a Statamic site backed by a database, this is the standard way to get off-server backups.
32
+
33
+ | Operation | Method | Path | Body / notes |
34
+ | --------------------- | ------ | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
35
+ | List configs | GET | `/servers/{serverId}/backup-configs` | — |
36
+ | Create config | POST | `/servers/{serverId}/backup-configs` | required: `provider` (`s3`, `spaces`, `custom`), `credentials`, `frequency`, `databases[]`; optional: `directory`, `email`, `retention` (number to keep) |
37
+ | Get config | GET | `/servers/{serverId}/backup-configs/{backupConfigurationId}` | — |
38
+ | Update config | PUT | `/servers/{serverId}/backup-configs/{backupConfigurationId}` | Same fields as create |
39
+ | Run backup now | POST | `/servers/{serverId}/backup-configs/{backupConfigurationId}` | Triggers a one-off run, on top of the schedule |
40
+ | Delete config | DELETE | `/servers/{serverId}/backup-configs/{backupConfigurationId}` | Stops future backups; does not remove existing archives from object storage |
41
+ | Restore one backup | POST | `/servers/{serverId}/backup-configs/{backupConfigurationId}/backups/{backupId}` | optional: `database` (specific DB ID to restore into) |
42
+ | Delete one backup | DELETE | `/servers/{serverId}/backup-configs/{backupConfigurationId}/backups/{backupId}` | Removes the archive from the remote store |
43
+
44
+ Notes:
45
+
46
+ - Statamic content lives on disk under `content/`, `assets/`, and (sometimes) `users/`. Database backups alone do not cover these — pair with a filesystem snapshot or Statamic's own backup add-on for full coverage.
47
+ - The `credentials` shape varies per provider (e.g. S3 wants `key`, `secret`, `region`, `bucket`). Check the Forge UI for the exact field names if creating from scratch.
48
+ - `frequency` accepts standard cron-style scheduling — confirm in the Forge UI before creating programmatically.
@@ -0,0 +1,90 @@
1
+ # Forge HTTP API Overview
2
+
3
+ Use this reference when the Forge CLI does not expose an operation you need. The CLI covers day-to-day deploys, env management, logs, restarts, and Tinker; the HTTP API covers everything else (site creation, PHP version changes, SSL issuance, workers, scheduler integration, backups, recipes, and more).
4
+
5
+ The API pages in this directory are scoped to operations that apply to **Statamic sites** (a Laravel-based flat-file or DB-backed CMS). WordPress, Octane, Reverb, Pulse, Horizon, Inertia SSR, load balancers, and server provisioning are intentionally omitted.
6
+
7
+ ## Authentication and Transport
8
+
9
+ - Base URL: `https://forge.laravel.com/api/v1`
10
+ - Header: `Authorization: Bearer <FORGE_API_TOKEN>`
11
+ - Always send `Accept: application/json` and, for write requests, `Content-Type: application/json`.
12
+ - Reuse the same `FORGE_API_TOKEN` the CLI uses. If it is not in the env, ask the user; do not try to read tokens from disk.
13
+
14
+ ```bash
15
+ curl -sS https://forge.laravel.com/api/v1/user \
16
+ -H "Authorization: Bearer $FORGE_API_TOKEN" \
17
+ -H "Accept: application/json"
18
+ ```
19
+
20
+ ## When to Use the API Instead of the CLI
21
+
22
+ | Need | CLI? | API? |
23
+ | --------------------------------------------- | --------------------- | ----------------------------------------------------------- |
24
+ | Deploy a site, view logs, push env | Yes | Optional |
25
+ | Create a new site / install a repo | No | Yes — `POST /servers/{id}/sites` + `POST .../git` |
26
+ | Change a site's PHP version | No | Yes — `PUT .../sites/{id}/php` |
27
+ | Issue or renew Let's Encrypt SSL | No | Yes — `POST .../certificates/letsencrypt` |
28
+ | Edit deployment script or Nginx config | No | Yes — `PUT .../deployment/script` or `PUT .../nginx` |
29
+ | Create queue workers, daemons, scheduled jobs | No | Yes |
30
+ | Enable Laravel scheduler or maintenance mode | No | Yes |
31
+ | Create/restore database backups | No | Yes |
32
+ | Run a saved Recipe across servers | No | Yes |
33
+ | Add a webhook for deploys | No | Yes |
34
+
35
+ Statamic note: many sites do not run a queue or scheduler. Only create workers, daemons, or scheduled jobs when the project actually defines queue connections or `php please schedule:run` tasks; do not provision them by default.
36
+
37
+ ## Finding IDs the API Needs
38
+
39
+ Almost every endpoint needs `serverId` and most need `siteId`. The CLI can supply both without separate API calls:
40
+
41
+ ```bash
42
+ forge server:list # → server IDs and names
43
+ forge server:current # → active server ID
44
+ forge site:list # → site IDs on the active server
45
+ ```
46
+
47
+ If scripting, list via API:
48
+
49
+ ```bash
50
+ curl -sS "$BASE/servers" # all servers on the account
51
+ curl -sS "$BASE/servers/$SERVER/sites" # all sites on a server
52
+ ```
53
+
54
+ ## Common Response Codes
55
+
56
+ | Code | Meaning |
57
+ | ---- | ------------------------------------------------------ |
58
+ | 200 | Success |
59
+ | 204 | Success with no body (e.g. delete, clear logs) |
60
+ | 400 | Request failed despite valid data |
61
+ | 401 | Invalid or missing API token |
62
+ | 404 | Resource not found (wrong server/site ID is the usual) |
63
+ | 422 | Validation error — body lists which fields are wrong |
64
+ | 429 | Rate-limited — back off and retry |
65
+ | 500 | Forge-side server error |
66
+
67
+ 422 responses include a JSON body of field-level errors. Read it before retrying.
68
+
69
+ ## Convention Used in These References
70
+
71
+ Each endpoint table shows:
72
+
73
+ - Method and path (relative to `https://forge.laravel.com/api/v1`)
74
+ - Required body fields, then optional ones
75
+ - Notes that are easy to miss (enum values, side effects, "this returns plain text not JSON", etc.)
76
+
77
+ Example invocation pattern used throughout:
78
+
79
+ ```bash
80
+ BASE="https://forge.laravel.com/api/v1"
81
+ AUTH=(-H "Authorization: Bearer $FORGE_API_TOKEN" -H "Accept: application/json")
82
+ JSON=(-H "Content-Type: application/json")
83
+
84
+ curl -sS "${AUTH[@]}" "${JSON[@]}" \
85
+ -X POST "$BASE/servers/$SERVER/sites/$SITE/deployment/deploy"
86
+ ```
87
+
88
+ ## Deprecation Notice
89
+
90
+ The official docs flag the v1 API as deprecated with a discontinuation date of June 30, 2026. Until a v2 is announced for general use, v1 is what the CLI itself targets and what these references describe. Re-check the [official API docs](https://forge.laravel.com/api-documentation) before doing migration work.
@@ -0,0 +1,88 @@
1
+ # Forge API — PHP, Services, Server Logs, Recipes, Composer Auth
2
+
3
+ Endpoint paths are relative to `https://forge.laravel.com/api/v1`.
4
+
5
+ ## PHP Versions on a Server
6
+
7
+ | Operation | Method | Path | Body / notes |
8
+ | ----------------- | ------ | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
9
+ | List installed | GET | `/servers/{serverId}/php` | Each entry has `status`, `displayable_version`, `binary_name`, and flags for default and CLI version |
10
+ | Install a version | POST | `/servers/{serverId}/php` | `version`: `php84`, `php83`, `php82`, `php81`, `php80`, `php74`, `php73`, `php72`, `php71`, `php70`, `php56` |
11
+ | Patch update | POST | `/servers/{serverId}/php/update` | `version`: same enum — patches the named major.minor to its latest point release |
12
+ | Enable OPCache | POST | `/servers/{serverId}/php/opcache` | Use in production after the site is stable; do not enable on dev servers where you're actively editing PHP |
13
+ | Disable OPCache | DELETE | `/servers/{serverId}/php/opcache` | — |
14
+
15
+ Statamic version floor — install the matching PHP version on the server before pointing a site at it:
16
+
17
+ | Statamic | Required PHP |
18
+ | -------- | ------------ |
19
+ | 4.x | 8.1+ |
20
+ | 5.x | 8.2+ |
21
+
22
+ After installing a new PHP version, set it on the site with `PUT /servers/{id}/sites/{siteId}/php` (`version`).
23
+
24
+ ## Service Control (start / stop / restart)
25
+
26
+ | Service | Method | Path | Body / notes |
27
+ | ------------------- | ------ | ------------------------------------------ | -------------------------------------------------- |
28
+ | MySQL reboot | POST | `/servers/{serverId}/mysql/reboot` | — |
29
+ | MySQL stop | POST | `/servers/{serverId}/mysql/stop` | — |
30
+ | Postgres reboot | POST | `/servers/{serverId}/postgres/reboot` | — |
31
+ | Postgres stop | POST | `/servers/{serverId}/postgres/stop` | — |
32
+ | Nginx reboot | POST | `/servers/{serverId}/nginx/reboot` | — |
33
+ | Nginx stop | POST | `/servers/{serverId}/nginx/stop` | — |
34
+ | Nginx test config | GET | `/servers/{serverId}/nginx/test` | Returns parse errors, if any. Run this before reloading after edits to site nginx blocks. |
35
+ | PHP-FPM reboot | POST | `/servers/{serverId}/php/reboot` | Body: `version` — same enum as PHP install |
36
+ | Generic start | POST | `/servers/{serverId}/services/start` | Body: service name |
37
+ | Generic stop | POST | `/servers/{serverId}/services/stop` | Body: service name |
38
+ | Generic restart | POST | `/servers/{serverId}/services/restart` | Body: service name |
39
+
40
+ After editing site Nginx config via the API, hit `GET .../nginx/test`. If it passes, `POST .../nginx/reboot` (or rely on Forge to reload — the API also accepts a reload via the update endpoint).
41
+
42
+ ## Server Logs
43
+
44
+ | Operation | Method | Path | Body / notes |
45
+ | --------------- | ------ | ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
46
+ | Read a log | GET | `/servers/{serverId}/logs` | Query `?file=` with one of `nginx_access`, `nginx_error`, `database`, `php7x`, `php56`. Returns a tail of the log as text. |
47
+
48
+ For day-to-day tailing, `forge nginx:logs`, `forge php:logs`, and `forge database:logs` are simpler than the API.
49
+
50
+ ## Recipes
51
+
52
+ Recipes are saved provisioning scripts you can run across one or many servers. Handy for installing extra extensions Statamic add-ons might require (Imagick variants, FFmpeg for video transcoding, GhostScript for PDF assets, etc.) without redoing manual SSH steps.
53
+
54
+ | Operation | Method | Path | Body |
55
+ | --------------- | ------ | ------------------------------------- | --------------------------------------------------------------------- |
56
+ | List | GET | `/recipes` | — |
57
+ | Create | POST | `/recipes` | required: `name`, `user`, `script` |
58
+ | Get | GET | `/recipes/{recipeId}` | — |
59
+ | Update | PUT | `/recipes/{recipeId}` | `name`, `user`, `script` |
60
+ | Delete | DELETE | `/recipes/{recipeId}` | — |
61
+ | Run | POST | `/recipes/{recipeId}/run` | `servers[]` (server IDs), `notify` (bool — email when finished) |
62
+
63
+ `user` is the OS user the script runs as (`root` for installing system packages, `forge` for user-scoped work).
64
+
65
+ ## Composer Package Authentication (per site)
66
+
67
+ Statamic Pro and many commercial add-ons live behind `https://composer.statamic.com` with a license-keyed username/password. Forge stores these as Composer auth credentials so deploys can install them.
68
+
69
+ | Operation | Method | Path | Body |
70
+ | --------------- | ------ | --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
71
+ | Get | GET | `/servers/{serverId}/sites/{siteId}/packages` | — |
72
+ | Update | PUT | `/servers/{serverId}/sites/{siteId}/packages` | `credentials[]` with `{repository_url, username, password}` per entry — PUT replaces the full list |
73
+
74
+ Typical Statamic entry:
75
+
76
+ ```json
77
+ {
78
+ "credentials": [
79
+ {
80
+ "repository_url": "composer.statamic.com",
81
+ "username": "<site-domain>",
82
+ "password": "<statamic-pro-license-key>"
83
+ }
84
+ ]
85
+ }
86
+ ```
87
+
88
+ After updating, trigger a deploy so `composer install` runs with the new auth.
@@ -0,0 +1,135 @@
1
+ # Forge API — Sites, Deployments, Git, Logs
2
+
3
+ Endpoint paths are relative to `https://forge.laravel.com/api/v1`. All requests carry the bearer token described in `api-overview.md`.
4
+
5
+ ## Sites
6
+
7
+ | Operation | Method | Path | Body |
8
+ | --------------- | ------ | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
9
+ | List sites | GET | `/servers/{serverId}/sites` | — |
10
+ | Create site | POST | `/servers/{serverId}/sites` | required: `domain`, `project_type` (`php` for Statamic, never `html`); optional: `aliases[]`, `directory` (default `/`), `isolated` (bool), `username`, `database`, `php_version`, `nginx_template` (`"default"` or template integer ID) |
11
+ | Get site | GET | `/servers/{serverId}/sites/{siteId}` | — |
12
+ | Update site | PUT | `/servers/{serverId}/sites/{siteId}` | optional: `directory`, `name`, `php_version`, `aliases[]`, `wildcards` (bool) |
13
+ | Delete site | DELETE | `/servers/{serverId}/sites/{siteId}` | — |
14
+ | Add aliases | PUT | `/servers/{serverId}/sites/{siteId}/aliases` | `aliases[]` — appends to existing list |
15
+ | Change PHP | PUT | `/servers/{serverId}/sites/{siteId}/php` | `version`: one of `php84`, `php83`, `php82`, `php81`, `php80`, `php74`, `php73`, `php72`, `php71`, `php70`, `php56`. Statamic 5 requires PHP 8.2+; Statamic 4 requires PHP 8.1+. |
16
+
17
+ Site creation for Statamic — minimal body:
18
+
19
+ ```json
20
+ {
21
+ "domain": "example.com",
22
+ "project_type": "php",
23
+ "directory": "/public",
24
+ "php_version": "php83",
25
+ "isolated": true
26
+ }
27
+ ```
28
+
29
+ Statamic projects deploy to a public-facing `/public` directory just like any Laravel app. `isolated: true` gives the site its own Linux user, which is the recommended setup for any production CMS.
30
+
31
+ ## Nginx Configuration
32
+
33
+ | Operation | Method | Path | Body / notes |
34
+ | ------------- | ------ | ------------------------------------------ | ----------------------------------------------------------- |
35
+ | Get nginx | GET | `/servers/{serverId}/sites/{siteId}/nginx` | Returns plain text, not JSON |
36
+ | Update nginx | PUT | `/servers/{serverId}/sites/{siteId}/nginx` | `content`: full file body. Forge validates before applying. |
37
+
38
+ Statamic-specific nginx tweaks live here: static-cache rewrite rules, `try_files` ordering, control panel route protection, `client_max_body_size` for asset uploads, etc. Always GET the current config first, edit, then PUT.
39
+
40
+ ## Environment File
41
+
42
+ | Operation | Method | Path | Body / notes |
43
+ | --------- | ------ | ---------------------------------------- | ------------------------------------------- |
44
+ | Get .env | GET | `/servers/{serverId}/sites/{siteId}/env` | Returns plain text |
45
+ | Put .env | PUT | `/servers/{serverId}/sites/{siteId}/env` | `content`: full file body |
46
+
47
+ Equivalent to `forge env:pull` / `forge env:push`. Prefer the CLI unless scripting from a context that cannot run the CLI.
48
+
49
+ If you change cached config (APP_KEY, queue/cache drivers, license keys) trigger a deploy afterwards — Statamic's stache and Laravel's config cache need to be rebuilt.
50
+
51
+ ## Git Project on a Site
52
+
53
+ | Operation | Method | Path | Body |
54
+ | --------------- | ------ | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
55
+ | Install repo | POST | `/servers/{serverId}/sites/{siteId}/git` | required: `provider` (`github`, `gitlab`, `gitlab-custom`, `bitbucket`, `custom`), `repository`, `branch`; optional: `composer` (bool — run `composer install`), `database` |
56
+ | Update repo | PUT | `/servers/{serverId}/sites/{siteId}/git` | required: `provider`, `repository`, `branch` |
57
+ | Remove repo | DELETE | `/servers/{serverId}/sites/{siteId}/git` | — |
58
+ | Create deploy key | POST | `/servers/{serverId}/sites/{siteId}/deploy-key` | Returns the SSH public key to add to the Git host |
59
+ | Delete deploy key | DELETE | `/servers/{serverId}/sites/{siteId}/deploy-key` | — |
60
+
61
+ When connecting a private Statamic repo, the typical flow is:
62
+
63
+ 1. `POST .../deploy-key` to mint the key.
64
+ 2. Paste the returned key into GitHub/GitLab as a read-only deploy key.
65
+ 3. `POST .../git` to install with `composer: true`.
66
+
67
+ ## Deployment
68
+
69
+ | Operation | Method | Path | Body / notes |
70
+ | --------------------- | ------ | ---------------------------------------------------------- | ------------------------------------------------------------------------- |
71
+ | Get deployment script | GET | `/servers/{serverId}/sites/{siteId}/deployment/script` | Plain text |
72
+ | Update deploy script | PUT | `/servers/{serverId}/sites/{siteId}/deployment/script` | `content`: full script; optional `auto_source` (bool) |
73
+ | Enable quick deploy | POST | `/servers/{serverId}/sites/{siteId}/deployment` | — |
74
+ | Disable quick deploy | DELETE | `/servers/{serverId}/sites/{siteId}/deployment` | — |
75
+ | Deploy now | POST | `/servers/{serverId}/sites/{siteId}/deployment/deploy` | Same as `forge deploy` |
76
+ | Reset deploy status | POST | `/servers/{serverId}/sites/{siteId}/deployment/reset` | Use when a previous deploy is stuck "in progress" |
77
+ | Latest deploy log | GET | `/servers/{serverId}/sites/{siteId}/deployment/log` | Plain text |
78
+
79
+ Common Statamic deploy script additions to remember when editing the script:
80
+
81
+ - `php please cache:clear` after dependencies install
82
+ - `php please stache:warm` to pre-build the Stache
83
+ - `php please assets:meta` if image presets changed
84
+ - `php artisan config:cache` / `route:cache` / `view:cache` for the Laravel layer
85
+ - Restart workers if any (`sudo -S service php8.x-fpm reload`)
86
+
87
+ ## Deployment History
88
+
89
+ | Operation | Method | Path | Notes |
90
+ | ---------------- | ------ | ------------------------------------------------------------------------------- | -------------------------------------- |
91
+ | List deploys | GET | `/servers/{serverId}/sites/{siteId}/deployment-history` | Returns commit, status, duration |
92
+ | Get one deploy | GET | `/servers/{serverId}/sites/{siteId}/deployment-history/{deploymentId}` | Metadata only |
93
+ | Get output | GET | `/servers/{serverId}/sites/{siteId}/deployment-history/{deploymentId}/output` | Plain-text script output for one run |
94
+
95
+ ## Site Commands
96
+
97
+ | Operation | Method | Path | Body / notes |
98
+ | ----------------- | ------ | ----------------------------------------------------------------- | ----------------------------------------------------- |
99
+ | Run command | POST | `/servers/{serverId}/sites/{siteId}/commands` | `command`: string, runs from site root |
100
+ | List history | GET | `/servers/{serverId}/sites/{siteId}/commands` | Includes who ran each command and timestamps |
101
+ | Get one command | GET | `/servers/{serverId}/sites/{siteId}/commands/{commandId}` | Includes captured output |
102
+
103
+ Useful Statamic invocations to fire via this endpoint (or via `forge command`):
104
+
105
+ - `php please cache:clear`
106
+ - `php please stache:warm`
107
+ - `php please search:update --all`
108
+ - `php please assets:meta`
109
+ - `php please user:make ...` (only via SSH/Tinker if interactive prompts are needed)
110
+
111
+ ## Site Logs
112
+
113
+ | Operation | Method | Path | Notes |
114
+ | --------------- | ------ | --------------------------------------------- | ------------------------------ |
115
+ | Get logs | GET | `/servers/{serverId}/sites/{siteId}/logs` | Returns the Laravel log tail |
116
+ | Clear logs | DELETE | `/servers/{serverId}/sites/{siteId}/logs` | 204 on success |
117
+
118
+ For follow / tail, prefer `forge site:logs --follow` — the API returns a snapshot only.
119
+
120
+ ## Webhooks
121
+
122
+ | Operation | Method | Path | Body / notes |
123
+ | ---------------- | ------ | ---------------------------------------------------------- | -------------------------------------------------- |
124
+ | List | GET | `/servers/{serverId}/sites/{siteId}/webhooks` | — |
125
+ | Create | POST | `/servers/{serverId}/sites/{siteId}/webhooks` | `url`: receiver. Fired on deployment events. |
126
+ | Get | GET | `/servers/{serverId}/sites/{siteId}/webhooks/{id}` | — |
127
+ | Delete | DELETE | `/servers/{serverId}/sites/{siteId}/webhooks/{id}` | — |
128
+
129
+ ## Deployment Failure Notifications
130
+
131
+ | Operation | Method | Path | Body |
132
+ | ----------------- | ------ | --------------------------------------------------------------------- | ------------- |
133
+ | Set emails | POST | `/servers/{serverId}/sites/{siteId}/deployment-failure-emails` | `emails[]` |
134
+
135
+ Posting again replaces the prior list.
@@ -0,0 +1,41 @@
1
+ # Forge API — SSL Certificates and Security Rules
2
+
3
+ Endpoint paths are relative to `https://forge.laravel.com/api/v1`.
4
+
5
+ ## SSL Certificates
6
+
7
+ A Statamic site needs HTTPS in production. Let's Encrypt is the default path; the API also supports importing or cloning a paid certificate.
8
+
9
+ | Operation | Method | Path | Body / notes |
10
+ | ----------------------------- | ------ | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
11
+ | List | GET | `/servers/{serverId}/sites/{siteId}/certificates` | — |
12
+ | Get one | GET | `/servers/{serverId}/sites/{siteId}/certificates/{id}` | — |
13
+ | Create new (CSR + key) | POST | `/servers/{serverId}/sites/{siteId}/certificates` | `type: "new"`, `domain`, `country`, `state`, `city`, `organization`, `department` |
14
+ | Install existing certificate | POST | `/servers/{serverId}/sites/{siteId}/certificates` | `type: "existing"`, `key`, `certificate` |
15
+ | Clone from another site | POST | `/servers/{serverId}/sites/{siteId}/certificates` | `type: "clone"`, `certificate_id` |
16
+ | Obtain Let's Encrypt | POST | `/servers/{serverId}/sites/{siteId}/certificates/letsencrypt` | required: `domains[]`; for wildcards or DNS-01 validation also send `dns_provider` (`cloudflare`, `route53`, `digitalocean`, `dnssimple`, `linode`, `ovh`, `google`) with the provider's credentials |
17
+ | Get CSR | GET | `/servers/{serverId}/sites/{siteId}/certificates/{id}/csr` | Plain-text CSR for the "new" flow |
18
+ | Install signed cert | POST | `/servers/{serverId}/sites/{siteId}/certificates/{id}/install` | required: `certificate`; optional: `add_intermediates` (bool) |
19
+ | Activate | POST | `/servers/{serverId}/sites/{siteId}/certificates/{id}/activate` | Swaps Nginx to use this cert |
20
+ | Delete | DELETE | `/servers/{serverId}/sites/{siteId}/certificates/{id}` | — |
21
+
22
+ Common Statamic flow:
23
+
24
+ 1. Make sure `aliases[]` on the site already lists every domain you intend to cover (`www.`, locales, etc.).
25
+ 2. `POST .../certificates/letsencrypt` with the matching `domains[]`.
26
+ 3. Forge auto-activates the new cert; verify with the list endpoint.
27
+
28
+ For wildcard certificates (e.g. multi-site Statamic with subdomain locales), DNS-01 with `dns_provider` is required — HTTP-01 cannot issue wildcards.
29
+
30
+ ## Security Rules (HTTP Basic Auth)
31
+
32
+ Useful for staging environments, locking down the Statamic control panel behind an extra credential, or shielding a pre-launch site.
33
+
34
+ | Operation | Method | Path | Body |
35
+ | --------------- | ------ | --------------------------------------------------------------- | ------------------------------------------------------------- |
36
+ | Create | POST | `/servers/{serverId}/sites/{siteId}/security-rules` | required: `name`, `credentials[]` (each `{username, password}`); optional: `path` (e.g. `/cp` to only protect the control panel) |
37
+ | List | GET | `/servers/{serverId}/sites/{siteId}/security-rules` | — |
38
+ | Get | GET | `/servers/{serverId}/sites/{siteId}/security-rules/{id}` | — |
39
+ | Delete | DELETE | `/servers/{serverId}/sites/{siteId}/security-rules/{id}` | — |
40
+
41
+ Tip: putting basic auth in front of `/cp` on top of Statamic's own user auth is a useful belt-and-braces defence on staging boxes that are reachable from the public internet but should not be discoverable. Remove the rule before going live so editors do not hit a double-auth wall.
@@ -0,0 +1,77 @@
1
+ # Forge API — Workers, Daemons, Scheduler, Maintenance
2
+
3
+ Endpoint paths are relative to `https://forge.laravel.com/api/v1`.
4
+
5
+ Statamic context: vanilla Statamic does not require queues or a scheduler. Only create these when the project's `config/queue.php` defines a non-`sync` connection (e.g. for Statamic Eloquent, search indexing, custom addons) or when `app/Console/Kernel.php` schedules work via `php please schedule:run`.
6
+
7
+ ## Queue Workers (per site)
8
+
9
+ | Operation | Method | Path | Body / notes |
10
+ | --------------- | ------ | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
11
+ | List | GET | `/servers/{serverId}/sites/{siteId}/workers` | — |
12
+ | Create | POST | `/servers/{serverId}/sites/{siteId}/workers` | required: `connection`, `timeout`, `sleep`, `tries`, `processes`, `stopwaitsecs`, `daemon` (bool), `force` (bool), `php_version`, `queue`; pass `php` as `php_version` to use the server CLI default |
13
+ | Get | GET | `/servers/{serverId}/sites/{siteId}/workers/{workerId}` | — |
14
+ | Restart | POST | `/servers/{serverId}/sites/{siteId}/workers/{workerId}/restart` | Use after a deploy if `daemon: true` |
15
+ | Delete | DELETE | `/servers/{serverId}/sites/{siteId}/workers/{workerId}` | — |
16
+ | Output | GET | `/servers/{serverId}/sites/{siteId}/workers/{workerId}/output` | Plain text — supervisor log |
17
+
18
+ Typical worker for a Statamic site that uses Redis queues:
19
+
20
+ ```json
21
+ {
22
+ "connection": "redis",
23
+ "queue": "default",
24
+ "timeout": 60,
25
+ "sleep": 3,
26
+ "tries": 3,
27
+ "processes": 1,
28
+ "stopwaitsecs": 10,
29
+ "daemon": true,
30
+ "force": false,
31
+ "php_version": "php"
32
+ }
33
+ ```
34
+
35
+ ## Daemons (server-wide)
36
+
37
+ Use these for long-running processes that are not Laravel queue workers — for example, an Inertia/Vite dev relay or a third-party service. For Laravel queues prefer the workers endpoint above so Forge wires up `queue:work` for you.
38
+
39
+ | Operation | Method | Path | Body |
40
+ | --------------- | ------ | ------------------------------------------------- | --------------------------------------------------------------------------------- |
41
+ | List | GET | `/servers/{serverId}/daemons` | — |
42
+ | Create | POST | `/servers/{serverId}/daemons` | required: `command`, `user`, `directory`; optional: `processes`, `startsecs`, `stopwaitsecs`, `stopsignal` |
43
+ | Get | GET | `/servers/{serverId}/daemons/{daemonId}` | — |
44
+ | Restart | POST | `/servers/{serverId}/daemons/{daemonId}/restart` | — |
45
+ | Delete | DELETE | `/servers/{serverId}/daemons/{daemonId}` | — |
46
+
47
+ ## Scheduled Jobs (server cron)
48
+
49
+ | Operation | Method | Path | Body / notes |
50
+ | --------------- | ------ | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
51
+ | List | GET | `/servers/{serverId}/jobs` | — |
52
+ | Create | POST | `/servers/{serverId}/jobs` | required: `command`, `frequency`, `user`. `frequency` ∈ `minutely`, `hourly`, `nightly`, `weekly`, `monthly`, `reboot`, `custom`. With `custom`, also send `minute`, `hour`, `day`, `month`, `weekday` (cron-style, `*` allowed). |
53
+ | Get | GET | `/servers/{serverId}/jobs/{jobId}` | — |
54
+ | Output | GET | `/servers/{serverId}/jobs/{jobId}/output` | Plain text |
55
+ | Delete | DELETE | `/servers/{serverId}/jobs/{jobId}` | — |
56
+
57
+ If the project uses the Laravel scheduler, prefer the integration endpoint below (single cron entry that calls `schedule:run`) over many individual jobs.
58
+
59
+ ## Laravel Scheduler Integration (per site)
60
+
61
+ This is the recommended way to enable `php please schedule:run` for a Statamic site. Forge writes a single `* * * * *` cron entry that calls the site's `schedule:run` and pipes output to `/dev/null`.
62
+
63
+ | Operation | Method | Path | Notes |
64
+ | --------------- | ------ | --------------------------------------------------------------------------------- | ------------------------------------------- |
65
+ | Status | GET | `/servers/{serverId}/sites/{siteId}/integrations/laravel-scheduler` | Reports whether the cron entry is present |
66
+ | Enable | POST | `/servers/{serverId}/sites/{siteId}/integrations/laravel-scheduler` | No body |
67
+ | Disable | DELETE | `/servers/{serverId}/sites/{siteId}/integrations/laravel-scheduler` | Removes the cron entry |
68
+
69
+ ## Laravel Maintenance Mode (per site)
70
+
71
+ Wraps `php artisan down` / `php artisan up`. Statamic sites inherit this from Laravel.
72
+
73
+ | Operation | Method | Path | Body |
74
+ | --------------- | ------ | --------------------------------------------------------------------------------- | --------------------------------------------------- |
75
+ | Status | GET | `/servers/{serverId}/sites/{siteId}/integrations/laravel-maintenance` | — |
76
+ | Enable | POST | `/servers/{serverId}/sites/{siteId}/integrations/laravel-maintenance` | optional: `secret` (bypass URL token), `status` (HTTP status code, default 503) |
77
+ | Disable | DELETE | `/servers/{serverId}/sites/{siteId}/integrations/laravel-maintenance` | — |
@@ -0,0 +1,176 @@
1
+ # Forge CLI Command Reference
2
+
3
+ This reference condenses the official Laravel Forge CLI documentation into the commands most likely to come up during support and operations work.
4
+
5
+ ## Installation and Authentication
6
+
7
+ Requirements:
8
+
9
+ - PHP 8.0 or newer
10
+ - Composer available on the machine
11
+
12
+ Install:
13
+
14
+ ```bash
15
+ composer global require laravel/forge-cli
16
+ ```
17
+
18
+ Basic checks:
19
+
20
+ ```bash
21
+ forge
22
+ ```
23
+
24
+ Authenticate:
25
+
26
+ ```bash
27
+ forge login
28
+ forge login --token=your-api-token
29
+ ```
30
+
31
+ CI authentication:
32
+
33
+ ```bash
34
+ export FORGE_API_TOKEN=your-api-token
35
+ ```
36
+
37
+ ## Active Server Model
38
+
39
+ Most Forge CLI commands run against the current active server. Check or change it before acting:
40
+
41
+ ```bash
42
+ forge server:current
43
+ forge server:list
44
+ forge server:switch
45
+ forge server:switch production
46
+ ```
47
+
48
+ Use this first when a task is ambiguous or when multiple Forge servers exist.
49
+
50
+ ## SSH Setup
51
+
52
+ Validate or configure SSH access for the `forge` user:
53
+
54
+ ```bash
55
+ forge ssh:test
56
+ forge ssh:configure
57
+ forge ssh:configure --key=/path/to/public/key.pub --name=laptop-key
58
+ forge ssh
59
+ forge ssh server-name
60
+ ```
61
+
62
+ ## Sites
63
+
64
+ List sites on the active server:
65
+
66
+ ```bash
67
+ forge site:list
68
+ ```
69
+
70
+ Deploy a site:
71
+
72
+ ```bash
73
+ forge deploy
74
+ forge deploy example.com
75
+ ```
76
+
77
+ Review deployment output:
78
+
79
+ ```bash
80
+ forge deploy:logs
81
+ forge deploy:logs 12345
82
+ ```
83
+
84
+ Manage environment variables:
85
+
86
+ ```bash
87
+ forge env:pull
88
+ forge env:pull example.com
89
+ forge env:pull example.com .env
90
+
91
+ forge env:push
92
+ forge env:push example.com
93
+ forge env:push example.com .env
94
+ ```
95
+
96
+ If the application uses Laravel config caching or queue workers, push alone is not enough. Redeploy so the new variables are actually loaded.
97
+
98
+ View application logs:
99
+
100
+ ```bash
101
+ forge site:logs
102
+ forge site:logs --follow
103
+ forge site:logs example.com
104
+ forge site:logs example.com --follow
105
+ ```
106
+
107
+ Run commands relative to the site's root:
108
+
109
+ ```bash
110
+ forge command
111
+ forge command example.com
112
+ forge command example.com --command="php artisan migrate --force"
113
+ ```
114
+
115
+ Open Tinker on a remote Laravel app:
116
+
117
+ ```bash
118
+ forge tinker
119
+ forge tinker example.com
120
+ ```
121
+
122
+ ## Resources
123
+
124
+ Forge exposes service-oriented commands with the pattern `{resource}:status`, `{resource}:logs`, `{resource}:restart`, and sometimes `{resource}:shell`.
125
+
126
+ ### Status
127
+
128
+ ```bash
129
+ forge daemon:status
130
+ forge database:status
131
+ forge nginx:status
132
+ forge php:status
133
+ forge php:status 8.5
134
+ ```
135
+
136
+ ### Logs
137
+
138
+ ```bash
139
+ forge daemon:logs
140
+ forge daemon:logs --follow
141
+ forge database:logs
142
+ forge nginx:logs
143
+ forge nginx:logs access
144
+ forge php:logs
145
+ forge php:logs 8.5
146
+ ```
147
+
148
+ ### Restart
149
+
150
+ ```bash
151
+ forge daemon:restart
152
+ forge database:restart
153
+ forge nginx:restart
154
+ forge php:restart
155
+ forge php:restart 8.5
156
+ ```
157
+
158
+ ### Local Shell Access to Resources
159
+
160
+ ```bash
161
+ forge database:shell
162
+ forge database:shell my-database-name
163
+ forge database:shell my-database-name --user=my-user
164
+ ```
165
+
166
+ ## Practical Usage Notes
167
+
168
+ - Prefer read-only commands first when the request is exploratory.
169
+ - Confirm the active server before running deploys, restarts, or environment pushes.
170
+ - Use explicit site names when there is any chance of ambiguity.
171
+ - Use `--follow` only when the user wants a live log tail.
172
+ - When sharing results back to the user, report the exact command run and whether it changed state.
173
+
174
+ ## Source
175
+
176
+ Official documentation: https://forge.laravel.com/docs/cli