@awesomate/hosting-mcp 0.10.0 → 0.12.0
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/dist/index.js +81 -13
- package/package.json +1 -1
- package/skill/awesomate-app-builder/SKILL.md +25 -7
- package/skill/awesomate-github/SKILL.md +27 -1
- package/skill/awesomate-github/scripts/vc-healthcheck.mjs +102 -0
- package/skill/awesomate-hosting/SKILL.md +49 -15
- package/skill/awesomate-hosting/scripts/deploy.sh +1 -1
- package/skill/awesomate-hosting/scripts/pull-live.sh +1 -1
package/dist/index.js
CHANGED
|
@@ -40111,29 +40111,43 @@ readTool(
|
|
|
40111
40111
|
"Usage vs plan limits across every dimension (sites, custom domains, apps, database provisions today, workflow credits, AI-editor credits) plus a nudges[] array. Call BEFORE any create action; when a nudge has severity 'approaching' or 'exceeded', surface it to the user with the recommended plan \u2014 never execute an upgrade without preview + explicit confirmation (upgrade tools ship in a later release; for now deep-link to the hub billing page). pgProvisionsToday is a flat daily cap that resets within 24h \u2014 no plan raises it, so don't pitch an upgrade for it.",
|
|
40112
40112
|
"/api/client-hosting/limits"
|
|
40113
40113
|
);
|
|
40114
|
+
var PLAN_LADDER_FALLBACK = {
|
|
40115
|
+
note: "Live per-account limits come from awesomate_get_limits \u2014 this is the plan ladder reference (static fallback).",
|
|
40116
|
+
plans: [
|
|
40117
|
+
{ name: "Essentials", purchasable: false, monthlyPriceUsd: 75, maxSites: 1, maxCustomDomains: 1, maxApps: 0, cpanelAccess: true, shellAccess: false, appBuilder: false },
|
|
40118
|
+
{ name: "Support Plus", purchasable: true, monthlyPriceUsd: 175, maxSites: 2, maxCustomDomains: 5, maxApps: 5, cpanelAccess: true, shellAccess: true, appBuilder: true },
|
|
40119
|
+
{ name: "Pro", purchasable: true, monthlyPriceUsd: 375, maxSites: 10, maxCustomDomains: 20, maxApps: 20, cpanelAccess: true, shellAccess: true, appBuilder: true },
|
|
40120
|
+
{ name: "Embedded", purchasable: false, monthlyPriceUsd: null, maxSites: 100, maxCustomDomains: 100, maxApps: 100, cpanelAccess: true, shellAccess: true, appBuilder: true, note: "Not generally available yet" }
|
|
40121
|
+
],
|
|
40122
|
+
upgradePath: "Essentials \u2192 Support Plus \u2192 Pro \u2192 Embedded; upgrades at hub.awesomate.ai/billing (only Support Plus and Pro are purchasable)"
|
|
40123
|
+
};
|
|
40114
40124
|
server.registerTool(
|
|
40115
40125
|
"awesomate_get_plan_features",
|
|
40116
40126
|
{
|
|
40117
|
-
description: "
|
|
40127
|
+
description: "The Awesomate plan ladder: what each plan includes for hosting (WordPress sites, custom domains, hosted apps, cPanel, shell/Claude Code access) and which plans are purchasable. Fetched live from the hub (single source of truth) with a static fallback. Use to explain what an upgrade unlocks; live per-account usage comes from awesomate_get_limits.",
|
|
40118
40128
|
inputSchema: {}
|
|
40119
40129
|
},
|
|
40120
|
-
async () =>
|
|
40121
|
-
|
|
40122
|
-
|
|
40123
|
-
|
|
40124
|
-
|
|
40125
|
-
|
|
40126
|
-
|
|
40127
|
-
|
|
40128
|
-
|
|
40129
|
-
|
|
40130
|
+
async () => {
|
|
40131
|
+
try {
|
|
40132
|
+
const live = await hubGet(requireConfig(), "/api/client-hosting/plan-ladder");
|
|
40133
|
+
if (Array.isArray(live?.plans) && live.plans.length > 0) {
|
|
40134
|
+
return textResult({
|
|
40135
|
+
note: "Live plan ladder from the hub. Per-account usage comes from awesomate_get_limits.",
|
|
40136
|
+
...live,
|
|
40137
|
+
upgradePath: PLAN_LADDER_FALLBACK.upgradePath
|
|
40138
|
+
});
|
|
40139
|
+
}
|
|
40140
|
+
} catch {
|
|
40141
|
+
}
|
|
40142
|
+
return textResult(PLAN_LADDER_FALLBACK);
|
|
40143
|
+
}
|
|
40130
40144
|
);
|
|
40131
40145
|
server.registerTool(
|
|
40132
40146
|
"awesomate_snapshot_site",
|
|
40133
40147
|
{
|
|
40134
40148
|
description: "Snapshot a WordPress site (files + database) BEFORE any risky change \u2014 an AI edit, a deploy, a plugin/theme/core update. Returns a snapshotId you can roll back to. ALWAYS snapshot before mutating a live site. Requires shell access (Support Plus+).",
|
|
40135
40149
|
inputSchema: {
|
|
40136
|
-
domain: external_exports.string().describe("The site domain (as shown by awesomate_list_sites), e.g. mysite.awesomate.
|
|
40150
|
+
domain: external_exports.string().describe("The site domain (as shown by awesomate_list_sites), e.g. mysite.awesomate.site"),
|
|
40137
40151
|
reason: external_exports.string().optional().describe('Why (stored in the snapshot list), e.g. "before deploy"')
|
|
40138
40152
|
}
|
|
40139
40153
|
},
|
|
@@ -40180,6 +40194,60 @@ server.registerTool(
|
|
|
40180
40194
|
}
|
|
40181
40195
|
}
|
|
40182
40196
|
);
|
|
40197
|
+
server.registerTool(
|
|
40198
|
+
"awesomate_site_staging_create",
|
|
40199
|
+
{
|
|
40200
|
+
description: "Create a staging copy of a WordPress site on the client's private awesomate.dev address (files + database cloned, URLs rewritten). Use this BEFORE making user-facing changes so the user can review at the staging URL first \u2014 post to dev, review, then awesomate_site_staging_promote. The staging site is hidden from search engines and AI crawlers by policy; anyone with the link can view it. One staging copy per site \u2014 a 409 with code 'staging_exists' means promote or discard the existing one first. Cloning can take a few minutes on large sites. Requires shell access (Support Plus+).",
|
|
40201
|
+
inputSchema: {
|
|
40202
|
+
domain: external_exports.string().describe("The LIVE site domain (as shown by awesomate_list_sites), e.g. mysite.awesomate.site")
|
|
40203
|
+
}
|
|
40204
|
+
},
|
|
40205
|
+
async ({ domain }) => {
|
|
40206
|
+
try {
|
|
40207
|
+
return textResult(
|
|
40208
|
+
await hubPost(requireConfig(), `/api/hosting-access/sites/${encodeURIComponent(domain)}/staging`, {})
|
|
40209
|
+
);
|
|
40210
|
+
} catch (err) {
|
|
40211
|
+
return errorResult(err);
|
|
40212
|
+
}
|
|
40213
|
+
}
|
|
40214
|
+
);
|
|
40215
|
+
server.registerTool(
|
|
40216
|
+
"awesomate_site_staging_promote",
|
|
40217
|
+
{
|
|
40218
|
+
description: "Publish the staging copy to the LIVE site (overwrites live files + database with staging). The live site is auto-snapshotted first \u2014 the result includes preSnapshotId, which awesomate_rollback_site can restore if anything looks wrong. **Confirm with the user before promoting \u2014 it replaces the live site.** Requires shell access (Support Plus+).",
|
|
40219
|
+
inputSchema: {
|
|
40220
|
+
domain: external_exports.string().describe("The LIVE site domain whose staging copy should go live")
|
|
40221
|
+
}
|
|
40222
|
+
},
|
|
40223
|
+
async ({ domain }) => {
|
|
40224
|
+
try {
|
|
40225
|
+
return textResult(
|
|
40226
|
+
await hubPost(requireConfig(), `/api/hosting-access/sites/${encodeURIComponent(domain)}/staging/promote`, {})
|
|
40227
|
+
);
|
|
40228
|
+
} catch (err) {
|
|
40229
|
+
return errorResult(err);
|
|
40230
|
+
}
|
|
40231
|
+
}
|
|
40232
|
+
);
|
|
40233
|
+
server.registerTool(
|
|
40234
|
+
"awesomate_site_staging_discard",
|
|
40235
|
+
{
|
|
40236
|
+
description: "Delete the staging copy of a site (staging WP install + its awesomate.dev address; the live site is untouched). **Confirm with the user before discarding \u2014 unpromoted staging changes are lost.** Requires shell access (Support Plus+).",
|
|
40237
|
+
inputSchema: {
|
|
40238
|
+
domain: external_exports.string().describe("The LIVE site domain whose staging copy should be discarded")
|
|
40239
|
+
}
|
|
40240
|
+
},
|
|
40241
|
+
async ({ domain }) => {
|
|
40242
|
+
try {
|
|
40243
|
+
return textResult(
|
|
40244
|
+
await hubDelete(requireConfig(), `/api/hosting-access/sites/${encodeURIComponent(domain)}/staging`)
|
|
40245
|
+
);
|
|
40246
|
+
} catch (err) {
|
|
40247
|
+
return errorResult(err);
|
|
40248
|
+
}
|
|
40249
|
+
}
|
|
40250
|
+
);
|
|
40183
40251
|
readTool(
|
|
40184
40252
|
"awesomate_app_context",
|
|
40185
40253
|
"Call FIRST before any app-builder work. Returns the connected account's plan, whether the app builder is unlocked (capability.appBuilder \u2014 Support Plus+), whether they have a cPanel hosting account yet, their existing apps, firstRun, and capability-aware next-step suggestions to offer the user. If appBuilder is false, relay the upgrade suggestion rather than attempting to build.",
|
|
@@ -40207,7 +40275,7 @@ server.registerTool(
|
|
|
40207
40275
|
server.registerTool(
|
|
40208
40276
|
"awesomate_app_create",
|
|
40209
40277
|
{
|
|
40210
|
-
description: "Provision a new app on the client's cPanel account. Choose the stack deliberately (see the awesomate-app-builder skill): kind 'static' = a single fast landing/lead page served straight from the docroot (no DB, no server process \u2014 pick this for brochure/landing/lead-capture); kind 'node' = a dynamic app with a backend + database (logins, custom logic, an API). Pick the template by job \u2014 'node-auth-sync' (user accounts/logins, MySQL), 'node-crud-postgres' (structured data without logins: trackers/dashboards \u2014 ready-made CRUD + UI, Postgres), 'node-api-only' (webhooks/integrations/glue, no DB wiring), 'static-landing' (marketing/lead page). If dbEngine is omitted the template's native engine is used (node-crud-postgres \u2192 postgres). Returns 202 immediately with an appId + subdomain(s); poll awesomate_app_get until status=active, then fetch the starter files with awesomate_app_scaffold. Requires apps:write (Support Plus+) \u2014 a 403 means offer an upgrade. Get the user's confirmation on the stack + name before calling.",
|
|
40278
|
+
description: "Provision a new app on the client's cPanel account. Choose the stack deliberately (see the awesomate-app-builder skill): kind 'static' = a single fast landing/lead page served straight from the docroot (no DB, no server process \u2014 pick this for brochure/landing/lead-capture); kind 'node' = a dynamic app with a backend + database (logins, custom logic, an API). Pick the template by job \u2014 'node-auth-sync' (user accounts/logins, MySQL), 'node-crud-postgres' (structured data without logins: trackers/dashboards \u2014 ready-made CRUD + UI, Postgres), 'node-api-only' (webhooks/integrations/glue, no DB wiring), 'static-landing' (marketing/lead page). If dbEngine is omitted the template's native engine is used (node-crud-postgres \u2192 postgres). Returns 202 immediately with an appId + subdomain(s); poll awesomate_app_get until status=active, then fetch the starter files with awesomate_app_scaffold. Requires apps:write (Support Plus+) \u2014 a 403 means offer an upgrade. Plans also cap the NUMBER of apps (Support Plus 5, Pro 20 \u2014 check awesomate_get_limits.dimensions.apps first): a 409 with code 'app_limit' means the cap is reached \u2014 do NOT retry; tell the user their allowance is full and surface the recommendedPlan/deepLink from the error. Get the user's confirmation on the stack + name before calling.",
|
|
40211
40279
|
inputSchema: {
|
|
40212
40280
|
appSlug: external_exports.string().regex(/^[a-z][a-z0-9]{1,15}$/).describe("2-16 chars, starts with a letter, lowercase alphanumeric \u2014 used for subdomains + db names"),
|
|
40213
40281
|
kind: external_exports.enum(["node", "static"]).default("node").describe("'static' for a landing/lead page (no DB); 'node' for a dynamic app"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awesomate/hosting-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Awesomate MCP server — lets Claude manage your Awesomate WordPress hosting, plan, limits, n8n automations, and build Node/static apps + databases",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -87,12 +87,22 @@ target; never touch prod without an explicit ask.**
|
|
|
87
87
|
[references/node-recipes.md](references/node-recipes.md) has the recipes
|
|
88
88
|
(add a table/endpoint, env vars, connection strings, promote/rollback).
|
|
89
89
|
Handle **secrets** only via the **awesomate-credentials** skill
|
|
90
|
-
(encrypted + injected, never committed/echoed).
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
90
|
+
(encrypted + injected, never committed/echoed). **Version control is not
|
|
91
|
+
optional**: as soon as the scaffold exists, run the awesomate-github setup
|
|
92
|
+
(repo + first commit + push-to-deploy) — ask only the project name and
|
|
93
|
+
private-y/n, in plain words ("I'll back your work up as we go"). From then
|
|
94
|
+
on, **auto-checkpoint**: commit after every working change with a message
|
|
95
|
+
you write, and run the github skill's `vc-healthcheck.mjs` at session start
|
|
96
|
+
and before every deploy. If it needs email/lookup/AI, attach n8n (§"when to
|
|
97
|
+
use n8n").
|
|
98
|
+
6. **Testing — always ask "live or dev?" before posting anything.** When the
|
|
99
|
+
user asks to publish/change something user-facing, ask: *"Want this on your
|
|
100
|
+
live site, or on your dev site (awesomate.dev) to review and test first?"*
|
|
101
|
+
Recommend dev. Deploy to **dev** (`git push` to `dev` — the dev site lives
|
|
102
|
+
at `{app}.{slug}.awesomate.dev`, hidden from search engines and AI crawlers
|
|
103
|
+
by policy), then `awesomate_app_health` to confirm it came up (Node:
|
|
104
|
+
`/api/ready`). Show the user the live dev URL and let them try it. Iterate
|
|
105
|
+
on dev until they're happy.
|
|
96
106
|
7. **Wrap-up / promote** — only when the user approves, promote **dev → staging
|
|
97
107
|
→ main** (merge + push per branch). `awesomate_app_deploy` reports the
|
|
98
108
|
branch→env map + last-deploy state. Prod is `main`. **Before merging to
|
|
@@ -113,8 +123,16 @@ files directly (no build step).
|
|
|
113
123
|
- Non-technical user: explain in plain words, one or two short questions at a
|
|
114
124
|
time, no unexplained jargon. Recommend; don't quiz them on architecture.
|
|
115
125
|
- Confirm the stack + name before `awesomate_app_create`. Default the target
|
|
116
|
-
to **dev**; never push to prod without an explicit ask
|
|
126
|
+
to **dev**; never push to prod without an explicit ask — and when they ask
|
|
127
|
+
to "post"/"publish" something, ask **"live or dev?"** first.
|
|
128
|
+
- You are the user's version-control expert (they don't know what a repo is):
|
|
129
|
+
set up GitHub right after the first build, auto-commit as you go, and run
|
|
130
|
+
the github skill's vc-healthcheck at session start + before deploys.
|
|
117
131
|
- A `403` on a write = plan gate (Support Plus+). Offer an upgrade, don't retry.
|
|
132
|
+
- A `409` with code `app_limit` = the plan's app allowance is full (Support
|
|
133
|
+
Plus 5, Pro 20 — `awesomate_app_context.limits` has the live numbers).
|
|
134
|
+
Don't retry; tell the user and surface the `recommendedPlan`/`deepLink`
|
|
135
|
+
from the error. Deleting an unused app also frees a slot.
|
|
118
136
|
- Never invent that a capability exists — read `awesomate_app_context` first.
|
|
119
137
|
- Never print a secret or commit a `.env` (the credentials + github skills
|
|
120
138
|
enforce this).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: awesomate-github
|
|
3
|
-
description: Set up GitHub version control for the user's app with zero Git knowledge required — connect their GitHub once, then create the repo, .gitignore, first commit and push-to-deploy for them. Use when the user says "connect GitHub", "back up my app", "save my work", "set up version control", "put this on GitHub", or after building an app when it should be version-controlled. Companion to awesomate-app-builder.
|
|
3
|
+
description: Set up GitHub version control for the user's app with zero Git knowledge required — connect their GitHub once, then create the repo, .gitignore, first commit and push-to-deploy for them. Use when the user says "connect GitHub", "back up my app", "save my work", "set up version control", "put this on GitHub", or after building an app when it should be version-controlled — and proactively: run its vc-healthcheck at session start and before deploys to keep commits/pushes/deploys healthy for users who do not know Git. Companion to awesomate-app-builder.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Awesomate GitHub — version control for people who don't know Git
|
|
@@ -62,6 +62,32 @@ Explain it as *"save your work = it goes live"* — don't lecture on branches.
|
|
|
62
62
|
- "Put it live" → push to the right branch (dev/staging/main) and tell them the URL.
|
|
63
63
|
- Always write clear commit messages **for** them; don't ask them to.
|
|
64
64
|
|
|
65
|
+
## 4. Be the version-control guardian (proactive, not reactive)
|
|
66
|
+
|
|
67
|
+
The user is ~99% likely to have no idea what a repo is. YOU own their version
|
|
68
|
+
control — they should never have to think about it:
|
|
69
|
+
|
|
70
|
+
- **Health check at session start.** Before touching an app folder, run:
|
|
71
|
+
```
|
|
72
|
+
node ~/.claude/skills/awesomate-github/scripts/vc-healthcheck.mjs <project-dir>
|
|
73
|
+
```
|
|
74
|
+
It prints JSON (`problems[]`: `no_repo`, `no_remote`, `uncommitted_changes`,
|
|
75
|
+
`unpushed_commits`, `env_file_tracked`, `last_deploy_failed`, …). Fix what
|
|
76
|
+
you can silently (commit + push loose work with a message you write); for
|
|
77
|
+
`no_repo`/`no_remote`, offer setup (§1) in plain words: *"your last changes
|
|
78
|
+
aren't backed up anywhere — want me to set that up? Takes a minute."*
|
|
79
|
+
`env_file_tracked` is urgent: untrack it, .gitignore it, and route the
|
|
80
|
+
secrets through awesomate-credentials.
|
|
81
|
+
- **Auto-checkpoint.** After every meaningful working change (feature works,
|
|
82
|
+
bug fixed, content updated), commit with a plain-English message — don't
|
|
83
|
+
wait for "save my work", and never ask them to write a message. Push at
|
|
84
|
+
natural pauses so their backup is never behind.
|
|
85
|
+
- **Health check before every deploy/publish.** Re-run the script; never push
|
|
86
|
+
to a deploy branch with a failing prior run you haven't explained.
|
|
87
|
+
- **Report in their language.** "Your work is backed up" / "your last 3
|
|
88
|
+
changes were never saved — I've saved them now" — never "you're 2 commits
|
|
89
|
+
ahead of origin/main".
|
|
90
|
+
|
|
65
91
|
## Hard rules
|
|
66
92
|
- Never commit a secret or a `.env`. The script's secret guard is a backstop,
|
|
67
93
|
not a licence to skip checking. If you spot a secret, route it through the
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Version-control health check for an Awesomate app folder.
|
|
4
|
+
*
|
|
5
|
+
* Run from (or pass) the project directory. Prints a JSON report Claude uses
|
|
6
|
+
* to keep the user's version control healthy WITHOUT them knowing Git:
|
|
7
|
+
* - repo/remote wiring, uncommitted + unpushed work
|
|
8
|
+
* - branch → deploy-env mapping (dev → awesomate.dev, main → live)
|
|
9
|
+
* - last GitHub Actions deploy run (when `gh` is authed)
|
|
10
|
+
*
|
|
11
|
+
* Exit code 0 always (reporting tool, not a gate) — Claude decides what to
|
|
12
|
+
* fix based on the JSON.
|
|
13
|
+
*/
|
|
14
|
+
import { execSync } from 'node:child_process';
|
|
15
|
+
import { existsSync } from 'node:fs';
|
|
16
|
+
import { resolve } from 'node:path';
|
|
17
|
+
|
|
18
|
+
const dir = resolve(process.argv[2] ?? '.');
|
|
19
|
+
const report = {
|
|
20
|
+
dir,
|
|
21
|
+
gitInstalled: false,
|
|
22
|
+
repoInitialized: false,
|
|
23
|
+
remote: null,
|
|
24
|
+
branch: null,
|
|
25
|
+
uncommittedFiles: 0,
|
|
26
|
+
unpushedCommits: null, // null = unknown (no upstream)
|
|
27
|
+
hasUpstream: false,
|
|
28
|
+
envTracked: false,
|
|
29
|
+
ghAuthed: false,
|
|
30
|
+
lastDeployRun: null,
|
|
31
|
+
problems: [],
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
function sh(cmd) {
|
|
35
|
+
return execSync(cmd, { cwd: dir, stdio: ['ignore', 'pipe', 'pipe'], timeout: 15_000 })
|
|
36
|
+
.toString()
|
|
37
|
+
.trim();
|
|
38
|
+
}
|
|
39
|
+
function trySh(cmd) {
|
|
40
|
+
try {
|
|
41
|
+
return sh(cmd);
|
|
42
|
+
} catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (trySh('git --version') === null) {
|
|
48
|
+
report.problems.push('git_not_installed');
|
|
49
|
+
} else {
|
|
50
|
+
report.gitInstalled = true;
|
|
51
|
+
report.repoInitialized = trySh('git rev-parse --is-inside-work-tree') === 'true';
|
|
52
|
+
if (!report.repoInitialized) {
|
|
53
|
+
report.problems.push('no_repo');
|
|
54
|
+
} else {
|
|
55
|
+
report.branch = trySh('git branch --show-current') || '(detached)';
|
|
56
|
+
report.remote = trySh('git remote get-url origin');
|
|
57
|
+
if (!report.remote) report.problems.push('no_remote');
|
|
58
|
+
|
|
59
|
+
const status = trySh('git status --porcelain') ?? '';
|
|
60
|
+
report.uncommittedFiles = status ? status.split('\n').length : 0;
|
|
61
|
+
if (report.uncommittedFiles > 0) report.problems.push('uncommitted_changes');
|
|
62
|
+
|
|
63
|
+
// .env must never be tracked — the single most dangerous drift.
|
|
64
|
+
const tracked = trySh('git ls-files .env */.env') ?? '';
|
|
65
|
+
report.envTracked = tracked.length > 0;
|
|
66
|
+
if (report.envTracked) report.problems.push('env_file_tracked');
|
|
67
|
+
|
|
68
|
+
const upstream = trySh('git rev-parse --abbrev-ref @{upstream}');
|
|
69
|
+
report.hasUpstream = !!upstream;
|
|
70
|
+
if (upstream) {
|
|
71
|
+
const ahead = trySh('git rev-list --count @{upstream}..HEAD');
|
|
72
|
+
report.unpushedCommits = ahead === null ? null : Number(ahead);
|
|
73
|
+
if (report.unpushedCommits > 0) report.problems.push('unpushed_commits');
|
|
74
|
+
} else if (report.remote) {
|
|
75
|
+
report.problems.push('branch_not_pushed');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (report.remote && trySh('gh auth status') !== null) {
|
|
79
|
+
report.ghAuthed = true;
|
|
80
|
+
const runs = trySh(
|
|
81
|
+
'gh run list --limit 1 --json displayTitle,conclusion,headBranch,updatedAt',
|
|
82
|
+
);
|
|
83
|
+
try {
|
|
84
|
+
const parsed = JSON.parse(runs ?? '[]');
|
|
85
|
+
if (parsed[0]) {
|
|
86
|
+
report.lastDeployRun = parsed[0];
|
|
87
|
+
if (parsed[0].conclusion && parsed[0].conclusion !== 'success') {
|
|
88
|
+
report.problems.push('last_deploy_failed');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
} catch {
|
|
92
|
+
/* no runs / not parseable — fine */
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (!existsSync(resolve(dir, '.gitignore')) && report.repoInitialized) {
|
|
99
|
+
report.problems.push('no_gitignore');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
console.log(JSON.stringify(report, null, 2));
|
|
@@ -3,7 +3,7 @@ name: awesomate-hosting
|
|
|
3
3
|
description: >
|
|
4
4
|
Manage, build, and grow your Awesomate WordPress hosting from Claude. Use when
|
|
5
5
|
the user mentions their Awesomate site or hosting, cPanel, a site on
|
|
6
|
-
*.awesomate.io or a custom domain hosted with Awesomate, WordPress admin,
|
|
6
|
+
*.awesomate.site (or legacy *.site.awesomate.io) or a custom domain hosted with Awesomate, WordPress admin,
|
|
7
7
|
installing a plugin/theme, running WP-CLI, "my site is slow / out of space /
|
|
8
8
|
broke", snapshotting or rolling back a site, deploying from a local WordPress
|
|
9
9
|
Studio site to live, checking hosting stats or how close they are to a plan
|
|
@@ -11,7 +11,9 @@ description: >
|
|
|
11
11
|
plan. Trigger phrases: "my awesomate site", "connect my hosting", "spin up a
|
|
12
12
|
wordpress site", "install wordpress", "add my domain", "why is my site slow",
|
|
13
13
|
"am I near my limit", "snapshot my site", "roll back my site", "deploy to
|
|
14
|
-
live", "run wp-cli", "upgrade my plan", "how many sites can I have"
|
|
14
|
+
live", "run wp-cli", "upgrade my plan", "how many sites can I have",
|
|
15
|
+
"create a staging site", "test changes before going live", "publish staging",
|
|
16
|
+
"post this to my dev site".
|
|
15
17
|
---
|
|
16
18
|
|
|
17
19
|
# Awesomate Hosting
|
|
@@ -148,15 +150,18 @@ natural break so the richer MCP integration loads.
|
|
|
148
150
|
|
|
149
151
|
## 1. The plan model (so your nudges are accurate)
|
|
150
152
|
|
|
151
|
-
| Plan | WP sites | Custom domains | Shell / Claude Code | Notes |
|
|
152
|
-
|
|
153
|
-
| **Essentials** | 1 | 0 | **No** | read/status + upgrade nudges only |
|
|
154
|
-
| **Support Plus** |
|
|
155
|
-
| **Pro** |
|
|
156
|
-
| **Embedded** |
|
|
153
|
+
| Plan | WP sites | Hosted apps | Custom domains | Shell / Claude Code | Notes |
|
|
154
|
+
|---|---|---|---|---|---|
|
|
155
|
+
| **Essentials** | 1 | 0 | 0 | **No** | read/status + upgrade nudges only |
|
|
156
|
+
| **Support Plus** | 2 | 5 | 3 | **Yes** | shell, WP-CLI, snapshot/rollback, deploy, app builder |
|
|
157
|
+
| **Pro** | 10 | 20 | 10 | **Yes** | + higher limits |
|
|
158
|
+
| **Embedded** | 100 | 100 | 100 | **Yes** | agency tier, not generally available |
|
|
157
159
|
|
|
158
160
|
Authoritative limits are always what `awesomate_get_limits` returns for THIS
|
|
159
|
-
account
|
|
161
|
+
account (and `awesomate_get_plan_features` fetches the live ladder from the
|
|
162
|
+
hub) — never quote the table above as fact; use it only to explain upgrades.
|
|
163
|
+
App creation past the cap returns a 409 with code `app_limit` — don't retry;
|
|
164
|
+
surface the recommended plan instead.
|
|
160
165
|
|
|
161
166
|
## 2. Branch by capability
|
|
162
167
|
|
|
@@ -167,25 +172,34 @@ Allowed: `awesomate_get_context`, `_get_hosting_status`, `_get_hosting_account`,
|
|
|
167
172
|
`_get_hosting_stats`, `_get_grafana_url`, `_get_credit_balance`, the billing
|
|
168
173
|
preview/deep-link tools, and 1-click WP-admin / cPanel SSO links.
|
|
169
174
|
|
|
170
|
-
Never attempt SSH, WP-CLI, snapshot/rollback, deploy, multi-site
|
|
171
|
-
|
|
175
|
+
Never attempt SSH, WP-CLI, snapshot/rollback, staging, deploy, multi-site —
|
|
176
|
+
those tools will 403. Instead, surface the specific limit and what
|
|
172
177
|
Support Plus/Pro unlocks (see §4), and offer to preview the upgrade.
|
|
173
178
|
|
|
174
179
|
### Support Plus and above (shell) — full workflow
|
|
175
180
|
|
|
176
181
|
You additionally have: jailed SSH to the client's own cPanel account, WP-CLI
|
|
177
182
|
(`awesomate_run_wp_cli` or raw SSH via `scripts/ssh-connect.sh`),
|
|
178
|
-
snapshot/rollback,
|
|
183
|
+
snapshot/rollback, **WP staging on awesomate.dev** (§5a), and the local-first
|
|
184
|
+
deploy flow (§5). Golden rule, always:
|
|
179
185
|
|
|
180
186
|
> **Local first, live never — and snapshot before you touch live.**
|
|
181
187
|
|
|
188
|
+
**Ask "live or dev?" before posting anything user-facing.** When the user asks
|
|
189
|
+
you to change/publish something on their WordPress site, ask: *"Want me to put
|
|
190
|
+
this on your live site, or on your private dev copy (awesomate.dev) so you can
|
|
191
|
+
review it first?"* Default suggestion: dev first, publish after they've looked
|
|
192
|
+
at it. Their dev copy is invisible to Google and AI crawlers by policy.
|
|
193
|
+
|
|
182
194
|
## 3. Safety rules (non-negotiable)
|
|
183
195
|
|
|
184
196
|
- **Before ANY change to a live site** — plugin/theme/core update, `search-replace`,
|
|
185
197
|
bulk edit, deploy — call **`awesomate_snapshot_site`** first and tell the user the
|
|
186
198
|
`snapshotId`. If it goes wrong, `awesomate_rollback_site` restores files + DB.
|
|
187
199
|
- **Confirm before destructive actions**: `awesomate_uninstall_site`,
|
|
188
|
-
`awesomate_rollback_site`,
|
|
200
|
+
`awesomate_rollback_site`, `awesomate_site_staging_promote` (replaces live),
|
|
201
|
+
`awesomate_site_staging_discard` (loses unpublished staging work), dropping
|
|
202
|
+
tables, `wp db reset`, deleting content.
|
|
189
203
|
State exactly what will be lost and wait for an explicit "yes".
|
|
190
204
|
- Prefer building/testing in **WordPress Studio locally**, then deploy (§5).
|
|
191
205
|
- Dry-run risky WP-CLI where the command supports it before the real run.
|
|
@@ -211,8 +225,8 @@ one command — `scripts/deploy.sh`, which **snapshots live first** (so a bad
|
|
|
211
225
|
deploy is one rollback away), pushes files, then optionally the DB:
|
|
212
226
|
|
|
213
227
|
```
|
|
214
|
-
scripts/deploy.sh --from ~/Studio/mysite --domain mysite.awesomate.
|
|
215
|
-
scripts/deploy.sh --from ~/Studio/mysite --domain mysite.awesomate.
|
|
228
|
+
scripts/deploy.sh --from ~/Studio/mysite --domain mysite.awesomate.site # files only
|
|
229
|
+
scripts/deploy.sh --from ~/Studio/mysite --domain mysite.awesomate.site --with-db # + database
|
|
216
230
|
```
|
|
217
231
|
|
|
218
232
|
- **Always files-first is the safe default.** `--with-db` also exports the
|
|
@@ -227,6 +241,26 @@ scripts/deploy.sh --from ~/Studio/mysite --domain mysite.awesomate.io --with-db
|
|
|
227
241
|
Never deploy without confirming with the user first, and always report the
|
|
228
242
|
snapshot id and the verified live status.
|
|
229
243
|
|
|
244
|
+
## 5a. Staging on awesomate.dev (Support Plus+)
|
|
245
|
+
|
|
246
|
+
The middle tier between "edit live" and "local Studio": a private full copy of
|
|
247
|
+
the site at `{name}.{slug}.awesomate.dev`, noindexed at the edge (no Google, no
|
|
248
|
+
AI crawlers — anyone with the link can view, perfect for client review).
|
|
249
|
+
|
|
250
|
+
- `awesomate_site_staging_create <live domain>` — clones files + DB, rewrites
|
|
251
|
+
URLs. One staging copy per site (409 `staging_exists` → promote or discard
|
|
252
|
+
first). Takes a few minutes on large sites.
|
|
253
|
+
- Make the changes ON the staging domain (WP-CLI / wp-admin / deploy.sh with
|
|
254
|
+
`--domain <staging domain>`), send the user the staging URL to review.
|
|
255
|
+
- `awesomate_site_staging_promote <live domain>` — publishes staging over live.
|
|
256
|
+
Live is auto-snapshotted first; report the returned `preSnapshotId` as the
|
|
257
|
+
undo handle (`awesomate_rollback_site`). **Confirm before promoting.**
|
|
258
|
+
- `awesomate_site_staging_discard <live domain>` — deletes the staging copy;
|
|
259
|
+
live untouched. **Confirm — unpublished staging changes are lost.**
|
|
260
|
+
|
|
261
|
+
Prefer this flow over editing live whenever the change is user-visible
|
|
262
|
+
(theme/layout/content restructures, plugin experiments, redesigns).
|
|
263
|
+
|
|
230
264
|
## 6. Version control with GitHub (optional)
|
|
231
265
|
|
|
232
266
|
Awesomate's snapshots are your safety net, so Git isn't required — but for real
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# Awesomate site. SNAPSHOTS LIVE FIRST via the hub (so a bad deploy is one
|
|
5
5
|
# rollback away), then pushes files, then optionally the database.
|
|
6
6
|
#
|
|
7
|
-
# deploy.sh --from ~/Studio/mysite --domain mysite.awesomate.
|
|
7
|
+
# deploy.sh --from ~/Studio/mysite --domain mysite.awesomate.site [options]
|
|
8
8
|
#
|
|
9
9
|
# Options:
|
|
10
10
|
# --docroot PATH Live docroot (default: /home/<cpanel-user>/public_html)
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# from an existing live site). Read-only against live — it never changes the
|
|
5
5
|
# live site. Copies files + exports the live DB.
|
|
6
6
|
#
|
|
7
|
-
# pull-live.sh --domain mysite.awesomate.
|
|
7
|
+
# pull-live.sh --domain mysite.awesomate.site --to ~/Studio/mysite [--docroot PATH]
|
|
8
8
|
#
|
|
9
9
|
# Then import the files into a new WordPress Studio site and load db.sql.
|
|
10
10
|
# Client-side deps: bash, ssh, rsync, scp.
|