@statechange/xano-cli 0.2.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 (72) hide show
  1. package/README.md +251 -0
  2. package/dist/auth.d.ts +22 -0
  3. package/dist/auth.d.ts.map +1 -0
  4. package/dist/auth.js +94 -0
  5. package/dist/auth.js.map +1 -0
  6. package/dist/commands/audit.d.ts +6 -0
  7. package/dist/commands/audit.d.ts.map +1 -0
  8. package/dist/commands/audit.js +316 -0
  9. package/dist/commands/audit.js.map +1 -0
  10. package/dist/commands/auth.d.ts +6 -0
  11. package/dist/commands/auth.d.ts.map +1 -0
  12. package/dist/commands/auth.js +179 -0
  13. package/dist/commands/auth.js.map +1 -0
  14. package/dist/commands/health.d.ts +6 -0
  15. package/dist/commands/health.d.ts.map +1 -0
  16. package/dist/commands/health.js +115 -0
  17. package/dist/commands/health.js.map +1 -0
  18. package/dist/commands/history.d.ts +6 -0
  19. package/dist/commands/history.d.ts.map +1 -0
  20. package/dist/commands/history.js +250 -0
  21. package/dist/commands/history.js.map +1 -0
  22. package/dist/commands/inventory.d.ts +6 -0
  23. package/dist/commands/inventory.d.ts.map +1 -0
  24. package/dist/commands/inventory.js +282 -0
  25. package/dist/commands/inventory.js.map +1 -0
  26. package/dist/commands/logs.d.ts +6 -0
  27. package/dist/commands/logs.d.ts.map +1 -0
  28. package/dist/commands/logs.js +411 -0
  29. package/dist/commands/logs.js.map +1 -0
  30. package/dist/commands/performance.d.ts +6 -0
  31. package/dist/commands/performance.d.ts.map +1 -0
  32. package/dist/commands/performance.js +520 -0
  33. package/dist/commands/performance.js.map +1 -0
  34. package/dist/commands/secure.d.ts +6 -0
  35. package/dist/commands/secure.d.ts.map +1 -0
  36. package/dist/commands/secure.js +52 -0
  37. package/dist/commands/secure.js.map +1 -0
  38. package/dist/commands/xanoscript.d.ts +6 -0
  39. package/dist/commands/xanoscript.d.ts.map +1 -0
  40. package/dist/commands/xanoscript.js +216 -0
  41. package/dist/commands/xanoscript.js.map +1 -0
  42. package/dist/commands/xray.d.ts +6 -0
  43. package/dist/commands/xray.d.ts.map +1 -0
  44. package/dist/commands/xray.js +194 -0
  45. package/dist/commands/xray.js.map +1 -0
  46. package/dist/format.d.ts +10 -0
  47. package/dist/format.d.ts.map +1 -0
  48. package/dist/format.js +59 -0
  49. package/dist/format.js.map +1 -0
  50. package/dist/index.d.ts +7 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +43 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/performance/load-analysis.d.ts +33 -0
  55. package/dist/performance/load-analysis.d.ts.map +1 -0
  56. package/dist/performance/load-analysis.js +290 -0
  57. package/dist/performance/load-analysis.js.map +1 -0
  58. package/dist/performance/stack-rollup.d.ts +57 -0
  59. package/dist/performance/stack-rollup.d.ts.map +1 -0
  60. package/dist/performance/stack-rollup.js +108 -0
  61. package/dist/performance/stack-rollup.js.map +1 -0
  62. package/dist/registry-client.d.ts +81 -0
  63. package/dist/registry-client.d.ts.map +1 -0
  64. package/dist/registry-client.js +333 -0
  65. package/dist/registry-client.js.map +1 -0
  66. package/dist/xano-client.d.ts +103 -0
  67. package/dist/xano-client.d.ts.map +1 -0
  68. package/dist/xano-client.js +399 -0
  69. package/dist/xano-client.js.map +1 -0
  70. package/package.json +49 -0
  71. package/skills/performance-analysis/SKILL.md +135 -0
  72. package/skills/xano-cli/SKILL.md +158 -0
@@ -0,0 +1,399 @@
1
+ /**
2
+ * Xano API Client - Portable version for CLI use
3
+ * Based on src/workers/xanoapi.ts
4
+ */
5
+ const sinkCache = new Map();
6
+ const SINK_TTL_MS = 60_000; // 1 minute
7
+ /** Flush all sink caches (or a specific key) */
8
+ export function flushSinkCache(key) {
9
+ if (key) {
10
+ sinkCache.delete(key);
11
+ }
12
+ else {
13
+ sinkCache.clear();
14
+ }
15
+ }
16
+ export class XanoClient {
17
+ instance;
18
+ token;
19
+ onTokenExpired;
20
+ constructor(config) {
21
+ this.instance = config.instance;
22
+ this.token = config.token;
23
+ this.onTokenExpired = config.onTokenExpired;
24
+ }
25
+ /** Flush the sink cache (call after writes) */
26
+ flushCache() {
27
+ flushSinkCache();
28
+ }
29
+ getCached(key) {
30
+ const entry = sinkCache.get(key);
31
+ if (entry && Date.now() - entry.timestamp < SINK_TTL_MS) {
32
+ return entry.data;
33
+ }
34
+ if (entry)
35
+ sinkCache.delete(key);
36
+ return undefined;
37
+ }
38
+ setCache(key, data) {
39
+ sinkCache.set(key, { data, timestamp: Date.now() });
40
+ }
41
+ async fetch(path, options) {
42
+ const uri = `https://${this.instance}/${path}`;
43
+ const response = await fetch(uri, {
44
+ ...(options || {}),
45
+ headers: {
46
+ ...(options?.headers || {}),
47
+ Authorization: `Bearer ${this.token}`,
48
+ "Content-Type": "application/json",
49
+ },
50
+ });
51
+ return response;
52
+ }
53
+ async fetchJson(path, options, attempts = 6, attemptTimeout = 10000) {
54
+ let currentAttempt = 0;
55
+ const opts = options ? { ...options } : {};
56
+ while (true) {
57
+ try {
58
+ const response = await this.fetch(path, opts);
59
+ if (!response.ok) {
60
+ if (currentAttempt >= attempts) {
61
+ throw new Error(`Failed to fetch ${path} after ${attempts} attempts: ${response.status} ${response.statusText}`);
62
+ }
63
+ else if (response.status >= 500) {
64
+ await new Promise((resolve) => setTimeout(resolve, attemptTimeout * (currentAttempt + 1)));
65
+ currentAttempt++;
66
+ continue;
67
+ }
68
+ else if (response.status === 401 && this.onTokenExpired && currentAttempt === 0) {
69
+ // Token rejected — try to refresh via callback
70
+ try {
71
+ this.token = await this.onTokenExpired();
72
+ currentAttempt++;
73
+ continue;
74
+ }
75
+ catch {
76
+ // Refresh failed — fall through to throw the API error
77
+ }
78
+ const errorText = await response.text();
79
+ const apiError = new Error(`Xano API error: 401 Unauthorized - ${errorText}\n\nYour Xano session may have expired. Run 'sc-xano auth status' to check token health.`);
80
+ apiError.isApiError = true;
81
+ throw apiError;
82
+ }
83
+ else {
84
+ const errorText = await response.text();
85
+ let hint = "";
86
+ if (response.status === 401 || response.status === 403) {
87
+ hint = `\n\nRun 'sc-xano auth status' to check your Xano session.`;
88
+ }
89
+ const apiError = new Error(`Xano API error: ${response.status} ${response.statusText} - ${errorText}${hint}`);
90
+ apiError.isApiError = true;
91
+ throw apiError;
92
+ }
93
+ }
94
+ const json = (await response.json());
95
+ return json;
96
+ }
97
+ catch (error) {
98
+ // Don't retry on 4xx API errors — only retry on network/timeout failures
99
+ if (error.isApiError || currentAttempt >= attempts) {
100
+ throw error;
101
+ }
102
+ await new Promise((resolve) => setTimeout(resolve, attemptTimeout * (currentAttempt + 1)));
103
+ currentAttempt++;
104
+ }
105
+ }
106
+ }
107
+ // Workspace methods
108
+ async getWorkspaces() {
109
+ return this.fetchJson(`api:mvp-admin/workspace`);
110
+ }
111
+ // Function methods (cached via sink)
112
+ async getFunctions(workspaceId, branchId = 0) {
113
+ const cacheKey = `functions:${workspaceId}:${branchId}`;
114
+ const cached = this.getCached(cacheKey);
115
+ if (cached)
116
+ return cached;
117
+ const result = await this.fetchJson(`api:mvp-admin/workspace/${workspaceId}/sink/functions?branch_id=${branchId}`);
118
+ this.setCache(cacheKey, result);
119
+ return result;
120
+ }
121
+ /** Get a single function by plucking from the sink list */
122
+ async getFunction(functionId, workspaceId, branchId = 0) {
123
+ if (workspaceId != null) {
124
+ const { functions } = await this.getFunctions(workspaceId, branchId);
125
+ const func = functions.find((f) => f.id === functionId);
126
+ if (func)
127
+ return func;
128
+ }
129
+ // Fallback to individual endpoint (may 404 on some instances)
130
+ return this.fetchJson(`api:mvp-admin/function/${functionId}`);
131
+ }
132
+ // App/API methods (cached via sink)
133
+ async getAPIAppsAndQueries(workspaceId, branchId = 0) {
134
+ const cacheKey = `api:${workspaceId}:${branchId}`;
135
+ const cached = this.getCached(cacheKey);
136
+ if (cached)
137
+ return cached;
138
+ const result = await this.fetchJson(`api:mvp-admin/workspace/${workspaceId}/sink/api?branch_id=${branchId}`);
139
+ this.setCache(cacheKey, result);
140
+ return result;
141
+ }
142
+ async getApp(appId, branchId) {
143
+ return this.fetchJson(`api:mvp-admin/app/${appId}?branch_id=${branchId}`);
144
+ }
145
+ async updateApp(app) {
146
+ this.flushCache();
147
+ return this.fetchJson(`api:mvp-admin/app/${app.id}`, {
148
+ method: "POST",
149
+ body: JSON.stringify({
150
+ data: app,
151
+ last_updated_at: app.updated_at,
152
+ }),
153
+ });
154
+ }
155
+ // Query (endpoint) methods
156
+ async getQuery(queryId) {
157
+ return this.fetchJson(`api:mvp-admin/query/${queryId}`);
158
+ }
159
+ async updateQuery(query) {
160
+ this.flushCache();
161
+ return this.fetchJson(`api:mvp-admin/query/${query.id}`, {
162
+ method: "POST",
163
+ body: JSON.stringify({
164
+ data: query,
165
+ last_updated_at: query.updated_at,
166
+ }),
167
+ });
168
+ }
169
+ // Task update
170
+ async updateTask(task) {
171
+ this.flushCache();
172
+ return this.fetchJson(`api:mvp-admin/task/${task.id}`, {
173
+ method: "POST",
174
+ body: JSON.stringify({
175
+ data: task,
176
+ last_updated_at: task.updated_at,
177
+ }),
178
+ });
179
+ }
180
+ // Trigger update
181
+ async updateTrigger(trigger) {
182
+ this.flushCache();
183
+ return this.fetchJson(`api:mvp-admin/trigger/${trigger.id}`, {
184
+ method: "POST",
185
+ body: JSON.stringify({
186
+ data: trigger,
187
+ last_updated_at: trigger.updated_at,
188
+ }),
189
+ });
190
+ }
191
+ // History methods
192
+ async getRequestHistory(workspaceId, page = 1, branchId = -1) {
193
+ return this.fetchJson(`api:mvp-admin/workspace/${workspaceId}/request?page=${page}&branch_id=${branchId}`);
194
+ }
195
+ async getRequestHistoryForQuery(queryId, page = 1, branchId = -1) {
196
+ return this.fetchJson(`api:mvp-admin/query/${queryId}/request?page=${page}&branch_id=${branchId}`);
197
+ }
198
+ async getRequest(requestId) {
199
+ return this.fetchJson(`api:mvp-admin/request/${requestId}`);
200
+ }
201
+ // Task methods (cached via sink)
202
+ async getTasks(workspaceId, branchId = 0) {
203
+ const cacheKey = `tasks:${workspaceId}:${branchId}`;
204
+ const cached = this.getCached(cacheKey);
205
+ if (cached)
206
+ return cached;
207
+ const payload = await this.fetchJson(`api:mvp-admin/workspace/${workspaceId}/sink/tasks?branch_id=${branchId}`);
208
+ const tasks = payload.tasks ?? [];
209
+ this.setCache(cacheKey, tasks);
210
+ return tasks;
211
+ }
212
+ async getTaskHistory(taskId, page = 1) {
213
+ return this.fetchJson(`api:mvp-admin/task/${taskId}/history?page=${page}`);
214
+ }
215
+ // Trigger methods (cached via sink)
216
+ async getTriggers(workspaceId, branchId = 0) {
217
+ const cacheKey = `triggers:${workspaceId}:${branchId}`;
218
+ const cached = this.getCached(cacheKey);
219
+ if (cached)
220
+ return cached;
221
+ const payload = await this.fetchJson(`api:mvp-admin/workspace/${workspaceId}/sink/trigger?branch_id=${branchId}`);
222
+ const triggers = payload.triggers ?? [];
223
+ this.setCache(cacheKey, triggers);
224
+ return triggers;
225
+ }
226
+ async getTriggerHistory(triggerId, branchId = 0, page = 1) {
227
+ return this.fetchJson(`api:mvp-admin/trigger/${triggerId}/request?branch_id=${branchId}&page=${page}`);
228
+ }
229
+ // MCP/Tool methods (cached via sink)
230
+ async getMCPServers(workspaceId, branchId = 0) {
231
+ const cacheKey = `toolsets:${workspaceId}:${branchId}`;
232
+ const cached = this.getCached(cacheKey);
233
+ if (cached)
234
+ return cached;
235
+ const payload = await this.fetchJson(`api:mvp-admin/workspace/${workspaceId}/sink/toolset?branch_id=${branchId}`);
236
+ const toolsets = payload.toolsets ?? [];
237
+ this.setCache(cacheKey, toolsets);
238
+ return toolsets;
239
+ }
240
+ async getMCPServerHistory(toolId, branchId = 0, page = 1) {
241
+ return this.fetchJson(`api:mvp-admin/toolset/${toolId}/request?branch_id=${branchId}&page=${page}`);
242
+ }
243
+ // Middleware methods (cached via sink)
244
+ async getMiddleware(workspaceId, branchId = 0) {
245
+ const cacheKey = `middleware:${workspaceId}:${branchId}`;
246
+ const cached = this.getCached(cacheKey);
247
+ if (cached)
248
+ return cached;
249
+ const payload = await this.fetchJson(`api:mvp-admin/workspace/${workspaceId}/sink/middleware?branch_id=${branchId}`);
250
+ const middleware = payload.middleware ?? [];
251
+ this.setCache(cacheKey, middleware);
252
+ return middleware;
253
+ }
254
+ // Addon methods (cached via sink)
255
+ async getAddons(workspaceId, branchId = 0) {
256
+ const cacheKey = `addons:${workspaceId}:${branchId}`;
257
+ const cached = this.getCached(cacheKey);
258
+ if (cached)
259
+ return cached;
260
+ const payload = await this.fetchJson(`api:mvp-admin/workspace/${workspaceId}/sink/addons?branch_id=${branchId}`);
261
+ const addons = payload.addons ?? [];
262
+ this.setCache(cacheKey, addons);
263
+ return addons;
264
+ }
265
+ // Workspace sink — tables/dbos (cached)
266
+ async getWorkspaceSink(workspaceId) {
267
+ const cacheKey = `sink:${workspaceId}`;
268
+ const cached = this.getCached(cacheKey);
269
+ if (cached)
270
+ return cached;
271
+ const result = await this.fetchJson(`api:mvp-admin/workspace/${workspaceId}/sink`);
272
+ this.setCache(cacheKey, result);
273
+ return result;
274
+ }
275
+ /** Get a single table by plucking from the workspace sink */
276
+ async getTable(tableId, workspaceId) {
277
+ if (workspaceId != null) {
278
+ const sink = await this.getWorkspaceSink(workspaceId);
279
+ const table = (sink.dbos ?? []).find((t) => t.id === tableId);
280
+ if (table)
281
+ return table;
282
+ }
283
+ // Fallback to individual endpoint
284
+ return this.fetchJson(`api:mvp-admin/dbo/${tableId}`);
285
+ }
286
+ // Task history item detail
287
+ async getTaskHistoryItem(taskId, runId) {
288
+ return this.fetchJson(`api:mvp-admin/task/${taskId}/history/${runId}`);
289
+ }
290
+ // XanoScript generation with 429 rate-limit retry
291
+ async generateXanoScript(workspaceId, data, kind) {
292
+ const body = JSON.stringify({ data, kind, path: "", type: "xs" });
293
+ const maxRetries = 5;
294
+ const baseDelay = 1000;
295
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
296
+ const response = await this.fetch(`api:mvp-admin/workspace/${workspaceId}/script`, { method: "POST", body });
297
+ if (response.ok) {
298
+ const result = await response.json();
299
+ return { status: "success", payload: result };
300
+ }
301
+ if (response.status === 429 && attempt < maxRetries) {
302
+ const delay = baseDelay * Math.pow(2, attempt);
303
+ await new Promise((resolve) => setTimeout(resolve, delay));
304
+ continue;
305
+ }
306
+ try {
307
+ const result = await response.json();
308
+ return { status: "error", payload: result };
309
+ }
310
+ catch {
311
+ return {
312
+ status: "error",
313
+ payload: {
314
+ message: response.status === 429
315
+ ? `Rate limited. Failed after ${maxRetries} retries.`
316
+ : "Failed to generate XanoScript",
317
+ doIgnore: response.status !== 429,
318
+ },
319
+ };
320
+ }
321
+ }
322
+ return { status: "error", payload: { message: "Failed to generate XanoScript", doIgnore: true } };
323
+ }
324
+ // XanoScript conversion with 429 rate-limit retry
325
+ async convertXanoScript(workspaceId, script) {
326
+ const body = JSON.stringify({ script, type: "xs" });
327
+ const maxRetries = 5;
328
+ const baseDelay = 1000;
329
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
330
+ const response = await this.fetch(`api:mvp-admin/workspace/${workspaceId}/script/convert`, { method: "POST", body });
331
+ if (response.ok) {
332
+ const result = await response.json();
333
+ return { status: "success", payload: result };
334
+ }
335
+ if (response.status === 429 && attempt < maxRetries) {
336
+ const delay = baseDelay * Math.pow(2, attempt);
337
+ await new Promise((resolve) => setTimeout(resolve, delay));
338
+ continue;
339
+ }
340
+ try {
341
+ const result = await response.json();
342
+ return { status: "error", payload: result };
343
+ }
344
+ catch {
345
+ return {
346
+ status: "error",
347
+ payload: {
348
+ message: response.status === 429
349
+ ? `Rate limited. Failed after ${maxRetries} retries.`
350
+ : "Failed to convert XanoScript",
351
+ doIgnore: response.status !== 429,
352
+ },
353
+ };
354
+ }
355
+ }
356
+ return { status: "error", payload: { message: "Failed to convert XanoScript", doIgnore: true } };
357
+ }
358
+ }
359
+ export class XanoMasterClient {
360
+ token;
361
+ constructor(config) {
362
+ this.token = config.token;
363
+ }
364
+ async fetchJson(path, options) {
365
+ const url = `https://app.xano.com/api:master/${path}`;
366
+ const response = await fetch(url, {
367
+ ...(options || {}),
368
+ headers: {
369
+ ...(options?.headers || {}),
370
+ Authorization: `Bearer ${this.token}`,
371
+ "Content-Type": "application/json",
372
+ },
373
+ });
374
+ if (!response.ok) {
375
+ const errorText = await response.text();
376
+ throw new Error(`Xano Master API error: ${response.status} ${response.statusText} - ${errorText}`);
377
+ }
378
+ return (await response.json());
379
+ }
380
+ async getInstances() {
381
+ return this.fetchJson("instance");
382
+ }
383
+ async getInstanceDatabases(instanceId) {
384
+ return this.fetchJson(`instance/${instanceId}/request-history/database`);
385
+ }
386
+ async clearInstanceDatabases(instanceId, tables, force = false) {
387
+ await this.fetchJson(`instance/${instanceId}/request-history/database/clear`, {
388
+ method: "POST",
389
+ body: JSON.stringify({ tables, force }),
390
+ });
391
+ }
392
+ async restartDeployment(instanceId, name) {
393
+ await this.fetchJson(`instance/${instanceId}/deployments/restart`, {
394
+ method: "POST",
395
+ body: JSON.stringify({ name }),
396
+ });
397
+ }
398
+ }
399
+ //# sourceMappingURL=xano-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xano-client.js","sourceRoot":"","sources":["../src/xano-client.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@statechange/xano-cli",
3
+ "version": "0.2.0",
4
+ "description": "CLI for Xano workspace management, performance analysis, XanoScript generation, and operational insights via private APIs",
5
+ "type": "module",
6
+ "bin": {
7
+ "sc-xano": "./dist/index.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "files": [
11
+ "dist",
12
+ "skills",
13
+ "README.md"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "dev": "tsc --watch",
18
+ "start": "node dist/index.js",
19
+ "prepublishOnly": "npm run build"
20
+ },
21
+ "keywords": [
22
+ "xano",
23
+ "cli",
24
+ "statechange",
25
+ "xanoscript",
26
+ "performance",
27
+ "audit",
28
+ "no-code",
29
+ "backend"
30
+ ],
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/statechange/xano-cli.git"
34
+ },
35
+ "homepage": "https://github.com/statechange/xano-cli#readme",
36
+ "bugs": {
37
+ "url": "https://github.com/statechange/xano-cli/issues"
38
+ },
39
+ "license": "MIT",
40
+ "dependencies": {
41
+ "@statechange/xano-xray": "^0.1.0",
42
+ "commander": "^11.1.0"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^20.10.0",
46
+ "tsx": "^4.21.0",
47
+ "typescript": "^5.3.0"
48
+ }
49
+ }
@@ -0,0 +1,135 @@
1
+ ---
2
+ name: performance-analysis
3
+ description: Analyze and optimize Xano workspace performance. Use when the user wants to find slow endpoints, trace execution bottlenecks, deep-dive request stacks, or understand why their Xano API is slow. Also use when the user mentions "performance," "slow endpoint," "bottleneck," "stack trace," or "optimization."
4
+ ---
5
+
6
+ # Xano Performance Analysis
7
+
8
+ Requires the `sc-xano` CLI to be authenticated (see the `sc-xano` skill).
9
+
10
+ ## Workflow: "Why is my workspace slow?"
11
+
12
+ Start broad, then drill into specifics.
13
+
14
+ ### Step 1: Identify the hottest endpoints
15
+
16
+ ```bash
17
+ npx @statechange/xano-cli performance top-endpoints --lookback 24 --format yaml
18
+ ```
19
+
20
+ Returns all endpoints, tasks, triggers, and MCP tools ranked by total duration. Look at:
21
+ - **Total duration** — which objects consume the most aggregate server time
22
+ - **Avg duration** — which individual calls are slowest
23
+ - **Request count** — high-frequency low-duration items may still matter
24
+
25
+ ### Step 2: Trace the worst offender
26
+
27
+ ```bash
28
+ npx @statechange/xano-cli performance trace endpoint <query-id> --samples 10 --format yaml
29
+ npx @statechange/xano-cli performance trace task <task-id> --samples 10 --format yaml
30
+ npx @statechange/xano-cli performance trace trigger <trigger-id> --samples 10 --format yaml
31
+ ```
32
+
33
+ **Note:** Task history items don't include stack traces (Xano API limitation). Trace will show duration percentiles but no step breakdown for tasks.
34
+
35
+ The trace output shows:
36
+ - **Duration percentiles** (avg, p50, p95, p99) across samples
37
+ - **Step breakdown** aggregated by `_xsid` — which steps consume the most time across all executions
38
+ - **Functions called** — which custom functions are invoked and how often
39
+ - Steps with high `occurrences` relative to `samples` indicate they run inside loops
40
+
41
+ ### Step 3: Deep-dive a single request
42
+
43
+ ```bash
44
+ npx @statechange/xano-cli performance deep-dive <request-id> --format yaml
45
+ ```
46
+
47
+ This shows:
48
+ - **Recursive stack tree** with direct vs rollup timing at each step
49
+ - **pct_of_total** / **pct_of_parent** — percentage breakdowns
50
+ - **iterations** — how many times loop bodies executed
51
+ - **Warnings** for slow steps inside loops (DB queries, lambdas, external API calls)
52
+ - **functions_called** summary with call counts and total time
53
+ - **stack_truncated: true** means Xano capped the stack — see "Handling truncated stacks" below
54
+
55
+ ### Step 4: X-Ray the hot function
56
+
57
+ ```bash
58
+ npx @statechange/xano-cli xray function --id <function-id> --format yaml
59
+ ```
60
+
61
+ Static analysis of the function's step hierarchy — warnings about nested slow steps, dependencies on other functions.
62
+
63
+ ### Step 5: Read the source
64
+
65
+ ```bash
66
+ npx @statechange/xano-cli xanoscript generate function <function-id>
67
+ ```
68
+
69
+ Generate XanoScript source to understand what the function does and recommend fixes.
70
+
71
+ ## Workflow: "Why do I get errors?"
72
+
73
+ ```bash
74
+ # 1. Find requests with error status codes
75
+ npx @statechange/xano-cli history requests --format yaml
76
+
77
+ # 2. Deep-dive the error request to see which step failed
78
+ npx @statechange/xano-cli performance deep-dive <error-request-id> --format yaml
79
+
80
+ # 3. X-Ray the failing function for structural issues
81
+ npx @statechange/xano-cli xray function --id <failing-function-id> --format yaml
82
+ ```
83
+
84
+ ## Workflow: "Which functions should I optimize first?"
85
+
86
+ ```bash
87
+ # 1. Get endpoint ranking
88
+ npx @statechange/xano-cli performance top-endpoints --lookback 24 --format yaml
89
+
90
+ # 2. Trace the top 3-5 endpoints
91
+ npx @statechange/xano-cli performance trace endpoint <id1> --format yaml
92
+ npx @statechange/xano-cli performance trace endpoint <id2> --format yaml
93
+ npx @statechange/xano-cli performance trace endpoint <id3> --format yaml
94
+
95
+ # 3. Look at functions_called across all traces
96
+ # Rank by: avg_seconds_per_call x total_calls x number_of_callers
97
+ # This gives "optimization ROI" — fixing one function improves many endpoints
98
+ ```
99
+
100
+ ## Handling truncated stacks
101
+
102
+ When `stack_truncated: true` appears in a deep-dive, Xano capped the stack at the endpoint's retention limit. Large `direct_seconds` on a function step with truncation means the real bottleneck is hidden.
103
+
104
+ ```bash
105
+ # 1. Check current retention settings
106
+ npx @statechange/xano-cli logs show endpoint <id>
107
+
108
+ # 2. Set to unlimited to capture full stacks
109
+ npx @statechange/xano-cli logs set endpoint <id> --limit -1
110
+
111
+ # 3. Watch for new executions
112
+ npx @statechange/xano-cli logs watch endpoint <id>
113
+
114
+ # 4. Deep-dive the new (untruncated) execution
115
+ npx @statechange/xano-cli performance deep-dive <new-request-id> --format yaml
116
+
117
+ # 5. Restore the default limit when done
118
+ npx @statechange/xano-cli logs set endpoint <id> --limit 100
119
+ ```
120
+
121
+ ## Interpreting Results
122
+
123
+ - **High `direct_seconds` with no children** — the step itself is slow (external API call, lambda, complex query)
124
+ - **Low `direct_seconds` but high `rollup_seconds`** — children are slow, drill deeper
125
+ - **Same `_xsid` with high `occurrences`** in trace — step runs inside a loop. Multiply `avg_rollup_seconds` by occurrences/samples to get per-request impact
126
+ - **DB queries inside loops** (warnings) — classic N+1 problem. Move the query outside the loop or use a batch query
127
+ - **Lambda steps with high timing** — interpreted code blocks are slower than native Xano steps
128
+
129
+ ### History retention values
130
+
131
+ - `limit: 100` (default) — keeps top 100 stack steps, may truncate deep stacks
132
+ - `limit: -1` — unlimited, captures full stack (use for debugging)
133
+ - `limit: 0` — disabled, no history retained
134
+ - `inherit: true` — inherits from the parent API app settings
135
+ - `enabled: false` — history recording is off entirely