@netlify/agent-runner-cli 2.15.1-nb6c91432cb9d2.0 → 2.16.0-server.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/README.md +5 -0
- package/dist/bin-local.js +242 -237
- package/dist/bin.js +269 -264
- package/dist/index.js +217 -212
- package/dist/skills/general-backend@backend/SKILL.md +78 -0
- package/dist/skills/netlify-access-control/SKILL.md +32 -14
- package/dist/skills/netlify-forms/SKILL.md +9 -1
- package/dist/skills/netlify-functions/SKILL@backend.md +610 -0
- package/dist/skills/netlify-server@backend/SKILL.md +227 -0
- package/dist/skills/netlify-server@netlifyserver/SKILL.md +84 -30
- package/package.json +2 -2
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: general-backend
|
|
3
|
+
description: Use this skill whenever the task involves server-side code — API endpoints, backend logic, request handlers, WebSockets, server-side AI calls, auth checks, or any code that must run on a server rather than in the browser. Covers Netlify Server, Netlify Functions, Edge Functions, and full-stack framework server routes.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Server-side code on Netlify
|
|
7
|
+
|
|
8
|
+
Where server-side code goes depends on the project. Work out which case applies before writing code, and for a
|
|
9
|
+
new project, before scaffolding a template.
|
|
10
|
+
|
|
11
|
+
## New project that needs a Netlify Server: no template
|
|
12
|
+
|
|
13
|
+
The create-mode templates are built on a full-stack framework that deploys its server-side rendering as a Netlify
|
|
14
|
+
Function on every path, so a Netlify Server added to a template project never receives requests. If the project
|
|
15
|
+
needs a Netlify Server, don't scaffold a template. A new project needs one when it has any request-driven backend
|
|
16
|
+
code: API endpoints, data saved and read through the backend, WebSockets, server-side AI calls, or an HTTP server
|
|
17
|
+
framework such as Express, Hono, or Fastify.
|
|
18
|
+
|
|
19
|
+
A site with no backend code (static pages, a marketing or content site, a client-only tool) needs neither a server
|
|
20
|
+
nor functions. Use the templates as usual for it.
|
|
21
|
+
|
|
22
|
+
## Project with a full-stack framework: use its server routes
|
|
23
|
+
|
|
24
|
+
Full-stack frameworks (such as TanStack Start, Next.js, Astro, SvelteKit, Remix, Nuxt) build
|
|
25
|
+
their own server code into Netlify Functions at deploy time. In these projects, put request handling in the
|
|
26
|
+
framework's server routes or server functions instead of adding a Netlify Server. Call Netlify Database, Blobs, and
|
|
27
|
+
the AI Gateway from those routes. Use Netlify Functions alongside them only for the cases listed under "Only when
|
|
28
|
+
Server can't" below.
|
|
29
|
+
|
|
30
|
+
HTTP server frameworks such as Express, Hono, Fastify, and Koa are different: nothing deploys them for you, so they
|
|
31
|
+
run as a Netlify Server, covered next.
|
|
32
|
+
|
|
33
|
+
## Otherwise: Netlify Server
|
|
34
|
+
|
|
35
|
+
**Netlify Server** runs one long-running Node.js process (Express, Hono, Fastify, or plain `node:http`) from
|
|
36
|
+
`netlify/server/index.mjs`. Put every request-driven piece of backend code in it:
|
|
37
|
+
|
|
38
|
+
- API endpoints and route handlers
|
|
39
|
+
- Server-rendered pages and form handling in your own routes
|
|
40
|
+
- WebSockets and streaming responses
|
|
41
|
+
- Calls to the Netlify AI Gateway, Netlify Database, and Netlify Blobs
|
|
42
|
+
- Short work that continues after the response (seconds, such as sending an email), registered with `waitUntil`
|
|
43
|
+
- Auth checks, webhooks from third-party services, proxies to external APIs
|
|
44
|
+
|
|
45
|
+
Don't pick Functions just because the task is small or looks like a single endpoint.
|
|
46
|
+
|
|
47
|
+
See the **netlify-server** skill for complete setup instructions and usage examples.
|
|
48
|
+
|
|
49
|
+
## Only when Server can't: Netlify Functions
|
|
50
|
+
|
|
51
|
+
Use **Netlify Functions** alongside the server only for:
|
|
52
|
+
|
|
53
|
+
- **Scheduled functions**: work that runs on a cron schedule, with no incoming request.
|
|
54
|
+
- **Event handlers**: code triggered by platform events, such as Netlify Forms submissions, Netlify Identity events
|
|
55
|
+
(signup, login, validate), or deploy events.
|
|
56
|
+
- **Background functions**: jobs that can run longer than about a minute and must not be cut off midway, such as
|
|
57
|
+
generating a report or processing an upload (up to 15 minutes). When a server instance is replaced by a deploy or
|
|
58
|
+
scaling event, its background work gets only 90 seconds to finish. The server enqueues the job by calling the
|
|
59
|
+
background function and returns right away.
|
|
60
|
+
|
|
61
|
+
Scheduled functions and event handlers run without an incoming request, which a server can't do, and background
|
|
62
|
+
functions aren't cut off when a server instance is replaced. Everything else stays in the server, including the
|
|
63
|
+
endpoints these functions talk to.
|
|
64
|
+
|
|
65
|
+
See the **netlify-functions** skill for complete setup instructions and usage examples.
|
|
66
|
+
|
|
67
|
+
## Request and response changes at the edge: Edge Functions
|
|
68
|
+
|
|
69
|
+
Use **Edge Functions** for logic that runs on every request before it reaches the server or the site: rewrites and
|
|
70
|
+
redirects based on geolocation or cookies, A/B tests, header changes, or lightweight auth checks. They run in Deno
|
|
71
|
+
close to visitors and don't replace the server for application logic.
|
|
72
|
+
|
|
73
|
+
See the **netlify-edge-functions** skill for setup instructions.
|
|
74
|
+
|
|
75
|
+
## Existing projects
|
|
76
|
+
|
|
77
|
+
If an existing project already serves its backend from `netlify/functions/`, keep using that for changes to it.
|
|
78
|
+
Don't migrate an existing backend to a Netlify Server unless asked.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: netlify-access-control
|
|
3
|
-
description: 'Picks the right Netlify site-protection layer and disambiguates the three unrelated "auth" concepts users conflate — app-user login (Netlify Identity), site-load gating (Password Protection / project visibility), and dashboard SAML SSO. Use it when asked to password-protect a site or Deploy Preview, make a project private/public, restrict a site to your team, require SSO to view a site, set up company-wide app SSO,
|
|
3
|
+
description: 'Picks the right Netlify site-protection layer and disambiguates the three unrelated "auth" concepts users conflate — app-user login (Netlify Identity), site-load gating (Password Protection / project visibility), and dashboard SAML SSO. Use it when asked to password-protect a site or Deploy Preview, make a project private/public, restrict a site to your team, require SSO to view a site, set up company-wide or internal-app SSO, invite users to a private project, or know which team member made a request to a private site. Also use it for SSO-session symptoms on protected sites: "logged out mid-session", 401s after about an hour, or token expiry/refresh questions. Not for wiring auth code — route app-login setup to netlify-identity.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Netlify access control — pick the protection layer
|
|
@@ -17,16 +17,19 @@ Users constantly conflate these. Identify which one is meant before recommending
|
|
|
17
17
|
|
|
18
18
|
Sessions are separate. The same provider (e.g. Google) can appear twice unrelated — Identity OAuth for app users vs. SAML IdP for team members.
|
|
19
19
|
|
|
20
|
-
**Double-login footgun:** a Password-Protection/team-login perimeter session and an Identity app session have **no bridge** — no shared cookie, no header forwarding, no JWT exchange. Don't try to wire them together. For the combined layered pattern and its tradeoffs, see `references/two-layer-pattern.md`.
|
|
20
|
+
**Double-login footgun:** a Password-Protection/team-login perimeter session and an Identity app session have **no bridge** — no shared cookie, no header forwarding, no JWT exchange. Don't try to wire them together. For the combined layered pattern and its tradeoffs, see `references/two-layer-pattern.md`. The Netlify login itself *does* reach app code: on a private project or with team login protection, functions and edge functions receive the signed-in Netlify user as **`context.user`** — if every app user can pass that login, it is the app's identity and no second login is needed.
|
|
21
21
|
|
|
22
|
-
**Want
|
|
22
|
+
**Want an internal app with a single sign-in (no double login)?** First ask who uses it:
|
|
23
|
+
- **They can pass the project's Netlify login** → **Private project** (Credit-based plans; Pro for anyone beyond the Team Owner) or **team login protection** (Enterprise), and use `context.user` in functions for per-person behavior.
|
|
24
|
+
- **They can't** (e.g. employees without Netlify seats) → **Auth0 extension** federating to the corporate IdP, *before* the two-layer stack.
|
|
23
25
|
|
|
24
26
|
## Decision guide (this skill's job)
|
|
25
27
|
|
|
26
28
|
- Restrict entire site to your team, invite by email → **Private project** (Credit-based) or **Team login protection** (Password Protection).
|
|
27
|
-
- Share with anyone holding one shared password → **Basic password protection** (Pro) or **Password** visibility (Pro
|
|
29
|
+
- Share with anyone holding one shared password → **Basic password protection** (Pro) or **Password** visibility (Credit-based Pro only). **Not available on Credit-based Free/Personal** — make the project **Private** instead.
|
|
28
30
|
- Keep production public, protect previews only → scope **Previews only** / **Non-production deploys only**.
|
|
29
31
|
- Require SSO to *view a site* → Organization/Team SSO with **Only SSO allowed (strict)**, then Password Protection with **Team login protection**.
|
|
32
|
+
- Know *which team member* made a request → private project or team login protection, then read `context.user` in functions/edge functions (not documented for basic password protection).
|
|
30
33
|
- Protect specific pages/sections with multiple passwords → **Basic authentication with custom HTTP headers** (formerly Selective password protection): https://docs.netlify.com/manage/security/secure-access-to-sites/basic-authentication-with-custom-http-headers/
|
|
31
34
|
- Authenticate your own end users → **Netlify Identity** / **OAuth provider tokens** / **Role-based access control with JWT** → route to netlify-identity.
|
|
32
35
|
- Block malicious/automated traffic or AI crawlers → **Advanced Web Security** (WAF / Firewall Traffic Rules / rate limiting) or **User Agent Blocker** extension: https://docs.netlify.com/build/build-with-ai/block-ai-crawlers/
|
|
@@ -34,9 +37,13 @@ Sessions are separate. The same provider (e.g. Google) can appear twice unrelate
|
|
|
34
37
|
## Key distinction: Private vs Password
|
|
35
38
|
|
|
36
39
|
- **Private** already requires Netlify credentials — no shared password. Invite by email; recommended for team-only access.
|
|
37
|
-
- **Password** = one universal shared password anyone can use (including managing team members, who must also enter it). No SSO.
|
|
40
|
+
- **Password** = one universal shared password anyone can use (including managing team members, who must also enter it). No SSO. Doesn't identify individual visitors.
|
|
38
41
|
- **Team login protection** = same mechanism as Private: a visitor must log in as a member of your Netlify team, and **Reviewers** you invite can get in too (unlimited and not counted toward the member count on legacy plans; Pro or higher on Credit-based plans). **Git Contributors cannot log in** — invite them as Reviewers rather than upgrading them to Developer.
|
|
39
42
|
|
|
43
|
+
## Identify the visitor: `context.user`
|
|
44
|
+
|
|
45
|
+
With **team login protection** or on a **private project**, functions and edge functions get the signed-in Netlify user as `context.user`. Don't guess its fields — see https://docs.netlify.com/build/functions/api/#user and https://docs.netlify.com/build/edge-functions/api/#user.
|
|
46
|
+
|
|
40
47
|
## SSO-session symptom: 401s after ~1 hour
|
|
41
48
|
|
|
42
49
|
If a user reports being "logged out mid-session" or 401s on an SSO-protected site: **SSO auth tokens expire after 1 hour**, after which requests return `401`. Sites with SSO protection return the header **`Netlify-Site-Protection-Expires-In`** — seconds until the request's token expires. Refresh proactively:
|
|
@@ -55,6 +62,7 @@ if (!Number.isNaN(secondsLeft) && secondsLeft < 60) {
|
|
|
55
62
|
|
|
56
63
|
**Credit-based plans (Free, Personal, Pro)** — project-level "Password Protection" is replaced by **Project visibility**:
|
|
57
64
|
- Per project: Project configuration > General > Visitor access > **Project visibility** — `https://app.netlify.com/projects/{site_name}/configuration/general/#project-visibility`. Edit visibility → (Customize if a team default exists) → **Public** / **Password** (Pro only) / **Private** → set **Preview access** (Production and previews / Previews only) → Save.
|
|
65
|
+
- **Free/Personal have no Password option** — use **Private** to restrict viewers (visible only to the Team Owner; invite others requires Pro).
|
|
58
66
|
- Team default: Team settings > General > Visitor access > **Default project visibility** — `https://app.netlify.com/teams/{team_name}/settings/general#default-project-visibility`. Options: Private for new projects / Private for all projects / Public for new projects.
|
|
59
67
|
- No per-team default *password* here; set a password per project.
|
|
60
68
|
|
|
@@ -62,7 +70,7 @@ if (!Number.isNaN(secondsLeft) && secondsLeft < 60) {
|
|
|
62
70
|
- Per site: Project configuration > General > Visitor access > **Password Protection** — `https://app.netlify.com/projects/{site_name}/configuration/general#visitor-access`. Configure → Basic or Team login → scope (All deploys / Non-production deploys only) → Save.
|
|
63
71
|
- Team default: Team settings > Access & security > Visitor access > **Default Password Protection settings** — `https://app.netlify.com/teams/{team_name}/settings/access#default-site-protection-settings`. Applies to all sites without their own settings.
|
|
64
72
|
|
|
65
|
-
**Legacy → Credit-based mapping:** No protection→Public · Basic protection→Password · Team protection→Private · All deploys→Production and previews · Non-production deploys only→Previews only.
|
|
73
|
+
**Legacy → Credit-based mapping:** No protection→Public · Basic protection→Password (Pro only) · Team protection→Private · All deploys→Production and previews · Non-production deploys only→Previews only.
|
|
66
74
|
|
|
67
75
|
## Constraints & footguns
|
|
68
76
|
|
|
@@ -72,14 +80,15 @@ if (!Number.isNaN(secondsLeft) && secondsLeft < 60) {
|
|
|
72
80
|
- **Third-party webhooks (Slack, Stripe, etc.) cannot reach a private project** — receiving webhooks requires the project to be **public**.
|
|
73
81
|
- **Make public** requires at least one successful **production deploy**.
|
|
74
82
|
- **Protecting only non-production deploys** with Password Protection is **Enterprise only**.
|
|
75
|
-
- **Plan gating:** Basic password protection for the whole site → all Pro plans; all Password Protection options → Enterprise. Project visibility (public/private, private-by-default) → Credit-based Free/Personal/Pro only; password-protected visibility → Pro only. On Free/Personal a private project is visible only to the Team Owner (single-seat); Pro allows unlimited members.
|
|
83
|
+
- **Plan gating:** Basic password protection for the whole site → all Pro plans; all Password Protection options → Enterprise. **Password protection is not available on Credit-based Free/Personal.** Project visibility (public/private, private-by-default) → Credit-based Free/Personal/Pro only; password-protected visibility → Pro only. On Free/Personal a private project is visible only to the Team Owner (single-seat); Pro allows unlimited members.
|
|
76
84
|
- **Team default changes by creation date:** teams created on/after **July 28, 2026** default to **Private for new projects**; earlier teams default to **Public**.
|
|
77
85
|
- **Renamed:** "site-wide password protection" (old name of a Password Protection option); "Selective password protection" → Basic authentication with custom HTTP headers.
|
|
78
86
|
|
|
79
87
|
Reference: https://docs.netlify.com/manage/security/secure-access-to-sites/overview/ · https://docs.netlify.com/manage/security/secure-access-to-sites/password-protection/ · https://docs.netlify.com/manage/security/secure-access-to-sites/project-visibility/
|
|
80
88
|
|
|
81
89
|
<!-- Advanced Web Security (WAF, Firewall Traffic Rules, rate limiting) specifics — limits, config keys, plan gating — not in source; referenced by URL only. -->
|
|
82
|
-
<!-- Exact per-tier matrix of basic vs team-login options
|
|
90
|
+
<!-- Exact per-tier matrix of basic vs team-login options (incl. Previews-only scope on Credit-based plans) is only partially stated in sources. -->
|
|
91
|
+
<!-- context.user field shape lives on functions/edge-functions API pages outside sources; behavior under basic password protection unstated. -->
|
|
83
92
|
|
|
84
93
|
<!-- system: agent-context/access-control/system.md — human-owned, merged by ctx-gen; edit system.md, not this section -->
|
|
85
94
|
# Netlify house rules (access-control)
|
|
@@ -98,18 +107,27 @@ ctx-gen and never generated. Owned by the skills maintainer.
|
|
|
98
107
|
dashboard"). Sessions are separate; the same provider (Google) can appear
|
|
99
108
|
in two unrelated places — Identity OAuth for app users, SAML IdP for team
|
|
100
109
|
members. Disambiguate before recommending anything.
|
|
101
|
-
4. The double login is real
|
|
102
|
-
session and an Identity app session
|
|
103
|
-
|
|
104
|
-
together; tradeoffs live in `references/two-layer-pattern.md`.
|
|
110
|
+
4. The double login is real between a team-login or private-project
|
|
111
|
+
session and an Identity app session: no shared cookie, no header
|
|
112
|
+
forwarding, no JWT exchange. Don't burn iterations wiring those two
|
|
113
|
+
together; tradeoffs live in `references/two-layer-pattern.md`. The
|
|
114
|
+
Netlify login itself does reach app code: on a private project or with
|
|
115
|
+
team login protection, functions and edge functions receive the
|
|
116
|
+
signed-in Netlify user as `context.user`. When everyone using the app
|
|
117
|
+
can pass that login, it is the app's identity and no second login is
|
|
118
|
+
needed.
|
|
105
119
|
5. These settings have no public API, CLI command, or MCP tool. Never curl
|
|
106
120
|
`api.netlify.com` or read local auth tokens to inspect or change them —
|
|
107
121
|
hand the user the dashboard path and checklist; on failure, report what
|
|
108
122
|
you tried and stop.
|
|
109
123
|
6. Identity setup, auth code, and OAuth providers for app users belong to the
|
|
110
124
|
netlify-identity skill — route there; this skill only picks the layer.
|
|
111
|
-
7. For
|
|
112
|
-
|
|
125
|
+
7. For an internal app with a single sign-in, first ask who uses it. If
|
|
126
|
+
they can pass the project's Netlify login, recommend a private project
|
|
127
|
+
(Credit-based plans; Pro for anyone beyond the Team Owner) or team
|
|
128
|
+
login protection (Enterprise), with `context.user` in functions for
|
|
129
|
+
per-person behavior. If they can't, such as employees without Netlify
|
|
130
|
+
seats, the Auth0 extension federating to the corporate IdP is the
|
|
113
131
|
recommendation before the two-layer stack.
|
|
114
132
|
8. The description's triggers must include the SSO-session symptoms users
|
|
115
133
|
actually report — "logged out mid-session", 401s on an SSO-protected
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: netlify-forms
|
|
3
|
-
description: Serverless form handling on Netlify-hosted sites — detects HTML forms at deploy time, stores submissions, filters spam, and sends notifications. Use when adding a contact form, lead-capture form, file-upload form, or newsletter signup to a Netlify site; wiring AJAX form submission; setting up a custom thank-you page; adding a honeypot or reCAPTCHA to a form; getting forms working in Next.js, Nuxt, SvelteKit, Astro, or Gatsby; reading form submissions via the Netlify API; or debugging missing submissions and forms that silently fail to register.
|
|
3
|
+
description: Serverless form handling on Netlify-hosted sites — detects HTML forms at deploy time, stores submissions, filters spam, and sends notifications. Use when adding a contact form, lead-capture form, file-upload form, or newsletter signup to a Netlify site; wiring AJAX form submission; setting up a custom thank-you page; adding a honeypot or reCAPTCHA to a form; getting forms working in Next.js, Nuxt, SvelteKit, Astro, or Gatsby; reading form submissions via the Netlify API; setting up submission notifications or ChatGPT automations on form submission events; or debugging missing submissions and forms that silently fail to register.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Netlify Forms
|
|
@@ -130,6 +130,10 @@ Variables: `%{formName}`, `%{siteName}`, `%{submissionId}`. Forms created before
|
|
|
130
130
|
|
|
131
131
|
Set up notifications (email/webhook/Slack) in the UI: Forms > Submission notifications > **Add notification**.
|
|
132
132
|
|
|
133
|
+
**⚠️ Email recipient must be an active member of your Netlify team.** Any other address produces a validation error and the notification is not saved. To notify someone outside the team, invite them first (https://docs.netlify.com/manage/accounts-and-billing/team-management/manage-team-members#add-new-team-members), then add their email. To change the recipient: Forms > Submission notifications > **Options > Edit notifications**, enter an active team member's email, save.
|
|
134
|
+
|
|
135
|
+
ChatGPT automations: subscribe to form submission events from ChatGPT and run automations on them (e.g. review new submissions and flag ones needing follow-up). Setup: https://docs.netlify.com/build/build-with-ai/agent-setup-guides/use-netlify-with-chatgpt/#subscribe-to-netlify-events
|
|
136
|
+
|
|
133
137
|
## Reading submissions via the API
|
|
134
138
|
|
|
135
139
|
Use only documented surfaces. Do NOT invent `api.netlify.com` endpoints or read tokens from local CLI config files. Reference: https://open-api.netlify.com/#tag/submission/operation/listFormSubmissions
|
|
@@ -153,6 +157,7 @@ Field order in the HTML affects what appears in the summary.
|
|
|
153
157
|
- No submissions at all: confirm form detection is enabled (Forms > Form detection) and redeploy.
|
|
154
158
|
- SSR/JS forms silently failing: verify the static skeleton file exists with exactly-matching field names and that AJAX targets the skeleton file, not `/`.
|
|
155
159
|
- Missing old-field data: the UI shows only fields from the last deployed form version. Mark old fields `hidden` instead of removing them to keep them visible; old data remains available via `listFormSubmissions`.
|
|
160
|
+
- Email notification won't save (validation error): the recipient isn't an active team member — use a team member's email or invite the person first.
|
|
156
161
|
- Still stuck: Netlify Support Guide on how to debug your form — https://answers.netlify.com/t/common-issue-how-to-debug-your-form/92
|
|
157
162
|
|
|
158
163
|
## Constraints
|
|
@@ -162,6 +167,9 @@ Field order in the HTML affects what appears in the summary.
|
|
|
162
167
|
- For PII, export and delete data regularly.
|
|
163
168
|
- Data is stored in Netlify's database, not accessible except via UI/API/CSV.
|
|
164
169
|
|
|
170
|
+
<!-- Gap: ChatGPT automation event names, plan gating, and setup steps are not in this grouping; see the linked ChatGPT setup guide.
|
|
171
|
+
Gap: docs don't say whether the active-team-member recipient rule applies to webhooks or to pre-existing notifications. -->
|
|
172
|
+
|
|
165
173
|
<!-- system: agent-context/forms/system.md — human-owned, merged by ctx-gen; edit system.md, not this section -->
|
|
166
174
|
# Netlify house rules (forms)
|
|
167
175
|
|