@pipod/cli 0.1.6 → 0.1.8

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/man/pipod.1 ADDED
@@ -0,0 +1,865 @@
1
+ .TH "PIPOD" "1" "October 2026" "0.1.8"
2
+ .SH "NAME"
3
+ \fBpipod\fR \- run pi coding\-agent sessions in server\-managed pods
4
+ .SH SYNOPSIS
5
+ .RS 2
6
+ .nf
7
+ Usage:
8
+ pipod [options] launch a pod for this project and start pi
9
+ pipod [options] \-\- <pi args…> launch and pass arguments to pi: prompt words,
10
+ \-\-model <id>, \-\-thinking <level>, \-\-tui\-mode <mode>,
11
+ \-e/\-\-extension <path>, \-\-skill <path>,
12
+ \-\-prompt\-template <path> (each repeatable)
13
+ pipod <command> [options] run a command
14
+ pipod help [command|topic] print the full manual entry
15
+
16
+ Sign in first with `pipod login`\. A pod\-scoped PI_POD_SERVER_TOKEN also counts as
17
+ signed in\. While signed out, only login, whoami, init, doctor, update, help, and
18
+ version are available\.
19
+
20
+ Pod commands:
21
+ list [pod] List pods; `list <pod>` shows one machine's group (ls)
22
+ attach [pod] Reconnect to a pod session (a)
23
+ stop [pod…] Stop pods now (files kept; attach restarts them)
24
+ fork <pod> Launch a new pod forked from a pod's session
25
+ rename <pod> <name> Rename a pod
26
+ send [pod] <path> Copy host files into a pod
27
+ receive [pod] <path> Copy pod files into the current directory
28
+ archive [pod…] Hide pods from the list (files kept; restore brings them back)
29
+ restore [pod…] Bring archived pods back
30
+ gc Report retention state; \-\-delete removes reclaimable pods
31
+
32
+ Account commands:
33
+ login Sign in to a pi pod server via Zitadel
34
+ logout Revoke this session and delete the stored credentials
35
+ whoami Show the signed\-in account
36
+ account Open the Zitadel self\-service console
37
+ org\-admin Open the Zitadel Console for this organization
38
+ billing Open Stripe Checkout or the billing portal (authenticated)
39
+ credentials Connect account model\-provider sign\-ins
40
+
41
+ Configuration commands:
42
+ init Scaffold \.pi\-pod/ config, env, env\.example, and init\.sh
43
+ templates Manage account templates
44
+ push Upload a local config layer to its server bundle
45
+ pull Write a server bundle into its local config layer
46
+ diff Show local vs server drift for a config layer
47
+ secrets Manage server and project secret scopes
48
+ settings Show or edit one server settings config directly
49
+ jobs Manage server\-scheduled jobs
50
+
51
+ Maintenance commands:
52
+ doctor Check auth, server, org, and launch\-resolution layers
53
+ update Upgrade pi pod itself
54
+
55
+ Launch options:
56
+ \-\-template <name|id> Launch from an account template
57
+ \-\-on <pod|self> Co\-locate the new pod on an existing pod's machine
58
+ \-\-reuse Restart this project's newest stopped pod instead of creating one
59
+ \-\-no\-seed Start the pod with an empty workspace (skip workspace seeding)
60
+ \-\-dry\-run Resolve and print the launch plan; create nothing
61
+
62
+ General options:
63
+ \-y, \-\-yes Skip supported confirmations
64
+ \-v, \-\-verbose Debug logging (secrets redacted)
65
+ \-\-version Print CLI, Node, and bundled Pi versions
66
+ \-h, \-\-help Show help
67
+
68
+ Topics (pipod help <topic>):
69
+ setup First\-time setup, in order, and who does each step
70
+ layers How org, user, and template settings combine
71
+ launch What a launch does: templates, workspace seeding, Pi resources
72
+ config Every config\.json key (man pipod\-config)
73
+ files Every file pipod reads or writes
74
+ environment Environment variables
75
+
76
+ `pipod <command> \-\-help` is a command's usage; `pipod help <command>` is its full
77
+ manual entry; `man pipod` is the whole manual\.
78
+ .fi
79
+ .RE
80
+ .SH DESCRIPTION
81
+ .P
82
+ pi pod runs pi sessions in pods: sandboxes on a pi pod server, which you attach to from a
83
+ terminal or the phone apps and leave running when you detach\. You use one server, as a
84
+ member of one organization on it\.
85
+ .P
86
+ What a pod starts with is decided on the server, from settings layers: the organization's
87
+ defaults, your own defaults, and a template, which is the environment for one project\. Each
88
+ layer holds pod config (pipod\-config(5)), an init script that runs in every pod at launch, a
89
+ bake script that is built into the pod image once, and Pi files\. Secrets are stored apart from
90
+ the layers and reach pods as environment variables\. \fBpipod help layers\fP explains how they
91
+ combine\.
92
+ .P
93
+ Every server layer has a local source of truth: a directory you edit with any editor, then
94
+ upload with \fBpipod push\fP\|\. \fBpipod pull\fP writes the server's copy back, and \fBpipod diff\fP
95
+ compares the two\.
96
+ .SH SETUP
97
+ .P
98
+ Setting pi pod up for yourself or an organization, in order\. A person has to do the steps
99
+ marked (person): each needs a browser, a hidden prompt, or a decision about access or money\.
100
+ An agent can do the rest with the commands shown, but should show the person every change
101
+ before applying it\.
102
+ .SS 1\. A server and an account (person)
103
+ .P
104
+ On your own server, the host's owner installs it (docs/self\-host\.md in the pipod repository)
105
+ and creates accounts with \fBselfhost/add\-user <email>\fP on the host, adding \fB\-\-owner\fP for
106
+ someone who may change organization settings\. On a server someone else runs, ask its owner
107
+ for an account\.
108
+ .SS 2\. Install the CLI and sign in (person)
109
+ .RS 2
110
+ .nf
111
+ npm install \-g @pipod/cli # Node 22\.19 or later
112
+ pipod login \-\-server <url>
113
+ pipod doctor
114
+ .fi
115
+ .RE
116
+ .P
117
+ \fBlogin\fP opens a browser, or prints a code to confirm on another device\. \fBdoctor\fP checks the
118
+ sign\-in, the server, your organization and roles, and what a launch here would resolve\.
119
+ .SS 3\. Model providers (person)
120
+ .P
121
+ \fBpipod credentials connect\fP connects every provider your local pi is signed in to;
122
+ \fBpipod credentials connect <provider>\fP signs in to one\. The sign\-ins belong to your account
123
+ and apply to every pod you launch\.
124
+ .SS 4\. Organization defaults
125
+ .P
126
+ Only with the org:manage permission (\fBpipod whoami\fP lists yours); otherwise skip to step 5\.
127
+ These reach every member's next pod: pod size, network policy, a default model, tools baked
128
+ into the image, shared setup\. Change one key with \fBpipod settings org set <key> <value>\fP, or
129
+ the whole layer from its local source:
130
+ .RS 2
131
+ .nf
132
+ pipod pull org # writes ~/\.pi\-pod/org/
133
+ # edit config\.json, init\.sh, bake\.sh, pi/
134
+ pipod diff org
135
+ pipod push org
136
+ .fi
137
+ .RE
138
+ .P
139
+ Values for secrets the whole organization shares: \fBpipod secrets set org <NAME>\fP (person)\.
140
+ Organization policy (limits rather than defaults) is set in the web dashboard,
141
+ \fB<server>/dashboard/\fP\|\.
142
+ .SS 5\. Your own defaults
143
+ .P
144
+ Your model and thinking level, your Pi settings, personal setup such as a git identity:
145
+ .RS 2
146
+ .nf
147
+ pipod settings user set pi\.model <provider>/<model>
148
+ pipod settings user set pi\.thinking high
149
+ .fi
150
+ .RE
151
+ .P
152
+ or the whole layer: \fBpipod pull user\fP, edit ~/\.pi\-pod/config\.json and ~/\.pi/agent/, then
153
+ \fBpipod diff user\fP and \fBpipod push user\fP\|\.
154
+ .SS 6\. A template for each project
155
+ .P
156
+ In the project's directory:
157
+ .RS 2
158
+ .nf
159
+ pipod init # writes \.pi\-pod/
160
+ # edit \.pi\-pod/config\.json, init\.sh, and bake\.sh
161
+ pipod \-\-dry\-run # what a launch would resolve; creates nothing
162
+ pipod # the first launch offers to create the template and pin it
163
+ .fi
164
+ .RE
165
+ .P
166
+ Without a launch, \fBpipod templates create <name> \-\-from\-here\fP creates it; then pin it by
167
+ adding \fB&quot;template&quot;: &quot;<name>&quot;\fP to \.pi\-pod/config\.json\. Afterwards the project stays its
168
+ source: edit the files, \fBpipod diff\fP, \fBpipod push\fP\|\. Its secret values:
169
+ \fBpipod secrets set template/<name> <NAME>\fP (person), or \fB\|\.pi\-pod/env\fP on this machine\. To
170
+ tell its pods' agents what access the template is meant to have:
171
+ \fBpipod templates edit <name> \-\-agent\-instructions <file>\fP\|\.
172
+ .SS Rules for an agent
173
+
174
+ .RS 1
175
+ .IP \(bu 2
176
+ Never put a secret value on a command line or in a chat; transcripts are stored\. Name the
177
+ secret and let the person type it into \fBpipod secrets set\fP\|\.
178
+ .IP \(bu 2
179
+ Run \fBpipod diff <layer>\fP before \fBpipod push <layer>\fP: a push replaces the whole layer\.
180
+ With no terminal, push declines instead of asking, so show the person the diff, then run
181
+ \fBpipod push <layer> \-\-yes\fP\|\.
182
+ .IP \(bu 2
183
+ Organization changes reach every member's next pod, and \fBpipod templates share\fP cannot be
184
+ undone: confirm both with the person first\.
185
+ .IP \(bu 2
186
+ Iterate with \fBpipod doctor\fP and \fBpipod \-\-dry\-run\fP; both create nothing\.
187
+
188
+ .RE
189
+ .SH LAYERS
190
+ .P
191
+ Each launch is resolved on the server from these layers, lowest first:
192
+ .RS 2
193
+ .nf
194
+ built\-in defaults
195
+ organization defaults
196
+ org\-wide template (when the launch uses one)
197
+ your user layer
198
+ personal template (when the launch uses one)
199
+ organization policy (limits, applied last)
200
+ .fi
201
+ .RE
202
+ .P
203
+ The template is the one the launch names: \fB\-\-template\fP, or the \fBtemplate\fP pinned in the
204
+ project's \.pi\-pod/config\.json\. Within the layers:
205
+
206
+ .RS 1
207
+ .IP \(bu 2
208
+ config merges key by key, and the later layer wins; an array replaces the one below it\.
209
+ .IP \(bu 2
210
+ init scripts all run, in layer order, and so do bake scripts\.
211
+ .IP \(bu 2
212
+ Pi files merge the same way, file by file, except that settings\.json package lists add
213
+ up\. They hold no credentials: models\.json and mcporter\.json name a secret as \fB$NAME\fP,
214
+ and the server refuses a literal key\.
215
+
216
+ .RE
217
+ .P
218
+ Organization policy holds limits rather than defaults: maximum idle and archive times,
219
+ allowed providers, a required template, network rules, concurrency\. It clamps the merged
220
+ result, and \fBpipod doctor\fP and \fBpipod \-\-dry\-run\fP report every clamp\. It is set in the web
221
+ dashboard by someone with the policy:write permission\.
222
+ .P
223
+ Where each layer's source lives, and the commands that change it:
224
+ .RS 2
225
+ .nf
226
+ org ~/\.pi\-pod/org/: config\.json, init\.sh, bake\.sh, pi/, env
227
+ pipod pull|diff|push org; pipod settings org set (org:manage)
228
+ user ~/\.pi\-pod/config\.json and ~/\.pi/agent/
229
+ pipod pull|diff|push user; pipod settings user set
230
+ template a project: \.pi\-pod/config\.json, init\.sh, bake\.sh, env, and \.pi/
231
+ pipod pull|diff|push [template [<name>]]; pipod templates
232
+ .fi
233
+ .RE
234
+ .P
235
+ What belongs where: the organization layer holds what everyone needs (pod size, network
236
+ policy, shared tools); your user layer holds your preferences (model, Pi settings, git
237
+ identity); a template holds one project's environment (cloning and installing it, the hosts
238
+ it needs, its secrets)\. A project's own files reach pods only through its template, after
239
+ \fBpipod push\fP\|\. The web dashboard, \fB<server>/dashboard/\fP, edits the same layers\.
240
+ .P
241
+ Secrets have their own order, lowest first: org, user, template, then the project's
242
+ \|\.pi\-pod/env on the machine you launch from\. \fBpipod secrets list\fP shows which layer each
243
+ name comes from\.
244
+ .SH LAUNCH
245
+ .P
246
+ \fBpipod\fP with no command launches a pod for the current directory and attaches to it\.
247
+ \fBpipod \-\-dry\-run\fP resolves the same launch and prints it without creating anything\.
248
+ .P
249
+ The launch uses the template named by \fB\-\-template\fP, or else the one pinned in the project's
250
+ \|\.pi\-pod/config\.json\. In a project with a \.pi\-pod/config\.json and no pinned template, the
251
+ first launch offers to create a template from the project and pin it\.
252
+ .P
253
+ Workspace seeding: launching from a directory with no \.pi\-pod/config\.json seeds the new pod
254
+ from that directory (its git repository root when inside one)\. A clean, pushed checkout whose
255
+ remote tip matches HEAD is cloned at that exact commit; anything else (dirty trees, unpushed
256
+ commits, private remotes without usable credentials, plain directories) is streamed in as a
257
+ tar archive, without git\-ignored paths, node_modules, or \.pi\-pod/env\. Private\-remote
258
+ credentials are forwarded only after a prompt (\fB\-\-yes\fP approves it) and are never stored\.
259
+ \fB\-\-dry\-run\fP prints the decision without prompting or creating a pod\. Forks, reused pods,
260
+ \fB\-\-on\fP co\-location, and \fB\-\-no\-seed\fP never seed\. A project with a \.pi\-pod/config\.json gets its
261
+ workspace from its init scripts instead\.
262
+ .P
263
+ Arguments after \fB\-\-\fP go to pi: prompt words start the session, and \fB\-\-model\fP, \fB\-\-thinking\fP,
264
+ and \fB\-\-tui\-mode\fP apply to this launch\. Per\-launch Pi resources (\fB\-\-extension\fP, \fB\-\-skill\fP,
265
+ \fB\-\-prompt\-template\fP) name files or directories inside the pod as absolute paths and add to
266
+ the pod's configured Pi resources for that launch; anything else Pi\-related belongs in the
267
+ \fBpi\.args\fP config\.
268
+ .P
269
+ \fB\-\-reuse\fP restarts this project's newest stopped pod instead of creating one\. \fB\-\-on <pod>\fP
270
+ starts the new pod on an existing pod's machine, sharing its files; \fB\-\-on self\fP does that
271
+ from inside a pod\.
272
+ .P
273
+ Inside a pod, signed in with the pod's own token, every launch (\fB\-\-on self\fP included) and
274
+ every job it schedules uses the template that pod launched from; the server refuses any other\.
275
+ .SH COMMANDS
276
+ .SS pipod login
277
+ .RS 2
278
+ .nf
279
+ Usage: pipod login [\-\-server <url>] [\-\-issuer <url>] [\-\-org <alias>] [\-\-device] [\-\-token <jwt>]
280
+
281
+ Sign this machine in to a pi pod server via Zitadel (authorization code + PKCE,
282
+ in your browser)\. Where no browser can open here (over SSH, on a headless
283
+ server), it prints a page and a code to confirm on any other device instead\.
284
+ The session is stored in ~/\.pi\-pod/auth\.json\.
285
+
286
+ Options:
287
+ \-\-server <url> Server to sign in to (default: the previous session's server,
288
+ $PI_POD_ACCOUNT_URL, or the production server)
289
+ \-\-issuer <url> OIDC issuer (default: $PI_POD_ISSUER, else the one the
290
+ server publishes); needed only for a server too old to
291
+ publish its own
292
+ \-\-org <alias> Only sign in to the organization with this primary domain;
293
+ omit it to sign in to your own organization
294
+ \-\-device Sign in with a code on another device even if a browser
295
+ could open here
296
+ \-\-token <jwt> Use an existing access token instead of the browser flow (dev/CI)
297
+ .fi
298
+ .RE
299
+ .P
300
+ A person finishes the sign\-in, in a browser or with the printed code; an agent can start
301
+ \fBpipod login\fP and wait for it\. Signing in works before you belong to an organization, but
302
+ then nothing is permitted and \fBlogin\fP says access is pending organization membership: the
303
+ server's owner adds you (\fBselfhost/add\-user\fP on a self\-hosted host), or an organization owner
304
+ grants you a role in the Zitadel Console (\fBpipod org\-admin\fP)\.
305
+ .SS pipod logout
306
+ .RS 2
307
+ .nf
308
+ Usage: pipod logout
309
+
310
+ Revoke the current account session and delete ~/\.pi\-pod/auth\.json\. Pod
311
+ operations are unavailable until the next `pipod login`\.
312
+ .fi
313
+ .RE
314
+ .SS pipod whoami
315
+ .RS 2
316
+ .nf
317
+ Usage: pipod whoami
318
+
319
+ Show the signed\-in server, user, permissions, active organization, and console
320
+ links\. Exits 1 when signed out\.
321
+ .fi
322
+ .RE
323
+ .SS pipod account
324
+ .RS 2
325
+ .nf
326
+ Usage: pipod account
327
+
328
+ Open the Zitadel self\-service console in your browser to manage profile,
329
+ password, MFA, and active sessions\.
330
+ .fi
331
+ .RE
332
+ .SS pipod org\-admin
333
+ .RS 2
334
+ .nf
335
+ Usage: pipod org\-admin
336
+
337
+ Open the Zitadel Console in your browser\. Organization owners manage members
338
+ and role grants there\.
339
+ .fi
340
+ .RE
341
+ .SS pipod billing
342
+ .RS 2
343
+ .nf
344
+ Usage: pipod billing checkout [\-\-plan standard|pro] [\-\-trial]
345
+ pipod billing portal
346
+ pipod billing change \-\-plan standard|pro [\-\-yes]
347
+ pipod billing change preview \-\-plan standard|pro
348
+ pipod billing change confirm \-\-quote <quoteId> [\-\-yes]
349
+
350
+ Authenticated Stripe Checkout and billing portal\. Checkout sends trial:false
351
+ (paid) unless \-\-trial\. Closed public trial refuses \-\-trial with 402\. Change
352
+ previews a Standard<\->Pro plan change and confirms it only after an explicit
353
+ yes; stale quotes are never auto\-confirmed\. Return
354
+ pages do not grant a plan\.
355
+ .fi
356
+ .RE
357
+ .P
358
+ Billing exists only on the hosted service; a self\-hosted server has none\. Paying, and
359
+ changing plans, are a person's decisions: an agent may run \fBpreview\fP, never \fBconfirm\fP\|\.
360
+ .SS pipod credentials
361
+ .RS 2
362
+ .nf
363
+ Usage: pipod credentials [action]
364
+
365
+ Manage account\-scoped model\-provider sign\-ins\. Connected credentials apply to
366
+ every pod you launch; OAuth refresh tokens stay in server custody and never
367
+ reach pods or this machine\.
368
+
369
+ Actions:
370
+ list Saved credentials and connectable providers (default)
371
+ connect Connect every provider your local pi is signed in to:
372
+ API keys are imported, everything else is a fresh
373
+ account login; ready credentials are left alone
374
+ connect <provider> Sign in to a provider (OAuth by default)
375
+ reconnect <provider> Redo the sign\-in for a saved credential
376
+ test <provider> Verify a saved credential against the provider
377
+ remove <provider> [\-\-yes] Delete a saved credential (alias: rm)
378
+
379
+ connect options:
380
+ \-\-api\-key Enter an API key instead of the OAuth flow
381
+ \-\-api\-key \-\-from\-pi Import the API key your local pi resolves for that
382
+ provider (auth\.json or env) instead of typing it\.
383
+ OAuth grants are never imported\.
384
+ .fi
385
+ .RE
386
+ .P
387
+ \fBconnect\fP and \fBreconnect\fP need a person, for the browser sign\-in or the hidden key prompt;
388
+ \fBlist\fP and \fBtest\fP do not\. A model\-provider key is a credential here, not a secret: a template
389
+ refuses one\.
390
+ .SS pipod init
391
+ .RS 2
392
+ .nf
393
+ Usage: pipod init [\-\-force]
394
+
395
+ Scaffold project configuration under \.pi\-pod/ in the current directory:
396
+ config\.json, env\.example, env (mode 600), and init\.sh\.
397
+
398
+ Options:
399
+ \-\-force Overwrite scaffold files that already exist
400
+ .fi
401
+ .RE
402
+ .P
403
+ The files are the local source of the project's template\. config\.json starts with every
404
+ setting commented out: uncomment only what this project must decide for itself
405
+ (pipod\-config(5))\. init\.sh runs in each new pod, in an empty workspace, so it usually clones
406
+ the repository and installs dependencies\. Add \.pi\-pod/bake\.sh for setup that belongs in the
407
+ image\. env holds the project's secret values and is added to \.gitignore; env\.example lists
408
+ their names and is committed\.
409
+ .SS pipod templates
410
+ .RS 2
411
+ .nf
412
+ Usage: pipod templates [action]
413
+
414
+ Manage pod templates on the pi pod server\. A template stores config, init and
415
+ bake scripts, Pi settings files, named secrets, and agent instructions\.
416
+ Templates are personal by default: only their owner sees and launches them\.
417
+ \-\-org at creation or `templates share` makes one org\-wide\.
418
+
419
+ Agent instructions are added to the agent's system prompt in every pod launched
420
+ from the template, with the hosts and secrets the pod actually has: say what
421
+ access the template is meant to have\. They guide the agent and enforce nothing;
422
+ the template's secrets and egress decide what a pod can reach\. A pod's child
423
+ pods and the jobs it schedules launch from the pod's own template\.
424
+
425
+ Actions:
426
+ list List templates with scope and key counts (default)
427
+ show <name|id> Show config, scripts, agent instructions, Pi settings, and
428
+ secret names
429
+ create <name> Create a template
430
+ edit <name|id> Update a template's name, description, config, scripts, or
431
+ agent instructions
432
+ share <name|id> Make a personal template org\-wide (cannot be undone)
433
+ rm <name|id> Delete a template (alias: delete)
434
+
435
+ create/edit options:
436
+ \-\-name <name> New name (edit only)
437
+ \-\-description <text> Set the description
438
+ \-\-config <file> Store this config file (same shape as \.pi\-pod/config\.json)
439
+ \-\-from\-here create only: store this project's authored config,
440
+ scripts, and sanitized Pi files (contradicts \-\-config)
441
+ \-\-init\-script <file> Store this init script
442
+ \-\-bake\-script <file> Store this bake script
443
+ \-\-agent\-instructions <file>
444
+ Store this file as the agent instructions (an empty
445
+ file removes them); `pipod push` leaves them alone
446
+ \-\-org create only: make the template org\-wide from the start
447
+ \-\-with\-secrets With \-\-from\-here: also upload project env values as
448
+ template secrets
449
+ \-y, \-\-yes Skip confirmations (rm)
450
+ .fi
451
+ .RE
452
+ .P
453
+ A template is one project's environment\. Keep a project as its source: accept the first
454
+ launch's offer, which creates the template and pins it in \.pi\-pod/config\.json, or run
455
+ \fBcreate \-\-from\-here\fP and add \fB&quot;template&quot;: &quot;<name>&quot;\fP to that file yourself\. Then change it
456
+ with \fBpipod diff\fP and \fBpipod push\fP from the project\.
457
+ A personal template sits above your user layer and an org\-wide one below it
458
+ (\fBpipod help layers\fP); making one org\-wide needs the org:manage permission\.
459
+ .SS pipod push
460
+ .RS 2
461
+ .nf
462
+ Usage: pipod push [template [<name>] | user | org] [\-\-dir <path>]
463
+ [\-\-with\-secrets] [\-\-yes]
464
+
465
+ Replace a server config bundle with its local source, whole\. The layer names
466
+ both sides; edit the local files with any editor, then push\. A diff preview
467
+ precedes the confirmation\.
468
+
469
+ Layers and their local source:
470
+ template [<name>] This project: \.pi\-pod/config\.json, its init and bake
471
+ scripts, Pi files under \.pi/, and the project env file
472
+ (secrets, with \-\-with\-secrets or a prompt)\. Without
473
+ <name> the project's pinned template is used\.
474
+ user ~/\.pi\-pod/config\.json and ~/\.pi/agent/ (settings\.json,
475
+ models\.json, mcporter\.json, subagents\.json, agents/)
476
+ org ~/\.pi\-pod/org/: config\.json, init\.sh, bake\.sh, pi/…, and
477
+ an optional env file whose values become org secrets
478
+
479
+ Inside a project the layer defaults to template; elsewhere it is required\.
480
+ Provider credentials, hooks, mcpServers, and model credential values never
481
+ leave this machine\.
482
+
483
+ Options:
484
+ \-\-dir <path> org only: read the org source from <path> instead
485
+ \-\-with\-secrets Also upload the layer's env values as secrets
486
+ \-y, \-\-yes Apply the replacement without the confirmation prompt
487
+ .fi
488
+ .RE
489
+ .P
490
+ Whatever the local source lacks is removed from the server layer, so start from
491
+ \fBpipod pull\fP when the server may have changes this machine does not\. With no terminal to
492
+ confirm on, push declines unless \fB\-\-yes\fP is given\.
493
+ .SS pipod pull
494
+ .RS 2
495
+ .nf
496
+ Usage: pipod pull [template [<name>] | user | org] [\-\-dir <path>] [\-\-yes]
497
+
498
+ Write a server config bundle into its local source files (see
499
+ `pipod push \-\-help` for the layer → directory table)\. A diff preview
500
+ precedes the confirmation; nothing is written when the two already match\.
501
+
502
+ What pull keeps from the local files:
503
+ config\.json client\-only keys: $schema, template, secretResolver,
504
+ pi\.chords, pi\.sessionNaming
505
+ settings\.json hooks and mcpServers (and packages when hostConfig\.packages
506
+ is off)
507
+ models\.json credential values the push had dropped
508
+ agents/ files the bundle no longer contains are removed
509
+
510
+ Secrets stay on the server; their names are listed\. The user layer has no
511
+ local script files, so user bundle scripts are shown but not written\.
512
+
513
+ Options:
514
+ \-\-dir <path> org only: write the org source to <path> instead
515
+ \-y, \-\-yes Apply the local changes without the confirmation prompt
516
+ .fi
517
+ .RE
518
+ .SS pipod diff
519
+ .RS 2
520
+ .nf
521
+ Usage: pipod diff [template [<name>] | user | org] [\-\-dir <path>]
522
+
523
+ Compare a config layer's local source with its server bundle (see
524
+ `pipod push \-\-help` for the layer → directory table)\. Secrets compare by
525
+ name only\. Exits 1 when they differ, 0 when they match\.
526
+
527
+ Options:
528
+ \-\-dir <path> org only: read the org source from <path> instead
529
+ .fi
530
+ .RE
531
+ .SS pipod secrets
532
+ .RS 2
533
+ .nf
534
+ Usage: pipod secrets [action]
535
+
536
+ Manage the secret layers pods see\. Requires account or pod\-token auth\. Server
537
+ scopes are org, user, and template/<name>; project is this project's dotenv
538
+ file, the highest\-precedence layer for launches from the project\.
539
+
540
+ Actions:
541
+ list Every secret a pod launched here would see,
542
+ which layer wins, and who set it (default)
543
+ set <scope> <NAME> Store a secret, its value read from a hidden
544
+ prompt or stdin (never the command line)
545
+ rm <scope> <NAME> Remove a secret (aliases: remove, unset)
546
+ sync <scope> Upload a dotenv file to a server scope
547
+
548
+ sync options (scope must be org, user, or template/<name>):
549
+ \-\-file <path> Dotenv file to upload (default: ~/\.pi\-pod/secrets/<scope>\.env)
550
+ \-\-prune Also delete server secrets that are not in the file
551
+ \-\-dry\-run Show what would change without writing
552
+
553
+ Values may be op:// references; they resolve just\-in\-time (at upload for
554
+ server scopes, at launch for the project file) and the references themselves
555
+ are never stored on the server\.
556
+ .fi
557
+ .RE
558
+ .P
559
+ Precedence, lowest first: org, user, template, project\. A pod receives its secrets as
560
+ environment variables, and anything running in it can read them all\. Stored values cannot be
561
+ read back, only replaced\.
562
+ .P
563
+ Keep values out of command lines and chats: a person types them at \fBset\fP\|'s hidden prompt,
564
+ or \fBsync\fP reads a dotenv file kept at mode 600\. op:// references resolve through the
565
+ 1Password CLI (\fBop\fP) on this machine\. Model\-provider keys belong in \fBpipod credentials\fP\|\.
566
+ .SS pipod settings
567
+ .RS 2
568
+ .nf
569
+ Usage: pipod settings <user|org> [show | edit | set <key> <value> | unset <key>]
570
+
571
+ Show or edit a persistent settings bundle on the server: your own user bundle,
572
+ or the org\-wide defaults (org scope needs the org:manage permission)\. Edits
573
+ change only the config; scripts and Pi files stay as they are — replace the
574
+ whole bundle from local files with `pipod push user` or `pipod push org`\.
575
+ Edits use compare\-and\-swap on the bundle version, so concurrent changes fail
576
+ cleanly instead of overwriting each other\.
577
+
578
+ Actions:
579
+ show Print the settings bundle as JSON (default)
580
+ edit Edit the config in $VISUAL/$EDITOR, then save
581
+ set <key> <value> Set one dotted key to a JSON value, or to the text as
582
+ a string: pipod settings user set pi\.model provider/model
583
+ unset <key> Remove one dotted key, so the layers below decide it
584
+ .fi
585
+ .RE
586
+ .P
587
+ Keys are those of pipod\-config(5)\. \fBset\fP changes the server only: a later \fBpipod push\fP of the
588
+ same layer replaces it with the local source, so after a \fBset\fP, run \fBpipod pull\fP before
589
+ editing that source\.
590
+ .SS pipod jobs
591
+ .RS 2
592
+ .nf
593
+ Usage: pipod jobs [action] [args] [\-\-quiet] [\-\-yes] [\-\-project] [\-\-org]
594
+
595
+ Manage scheduled jobs the pi pod server runs for you: at each trigger it
596
+ launches a pod from the job's template and sends the job's prompt\. Local job
597
+ files in \.pi\-pod/jobs/ (project) or ~/\.pi\-pod/jobs/ (user) are the reviewable
598
+ source; `jobs push` promotes them to the server\. <job> is an id, short ref
599
+ (j\-…), or name\.
600
+
601
+ Actions:
602
+ list List server jobs (default)
603
+ show <job> Show a job's schedule, template, model, and prompt
604
+ runs <job> List a job's recent runs
605
+ run <job> Run an active job once, now; its schedule is unchanged
606
+ activate <job> Activate a job
607
+ pause <job> Pause a job's schedule
608
+ resume <job> Resume a paused job
609
+ rm <job> Remove a job; its schedule stops firing
610
+ push [job…] Create or update server jobs from local job files
611
+ pull <job> Write a server job to a local job file
612
+ diff [job…] Show local vs server drift; exits 1 when drifted
613
+
614
+ Options:
615
+ \-\-org push: create org\-scoped jobs or promote matching user jobs
616
+ (promotion is one\-way)
617
+ \-\-project pull: write into this project's \.pi\-pod/jobs/ instead of
618
+ ~/\.pi\-pod/jobs/
619
+ \-q, \-\-quiet list: print job ids only, one per line
620
+ \-y, \-\-yes Skip confirmations; pull: overwrite an existing local file
621
+ .fi
622
+ .RE
623
+ .P
624
+ A job file is \fB<name>\.json\fP (comments allowed), and its file name is the job's name:
625
+ .RS 2
626
+ .nf
627
+ {
628
+ "description": "Triage new issues every morning",
629
+ "trigger": { "type": "cron", "cron": "0 6 * * *" },
630
+ "template": "my\-service",
631
+ "model": "anthropic/claude\-opus\-4\-7",
632
+ "prompt": "Review yesterday's new issues and post a triage summary\."
633
+ }
634
+ .fi
635
+ .RE
636
+ .P
637
+ \fBtrigger\fP is a cron expression, evaluated in UTC, or \fB{ &quot;type&quot;: &quot;at&quot;, &quot;times&quot;: [\.\.\.] }\fP with
638
+ up to 100 ISO 8601 timestamps that each name their timezone\. Runs must be at least 5
639
+ minutes apart, since each run is a pod\. \fBmodel\fP (provider/model\-id) is required\.
640
+ \fBpromptFile\fP names a file beside the job file instead of \fBprompt\fP; prompts are at most 64 KiB
641
+ and must say everything the run needs, since it starts in a fresh pod\. A job runs on its own
642
+ until paused, so agree its schedule with the person before \fBpipod jobs push\fP\|\.
643
+ .SS pipod list
644
+ .RS 2
645
+ .nf
646
+ Usage: pipod list [pod] [\-\-all] [\-\-archived] [\-\-template <name|id>] [\-\-quiet]
647
+
648
+ Alias: ls
649
+
650
+ List pods on the signed\-in server with stable short refs (p\-…)\. The project is
651
+ the directory's git repository (or the directory, or its \.pi\-pod/ config): a
652
+ listing shows that project's pods when it has any — its pinned template's when
653
+ it pins one — and every pod otherwise\. Co\-located pods are grouped under the pod
654
+ whose machine they share, with an ON column naming it\.
655
+ With a pod argument, show just that machine's group: the pod and everything
656
+ co\-located on it\.
657
+
658
+ Status says where a pod's files are: a stopped pod keeps them on disk and restarts on
659
+ attach; an archived workspace is restored on next use, which takes longer the bigger it is\.
660
+ Pods you archive stay hidden unless \-\-archived is passed\.
661
+
662
+ Options:
663
+ \-a, \-\-all Every pod; ignore the current project and its template pin
664
+ \-\-archived Include logically archived pods
665
+ \-\-template <name|id> Only pods launched from that template (whole account)
666
+ \-q, \-\-quiet Print pod ids only, one per line
667
+ .fi
668
+ .RE
669
+ .SS pipod attach
670
+ .RS 2
671
+ .nf
672
+ Usage: pipod attach [pod] [\-\-yes] [\-\- <prompt…> [\-\-tui\-mode <mode>]]
673
+
674
+ Alias: a
675
+
676
+ Reconnect to a pod session through the server gateway\. Name the pod by id,
677
+ short ref (p\-…), or name; omit it when this project has exactly one pod\.
678
+ Quitting detaches: the pod keeps running until the server's idle policy reaps
679
+ it or `pipod stop` stops it\. Raw pod shells are not available\.
680
+ Attaching to an archived pod offers to restore it first\.
681
+
682
+ After \-\-:
683
+ <prompt…> Words are sent to the session as a startup prompt
684
+ \-\-tui\-mode <mode> Local TUI layout for this attach: regular or fullscreen
685
+
686
+ Options:
687
+ \-y, \-\-yes Restore an archived pod without asking
688
+ .fi
689
+ .RE
690
+ .SS pipod stop
691
+ .RS 2
692
+ .nf
693
+ Usage: pipod stop [pod…]
694
+
695
+ Stop pods now by id, short ref (p\-…), or name; omit the argument when this
696
+ project has exactly one pod\. Stopped pods keep their files and `pipod attach`
697
+ restarts them\. Stopping a pod that hosts co\-located pods stops those too\.
698
+ .fi
699
+ .RE
700
+ .SS pipod fork
701
+ .RS 2
702
+ .nf
703
+ Usage: pipod fork <pod> [\-\-session <path>] [launch options] [\-\- <pi args…>]
704
+
705
+ Launch a new pod whose session starts as a fork of <pod>'s current session\.
706
+ <pod> is an id, short ref (p\-…), or name\. The workspace is not copied —
707
+ commit and push first if the new pod needs those changes\. \-\-on is not
708
+ supported: a fork launches a new sandbox, not a co\-located pod\.
709
+
710
+ Options:
711
+ \-\-session <path> Fork a specific session file instead of the newest
712
+ \-\-template <name|id> Launch the new pod from an account template
713
+ \-\-dry\-run Resolve and print the launch plan; create nothing
714
+ \-y, \-\-yes Skip supported confirmations
715
+ .fi
716
+ .RE
717
+ .SS pipod rename
718
+ .RS 2
719
+ .nf
720
+ Usage: pipod rename <pod> <name>
721
+
722
+ Rename a server\-managed pod\. <pod> is an id, short ref (p\-…), or the current
723
+ name\.
724
+ .fi
725
+ .RE
726
+ .SS pipod send
727
+ .RS 2
728
+ .nf
729
+ Usage: pipod send [pod] <path> [\-\-yes]
730
+
731
+ Copy a host file or directory into a pod through the server\. Omit the pod when
732
+ this project has exactly one\. Sending to an archived pod offers to restore it
733
+ first\.
734
+
735
+ Options:
736
+ \-y, \-\-yes Restore an archived pod without asking
737
+ .fi
738
+ .RE
739
+ .SS pipod receive
740
+ .RS 2
741
+ .nf
742
+ Usage: pipod receive [pod] <path> [\-\-yes]
743
+
744
+ Copy a file or directory from a pod into the current local directory\. <path>
745
+ may be a workdir\-relative path or an absolute path inside that workdir, such
746
+ as foo or /workspace/foo\. The destination must not already exist\. Omit the
747
+ pod when this project has exactly one\. Receiving from an archived pod offers
748
+ to restore it first\.
749
+
750
+ Options:
751
+ \-y, \-\-yes Restore an archived pod without asking
752
+ .fi
753
+ .RE
754
+ .SS pipod archive
755
+ .RS 2
756
+ .nf
757
+ Usage: pipod archive [pod…] [\-\-all] [\-\-template <name|id>] [\-\-idle <duration>] [\-\-dry\-run] [\-\-yes]
758
+
759
+ Archive pods by id, short ref (p\-…), or name\. Archiving hides pods from
760
+ `pipod list` (`pipod list \-\-archived` shows them); it never deletes work, and
761
+ `pipod restore` brings them back\. Archiving a pod that hosts co\-located pods
762
+ archives those too\.
763
+
764
+ Options:
765
+ \-a, \-\-all Archive every pod (cannot be combined with pod refs)
766
+ \-\-template <name|id> Only pods launched from that template (whole account)
767
+ \-\-idle <duration> Only pods whose last activity is older than this (4h, 2d, 30m)
768
+ \-\-dry\-run Print the matching pods; archive nothing
769
+ \-y, \-\-yes Skip the bulk confirmation
770
+ .fi
771
+ .RE
772
+ .SS pipod restore
773
+ .RS 2
774
+ .nf
775
+ Usage: pipod restore [pod…] [\-\-all] [\-\-yes]
776
+
777
+ Bring archived pods back by id, short ref (p\-…), or name\. Restoring a host
778
+ restores the co\-located pods archived with it\. `pipod attach` then starts the
779
+ pod; a workspace in cold storage takes longer the bigger it is\.
780
+
781
+ Options:
782
+ \-a, \-\-all Restore every archived pod (cannot be combined with pod refs)
783
+ \-y, \-\-yes Skip the \-\-all confirmation
784
+ .fi
785
+ .RE
786
+ .SS pipod gc
787
+ .RS 2
788
+ .nf
789
+ Usage: pipod gc [\-\-delete] [\-\-yes]
790
+
791
+ List the archived and failed pods that can be deleted for good; \-\-delete deletes
792
+ them\. (The server stops idle pods and moves stopped workspaces to cold storage on
793
+ its own schedule; that never deletes anything\.)
794
+
795
+ Options:
796
+ \-\-delete Permanently delete the reclaimable pods
797
+ \-y, \-\-yes Delete without a confirmation prompt
798
+ .fi
799
+ .RE
800
+ .SS pipod doctor
801
+ .RS 2
802
+ .nf
803
+ Usage: pipod doctor [\-\-template <name|id>]
804
+
805
+ Check each layer a launch depends on: account auth, server reachability and
806
+ version, organization membership and roles, secret references, and the
807
+ server\-resolved settings bundle chain for this directory\. Works while signed
808
+ out to diagnose auth problems\. Exits non\-zero when a layer fails\.
809
+
810
+ Options:
811
+ \-\-template <name|id> Plan the checked launch with this template
812
+ .fi
813
+ .RE
814
+ .SS pipod update
815
+ .RS 2
816
+ .nf
817
+ Usage: pipod update [\-\-dry\-run]
818
+
819
+ Upgrade pi pod itself: a registry install updates to the latest published
820
+ version; a git checkout pulls its upstream and rebuilds\.
821
+
822
+ Options:
823
+ \-\-dry\-run Report what an update would do without changing anything
824
+ .fi
825
+ .RE
826
+ .SH FILES
827
+ .RS 2
828
+ .nf
829
+ ~/\.pi\-pod/auth\.json this machine's sign\-in (pipod login)
830
+ ~/\.pi\-pod/config\.json this machine's preferences, and the config of your
831
+ user layer (pipod\-config(5))
832
+ ~/\.pi/agent/ your Pi files, the rest of your user layer:
833
+ settings\.json, models\.json, mcporter\.json,
834
+ subagents\.json, agents/
835
+ ~/\.pi\-pod/org/ the organization layer's source: config\.json,
836
+ init\.sh, bake\.sh, pi/, env
837
+ ~/\.pi\-pod/secrets/ dotenv files for pipod secrets sync
838
+ ~/\.pi\-pod/jobs/ your job files
839
+ \|\.pi\-pod/config\.json a project's config and its template pin
840
+ \|\.pi\-pod/init\.sh runs in each of the project's new pods
841
+ \|\.pi\-pod/bake\.sh built into the project's pod image
842
+ \|\.pi\-pod/env the project's secret values; never committed
843
+ \|\.pi\-pod/env\.example the names of the project's secrets; committed
844
+ \|\.pi\-pod/jobs/ the project's job files
845
+ \|\.pi/ the project's Pi files, as in ~/\.pi/agent/
846
+ .fi
847
+ .RE
848
+ .SH ENVIRONMENT
849
+ .RS 2
850
+ .nf
851
+ PI_POD_ACCOUNT_URL the server pipod login uses with no \-\-server and no
852
+ previous session
853
+ PI_POD_ISSUER the OIDC issuer pipod login uses, for a server too old
854
+ to publish its own
855
+ PI_POD_SERVER_URL set in every pod: pipod there signs in with the pod's
856
+ PI_POD_SERVER_TOKEN own token, which reaches only the pods it launched and
857
+ launches only from the pod's own template
858
+ VISUAL, EDITOR the editor for pipod settings edit
859
+ NO_COLOR plain output without color
860
+ .fi
861
+ .RE
862
+ .SH SEE ALSO
863
+ .P
864
+ pipod\-config(5), https://github.com/pi-pod/pipod and docs/self\-host\.md there for running
865
+ a server\.