opencastle 0.33.9 → 0.34.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.
Files changed (112) hide show
  1. package/dist/cli/init.d.ts.map +1 -1
  2. package/dist/cli/init.js +39 -17
  3. package/dist/cli/init.js.map +1 -1
  4. package/dist/cli/stack-config.d.ts.map +1 -1
  5. package/dist/cli/stack-config.js +5 -0
  6. package/dist/cli/stack-config.js.map +1 -1
  7. package/dist/cli/types.d.ts +1 -1
  8. package/dist/cli/types.d.ts.map +1 -1
  9. package/dist/orchestrator/plugins/cloudflare/config.d.ts +3 -0
  10. package/dist/orchestrator/plugins/cloudflare/config.d.ts.map +1 -0
  11. package/dist/orchestrator/plugins/cloudflare/config.js +23 -0
  12. package/dist/orchestrator/plugins/cloudflare/config.js.map +1 -0
  13. package/dist/orchestrator/plugins/coolify/config.d.ts +3 -0
  14. package/dist/orchestrator/plugins/coolify/config.d.ts.map +1 -0
  15. package/dist/orchestrator/plugins/coolify/config.js +28 -0
  16. package/dist/orchestrator/plugins/coolify/config.js.map +1 -0
  17. package/dist/orchestrator/plugins/drizzle/config.d.ts +3 -0
  18. package/dist/orchestrator/plugins/drizzle/config.d.ts.map +1 -0
  19. package/dist/orchestrator/plugins/drizzle/config.js +15 -0
  20. package/dist/orchestrator/plugins/drizzle/config.js.map +1 -0
  21. package/dist/orchestrator/plugins/expo/config.d.ts +3 -0
  22. package/dist/orchestrator/plugins/expo/config.d.ts.map +1 -0
  23. package/dist/orchestrator/plugins/expo/config.js +23 -0
  24. package/dist/orchestrator/plugins/expo/config.js.map +1 -0
  25. package/dist/orchestrator/plugins/index.d.ts.map +1 -1
  26. package/dist/orchestrator/plugins/index.js +12 -0
  27. package/dist/orchestrator/plugins/index.js.map +1 -1
  28. package/dist/orchestrator/plugins/sentry/config.d.ts +3 -0
  29. package/dist/orchestrator/plugins/sentry/config.d.ts.map +1 -0
  30. package/dist/orchestrator/plugins/sentry/config.js +28 -0
  31. package/dist/orchestrator/plugins/sentry/config.js.map +1 -0
  32. package/dist/orchestrator/plugins/stripe/config.d.ts +3 -0
  33. package/dist/orchestrator/plugins/stripe/config.d.ts.map +1 -0
  34. package/dist/orchestrator/plugins/stripe/config.js +42 -0
  35. package/dist/orchestrator/plugins/stripe/config.js.map +1 -0
  36. package/dist/orchestrator/plugins/types.d.ts +1 -1
  37. package/dist/orchestrator/plugins/types.d.ts.map +1 -1
  38. package/package.json +1 -1
  39. package/src/cli/init.ts +43 -22
  40. package/src/cli/stack-config.ts +5 -0
  41. package/src/cli/types.ts +1 -1
  42. package/src/dashboard/dist/data/convoys/demo-api-v2.json +3 -3
  43. package/src/dashboard/dist/data/convoys/demo-auth-revamp.json +4 -4
  44. package/src/dashboard/dist/data/convoys/demo-dashboard-ui.json +12 -12
  45. package/src/dashboard/dist/data/convoys/demo-data-pipeline.json +3 -3
  46. package/src/dashboard/dist/data/convoys/demo-deploy-ci.json +1 -1
  47. package/src/dashboard/dist/data/convoys/demo-docs-update.json +3 -3
  48. package/src/dashboard/dist/data/convoys/demo-perf-opt.json +4 -4
  49. package/src/dashboard/node_modules/.vite/deps/_metadata.json +6 -6
  50. package/src/dashboard/public/data/convoys/demo-api-v2.json +3 -3
  51. package/src/dashboard/public/data/convoys/demo-auth-revamp.json +4 -4
  52. package/src/dashboard/public/data/convoys/demo-dashboard-ui.json +12 -12
  53. package/src/dashboard/public/data/convoys/demo-data-pipeline.json +3 -3
  54. package/src/dashboard/public/data/convoys/demo-deploy-ci.json +1 -1
  55. package/src/dashboard/public/data/convoys/demo-docs-update.json +3 -3
  56. package/src/dashboard/public/data/convoys/demo-perf-opt.json +4 -4
  57. package/src/orchestrator/customizations/agents/skill-matrix.json +24 -4
  58. package/src/orchestrator/customizations/agents/skill-matrix.md +5 -0
  59. package/src/orchestrator/plugins/cloudflare/SKILL.md +111 -0
  60. package/src/orchestrator/plugins/cloudflare/config.ts +24 -0
  61. package/src/orchestrator/plugins/cloudflare/references/deployment.md +147 -0
  62. package/src/orchestrator/plugins/cloudflare/references/storage.md +118 -0
  63. package/src/orchestrator/plugins/cloudflare/references/workers.md +135 -0
  64. package/src/orchestrator/plugins/convex/SKILL.md +62 -20
  65. package/src/orchestrator/plugins/convex/references/auth-auth0.md +116 -0
  66. package/src/orchestrator/plugins/convex/references/auth-clerk.md +113 -0
  67. package/src/orchestrator/plugins/convex/references/auth-convex-auth.md +143 -0
  68. package/src/orchestrator/plugins/convex/references/auth-setup.md +87 -0
  69. package/src/orchestrator/plugins/convex/references/auth-workos.md +114 -0
  70. package/src/orchestrator/plugins/convex/references/components-advanced.md +134 -0
  71. package/src/orchestrator/plugins/convex/references/components.md +171 -0
  72. package/src/orchestrator/plugins/convex/references/function-budget.md +232 -0
  73. package/src/orchestrator/plugins/convex/references/hot-path-rules.md +371 -0
  74. package/src/orchestrator/plugins/convex/references/migrations-component.md +170 -0
  75. package/src/orchestrator/plugins/convex/references/migrations.md +259 -0
  76. package/src/orchestrator/plugins/convex/references/occ-conflicts.md +126 -0
  77. package/src/orchestrator/plugins/convex/references/performance-audit.md +80 -0
  78. package/src/orchestrator/plugins/convex/references/quickstart.md +176 -0
  79. package/src/orchestrator/plugins/convex/references/subscription-cost.md +252 -0
  80. package/src/orchestrator/plugins/coolify/SKILL.md +134 -0
  81. package/src/orchestrator/plugins/coolify/config.ts +29 -0
  82. package/src/orchestrator/plugins/coolify/references/applications.md +65 -0
  83. package/src/orchestrator/plugins/coolify/references/ci-cd-webhooks.md +73 -0
  84. package/src/orchestrator/plugins/coolify/references/databases-services.md +57 -0
  85. package/src/orchestrator/plugins/coolify/references/docker-compose.md +121 -0
  86. package/src/orchestrator/plugins/coolify/references/infrastructure.md +77 -0
  87. package/src/orchestrator/plugins/drizzle/SKILL.md +123 -0
  88. package/src/orchestrator/plugins/drizzle/config.ts +16 -0
  89. package/src/orchestrator/plugins/drizzle/references/migrations.md +112 -0
  90. package/src/orchestrator/plugins/drizzle/references/query-patterns.md +127 -0
  91. package/src/orchestrator/plugins/drizzle/references/schema-patterns.md +105 -0
  92. package/src/orchestrator/plugins/expo/SKILL.md +114 -0
  93. package/src/orchestrator/plugins/expo/config.ts +24 -0
  94. package/src/orchestrator/plugins/expo/references/eas-build.md +73 -0
  95. package/src/orchestrator/plugins/expo/references/native-modules.md +71 -0
  96. package/src/orchestrator/plugins/expo/references/routing.md +83 -0
  97. package/src/orchestrator/plugins/index.ts +12 -0
  98. package/src/orchestrator/plugins/linear/SKILL.md +21 -3
  99. package/src/orchestrator/plugins/sentry/SKILL.md +94 -0
  100. package/src/orchestrator/plugins/sentry/config.ts +29 -0
  101. package/src/orchestrator/plugins/sentry/references/error-patterns.md +112 -0
  102. package/src/orchestrator/plugins/sentry/references/performance.md +66 -0
  103. package/src/orchestrator/plugins/sentry/references/sdk-setup.md +108 -0
  104. package/src/orchestrator/plugins/stripe/SKILL.md +138 -0
  105. package/src/orchestrator/plugins/stripe/config.ts +43 -0
  106. package/src/orchestrator/plugins/stripe/references/api-patterns.md +57 -0
  107. package/src/orchestrator/plugins/stripe/references/projects-setup.md +30 -0
  108. package/src/orchestrator/plugins/stripe/references/upgrade-guide.md +105 -0
  109. package/src/orchestrator/plugins/types.ts +1 -1
  110. package/src/orchestrator/skills/backbone-scaffolding/EXAMPLES.md +1 -1
  111. package/src/orchestrator/skills/backbone-scaffolding/SKILL.md +32 -16
  112. package/src/orchestrator/plugins/convex/REFERENCE.md +0 -9
@@ -0,0 +1,252 @@
1
+ # Subscription Cost
2
+
3
+ Use these rules when the problem is too many reactive subscriptions, queries invalidating too frequently, or React components re-rendering excessively due to Convex state changes.
4
+
5
+ ## Core Principle
6
+
7
+ Every `useQuery` and `usePaginatedQuery` call creates a live subscription. The server tracks the query's read set and re-executes the query whenever any document in that read set changes. Subscription cost scales with:
8
+
9
+ `subscriptions x invalidation_frequency x query_cost`
10
+
11
+ Subscriptions are not inherently bad. Convex reactivity is often the right default. The goal is to reduce unnecessary invalidation work, not to eliminate subscriptions on principle.
12
+
13
+ ## Symptoms
14
+
15
+ - Dashboard shows high active subscription count
16
+ - UI feels sluggish or laggy despite fast individual queries
17
+ - React profiling shows frequent re-renders from Convex state
18
+ - Pages with many components each running their own `useQuery`
19
+ - Paginated lists where every loaded page stays subscribed
20
+
21
+ ## Common Causes
22
+
23
+ ### Reactive queries on low-freshness flows
24
+
25
+ Some user flows are read-heavy and do not need live updates every time the underlying data changes. In those cases, ongoing subscriptions may cost more than they are worth.
26
+
27
+ ### Overly broad queries
28
+
29
+ A query that returns a large result set invalidates whenever any document in that set changes. The broader the query, the more frequent the invalidation.
30
+
31
+ ### Too many subscriptions per page
32
+
33
+ A page with 20 list items, each running its own `useQuery` to fetch related data, creates 20+ subscriptions per visitor.
34
+
35
+ ### Paginated queries keeping all pages live
36
+
37
+ `usePaginatedQuery` with `loadMore` keeps every loaded page subscribed. On a page where a user has scrolled through 10 pages, all 10 stay reactive.
38
+
39
+ ### Frequently-updated fields on widely-read documents
40
+
41
+ A document that many queries touch gets a frequently-updated field (like `lastSeen`, `lastActiveAt`, or a counter). Every write to that field invalidates every subscription that reads the document, even if those subscriptions never use the field. This is different from OCC conflicts (see `occ-conflicts.md`), which are write-vs-write contention. This is write-vs-subscription: the write succeeds fine, but it forces hundreds of queries to re-run for no reason.
42
+
43
+ ## Fix Order
44
+
45
+ ### 1. Use point-in-time reads when live updates are not valuable
46
+
47
+ Keep `useQuery` and `usePaginatedQuery` by default when the product benefits from fresh live data.
48
+
49
+ Consider a point-in-time read instead when all of these are true:
50
+
51
+ - the flow is high-read
52
+ - the underlying data changes less often than users need to see
53
+ - explicit refresh, periodic refresh, or a fresh read on navigation is acceptable
54
+
55
+ Possible implementations depend on environment:
56
+
57
+ - a server-rendered fetch
58
+ - a framework helper like `fetchQuery`
59
+ - a point-in-time client read such as `ConvexHttpClient.query()`
60
+
61
+ ```ts
62
+ // Reactive by default when fresh live data matters
63
+ function TeamPresence() {
64
+ const presence = useQuery(api.teams.livePresence, { teamId });
65
+ return <PresenceList users={presence} />;
66
+ }
67
+ ```
68
+
69
+ ```ts
70
+ // Point-in-time read when explicit refresh is acceptable
71
+ import { ConvexHttpClient } from "convex/browser";
72
+
73
+ const client = new ConvexHttpClient(import.meta.env.VITE_CONVEX_URL);
74
+
75
+ function SnapshotView() {
76
+ const [items, setItems] = useState<Item[]>([]);
77
+
78
+ useEffect(() => {
79
+ client.query(api.items.snapshot).then(setItems);
80
+ }, []);
81
+
82
+ return <ItemGrid items={items} />;
83
+ }
84
+ ```
85
+
86
+ Good candidates for point-in-time reads:
87
+
88
+ - aggregate snapshots
89
+ - reports
90
+ - low-churn listings
91
+ - flows where explicit refresh is already acceptable
92
+
93
+ Keep reactive for:
94
+
95
+ - collaborative editing
96
+ - live dashboards
97
+ - presence-heavy views
98
+ - any surface where users expect fresh changes to appear automatically
99
+
100
+ ### 2. Batch related data into fewer queries
101
+
102
+ Instead of N components each fetching their own related data, fetch it in a single query.
103
+
104
+ ```ts
105
+ // Bad: each card fetches its own author
106
+ function ProjectCard({ project }: { project: Project }) {
107
+ const author = useQuery(api.users.get, { id: project.authorId });
108
+ return <Card title={project.name} author={author?.name} />;
109
+ }
110
+ ```
111
+
112
+ ```ts
113
+ // Good: parent query returns projects with author names included
114
+ function ProjectList() {
115
+ const projects = useQuery(api.projects.listWithAuthors);
116
+ return projects?.map((p) => (
117
+ <Card key={p._id} title={p.name} author={p.authorName} />
118
+ ));
119
+ }
120
+ ```
121
+
122
+ This can use denormalized fields or server-side joins in the query handler. Either way, it is one subscription instead of N.
123
+
124
+ This is not automatically better. If the combined query becomes much broader and invalidates much more often, several narrower subscriptions may be the better tradeoff. Optimize for total invalidation cost, not raw subscription count.
125
+
126
+ ### 3. Use skip to avoid unnecessary subscriptions
127
+
128
+ The `"skip"` value prevents a subscription from being created when the arguments are not ready.
129
+
130
+ ```ts
131
+ // Bad: subscribes with undefined args, wastes a subscription slot
132
+ const profile = useQuery(api.users.getProfile, { userId: selectedId! });
133
+ ```
134
+
135
+ ```ts
136
+ // Good: skip when there is nothing to fetch
137
+ const profile = useQuery(
138
+ api.users.getProfile,
139
+ selectedId ? { userId: selectedId } : "skip",
140
+ );
141
+ ```
142
+
143
+ ### 4. Isolate frequently-updated fields into separate documents
144
+
145
+ If a document is widely read but has a field that changes often, move that field to a separate document. Queries that do not need the field will no longer be invalidated by its writes.
146
+
147
+ ```ts
148
+ // Bad: lastSeen lives on the user doc, every heartbeat invalidates
149
+ // every query that reads this user
150
+ const users = defineTable({
151
+ name: v.string(),
152
+ email: v.string(),
153
+ lastSeen: v.number(),
154
+ });
155
+ ```
156
+
157
+ ```ts
158
+ // Good: lastSeen lives in a separate heartbeat doc
159
+ const users = defineTable({
160
+ name: v.string(),
161
+ email: v.string(),
162
+ heartbeatId: v.id("heartbeats"),
163
+ });
164
+
165
+ const heartbeats = defineTable({
166
+ lastSeen: v.number(),
167
+ });
168
+ ```
169
+
170
+ Queries that only need `name` and `email` no longer re-run on every heartbeat. Queries that actually need online status fetch the heartbeat document explicitly.
171
+
172
+ For an even further optimization, if you only need a coarse online/offline boolean rather than the exact `lastSeen` timestamp, add a separate presence document with an `isOnline` flag. Update it immediately when a user comes online, and use a cron to batch-mark users offline when their heartbeat goes stale. This way the presence query only invalidates when online status actually changes, not on every heartbeat.
173
+
174
+ ### 5. Use the aggregate component for counts and sums
175
+
176
+ Reactive global counts (`SELECT COUNT(*)` equivalent) invalidate on every insert or delete to the table. The [`@convex-dev/aggregate`](https://www.npmjs.com/package/@convex-dev/aggregate) component maintains denormalized COUNT, SUM, and MAX values efficiently so you do not need a reactive query scanning the full table.
177
+
178
+ Use it for leaderboards, totals, "X items" badges, or any stat that would otherwise require scanning many rows reactively.
179
+
180
+ If the aggregate component is not appropriate, prefer point-in-time reads for global stats, or precomputed summary rows updated by a cron or trigger, over reactive queries that scan large tables.
181
+
182
+ ### 6. Narrow query read sets
183
+
184
+ Queries that return less data and touch fewer documents invalidate less often.
185
+
186
+ ```ts
187
+ // Bad: returns all fields, invalidates on any field change
188
+ export const list = query({
189
+ handler: async (ctx) => {
190
+ return await ctx.db.query("projects").collect();
191
+ },
192
+ });
193
+ ```
194
+
195
+ ```ts
196
+ // Good: use a digest table with only the fields the list needs
197
+ export const listDigests = query({
198
+ handler: async (ctx) => {
199
+ return await ctx.db.query("projectDigests").collect();
200
+ },
201
+ });
202
+ ```
203
+
204
+ Writes to fields not in the digest table do not invalidate the digest query.
205
+
206
+ ### 7. Remove `Date.now()` from queries
207
+
208
+ Using `Date.now()` inside a query defeats Convex's query cache. The cache is invalidated frequently to avoid showing stale time-dependent results, which increases database work even when the underlying data has not changed.
209
+
210
+ ```ts
211
+ // Bad: Date.now() defeats query caching and causes frequent re-evaluation
212
+ const releasedPosts = await ctx.db
213
+ .query("posts")
214
+ .withIndex("by_released_at", (q) => q.lte("releasedAt", Date.now()))
215
+ .take(100);
216
+ ```
217
+
218
+ ```ts
219
+ // Good: use a boolean field updated by a scheduled function
220
+ const releasedPosts = await ctx.db
221
+ .query("posts")
222
+ .withIndex("by_is_released", (q) => q.eq("isReleased", true))
223
+ .take(100);
224
+ ```
225
+
226
+ If the query must compare against a time value, pass it as an explicit argument from the client and round it to a coarse interval (e.g. the most recent minute) so requests within that window share the same cache entry.
227
+
228
+ ### 8. Consider pagination strategy
229
+
230
+ For long lists where users scroll through many pages:
231
+
232
+ - If the data does not need live updates, use point-in-time fetching with manual "load more"
233
+ - If it does need live updates, accept the subscription cost but limit the number of loaded pages
234
+ - Consider whether older pages can be unloaded as the user scrolls forward
235
+
236
+ ### 9. Separate backend cost from UI churn
237
+
238
+ If the main problem is loading flash or UI churn when query arguments change, stabilizing the reactive UI behavior may be better than replacing reactivity altogether.
239
+
240
+ Treat this as a UX problem first when:
241
+
242
+ - the underlying query is already reasonably cheap
243
+ - the complaint is flicker, loading flashes, or re-render churn
244
+ - live updates are still desirable once fresh data arrives
245
+
246
+ ## Verification
247
+
248
+ 1. Subscription count in dashboard is lower for the affected pages
249
+ 2. UI responsiveness has improved
250
+ 3. React profiling shows fewer unnecessary re-renders
251
+ 4. Surfaces that do not need live updates are not paying for persistent subscriptions unnecessarily
252
+ 5. Sibling pages with similar patterns were updated consistently
@@ -0,0 +1,134 @@
1
+ ---
2
+ name: coolify-deployment
3
+ description: "Deploys applications, databases, and services on self-hosted Coolify instances, manages environments and env vars, runs infrastructure diagnostics, and performs batch operations. Use when deploying apps to Coolify, managing Coolify servers, debugging deployment issues, setting up databases, or managing Coolify infrastructure."
4
+ ---
5
+
6
+ # Coolify Deployment
7
+
8
+ ## Topic Routing
9
+
10
+ Read the matching reference before working on any of these topics:
11
+
12
+ | Topic | Reference |
13
+ |-------|-----------|
14
+ | Application deployment | `references/applications.md` |
15
+ | Database & service management | `references/databases-services.md` |
16
+ | Infrastructure & diagnostics | `references/infrastructure.md` |
17
+ | Docker Compose templates | `references/docker-compose.md` |
18
+ | CI/CD & Docker image deploys | `references/ci-cd-webhooks.md` |
19
+
20
+ ## Critical Rules
21
+
22
+ **Project Structure**
23
+ - Coolify organizes resources as: Server → Project → Environment → Resources (apps, databases, services)
24
+ - Always start with `get_infrastructure_overview` to understand the current state before making changes
25
+ - Use `projects` tool with action params (`list`, `get`, `create`) — one tool, multiple operations
26
+
27
+ **Application Deployment**
28
+ - Deploy from public repos, private GitHub repos (via GitHub App), SSH keys, or Docker images
29
+ - Configure health checks (path, interval, retries) during `application` create to avoid unhealthy deployments
30
+ - Use `deploy` with `force_rebuild: true` only when cache issues are suspected — normal deploys are faster
31
+ - Check deployment status with `deployment` action `list_for_app` after triggering a deploy
32
+
33
+ **Diagnostics**
34
+ - `diagnose_app` accepts name or domain (e.g., `"my-app"` or `"example.com"`) — not just UUIDs
35
+ - `diagnose_server` accepts name or IP address — use for connectivity and resource issues
36
+ - `find_issues` scans all infrastructure — use as a health check before and after changes
37
+
38
+ **Environment Variables**
39
+ - Use `env_vars` tool with `resource: "application"` or `resource: "service"` — supports `list`, `create`, `update`, `delete`
40
+ - `bulk_env_update` updates a variable across multiple apps at once — use for shared config like API URLs
41
+ - Env vars require app restart to take effect — use `control` with `action: "restart"` after updates
42
+
43
+ **Database Management**
44
+ - Supports 8 database types: PostgreSQL, MySQL, MariaDB, MongoDB, Redis, KeyDB, ClickHouse, Dragonfly
45
+ - Configure backup schedules via `database_backups` with `action: "create"` — set frequency and retention
46
+ - Backups can target S3-compatible storage — configure via backup schedule creation
47
+
48
+ **Security**
49
+ - Store `COOLIFY_ACCESS_TOKEN` in `.env` — never commit to source control
50
+ - Private keys for SSH deployments: manage via `private_keys` tool, never hardcode
51
+ - Use `validate_server` to verify SSH connectivity before deploying
52
+
53
+ **Docker Compose**
54
+ - Coolify supports two compose modes: Raw (paste YAML, no `build:`) and Repository (git URL, full features)
55
+ - Use magic variables (`SERVICE_PASSWORD_*`, `SERVICE_URL_*`) for auto-generated credentials and proxy URLs — never hardcode
56
+ - Remove `ports:` for proxied services — Traefik handles routing via `SERVICE_URL_NAME_PORT`
57
+
58
+ **CI/CD Integration**
59
+ - Trigger deploys via webhook with tag or UUID — use for automated pipelines
60
+ - Docker image deployments (`create_dockerimage`) skip the build step — use for pre-built images from registries
61
+
62
+ ## Workflow: Deploy Application
63
+
64
+ 1. **Survey** — `get_infrastructure_overview` → identify target server and project
65
+ 2. **Create project** (if needed) — `projects` action `create` with name and description
66
+ 3. **Create environment** — `environments` action `create` in the target project
67
+ 4. **Deploy** — `application` action `create_public` (or `create_github` / `create_dockerimage`) with health check config
68
+ 5. **Verify** — `deployment` action `list_for_app` → wait for `finished` status; if `failed` → `application_logs` → fix → redeploy
69
+ 6. **Set env vars** — `env_vars` resource `application` action `create` → `control` action `restart`
70
+ 7. **Validate** — `diagnose_app` by name → confirm status `running` and health check passing
71
+
72
+ ## Workflow: Diagnose & Fix
73
+
74
+ 1. **Scan** — `find_issues` → list all unhealthy resources
75
+ 2. **Investigate** — `diagnose_app` or `diagnose_server` with name/domain/IP
76
+ 3. **Check logs** — `application_logs` for the affected app
77
+ 4. **Fix** — update config, env vars, or redeploy as needed
78
+ 5. **Restart** — `control` resource `application` action `restart`
79
+ 6. **Verify** — `diagnose_app` again → confirm status `running`
80
+
81
+ ## Deployment Failure Recovery
82
+
83
+ ```
84
+ Deploy failed → check status
85
+ ├── Health check failing → verify health check path returns 200 → fix app → redeploy
86
+ ├── Build error → application_logs → fix Dockerfile/build config → deploy with force_rebuild
87
+ ├── Port conflict → check server_resources → update port mapping → redeploy
88
+ ├── SSH key invalid → validate_server → private_keys action update → retry
89
+ └── Out of resources → server diagnostics → scale server or stop unused apps
90
+ ```
91
+
92
+ ## Deploy Public Repo — Full Example
93
+
94
+ ```
95
+ # 1. Create app from public repo
96
+ application(
97
+ action="create_public",
98
+ project_uuid="proj-abc",
99
+ environment_name="production",
100
+ server_uuid="srv-xyz",
101
+ repository_url="https://github.com/org/my-app",
102
+ branch="main",
103
+ build_pack="dockerfile",
104
+ health_check_path="/health",
105
+ health_check_interval=30,
106
+ health_check_retries=3
107
+ )
108
+ # → returns { uuid: "app-123", status: "deploying" }
109
+
110
+ # 2. Set env vars
111
+ env_vars(resource="application", action="create", uuid="app-123", key="DATABASE_URL", value="postgres://...", is_preview=false)
112
+
113
+ # 3. Restart to pick up env vars
114
+ control(resource="application", action="restart", uuid="app-123")
115
+
116
+ # 4. Verify
117
+ diagnose_app(identifier="my-app")
118
+ # → status: "running", health_check: "healthy"
119
+ ```
120
+
121
+ ## MCP Config (VS Code)
122
+
123
+ ```json
124
+ {
125
+ "servers": {
126
+ "Coolify": {
127
+ "type": "stdio",
128
+ "command": "npx",
129
+ "args": ["-y", "@masonator/coolify-mcp"],
130
+ "envFile": "${workspaceFolder}/.env"
131
+ }
132
+ }
133
+ }
134
+ ```
@@ -0,0 +1,29 @@
1
+ import type { PluginConfig } from '../types.js';
2
+
3
+ export const config: PluginConfig = {
4
+ id: 'coolify',
5
+ name: 'Coolify',
6
+ category: 'tech',
7
+ subCategory: 'deployment',
8
+ label: 'Coolify',
9
+ hint: 'Self-hosted PaaS — deploy apps, databases, and services',
10
+ skillName: 'coolify-deployment',
11
+ mcpServerKey: 'Coolify',
12
+ mcpConfig: {
13
+ type: 'stdio',
14
+ command: 'npx',
15
+ args: ['-y', '@masonator/coolify-mcp'],
16
+ },
17
+ authType: 'env-token',
18
+ envVars: [
19
+ { name: 'COOLIFY_ACCESS_TOKEN', hint: 'Generate in Coolify Settings → API' },
20
+ { name: 'COOLIFY_BASE_URL', hint: 'Your Coolify instance URL (e.g. https://coolify.example.com)' },
21
+ ],
22
+ agentToolMap: {
23
+ 'developer': ['list_applications', 'get_application', 'application_logs', 'deploy'],
24
+ 'devops-expert': ['get_infrastructure_overview', 'diagnose_app', 'diagnose_server', 'find_issues', 'control', 'deploy', 'restart_project_apps'],
25
+ },
26
+ docsUrl: null,
27
+ officialDocs: 'https://coolify.io/docs',
28
+ mcpPackage: '@masonator/coolify-mcp',
29
+ };
@@ -0,0 +1,65 @@
1
+ # Application Deployment
2
+
3
+ ## Deployment Sources
4
+
5
+ | Source | Action | Key Args |
6
+ |--------|--------|----------|
7
+ | Public Git repo | `create_public` | `repository_url`, `branch` |
8
+ | GitHub App | `create_github` | `github_app_uuid`, `repository_url`, `branch` |
9
+ | SSH key | `create_key` | `private_key_uuid`, `repository_url`, `branch` |
10
+ | Docker image | `create_dockerimage` | `docker_image`, `docker_registry` |
11
+
12
+ ## Create Application
13
+
14
+ ```
15
+ application action="create_public"
16
+ project_uuid="<uuid>"
17
+ environment_name="production"
18
+ server_uuid="<uuid>"
19
+ repository_url="https://github.com/org/repo"
20
+ branch="main"
21
+ build_pack="dockerfile"
22
+ health_check_path="/health"
23
+ health_check_interval=30
24
+ health_check_retries=3
25
+ ```
26
+
27
+ ## Application Lifecycle
28
+
29
+ ```bash
30
+ # List all apps (summaries)
31
+ list_applications
32
+
33
+ # Full details for one app
34
+ get_application uuid="<uuid>"
35
+
36
+ # View logs
37
+ application_logs uuid="<uuid>" lines=100
38
+
39
+ # Deploy (with optional force rebuild)
40
+ deploy uuid="<uuid>" force_rebuild=true
41
+
42
+ # Restart/stop/start
43
+ control resource="application" action="restart" uuid="<uuid>"
44
+ ```
45
+
46
+ ## Environment Variables
47
+
48
+ ```bash
49
+ # List env vars
50
+ env_vars resource="application" action="list" uuid="<uuid>"
51
+
52
+ # Create env var
53
+ env_vars resource="application" action="create" uuid="<uuid>" key="DATABASE_URL" value="postgres://..." is_preview=false
54
+
55
+ # Bulk update across apps
56
+ bulk_env_update key="API_URL" value="https://api.example.com" uuids=["<uuid1>","<uuid2>"]
57
+ ```
58
+
59
+ ## Health Check Configuration
60
+
61
+ Always configure health checks to prevent deploying broken apps:
62
+
63
+ - `health_check_path` — endpoint that returns 200 (e.g., `/health`, `/api/health`)
64
+ - `health_check_interval` — seconds between checks (default: 30)
65
+ - `health_check_retries` — failures before marking unhealthy (default: 3)
@@ -0,0 +1,73 @@
1
+ # CI/CD & Docker Image Deployments
2
+
3
+ ## Webhook-Triggered Deployments
4
+
5
+ ```bash
6
+ # Trigger deploy by image tag
7
+ deploy_webhook tag="v1.2.3"
8
+
9
+ # Trigger deploy by application UUID
10
+ deploy_webhook uuid="<app-uuid>"
11
+ ```
12
+
13
+ REST API equivalent (outside MCP):
14
+ ```bash
15
+ # By tag
16
+ curl -H "Authorization: Bearer $COOLIFY_TOKEN" \
17
+ "$COOLIFY_URL/api/v1/deployments/deploy?tag=v1.2.3"
18
+
19
+ # By UUID
20
+ curl -H "Authorization: Bearer $COOLIFY_TOKEN" \
21
+ "$COOLIFY_URL/api/v1/deployments/deploy?uuid=<app-uuid>"
22
+ ```
23
+
24
+ ## Docker Image Deployment (no git repo)
25
+
26
+ ```
27
+ application action="create_dockerimage"
28
+ project_uuid="<uuid>"
29
+ environment_name="production"
30
+ server_uuid="<uuid>"
31
+ docker_image="nginx:latest"
32
+ docker_registry="docker.io"
33
+ health_check_path="/"
34
+ health_check_interval=30
35
+ health_check_retries=3
36
+ ```
37
+
38
+ **Private registry** (credentials configured in Coolify dashboard):
39
+ ```
40
+ application action="create_dockerimage"
41
+ project_uuid="<uuid>"
42
+ environment_name="production"
43
+ server_uuid="<uuid>"
44
+ docker_image="ghcr.io/org/app:latest"
45
+ docker_registry="ghcr.io"
46
+ health_check_path="/health"
47
+ ```
48
+
49
+ ## GitHub Actions Integration
50
+
51
+ ```yaml
52
+ # .github/workflows/deploy.yml
53
+ jobs:
54
+ deploy:
55
+ runs-on: ubuntu-latest
56
+ steps:
57
+ - name: Trigger Coolify Deploy
58
+ run: |
59
+ curl -sf -H "Authorization: Bearer ${{ secrets.COOLIFY_TOKEN }}" \
60
+ "${{ secrets.COOLIFY_URL }}/api/v1/deployments/deploy?uuid=${{ secrets.APP_UUID }}"
61
+ ```
62
+
63
+ Required GitHub secrets: `COOLIFY_TOKEN`, `COOLIFY_URL`, `APP_UUID`
64
+
65
+ ## Deployment Strategy Reference
66
+
67
+ | Strategy | When to Use |
68
+ |----------|-------------|
69
+ | Git push + auto-deploy | Default for most apps |
70
+ | Webhook by tag | Version-pinned releases, staging promotion |
71
+ | Webhook by UUID | CI/CD pipeline integration (specific app) |
72
+ | Docker image (`create_dockerimage`) | Pre-built images, registry-first workflow |
73
+ | `force_rebuild: true` | Cache corruption or dependency issues |
@@ -0,0 +1,57 @@
1
+ # Database & Service Management
2
+
3
+ ## Supported Database Types
4
+
5
+ PostgreSQL, MySQL, MariaDB, MongoDB, Redis, KeyDB, ClickHouse, Dragonfly.
6
+
7
+ ## Create Database
8
+
9
+ ```
10
+ database action="create"
11
+ type="postgresql"
12
+ project_uuid="<uuid>"
13
+ environment_name="production"
14
+ server_uuid="<uuid>"
15
+ ```
16
+
17
+ ## Backup Management
18
+
19
+ ```bash
20
+ # List backup schedules
21
+ database_backups action="list_schedules" database_uuid="<uuid>"
22
+
23
+ # Create schedule
24
+ database_backups action="create" database_uuid="<uuid>"
25
+ frequency="0 2 * * *" # Daily at 2 AM
26
+ retention=7
27
+
28
+ # View executions
29
+ database_backups action="list_executions" database_uuid="<uuid>"
30
+ ```
31
+
32
+ ## Services
33
+
34
+ One-click service deployments (e.g., Plausible, Gitea, Uptime Kuma):
35
+
36
+ ```bash
37
+ # List available services
38
+ list_services
39
+
40
+ # Create service
41
+ service action="create"
42
+ project_uuid="<uuid>"
43
+ environment_name="production"
44
+ server_uuid="<uuid>"
45
+ type="plausible"
46
+
47
+ # Manage env vars
48
+ env_vars resource="service" action="list" uuid="<uuid>"
49
+ ```
50
+
51
+ ## Database Lifecycle
52
+
53
+ ```bash
54
+ control resource="database" action="start" uuid="<uuid>"
55
+ control resource="database" action="stop" uuid="<uuid>"
56
+ control resource="database" action="restart" uuid="<uuid>"
57
+ ```