@zeyos/client 0.1.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 (110) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/LICENSE +21 -0
  3. package/README.md +458 -0
  4. package/agents/README.md +66 -0
  5. package/agents/shared/business-app-benchmarks.md +111 -0
  6. package/agents/shared/zeyos-entity-map.md +142 -0
  7. package/agents/shared/zeyos-entity-reference.md +570 -0
  8. package/agents/shared/zeyos-query-patterns.md +89 -0
  9. package/agents/zeyos-account-intelligence/SKILL.md +34 -0
  10. package/agents/zeyos-account-intelligence/agents/openai.yaml +4 -0
  11. package/agents/zeyos-account-intelligence/references/workflows.md +84 -0
  12. package/agents/zeyos-billing-insights/SKILL.md +41 -0
  13. package/agents/zeyos-billing-insights/agents/openai.yaml +4 -0
  14. package/agents/zeyos-billing-insights/references/workflows.md +106 -0
  15. package/agents/zeyos-campaign-and-outreach/SKILL.md +44 -0
  16. package/agents/zeyos-campaign-and-outreach/agents/openai.yaml +4 -0
  17. package/agents/zeyos-campaign-and-outreach/references/workflows.md +100 -0
  18. package/agents/zeyos-collaboration-and-activity/SKILL.md +37 -0
  19. package/agents/zeyos-collaboration-and-activity/agents/openai.yaml +4 -0
  20. package/agents/zeyos-collaboration-and-activity/references/workflows.md +104 -0
  21. package/agents/zeyos-collections-and-dunning/SKILL.md +46 -0
  22. package/agents/zeyos-collections-and-dunning/agents/openai.yaml +4 -0
  23. package/agents/zeyos-collections-and-dunning/references/workflows.md +132 -0
  24. package/agents/zeyos-commerce-and-inventory/SKILL.md +38 -0
  25. package/agents/zeyos-commerce-and-inventory/agents/openai.yaml +4 -0
  26. package/agents/zeyos-commerce-and-inventory/references/workflows.md +101 -0
  27. package/agents/zeyos-mail-operations/SKILL.md +35 -0
  28. package/agents/zeyos-mail-operations/agents/openai.yaml +4 -0
  29. package/agents/zeyos-mail-operations/references/workflows.md +110 -0
  30. package/agents/zeyos-notes-and-sops/SKILL.md +31 -0
  31. package/agents/zeyos-notes-and-sops/agents/openai.yaml +4 -0
  32. package/agents/zeyos-notes-and-sops/references/workflows.md +85 -0
  33. package/agents/zeyos-platform-and-schema/SKILL.md +37 -0
  34. package/agents/zeyos-platform-and-schema/agents/openai.yaml +4 -0
  35. package/agents/zeyos-platform-and-schema/references/workflows.md +97 -0
  36. package/agents/zeyos-work-management/SKILL.md +45 -0
  37. package/agents/zeyos-work-management/agents/openai.yaml +4 -0
  38. package/agents/zeyos-work-management/references/workflows.md +148 -0
  39. package/docs/01-api-reference/01-data-retrieval.md +601 -0
  40. package/docs/01-api-reference/02-authentication.md +288 -0
  41. package/docs/01-api-reference/03-resources.md +270 -0
  42. package/docs/01-api-reference/04-schema.md +539 -0
  43. package/docs/01-api-reference/_category_.json +9 -0
  44. package/docs/02-javascript-client/01-getting-started.md +146 -0
  45. package/docs/02-javascript-client/02-authentication.md +287 -0
  46. package/docs/02-javascript-client/03-making-requests.md +572 -0
  47. package/docs/02-javascript-client/04-practical-guide.md +348 -0
  48. package/docs/02-javascript-client/_category_.json +9 -0
  49. package/docs/03-cli/01-getting-started.md +219 -0
  50. package/docs/03-cli/02-commands.md +407 -0
  51. package/docs/03-cli/03-configuration.md +220 -0
  52. package/docs/03-cli/_category_.json +9 -0
  53. package/docs/04-agent-workflows/00-coding-agents.md +35 -0
  54. package/docs/04-agent-workflows/01-agent-quickstart.md +147 -0
  55. package/docs/04-agent-workflows/02-agent-recipes.md +109 -0
  56. package/docs/04-agent-workflows/03-cli-coverage-and-escalation.md +65 -0
  57. package/docs/04-agent-workflows/_category_.json +9 -0
  58. package/docs/04-sample-apps/01-kanban.md +89 -0
  59. package/docs/04-sample-apps/02-crm.md +81 -0
  60. package/docs/04-sample-apps/03-dashboard.md +80 -0
  61. package/docs/04-sample-apps/_category_.json +9 -0
  62. package/docs/05-tutorials/00-application-developers.md +43 -0
  63. package/docs/05-tutorials/01-integration-architecture.md +60 -0
  64. package/docs/05-tutorials/02-build-your-own-zeyos-frontend.md +517 -0
  65. package/docs/05-tutorials/03-server-side-integrations.md +185 -0
  66. package/docs/05-tutorials/_category_.json +9 -0
  67. package/docs/intro.md +197 -0
  68. package/openapi/api.json +24308 -0
  69. package/openapi/auth.json +415 -0
  70. package/openapi/dbref.json +56223 -0
  71. package/openapi/oauth2.json +781 -0
  72. package/openapi/sdk.json +949 -0
  73. package/openapi/views.txt +642 -0
  74. package/package.json +49 -0
  75. package/samples/crm/README.md +28 -0
  76. package/samples/crm/index.html +327 -0
  77. package/samples/crm/js/api.js +208 -0
  78. package/samples/crm/js/auth.js +61 -0
  79. package/samples/crm/js/main.js +545 -0
  80. package/samples/crm/js/state.js +90 -0
  81. package/samples/crm/js/ui.js +51 -0
  82. package/samples/dashboard/README.md +28 -0
  83. package/samples/dashboard/index.html +280 -0
  84. package/samples/dashboard/js/api.js +197 -0
  85. package/samples/dashboard/js/auth.js +59 -0
  86. package/samples/dashboard/js/main.js +382 -0
  87. package/samples/dashboard/js/state.js +81 -0
  88. package/samples/dashboard/js/ui.js +48 -0
  89. package/samples/kanban/README.md +28 -0
  90. package/samples/kanban/index.html +263 -0
  91. package/samples/kanban/js/api.js +152 -0
  92. package/samples/kanban/js/auth.js +59 -0
  93. package/samples/kanban/js/constants.js +40 -0
  94. package/samples/kanban/js/kanban.js +246 -0
  95. package/samples/kanban/js/main.js +362 -0
  96. package/samples/kanban/js/modals.js +474 -0
  97. package/samples/kanban/js/settings.js +82 -0
  98. package/samples/kanban/js/state.js +118 -0
  99. package/samples/kanban/js/ui.js +49 -0
  100. package/scripts/generate-client.mjs +344 -0
  101. package/src/generated/operations.js +9772 -0
  102. package/src/generated/schema.js +8982 -0
  103. package/src/index.js +85 -0
  104. package/src/runtime/client.js +1208 -0
  105. package/src/runtime/error.js +29 -0
  106. package/src/runtime/http.js +174 -0
  107. package/src/runtime/request-shape.js +35 -0
  108. package/src/runtime/schema.js +206 -0
  109. package/src/runtime/suggest.js +74 -0
  110. package/src/runtime/token-store.js +105 -0
@@ -0,0 +1,348 @@
1
+ ---
2
+ sidebar_label: Practical Guide
3
+ ---
4
+
5
+ # Practical Implementation Guide
6
+
7
+ This guide documents patterns and gotchas discovered while building a real application on top of the ZeyOS JavaScript client. It supplements the reference documentation with things that only become apparent once you start making actual API calls.
8
+
9
+ ## HTTP Method Conventions
10
+
11
+ ZeyOS uses an unconventional but consistent REST convention that often surprises developers:
12
+
13
+ | Operation | HTTP Method | Notes |
14
+ |-----------|-------------|-------|
15
+ | List records | **POST** | Query params (filters, sort, fields) go in the request body |
16
+ | Get a record | **GET** | |
17
+ | Create a record | **PUT** | Not POST — ZeyOS uses PUT for creation |
18
+ | Update a record | **PATCH** | Partial updates; only send fields you want to change |
19
+ | Delete a record | **DELETE** | |
20
+ | Check existence | **HEAD** | Returns `true` (no body) on success |
21
+
22
+ The most important one to internalise: **list operations are POST requests**. This makes sense once you consider that complex queries with nested filters would quickly exceed URL length limits as query strings.
23
+
24
+ ## Passing the Request Body for Update Operations
25
+
26
+ Generated methods accept the natural flat style for operations that have both a path parameter and a request body:
27
+
28
+ ```js
29
+ await client.api.updateTicket({ ID: 42, status: 4, priority: 2 });
30
+ ```
31
+
32
+ The client routes known path/query/header parameters to the request URL and sends the remaining non-reserved keys as the body. Explicit `body` and `data` keys are still supported when you want to separate those concerns yourself:
33
+
34
+ ```js
35
+ await client.api.updateTicket({ ID: 42, body: { status: 4, priority: 2 } });
36
+ await client.api.updateTask({ ID: taskId, data: { name: 'New name', duedate: ts } });
37
+ ```
38
+
39
+ For low-level `client.request()` calls, prefer explicit `body` because there is no generated operation metadata to tell the client which keys are URL parameters.
40
+
41
+ ## `filter` vs `filters`
42
+
43
+ The ZeyOS API exposes two distinct filtering parameters, and the one you need depends on the field type:
44
+
45
+ | Parameter | Use for | Example |
46
+ |-----------|---------|---------|
47
+ | `filter` | Simple scalar fields (integers, strings, enums) | `filter: { visibility: 0, status: 1 }` |
48
+ | `filters` | GIN-indexed fields — foreign key references and array-type columns | `filters: { ticket: ticketId, project: projectId }` |
49
+
50
+ In practice this means:
51
+
52
+ ```js
53
+ // Listing tickets — status and visibility are scalar fields → use 'filter'
54
+ const tickets = await client.api.listTickets({
55
+ filters: { visibility: 0, project: projectId },
56
+ sort: ['-lastmodified'],
57
+ limit: 500,
58
+ });
59
+
60
+ // Listing tasks for a ticket — 'ticket' is a GIN-indexed FK → use 'filters'
61
+ const tasks = await client.api.listTasks({
62
+ fields: ['ID', 'tasknum', 'name', 'duedate', 'assigneduser'],
63
+ filters: { ticket: ticketId, visibility: 0 },
64
+ sort: ['+name'],
65
+ limit: 200,
66
+ });
67
+ ```
68
+
69
+ :::tip
70
+ When in doubt, use `filters`. It appears to handle both scalar and FK fields correctly. Using `filter` for a FK field silently returns unfiltered results rather than throwing an error, which makes this particularly easy to miss.
71
+ :::
72
+
73
+ ## Always Include `visibility: 0`
74
+
75
+ ZeyOS records have a `visibility` field that controls soft-deletion and archiving. Records with `visibility > 0` are typically hidden from normal views. Always include `visibility: 0` in your filters unless you intentionally want to retrieve archived or deleted records:
76
+
77
+ ```js
78
+ const filter = { visibility: 0 };
79
+ // Add resource-specific filters after
80
+ if (projectId) filter.project = projectId;
81
+ ```
82
+
83
+ ## Normalising List Responses
84
+
85
+ List operations are not perfectly uniform across the whole surface area. Use the shared helper so every call site follows the same response-shape handling:
86
+
87
+ ```js
88
+ import { normalizeListResult } from '@zeyos/client';
89
+
90
+ const result = await client.api.listTickets({ filters: { visibility: 0 } });
91
+ const { data: tickets } = normalizeListResult(result);
92
+ ```
93
+
94
+ Use `normalizeCountResult()` for count-only requests.
95
+
96
+ ## Date and Timestamp Handling
97
+
98
+ ZeyOS stores all dates as **Unix timestamps in seconds** (not milliseconds). When reading:
99
+
100
+ ```js
101
+ // Convert to a JavaScript Date
102
+ const date = new Date(ticket.duedate * 1000);
103
+
104
+ // Format for display
105
+ const label = new Date(ticket.duedate * 1000).toLocaleDateString(undefined, {
106
+ month: 'short', day: 'numeric', year: 'numeric',
107
+ });
108
+
109
+ // Check if overdue
110
+ const isOverdue = ticket.duedate * 1000 < Date.now();
111
+ ```
112
+
113
+ When writing (e.g. from an HTML `<input type="date">`):
114
+
115
+ ```js
116
+ const dueDateVal = form.querySelector('#due-date').value; // '2026-03-15'
117
+ const duedate = dueDateVal
118
+ ? Math.floor(new Date(dueDateVal).getTime() / 1000)
119
+ : null;
120
+
121
+ await client.api.updateTicket({ ID: id, body: { duedate } });
122
+ ```
123
+
124
+ ## Selecting Fields for Performance
125
+
126
+ Always pass a `fields` array in list requests. Without it, every field on every record is returned, which can significantly increase payload size and response time:
127
+
128
+ ```js
129
+ // ✗ Returns all fields for every ticket
130
+ const tickets = await client.api.listTickets({ limit: 500 });
131
+
132
+ // ✓ Returns only what you need
133
+ const tickets = await client.api.listTickets({
134
+ fields: ['ID', 'ticketnum', 'name', 'status', 'priority', 'duedate'],
135
+ filters: { visibility: 0 },
136
+ limit: 500,
137
+ });
138
+ ```
139
+
140
+ For single-record GET operations, field selection is not available — all standard fields are returned. Use query flags like `extdata: 1` and `tags: 1` to opt into additional data:
141
+
142
+ ```js
143
+ const ticket = await client.api.getTicket({ ID: id, extdata: 1, tags: 1 });
144
+ ```
145
+
146
+ ## Optimistic UI Updates with Server Verification
147
+
148
+ For immediate feedback on user actions (like drag-and-drop), apply the change to local state first, then confirm with the server and revert if it fails. Use the response body to confirm the actual resulting value:
149
+
150
+ ```js
151
+ const fromStatus = ticket.status;
152
+
153
+ // 1. Optimistic update — instant visual feedback
154
+ ticket.status = toStatus;
155
+ updateColumn(fromStatus);
156
+ updateColumn(toStatus);
157
+
158
+ try {
159
+ // 2. Send PATCH — response body contains the updated record
160
+ const updated = await client.api.updateTicket({
161
+ ID: ticket.ID,
162
+ body: { status: toStatus },
163
+ });
164
+
165
+ // 3. Confirm — use the server's value in case it was clamped or rejected
166
+ const confirmedStatus = updated?.status ?? toStatus;
167
+ if (confirmedStatus !== toStatus) {
168
+ ticket.status = confirmedStatus;
169
+ updateColumn(toStatus);
170
+ updateColumn(confirmedStatus);
171
+ }
172
+ } catch (err) {
173
+ // 4. Revert on failure
174
+ ticket.status = fromStatus;
175
+ updateColumn(fromStatus);
176
+ updateColumn(toStatus);
177
+ showError(`Move failed: ${err.message}`);
178
+ }
179
+ ```
180
+
181
+ ## Persisting Refreshed Tokens
182
+
183
+ When using token mode with `autoRefresh: true` in a trusted environment, the client silently refreshes expired access tokens. The refreshed tokens are stored in the `MemoryTokenStore` but lost on page reload unless you persist them explicitly. Call a sync function after important API operations:
184
+
185
+ ```js
186
+ async function syncTokens() {
187
+ try {
188
+ const ts = await client.auth.getTokenSet();
189
+ if (ts?.accessToken) {
190
+ localStorage.setItem('zeyos_tokens', JSON.stringify({
191
+ accessToken: ts.accessToken,
192
+ refreshToken: ts.refreshToken,
193
+ expiresAt: ts.expiresAt,
194
+ refreshTokenExpiresAt: ts.refreshTokenExpiresAt,
195
+ }));
196
+ }
197
+ } catch {
198
+ // Non-critical — silently ignore
199
+ }
200
+ }
201
+
202
+ // Usage
203
+ const tickets = await client.api.listTickets({ filters: { visibility: 0 } });
204
+ await syncTokens(); // Persist any refreshed tokens
205
+ ```
206
+
207
+ ## Session Detection Without Tokens
208
+
209
+ If you don't have an OAuth token but the user is already logged into ZeyOS in the same browser, you can detect their session via the userinfo endpoint:
210
+
211
+ ```js
212
+ async function trySessionAuth(instanceUrl) {
213
+ try {
214
+ const res = await fetch(`${instanceUrl}oauth2/v1/userinfo`, {
215
+ credentials: 'include',
216
+ });
217
+ if (res.ok) return await res.json();
218
+ } catch {
219
+ // No session
220
+ }
221
+ return null;
222
+ }
223
+
224
+ const userInfo = await trySessionAuth('https://cloud.zeyos.com/demo/');
225
+ if (userInfo) {
226
+ // Session is active — initialize in session mode
227
+ const client = createZeyosClient({
228
+ platform: instanceUrl,
229
+ auth: { mode: 'session', session: { enabled: true, credentials: 'include' } },
230
+ });
231
+ }
232
+ ```
233
+
234
+ :::note
235
+ Session mode requires that your app is served from the same origin as ZeyOS, or that the ZeyOS instance is configured to allow cross-origin requests with credentials. If you are on a different domain, token mode is more reliable.
236
+ :::
237
+
238
+ ## Navigating to ZeyOS Views
239
+
240
+ To link users directly to a record inside the ZeyOS web interface, construct a URL in this format:
241
+
242
+ ```
243
+ <INSTANCE_URL>?umi=<MODULE>&page=<PAGE>&id=<RECORD_ID>&tab=<TAB>
244
+ ```
245
+
246
+ Common examples:
247
+
248
+ ```js
249
+ const baseUrl = 'https://cloud.zeyos.com/demo/';
250
+
251
+ // Link to a ticket
252
+ `${baseUrl}?umi=tickets&page=details_ticket&id=${ticketId}&tab=0`
253
+
254
+ // Link to a task (within the tickets module)
255
+ `${baseUrl}?umi=tickets&page=details_ticket&id=${taskId}&tab=0`
256
+
257
+ // Link to an account
258
+ `${baseUrl}?umi=accounts&page=details_account&id=${accountId}&tab=0`
259
+ ```
260
+
261
+ ## Extended Data (extdata)
262
+
263
+ Many ZeyOS entities support custom fields via `extdata`. These are returned as a nested object:
264
+
265
+ ```js
266
+ // Request extended data in a list
267
+ const tickets = await client.api.listTickets({
268
+ fields: ['ID', 'name', 'extdata.region', 'extdata.customer_type'],
269
+ filters: { visibility: 0 },
270
+ });
271
+
272
+ // Or include all extdata for single-record fetches
273
+ const ticket = await client.api.getTicket({ ID: id, extdata: 1 });
274
+ console.log(ticket.extdata); // { region: 'EMEA', customer_type: 'Enterprise', ... }
275
+ ```
276
+
277
+ When saving extended data back, pass it as a plain object:
278
+
279
+ ```js
280
+ await client.api.updateTicket({
281
+ ID: id,
282
+ body: {
283
+ extdata: { region: 'APAC', customer_type: 'SMB' },
284
+ },
285
+ });
286
+ ```
287
+
288
+ ## Common Status and Priority Values
289
+
290
+ Ticket and task status and priority values are plain integers. The canonical values observed in the ZeyOS API:
291
+
292
+ ### Ticket Status
293
+
294
+ | Value | Label |
295
+ |-------|-------|
296
+ | `0` | Not Started |
297
+ | `1` | Awaiting Acceptance |
298
+ | `2` | Accepted |
299
+ | `3` | Rejected |
300
+ | `4` | Active |
301
+ | `5` | Inactive |
302
+ | `6` | Feedback Required |
303
+ | `7` | Testing |
304
+ | `8` | Cancelled |
305
+ | `9` | Completed |
306
+ | `10` | Failed |
307
+ | `11` | Booked |
308
+
309
+ ### Ticket Priority
310
+
311
+ | Value | Label |
312
+ |-------|-------|
313
+ | `0` | Lowest |
314
+ | `1` | Low |
315
+ | `2` | Medium |
316
+ | `3` | High |
317
+ | `4` | Highest |
318
+
319
+ ## Error Handling Checklist
320
+
321
+ `ZeyosApiError` is thrown for all non-2xx responses. Key properties to check:
322
+
323
+ ```js
324
+ import { ZeyosApiError } from '@zeyos/client';
325
+
326
+ try {
327
+ await client.api.updateTicket({ ID: id, body: data });
328
+ } catch (err) {
329
+ if (!(err instanceof ZeyosApiError)) throw err; // Re-throw unexpected errors
330
+
331
+ if (err.status === 401) {
332
+ // Session expired or token invalid — redirect to login
333
+ } else if (err.status === 403) {
334
+ // Insufficient permissions
335
+ } else if (err.status === 404) {
336
+ // Record does not exist
337
+ } else if (err.status === 409) {
338
+ // Conflict — record was modified since last read (check If-Match header usage)
339
+ } else {
340
+ // Generic error — err.body often contains a human-readable message
341
+ console.error(err.body?.message ?? err.message);
342
+ }
343
+ }
344
+ ```
345
+
346
+ :::tip
347
+ On 401, the client automatically retries with a refreshed token if `autoRefresh: true` is set, a refresh token is available, and OAuth client credentials are configured. You will only see a 401 error if the refresh also fails — typically meaning the user's session has fully expired.
348
+ :::
@@ -0,0 +1,9 @@
1
+ {
2
+ "label": "JavaScript Client",
3
+ "position": 3,
4
+ "collapsed": false,
5
+ "link": {
6
+ "type": "generated-index",
7
+ "description": "The ZeyOS JavaScript client: installation, authentication, CRUD operations, and real-world implementation patterns."
8
+ }
9
+ }
@@ -0,0 +1,219 @@
1
+ ---
2
+ sidebar_label: Getting Started
3
+ ---
4
+
5
+ # CLI Getting Started
6
+
7
+ The ZeyOS CLI gives you fast, scriptable access to the ZeyOS REST API from your terminal. It is the default entry point for coding agents and shell automation against the CLI's curated resource registry.
8
+
9
+ ## Installation
10
+
11
+ :::info Requirements
12
+ Node.js 18.3+ is required. The CLI has zero external dependencies beyond the bundled `@zeyos/client` package.
13
+ :::
14
+
15
+ ### Published package (recommended)
16
+
17
+ Install the CLI globally from npm:
18
+
19
+ ```bash
20
+ npm install -g @zeyos/cli
21
+ zeyos --help
22
+ ```
23
+
24
+ ### Running from source
25
+
26
+ If you are contributing to the CLI or need to run an unreleased version, clone the repository and run directly from the source tree:
27
+
28
+ ```bash
29
+ # Clone the repository
30
+ git clone <repo-url>
31
+ cd client
32
+
33
+ # Run directly
34
+ ./cli/bin/zeyos.mjs --help
35
+ ```
36
+
37
+ For convenience, create a symlink so you can run `zeyos` from anywhere:
38
+
39
+ ```bash
40
+ ln -s $(pwd)/cli/bin/zeyos.mjs /usr/local/bin/zeyos
41
+ ```
42
+
43
+ ## First Login
44
+
45
+ Authenticate with your ZeyOS instance using the `login` command:
46
+
47
+ ```bash
48
+ # Interactive — prompts for URL, app ID, and secret
49
+ zeyos login
50
+
51
+ # Or provide all values upfront
52
+ zeyos login \
53
+ --base-url https://cloud.zeyos.com/demo \
54
+ --client-id myapp \
55
+ --secret "$ZEYOS_CLIENT_SECRET"
56
+ ```
57
+
58
+ For interactive use, omit `--secret`; the CLI prompts without echoing the secret to the terminal. Passing secrets as command-line arguments is best reserved for controlled automation.
59
+
60
+ **What happens:**
61
+
62
+ 1. The CLI opens your browser to the ZeyOS authorization page
63
+ 2. You log in and authorize the application
64
+ 3. The CLI exchanges the authorization code for access + refresh tokens
65
+ 4. Credentials are saved to `.zeyos/auth.json` in your project
66
+
67
+ :::tip Switching Instances
68
+ Use `--clean` to discard all saved credentials and start fresh:
69
+ ```bash
70
+ zeyos login --clean
71
+ ```
72
+ This is useful when switching between ZeyOS instances.
73
+ :::
74
+
75
+ ## Your First Commands
76
+
77
+ Once logged in, you can start working with your data:
78
+
79
+ ```bash
80
+ # Check who you're logged in as
81
+ zeyos whoami
82
+
83
+ # List tickets (table output by default)
84
+ zeyos list tickets
85
+
86
+ # Get a specific ticket with all details
87
+ zeyos get ticket 42 --all
88
+
89
+ # Count records
90
+ zeyos count accounts
91
+
92
+ # Create a new ticket
93
+ zeyos create ticket --name "Fix login bug" --status 0 --priority 3
94
+
95
+ # Update a ticket's status
96
+ zeyos update ticket 42 --status 4
97
+
98
+ # Delete a ticket
99
+ zeyos delete ticket 42
100
+ ```
101
+
102
+ Inspect the curated CLI-supported resource set at any time:
103
+
104
+ ```bash
105
+ zeyos resources
106
+ ```
107
+
108
+ If the resource you need does not appear there, switch to [`@zeyos/client`](../02-javascript-client/01-getting-started.md).
109
+
110
+ ## Discover the Schema
111
+
112
+ Inspect a resource's fields, types, foreign keys, and enum values before querying. This works offline -- no login required -- so it is a fast way to learn the data model:
113
+
114
+ ```bash
115
+ zeyos describe tickets
116
+ zeyos describe accounts --json
117
+ ```
118
+
119
+ ## Install Agent Skills
120
+
121
+ If you are driving the CLI from a coding agent (Claude, Codex, …), install the bundled ZeyOS skill packs into your project so the agent picks up the right query conventions:
122
+
123
+ ```bash
124
+ zeyos skills list # see the available skills
125
+ zeyos skills install # copy them into .claude/skills (or .codex)
126
+ ```
127
+
128
+ See the [Commands Reference](./02-commands.md#skills) for details.
129
+
130
+ ## Working with Filters
131
+
132
+ Query specific records using JSON filter expressions:
133
+
134
+ ```bash
135
+ # Tickets with status = 1 (In Progress)
136
+ zeyos list tickets --filter '{"status":1}'
137
+
138
+ # Combine multiple criteria (AND logic)
139
+ zeyos list tickets --filter '{"status":1,"priority":3}'
140
+
141
+ # Count matching records
142
+ zeyos count tickets --filter '{"status":1}'
143
+ ```
144
+
145
+ For normal operational views, include `visibility: 0`:
146
+
147
+ ```bash
148
+ zeyos list tickets --filter '{"visibility":0,"status":1}'
149
+ ```
150
+
151
+ ## Sorting and Pagination
152
+
153
+ ```bash
154
+ # Sort by name ascending, then by last modified descending
155
+ zeyos list tickets --sort "+name,-lastmodified"
156
+
157
+ # Limit results and paginate
158
+ zeyos list tickets --limit 10
159
+ zeyos list tickets --limit 10 --offset 10 # page 2
160
+ ```
161
+
162
+ When results fill the page limit, the CLI automatically shows pagination info:
163
+
164
+ ```
165
+ Showing 1–10 of 47 (--offset 10 for next page)
166
+ ```
167
+
168
+ ## Output Formats
169
+
170
+ Choose the format that fits your workflow:
171
+
172
+ ```bash
173
+ # Default: formatted table (human-readable)
174
+ zeyos list tickets
175
+
176
+ # JSON: for scripting and piping
177
+ zeyos list tickets --json
178
+
179
+ # YAML: for config-friendly output
180
+ zeyos list tickets --yaml
181
+ ```
182
+
183
+ :::tip Piping
184
+ JSON output works great with tools like `jq`:
185
+ ```bash
186
+ zeyos list tickets --json | jq '.[].name'
187
+ ```
188
+ :::
189
+
190
+ ## JSON-First Automation
191
+
192
+ For coding agents and non-interactive scripts, prefer `--json` output and JSON-first writes:
193
+
194
+ ```bash
195
+ zeyos create ticket --data '{"name":"Fix login bug","status":0,"priority":3,"visibility":0}' --json
196
+ zeyos update ticket 42 --data '{"status":4}' --json
197
+ ```
198
+
199
+ `zeyos whoami --json` does not print access tokens. If a local tool explicitly needs the current token, use `zeyos whoami --show-token --json` and treat the output as a secret.
200
+
201
+ ## Credential Storage
202
+
203
+ Tokens are saved to `.zeyos/auth.json` in your project directory (or the nearest parent that has one). For global credentials shared across projects:
204
+
205
+ ```bash
206
+ zeyos login --global
207
+ ```
208
+
209
+ This saves to `~/.config/zeyos/credentials.json` instead.
210
+
211
+ :::warning
212
+ Add `.zeyos/auth.json` to your `.gitignore` — it contains access tokens.
213
+ :::
214
+
215
+ ## Next Steps
216
+
217
+ - **[Coding Agents](../04-agent-workflows/00-coding-agents.md)** -- CLI-first workflows and escalation guidance
218
+ - **[Commands Reference](./02-commands.md)** — Full reference for every command
219
+ - **[Configuration](./03-configuration.md)** — Config files, environment variables, and resource field customization