staticx 0.1.2 → 0.1.5
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 +67 -0
- package/package.json +1 -1
- package/src/index.js +60 -1
- package/src/output.js +110 -0
package/README.md
CHANGED
|
@@ -14,11 +14,13 @@ npm install -g staticx
|
|
|
14
14
|
staticx login --base-url "https://staticx.site/api/v1" --token "STATICX_API_TOKEN"
|
|
15
15
|
staticx whoami
|
|
16
16
|
staticx guide
|
|
17
|
+
staticx mcp
|
|
17
18
|
```
|
|
18
19
|
|
|
19
20
|
`staticx login` stores the credentials locally, verifies them with `GET /user`, and prints the active user, token scope, access level, expiry, and next safe commands.
|
|
20
21
|
|
|
21
22
|
Use `staticx guide` or `staticx commands` when you want the full command map from the terminal.
|
|
23
|
+
Use `staticx mcp` when you want copy-safe MCP snippets for Claude, Cursor, Codex, Cline, Windsurf, Zed, and generic clients.
|
|
22
24
|
|
|
23
25
|
## Core commands
|
|
24
26
|
|
|
@@ -30,9 +32,47 @@ staticx create --workspace-id WORKSPACE_ID --name "Marketing Site"
|
|
|
30
32
|
staticx create --name "Imported Site" --archive site.zip
|
|
31
33
|
staticx create --name "Imported Site" --source-url "https://example.com"
|
|
32
34
|
staticx deploy --site-id SITE_ID --dir dist
|
|
35
|
+
staticx domain --site-id SITE_ID --domain app.example.com
|
|
36
|
+
staticx domain-status --site-id SITE_ID
|
|
33
37
|
staticx logs --site-id SITE_ID
|
|
38
|
+
staticx mcp
|
|
34
39
|
```
|
|
35
40
|
|
|
41
|
+
## Custom domains
|
|
42
|
+
|
|
43
|
+
Use the CLI when you want to connect a domain without opening the dashboard.
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
staticx domain --site-id SITE_ID --domain app.example.com
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The command moves the site to that domain and prints the single DNS record to create. After the DNS record is added, StaticX detects it and activates SSL automatically.
|
|
50
|
+
|
|
51
|
+
Check progress any time:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
staticx domain-status --site-id SITE_ID
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Machine-readable sources
|
|
58
|
+
|
|
59
|
+
Use these when you want the same contract that the dashboard, CLI, and agents share:
|
|
60
|
+
|
|
61
|
+
- https://staticx.site/llms.txt
|
|
62
|
+
- https://staticx.site/llms-full.txt
|
|
63
|
+
- https://staticx.site/api/v1/openapi.json
|
|
64
|
+
|
|
65
|
+
## Plan limits
|
|
66
|
+
|
|
67
|
+
StaticX enforces the same limits through the dashboard, API, CLI, MCP, URL imports, and hosted forms runtime.
|
|
68
|
+
|
|
69
|
+
| Plan | Sites | Storage | Max upload | Form entries |
|
|
70
|
+
| --- | ---: | ---: | ---: | ---: |
|
|
71
|
+
| Free | 1 | 500 MB | 500 MB | 10,000 |
|
|
72
|
+
| Unlimited | Unlimited | Unlimited | 50 GB | Unlimited |
|
|
73
|
+
|
|
74
|
+
If a command receives `PLAN_QUOTA_EXCEEDED`, stop and return the exact message. Clean up files/form entries or upgrade before retrying.
|
|
75
|
+
|
|
36
76
|
## Token scopes
|
|
37
77
|
|
|
38
78
|
- Global token: account-wide access for internal operator tools.
|
|
@@ -45,8 +85,35 @@ Generate those tokens from:
|
|
|
45
85
|
- `Project Settings → Agent deploy` for Site
|
|
46
86
|
- `Workspace → Agent deploy` for Workspace
|
|
47
87
|
|
|
88
|
+
## MCP for AI agents
|
|
89
|
+
|
|
90
|
+
StaticX MCP uses the separate public package `staticx-mcp-server` and the same scoped API tokens as the CLI.
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"mcpServers": {
|
|
95
|
+
"staticx": {
|
|
96
|
+
"command": "npx",
|
|
97
|
+
"args": ["-y", "staticx-mcp-server"],
|
|
98
|
+
"env": {
|
|
99
|
+
"STATICX_API_TOKEN": "sx_replace_with_your_token",
|
|
100
|
+
"STATICX_API_BASE_URL": "https://staticx.site/api/v1"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
For local HTTP debugging:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
STATICX_API_TOKEN=sx_replace_with_your_token npx staticx-mcp-server http
|
|
111
|
+
```
|
|
112
|
+
|
|
48
113
|
## Notes
|
|
49
114
|
|
|
50
115
|
- `staticx login` stores the base URL and bearer token locally.
|
|
51
116
|
- `staticx whoami` verifies the token with `GET /user`.
|
|
52
117
|
- `staticx deploy` zips the contents of the given build directory, uploads them, and publishes a new release. The directory must contain `index.html` or `index.htm` plus `404.html` at its root.
|
|
118
|
+
- `staticx domain` calls `POST /projects/{project}/domain` and returns the DNS record plus activation status.
|
|
119
|
+
- Golden deploy prompt: “Deploy `dist` to StaticX project `SITE_ID` using `STATICX_API_TOKEN`. Build, validate `index.html` + `404.html`, apply StaticX form rules if forms exist, zip `dist` root, upload, deploy, check logs, then return the live URL or the exact API error. If you receive `PLAN_QUOTA_EXCEEDED`, stop and return the exact quota message. Never expose the token.”
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -10,13 +10,16 @@ import {
|
|
|
10
10
|
cliGuideJson,
|
|
11
11
|
formatTokenSummary,
|
|
12
12
|
printCliGuide,
|
|
13
|
+
printDomainSetup,
|
|
13
14
|
printJson,
|
|
14
15
|
printKeyValue,
|
|
15
16
|
printLoginSuccess,
|
|
17
|
+
printMcpGuide,
|
|
16
18
|
printTable,
|
|
19
|
+
mcpGuideJson,
|
|
17
20
|
} from './output.js';
|
|
18
21
|
|
|
19
|
-
const CLI_VERSION = '0.1.
|
|
22
|
+
const CLI_VERSION = '0.1.5';
|
|
20
23
|
|
|
21
24
|
export async function run(argv) {
|
|
22
25
|
const program = new Command();
|
|
@@ -31,7 +34,9 @@ export async function run(argv) {
|
|
|
31
34
|
Common workflow:
|
|
32
35
|
staticx login --base-url "https://staticx.site/api/v1" --token "STATICX_API_TOKEN"
|
|
33
36
|
staticx guide
|
|
37
|
+
staticx mcp
|
|
34
38
|
staticx deploy --site-id SITE_ID --dir dist
|
|
39
|
+
staticx domain --site-id SITE_ID --domain app.example.com
|
|
35
40
|
|
|
36
41
|
Deploy rule:
|
|
37
42
|
The build directory must contain index.html or index.htm and 404.html at its root.
|
|
@@ -51,6 +56,19 @@ Deploy rule:
|
|
|
51
56
|
printCliGuide();
|
|
52
57
|
});
|
|
53
58
|
|
|
59
|
+
program
|
|
60
|
+
.command('mcp')
|
|
61
|
+
.description('Print MCP setup snippets for Claude, Cursor, Codex, Cline, Windsurf, Zed, and generic clients.')
|
|
62
|
+
.option('--json', 'Print JSON output')
|
|
63
|
+
.action((options) => {
|
|
64
|
+
if (options.json) {
|
|
65
|
+
printJson(mcpGuideJson());
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
printMcpGuide();
|
|
70
|
+
});
|
|
71
|
+
|
|
54
72
|
program
|
|
55
73
|
.command('login')
|
|
56
74
|
.description('Store the base URL and token locally, then verify them with GET /user.')
|
|
@@ -276,6 +294,47 @@ Deploy rule:
|
|
|
276
294
|
})));
|
|
277
295
|
});
|
|
278
296
|
|
|
297
|
+
program
|
|
298
|
+
.command('domain')
|
|
299
|
+
.description('Move a site to a custom domain and print the one DNS record to create.')
|
|
300
|
+
.requiredOption('--site-id <id>', 'Site ID')
|
|
301
|
+
.requiredOption('--domain <domain>', 'Custom domain, for example app.example.com')
|
|
302
|
+
.option('--json', 'Print JSON output')
|
|
303
|
+
.option('--base-url <url>', 'Override the stored STATICX API base URL')
|
|
304
|
+
.option('--token <token>', 'Override the stored STATICX bearer token')
|
|
305
|
+
.action(async (options, command) => {
|
|
306
|
+
const client = await clientFromCommand(command);
|
|
307
|
+
const response = await client.post(`/projects/${options.siteId}/domain`, {
|
|
308
|
+
json: { domain: options.domain },
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
if (options.json) {
|
|
312
|
+
printJson(response);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
printDomainSetup(response);
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
program
|
|
320
|
+
.command('domain-status')
|
|
321
|
+
.description('Check the custom domain status for one site.')
|
|
322
|
+
.requiredOption('--site-id <id>', 'Site ID')
|
|
323
|
+
.option('--json', 'Print JSON output')
|
|
324
|
+
.option('--base-url <url>', 'Override the stored STATICX API base URL')
|
|
325
|
+
.option('--token <token>', 'Override the stored STATICX bearer token')
|
|
326
|
+
.action(async (options, command) => {
|
|
327
|
+
const client = await clientFromCommand(command);
|
|
328
|
+
const response = await client.get(`/projects/${options.siteId}/domain`);
|
|
329
|
+
|
|
330
|
+
if (options.json) {
|
|
331
|
+
printJson(response);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
printDomainSetup({ message: 'Custom domain status.', data: response?.data ?? response }, { statusOnly: true });
|
|
336
|
+
});
|
|
337
|
+
|
|
279
338
|
await program.parseAsync(argv);
|
|
280
339
|
}
|
|
281
340
|
|
package/src/output.js
CHANGED
|
@@ -10,6 +10,46 @@ export function printTable(rows) {
|
|
|
10
10
|
console.table(rows);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
export function printDomainSetup(response, { statusOnly = false } = {}) {
|
|
14
|
+
const data = response?.data ?? {};
|
|
15
|
+
const project = data.project ?? {};
|
|
16
|
+
const domain = data.custom_domain ?? null;
|
|
17
|
+
const records = data.dns?.records ?? [];
|
|
18
|
+
const steps = Array.isArray(data.steps) ? data.steps : [];
|
|
19
|
+
|
|
20
|
+
console.log(response?.message || (statusOnly ? 'Custom domain status.' : 'Custom domain setup started.'));
|
|
21
|
+
console.log('');
|
|
22
|
+
printAlignedRows([
|
|
23
|
+
['Site', project.name || project.id || 'Unknown'],
|
|
24
|
+
['Current URL', project.public_url || 'Pending'],
|
|
25
|
+
['Custom domain', domain?.host || 'Not connected'],
|
|
26
|
+
['Status', domain?.status_label || data.status?.label || 'Pending'],
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
if (domain?.status_message || data.status?.message) {
|
|
30
|
+
console.log('');
|
|
31
|
+
console.log(domain?.status_message || data.status?.message);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (records.length > 0) {
|
|
35
|
+
console.log('');
|
|
36
|
+
console.log('Create this DNS record:');
|
|
37
|
+
printTable(records.map((record) => ({
|
|
38
|
+
type: record.type,
|
|
39
|
+
name: record.name,
|
|
40
|
+
value: record.value,
|
|
41
|
+
})));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (steps.length > 0) {
|
|
45
|
+
console.log('');
|
|
46
|
+
console.log('Next steps');
|
|
47
|
+
steps.forEach((step, index) => {
|
|
48
|
+
console.log(` ${index + 1}. ${step}`);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
13
53
|
export function printLoginSuccess({ baseUrl, user, token }) {
|
|
14
54
|
printBanner();
|
|
15
55
|
console.log('Successfully authenticated.');
|
|
@@ -25,6 +65,7 @@ export function printLoginSuccess({ baseUrl, user, token }) {
|
|
|
25
65
|
['staticx guide', 'Show the complete CLI workflow.'],
|
|
26
66
|
['staticx sites', 'List the sites visible to this token.'],
|
|
27
67
|
['staticx deploy --site-id SITE_ID --dir dist', 'Upload and publish a build folder.'],
|
|
68
|
+
['staticx domain --site-id SITE_ID --domain app.example.com', 'Move a site to a custom domain.'],
|
|
28
69
|
]);
|
|
29
70
|
console.log('');
|
|
30
71
|
console.log('Build rule: deploy folders must include index.html or index.htm and 404.html at the root.');
|
|
@@ -53,13 +94,64 @@ export function printCliGuide() {
|
|
|
53
94
|
['staticx deploy --site-id SITE_ID --dir dist', 'Zip, upload, and publish a build folder.'],
|
|
54
95
|
]);
|
|
55
96
|
console.log('');
|
|
97
|
+
printCommandGroup('Custom domains', [
|
|
98
|
+
['staticx domain --site-id SITE_ID --domain app.example.com', 'Move a site to a custom domain and print the DNS record.'],
|
|
99
|
+
['staticx domain-status --site-id SITE_ID', 'Check DNS, SSL, and activation status.'],
|
|
100
|
+
]);
|
|
101
|
+
console.log('');
|
|
56
102
|
printCommandGroup('Inspect', [
|
|
57
103
|
['staticx logs --site-id SITE_ID', 'Read recent site activity.'],
|
|
58
104
|
['staticx logs --site-id SITE_ID --limit 50', 'Read more rows.'],
|
|
59
105
|
]);
|
|
60
106
|
console.log('');
|
|
107
|
+
printCommandGroup('Machine-readable sources', [
|
|
108
|
+
['https://staticx.site/llms.txt', 'Short index for agents and crawlers.'],
|
|
109
|
+
['https://staticx.site/llms-full.txt', 'Expanded agent playbook with prompts and curl examples.'],
|
|
110
|
+
['https://staticx.site/api/v1/openapi.json', 'Canonical OpenAPI schema for the public API.'],
|
|
111
|
+
]);
|
|
112
|
+
console.log('');
|
|
61
113
|
console.log('Token scopes: use Site tokens for one-site deploys, Workspace tokens for client workspaces, and Global tokens only for broad operator workflows.');
|
|
62
114
|
console.log('Build rule: deploy folders must include index.html or index.htm and 404.html at the root.');
|
|
115
|
+
console.log('Plan limits: Free includes 1 site, 500 MB storage, 500 MB uploads, and 10,000 form entries. Unlimited includes 50 GB uploads with unlimited sites, storage, and form entries.');
|
|
116
|
+
console.log('Quota rule: stop on PLAN_QUOTA_EXCEEDED and return the exact API message before retrying.');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function printMcpGuide() {
|
|
120
|
+
printBanner();
|
|
121
|
+
console.log('MCP setup for AI agents');
|
|
122
|
+
console.log('');
|
|
123
|
+
printCommandGroup('Install and test', [
|
|
124
|
+
['npx -y staticx-mcp-server', 'Run the stdio MCP server from any compatible client.'],
|
|
125
|
+
['STATICX_API_TOKEN=sx_xxxxx npx staticx-mcp-server http', 'Start local HTTP mode at http://localhost:3100/mcp for debugging.'],
|
|
126
|
+
]);
|
|
127
|
+
console.log('');
|
|
128
|
+
console.log('Standard MCP config');
|
|
129
|
+
console.log(JSON.stringify(mcpGuideJson().config, null, 2));
|
|
130
|
+
console.log('');
|
|
131
|
+
console.log('Use a site-scoped token for one-site deploys. Rollback and delete tools require explicit confirmation.');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function mcpGuideJson() {
|
|
135
|
+
return {
|
|
136
|
+
package: 'staticx-mcp-server',
|
|
137
|
+
auth: 'Scoped API token through STATICX_API_TOKEN.',
|
|
138
|
+
config: {
|
|
139
|
+
mcpServers: {
|
|
140
|
+
staticx: {
|
|
141
|
+
command: 'npx',
|
|
142
|
+
args: ['-y', 'staticx-mcp-server'],
|
|
143
|
+
env: {
|
|
144
|
+
STATICX_API_TOKEN: 'sx_replace_with_your_token',
|
|
145
|
+
STATICX_API_BASE_URL: 'https://staticx.site/api/v1',
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
local_http: {
|
|
151
|
+
command: 'STATICX_API_TOKEN=sx_replace_with_your_token npx staticx-mcp-server http',
|
|
152
|
+
url: 'http://localhost:3100/mcp',
|
|
153
|
+
},
|
|
154
|
+
};
|
|
63
155
|
}
|
|
64
156
|
|
|
65
157
|
export function cliGuideJson() {
|
|
@@ -82,13 +174,31 @@ export function cliGuideJson() {
|
|
|
82
174
|
'staticx create --name "Imported Site" --source-url "https://example.com"',
|
|
83
175
|
'staticx deploy --site-id SITE_ID --dir dist',
|
|
84
176
|
],
|
|
177
|
+
domains: [
|
|
178
|
+
'staticx domain --site-id SITE_ID --domain app.example.com',
|
|
179
|
+
'staticx domain-status --site-id SITE_ID',
|
|
180
|
+
],
|
|
85
181
|
inspect: [
|
|
86
182
|
'staticx logs --site-id SITE_ID',
|
|
87
183
|
'staticx logs --site-id SITE_ID --limit 50',
|
|
88
184
|
],
|
|
185
|
+
mcp: [
|
|
186
|
+
'staticx mcp',
|
|
187
|
+
'npx -y staticx-mcp-server',
|
|
188
|
+
],
|
|
89
189
|
},
|
|
190
|
+
machine_readable: [
|
|
191
|
+
'https://staticx.site/llms.txt',
|
|
192
|
+
'https://staticx.site/llms-full.txt',
|
|
193
|
+
'https://staticx.site/api/v1/openapi.json',
|
|
194
|
+
],
|
|
90
195
|
build_rule: 'Deploy folders must include index.html or index.htm and 404.html at the root.',
|
|
91
196
|
token_scopes: 'Use Site tokens for one-site deploys, Workspace tokens for client workspaces, and Global tokens only for broad operator workflows.',
|
|
197
|
+
plan_limits: {
|
|
198
|
+
free: '1 site, 500 MB storage, 500 MB max upload, 10,000 form entries.',
|
|
199
|
+
unlimited: 'Unlimited sites, unlimited storage, 50 GB max upload, unlimited form entries.',
|
|
200
|
+
},
|
|
201
|
+
quota_rule: 'Stop on PLAN_QUOTA_EXCEEDED and return the exact API message.',
|
|
92
202
|
};
|
|
93
203
|
}
|
|
94
204
|
|