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 +1 -0
- package/agents/component-library-section-blocks/AGENTS.md +176 -0
- package/agents/component-library-section-blocks/README.md +10 -0
- package/agents/component-library-section-blocks/scripts/td-guard.sh +49 -0
- package/package.json +8 -2
- package/skills/forge-cli/SKILL.md +99 -0
- package/skills/forge-cli/references/api-databases-and-backups.md +48 -0
- package/skills/forge-cli/references/api-overview.md +90 -0
- package/skills/forge-cli/references/api-php-services-recipes.md +88 -0
- package/skills/forge-cli/references/api-sites.md +135 -0
- package/skills/forge-cli/references/api-ssl-and-security.md +41 -0
- package/skills/forge-cli/references/api-workers-and-scheduler.md +77 -0
- package/skills/forge-cli/references/command-reference.md +176 -0
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.
|
|
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": [
|
|
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
|