@pipod/cli 0.1.5 → 0.1.7

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,861 @@
1
+ .TH "PIPOD" "1" "October 2026" "0.1.7"
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
+ .SH COMMANDS
273
+ .SS pipod login
274
+ .RS 2
275
+ .nf
276
+ Usage: pipod login [\-\-server <url>] [\-\-issuer <url>] [\-\-org <alias>] [\-\-device] [\-\-token <jwt>]
277
+
278
+ Sign this machine in to a pi pod server via Zitadel (authorization code + PKCE,
279
+ in your browser)\. Where no browser can open here (over SSH, on a headless
280
+ server), it prints a page and a code to confirm on any other device instead\.
281
+ The session is stored in ~/\.pi\-pod/auth\.json\.
282
+
283
+ Options:
284
+ \-\-server <url> Server to sign in to (default: the previous session's server,
285
+ $PI_POD_ACCOUNT_URL, or the production server)
286
+ \-\-issuer <url> OIDC issuer (default: $PI_POD_ISSUER, else the one the
287
+ server publishes); needed only for a server too old to
288
+ publish its own
289
+ \-\-org <alias> Only sign in to the organization with this primary domain;
290
+ omit it to sign in to your own organization
291
+ \-\-device Sign in with a code on another device even if a browser
292
+ could open here
293
+ \-\-token <jwt> Use an existing access token instead of the browser flow (dev/CI)
294
+ .fi
295
+ .RE
296
+ .P
297
+ A person finishes the sign\-in, in a browser or with the printed code; an agent can start
298
+ \fBpipod login\fP and wait for it\. Signing in works before you belong to an organization, but
299
+ then nothing is permitted and \fBlogin\fP says access is pending organization membership: the
300
+ server's owner adds you (\fBselfhost/add\-user\fP on a self\-hosted host), or an organization owner
301
+ grants you a role in the Zitadel Console (\fBpipod org\-admin\fP)\.
302
+ .SS pipod logout
303
+ .RS 2
304
+ .nf
305
+ Usage: pipod logout
306
+
307
+ Revoke the current account session and delete ~/\.pi\-pod/auth\.json\. Pod
308
+ operations are unavailable until the next `pipod login`\.
309
+ .fi
310
+ .RE
311
+ .SS pipod whoami
312
+ .RS 2
313
+ .nf
314
+ Usage: pipod whoami
315
+
316
+ Show the signed\-in server, user, permissions, active organization, and console
317
+ links\. Exits 1 when signed out\.
318
+ .fi
319
+ .RE
320
+ .SS pipod account
321
+ .RS 2
322
+ .nf
323
+ Usage: pipod account
324
+
325
+ Open the Zitadel self\-service console in your browser to manage profile,
326
+ password, MFA, and active sessions\.
327
+ .fi
328
+ .RE
329
+ .SS pipod org\-admin
330
+ .RS 2
331
+ .nf
332
+ Usage: pipod org\-admin
333
+
334
+ Open the Zitadel Console in your browser\. Organization owners manage members
335
+ and role grants there\.
336
+ .fi
337
+ .RE
338
+ .SS pipod billing
339
+ .RS 2
340
+ .nf
341
+ Usage: pipod billing checkout [\-\-plan standard|pro] [\-\-trial]
342
+ pipod billing portal
343
+ pipod billing change \-\-plan standard|pro [\-\-yes]
344
+ pipod billing change preview \-\-plan standard|pro
345
+ pipod billing change confirm \-\-quote <quoteId> [\-\-yes]
346
+
347
+ Authenticated Stripe Checkout and billing portal\. Checkout sends trial:false
348
+ (paid) unless \-\-trial\. Closed public trial refuses \-\-trial with 402\. Change
349
+ previews a Standard<\->Pro plan change and confirms it only after an explicit
350
+ yes; stale quotes are never auto\-confirmed\. Return
351
+ pages do not grant a plan\.
352
+ .fi
353
+ .RE
354
+ .P
355
+ Billing exists only on the hosted service; a self\-hosted server has none\. Paying, and
356
+ changing plans, are a person's decisions: an agent may run \fBpreview\fP, never \fBconfirm\fP\|\.
357
+ .SS pipod credentials
358
+ .RS 2
359
+ .nf
360
+ Usage: pipod credentials [action]
361
+
362
+ Manage account\-scoped model\-provider sign\-ins\. Connected credentials apply to
363
+ every pod you launch; OAuth refresh tokens stay in server custody and never
364
+ reach pods or this machine\.
365
+
366
+ Actions:
367
+ list Saved credentials and connectable providers (default)
368
+ connect Connect every provider your local pi is signed in to:
369
+ API keys are imported, everything else is a fresh
370
+ account login; ready credentials are left alone
371
+ connect <provider> Sign in to a provider (OAuth by default)
372
+ reconnect <provider> Redo the sign\-in for a saved credential
373
+ test <provider> Verify a saved credential against the provider
374
+ remove <provider> [\-\-yes] Delete a saved credential (alias: rm)
375
+
376
+ connect options:
377
+ \-\-api\-key Enter an API key instead of the OAuth flow
378
+ \-\-api\-key \-\-from\-pi Import the API key your local pi resolves for that
379
+ provider (auth\.json or env) instead of typing it\.
380
+ OAuth grants are never imported\.
381
+ .fi
382
+ .RE
383
+ .P
384
+ \fBconnect\fP and \fBreconnect\fP need a person, for the browser sign\-in or the hidden key prompt;
385
+ \fBlist\fP and \fBtest\fP do not\. A model\-provider key is a credential here, not a secret: a template
386
+ refuses one\.
387
+ .SS pipod init
388
+ .RS 2
389
+ .nf
390
+ Usage: pipod init [\-\-force]
391
+
392
+ Scaffold project configuration under \.pi\-pod/ in the current directory:
393
+ config\.json, env\.example, env (mode 600), and init\.sh\.
394
+
395
+ Options:
396
+ \-\-force Overwrite scaffold files that already exist
397
+ .fi
398
+ .RE
399
+ .P
400
+ The files are the local source of the project's template\. config\.json starts with every
401
+ setting commented out: uncomment only what this project must decide for itself
402
+ (pipod\-config(5))\. init\.sh runs in each new pod, in an empty workspace, so it usually clones
403
+ the repository and installs dependencies\. Add \.pi\-pod/bake\.sh for setup that belongs in the
404
+ image\. env holds the project's secret values and is added to \.gitignore; env\.example lists
405
+ their names and is committed\.
406
+ .SS pipod templates
407
+ .RS 2
408
+ .nf
409
+ Usage: pipod templates [action]
410
+
411
+ Manage pod templates on the pi pod server\. A template stores config, init and
412
+ bake scripts, Pi settings files, named secrets, and agent instructions\.
413
+ Templates are personal by default: only their owner sees and launches them\.
414
+ \-\-org at creation or `templates share` makes one org\-wide\.
415
+
416
+ Agent instructions are added to the agent's system prompt in every pod launched
417
+ from the template, with the hosts and secrets the pod actually has: say what
418
+ access the template is meant to have\. They guide the agent and enforce nothing;
419
+ the template's secrets and egress decide what a pod can reach\. A pod's child
420
+ pods and the jobs it schedules launch from the pod's own template\.
421
+
422
+ Actions:
423
+ list List templates with scope and key counts (default)
424
+ show <name|id> Show config, scripts, agent instructions, Pi settings, and
425
+ secret names
426
+ create <name> Create a template
427
+ edit <name|id> Update a template's name, description, config, scripts, or
428
+ agent instructions
429
+ share <name|id> Make a personal template org\-wide (cannot be undone)
430
+ rm <name|id> Delete a template (alias: delete)
431
+
432
+ create/edit options:
433
+ \-\-name <name> New name (edit only)
434
+ \-\-description <text> Set the description
435
+ \-\-config <file> Store this config file (same shape as \.pi\-pod/config\.json)
436
+ \-\-from\-here create only: store this project's authored config,
437
+ scripts, and sanitized Pi files (contradicts \-\-config)
438
+ \-\-init\-script <file> Store this init script
439
+ \-\-bake\-script <file> Store this bake script
440
+ \-\-agent\-instructions <file>
441
+ Store this file as the agent instructions (an empty
442
+ file removes them); `pipod push` leaves them alone
443
+ \-\-org create only: make the template org\-wide from the start
444
+ \-\-with\-secrets With \-\-from\-here: also upload project env values as
445
+ template secrets
446
+ \-y, \-\-yes Skip confirmations (rm)
447
+ .fi
448
+ .RE
449
+ .P
450
+ A template is one project's environment\. Keep a project as its source: accept the first
451
+ launch's offer, which creates the template and pins it in \.pi\-pod/config\.json, or run
452
+ \fBcreate \-\-from\-here\fP and add \fB&quot;template&quot;: &quot;<name>&quot;\fP to that file yourself\. Then change it
453
+ with \fBpipod diff\fP and \fBpipod push\fP from the project\.
454
+ A personal template sits above your user layer and an org\-wide one below it
455
+ (\fBpipod help layers\fP); making one org\-wide needs the org:manage permission\.
456
+ .SS pipod push
457
+ .RS 2
458
+ .nf
459
+ Usage: pipod push [template [<name>] | user | org] [\-\-dir <path>]
460
+ [\-\-with\-secrets] [\-\-yes]
461
+
462
+ Replace a server config bundle with its local source, whole\. The layer names
463
+ both sides; edit the local files with any editor, then push\. A diff preview
464
+ precedes the confirmation\.
465
+
466
+ Layers and their local source:
467
+ template [<name>] This project: \.pi\-pod/config\.json, its init and bake
468
+ scripts, Pi files under \.pi/, and the project env file
469
+ (secrets, with \-\-with\-secrets or a prompt)\. Without
470
+ <name> the project's pinned template is used\.
471
+ user ~/\.pi\-pod/config\.json and ~/\.pi/agent/ (settings\.json,
472
+ models\.json, mcporter\.json, subagents\.json, agents/)
473
+ org ~/\.pi\-pod/org/: config\.json, init\.sh, bake\.sh, pi/…, and
474
+ an optional env file whose values become org secrets
475
+
476
+ Inside a project the layer defaults to template; elsewhere it is required\.
477
+ Provider credentials, hooks, mcpServers, and model credential values never
478
+ leave this machine\.
479
+
480
+ Options:
481
+ \-\-dir <path> org only: read the org source from <path> instead
482
+ \-\-with\-secrets Also upload the layer's env values as secrets
483
+ \-y, \-\-yes Apply the replacement without the confirmation prompt
484
+ .fi
485
+ .RE
486
+ .P
487
+ Whatever the local source lacks is removed from the server layer, so start from
488
+ \fBpipod pull\fP when the server may have changes this machine does not\. With no terminal to
489
+ confirm on, push declines unless \fB\-\-yes\fP is given\.
490
+ .SS pipod pull
491
+ .RS 2
492
+ .nf
493
+ Usage: pipod pull [template [<name>] | user | org] [\-\-dir <path>] [\-\-yes]
494
+
495
+ Write a server config bundle into its local source files (see
496
+ `pipod push \-\-help` for the layer → directory table)\. A diff preview
497
+ precedes the confirmation; nothing is written when the two already match\.
498
+
499
+ What pull keeps from the local files:
500
+ config\.json client\-only keys: $schema, template, secretResolver,
501
+ pi\.chords, pi\.sessionNaming
502
+ settings\.json hooks and mcpServers (and packages when hostConfig\.packages
503
+ is off)
504
+ models\.json credential values the push had dropped
505
+ agents/ files the bundle no longer contains are removed
506
+
507
+ Secrets stay on the server; their names are listed\. The user layer has no
508
+ local script files, so user bundle scripts are shown but not written\.
509
+
510
+ Options:
511
+ \-\-dir <path> org only: write the org source to <path> instead
512
+ \-y, \-\-yes Apply the local changes without the confirmation prompt
513
+ .fi
514
+ .RE
515
+ .SS pipod diff
516
+ .RS 2
517
+ .nf
518
+ Usage: pipod diff [template [<name>] | user | org] [\-\-dir <path>]
519
+
520
+ Compare a config layer's local source with its server bundle (see
521
+ `pipod push \-\-help` for the layer → directory table)\. Secrets compare by
522
+ name only\. Exits 1 when they differ, 0 when they match\.
523
+
524
+ Options:
525
+ \-\-dir <path> org only: read the org source from <path> instead
526
+ .fi
527
+ .RE
528
+ .SS pipod secrets
529
+ .RS 2
530
+ .nf
531
+ Usage: pipod secrets [action]
532
+
533
+ Manage the secret layers pods see\. Requires account or pod\-token auth\. Server
534
+ scopes are org, user, and template/<name>; project is this project's dotenv
535
+ file, the highest\-precedence layer for launches from the project\.
536
+
537
+ Actions:
538
+ list Every secret a pod launched here would see,
539
+ which layer wins, and who set it (default)
540
+ set <scope> <NAME> Store a secret, its value read from a hidden
541
+ prompt or stdin (never the command line)
542
+ rm <scope> <NAME> Remove a secret (aliases: remove, unset)
543
+ sync <scope> Upload a dotenv file to a server scope
544
+
545
+ sync options (scope must be org, user, or template/<name>):
546
+ \-\-file <path> Dotenv file to upload (default: ~/\.pi\-pod/secrets/<scope>\.env)
547
+ \-\-prune Also delete server secrets that are not in the file
548
+ \-\-dry\-run Show what would change without writing
549
+
550
+ Values may be op:// references; they resolve just\-in\-time (at upload for
551
+ server scopes, at launch for the project file) and the references themselves
552
+ are never stored on the server\.
553
+ .fi
554
+ .RE
555
+ .P
556
+ Precedence, lowest first: org, user, template, project\. A pod receives its secrets as
557
+ environment variables, and anything running in it can read them all\. Stored values cannot be
558
+ read back, only replaced\.
559
+ .P
560
+ Keep values out of command lines and chats: a person types them at \fBset\fP\|'s hidden prompt,
561
+ or \fBsync\fP reads a dotenv file kept at mode 600\. op:// references resolve through the
562
+ 1Password CLI (\fBop\fP) on this machine\. Model\-provider keys belong in \fBpipod credentials\fP\|\.
563
+ .SS pipod settings
564
+ .RS 2
565
+ .nf
566
+ Usage: pipod settings <user|org> [show | edit | set <key> <value> | unset <key>]
567
+
568
+ Show or edit a persistent settings bundle on the server: your own user bundle,
569
+ or the org\-wide defaults (org scope needs the org:manage permission)\. Edits
570
+ change only the config; scripts and Pi files stay as they are — replace the
571
+ whole bundle from local files with `pipod push user` or `pipod push org`\.
572
+ Edits use compare\-and\-swap on the bundle version, so concurrent changes fail
573
+ cleanly instead of overwriting each other\.
574
+
575
+ Actions:
576
+ show Print the settings bundle as JSON (default)
577
+ edit Edit the config in $VISUAL/$EDITOR, then save
578
+ set <key> <value> Set one dotted key to a JSON value, or to the text as
579
+ a string: pipod settings user set pi\.model provider/model
580
+ unset <key> Remove one dotted key, so the layers below decide it
581
+ .fi
582
+ .RE
583
+ .P
584
+ Keys are those of pipod\-config(5)\. \fBset\fP changes the server only: a later \fBpipod push\fP of the
585
+ same layer replaces it with the local source, so after a \fBset\fP, run \fBpipod pull\fP before
586
+ editing that source\.
587
+ .SS pipod jobs
588
+ .RS 2
589
+ .nf
590
+ Usage: pipod jobs [action] [args] [\-\-quiet] [\-\-yes] [\-\-project] [\-\-org]
591
+
592
+ Manage scheduled jobs the pi pod server runs for you: at each trigger it
593
+ launches a pod from the job's template and sends the job's prompt\. Local job
594
+ files in \.pi\-pod/jobs/ (project) or ~/\.pi\-pod/jobs/ (user) are the reviewable
595
+ source; `jobs push` promotes them to the server\. <job> is an id, short ref
596
+ (j\-…), or name\.
597
+
598
+ Actions:
599
+ list List server jobs (default)
600
+ show <job> Show a job's schedule, template, model, and prompt
601
+ runs <job> List a job's recent runs
602
+ run <job> Run an active job once, now; its schedule is unchanged
603
+ activate <job> Activate a job
604
+ pause <job> Pause a job's schedule
605
+ resume <job> Resume a paused job
606
+ rm <job> Remove a job; its schedule stops firing
607
+ push [job…] Create or update server jobs from local job files
608
+ pull <job> Write a server job to a local job file
609
+ diff [job…] Show local vs server drift; exits 1 when drifted
610
+
611
+ Options:
612
+ \-\-org push: create org\-scoped jobs or promote matching user jobs
613
+ (promotion is one\-way)
614
+ \-\-project pull: write into this project's \.pi\-pod/jobs/ instead of
615
+ ~/\.pi\-pod/jobs/
616
+ \-q, \-\-quiet list: print job ids only, one per line
617
+ \-y, \-\-yes Skip confirmations; pull: overwrite an existing local file
618
+ .fi
619
+ .RE
620
+ .P
621
+ A job file is \fB<name>\.json\fP (comments allowed), and its file name is the job's name:
622
+ .RS 2
623
+ .nf
624
+ {
625
+ "description": "Triage new issues every morning",
626
+ "trigger": { "type": "cron", "cron": "0 6 * * *" },
627
+ "template": "my\-service",
628
+ "model": "anthropic/claude\-opus\-4\-7",
629
+ "prompt": "Review yesterday's new issues and post a triage summary\."
630
+ }
631
+ .fi
632
+ .RE
633
+ .P
634
+ \fBtrigger\fP is a cron expression, evaluated in UTC, or \fB{ &quot;type&quot;: &quot;at&quot;, &quot;times&quot;: [\.\.\.] }\fP with
635
+ up to 100 ISO 8601 timestamps that each name their timezone\. Runs must be at least 5
636
+ minutes apart, since each run is a pod\. \fBmodel\fP (provider/model\-id) is required\.
637
+ \fBpromptFile\fP names a file beside the job file instead of \fBprompt\fP; prompts are at most 64 KiB
638
+ and must say everything the run needs, since it starts in a fresh pod\. A job runs on its own
639
+ until paused, so agree its schedule with the person before \fBpipod jobs push\fP\|\.
640
+ .SS pipod list
641
+ .RS 2
642
+ .nf
643
+ Usage: pipod list [pod] [\-\-all] [\-\-archived] [\-\-template <name|id>] [\-\-quiet]
644
+
645
+ Alias: ls
646
+
647
+ List pods on the signed\-in server with stable short refs (p\-…)\. The project is
648
+ the directory's git repository (or the directory, or its \.pi\-pod/ config): a
649
+ listing shows that project's pods when it has any — its pinned template's when
650
+ it pins one — and every pod otherwise\. Co\-located pods are grouped under the pod
651
+ whose machine they share, with an ON column naming it\.
652
+ With a pod argument, show just that machine's group: the pod and everything
653
+ co\-located on it\.
654
+
655
+ Status says where a pod's files are: a stopped pod keeps them on disk and restarts on
656
+ attach; an archived workspace is restored on next use, which takes longer the bigger it is\.
657
+ Pods you archive stay hidden unless \-\-archived is passed\.
658
+
659
+ Options:
660
+ \-a, \-\-all Every pod; ignore the current project and its template pin
661
+ \-\-archived Include logically archived pods
662
+ \-\-template <name|id> Only pods launched from that template (whole account)
663
+ \-q, \-\-quiet Print pod ids only, one per line
664
+ .fi
665
+ .RE
666
+ .SS pipod attach
667
+ .RS 2
668
+ .nf
669
+ Usage: pipod attach [pod] [\-\-yes] [\-\- <prompt…> [\-\-tui\-mode <mode>]]
670
+
671
+ Alias: a
672
+
673
+ Reconnect to a pod session through the server gateway\. Name the pod by id,
674
+ short ref (p\-…), or name; omit it when this project has exactly one pod\.
675
+ Quitting detaches: the pod keeps running until the server's idle policy reaps
676
+ it or `pipod stop` stops it\. Raw pod shells are not available\.
677
+ Attaching to an archived pod offers to restore it first\.
678
+
679
+ After \-\-:
680
+ <prompt…> Words are sent to the session as a startup prompt
681
+ \-\-tui\-mode <mode> Local TUI layout for this attach: regular or fullscreen
682
+
683
+ Options:
684
+ \-y, \-\-yes Restore an archived pod without asking
685
+ .fi
686
+ .RE
687
+ .SS pipod stop
688
+ .RS 2
689
+ .nf
690
+ Usage: pipod stop [pod…]
691
+
692
+ Stop pods now by id, short ref (p\-…), or name; omit the argument when this
693
+ project has exactly one pod\. Stopped pods keep their files and `pipod attach`
694
+ restarts them\. Stopping a pod that hosts co\-located pods stops those too\.
695
+ .fi
696
+ .RE
697
+ .SS pipod fork
698
+ .RS 2
699
+ .nf
700
+ Usage: pipod fork <pod> [\-\-session <path>] [launch options] [\-\- <pi args…>]
701
+
702
+ Launch a new pod whose session starts as a fork of <pod>'s current session\.
703
+ <pod> is an id, short ref (p\-…), or name\. The workspace is not copied —
704
+ commit and push first if the new pod needs those changes\. \-\-on is not
705
+ supported: a fork launches a new sandbox, not a co\-located pod\.
706
+
707
+ Options:
708
+ \-\-session <path> Fork a specific session file instead of the newest
709
+ \-\-template <name|id> Launch the new pod from an account template
710
+ \-\-dry\-run Resolve and print the launch plan; create nothing
711
+ \-y, \-\-yes Skip supported confirmations
712
+ .fi
713
+ .RE
714
+ .SS pipod rename
715
+ .RS 2
716
+ .nf
717
+ Usage: pipod rename <pod> <name>
718
+
719
+ Rename a server\-managed pod\. <pod> is an id, short ref (p\-…), or the current
720
+ name\.
721
+ .fi
722
+ .RE
723
+ .SS pipod send
724
+ .RS 2
725
+ .nf
726
+ Usage: pipod send [pod] <path> [\-\-yes]
727
+
728
+ Copy a host file or directory into a pod through the server\. Omit the pod when
729
+ this project has exactly one\. Sending to an archived pod offers to restore it
730
+ first\.
731
+
732
+ Options:
733
+ \-y, \-\-yes Restore an archived pod without asking
734
+ .fi
735
+ .RE
736
+ .SS pipod receive
737
+ .RS 2
738
+ .nf
739
+ Usage: pipod receive [pod] <path> [\-\-yes]
740
+
741
+ Copy a file or directory from a pod into the current local directory\. <path>
742
+ may be a workdir\-relative path or an absolute path inside that workdir, such
743
+ as foo or /workspace/foo\. The destination must not already exist\. Omit the
744
+ pod when this project has exactly one\. Receiving from an archived pod offers
745
+ to restore it first\.
746
+
747
+ Options:
748
+ \-y, \-\-yes Restore an archived pod without asking
749
+ .fi
750
+ .RE
751
+ .SS pipod archive
752
+ .RS 2
753
+ .nf
754
+ Usage: pipod archive [pod…] [\-\-all] [\-\-template <name|id>] [\-\-idle <duration>] [\-\-dry\-run] [\-\-yes]
755
+
756
+ Archive pods by id, short ref (p\-…), or name\. Archiving hides pods from
757
+ `pipod list` (`pipod list \-\-archived` shows them); it never deletes work, and
758
+ `pipod restore` brings them back\. Archiving a pod that hosts co\-located pods
759
+ archives those too\.
760
+
761
+ Options:
762
+ \-a, \-\-all Archive every pod (cannot be combined with pod refs)
763
+ \-\-template <name|id> Only pods launched from that template (whole account)
764
+ \-\-idle <duration> Only pods whose last activity is older than this (4h, 2d, 30m)
765
+ \-\-dry\-run Print the matching pods; archive nothing
766
+ \-y, \-\-yes Skip the bulk confirmation
767
+ .fi
768
+ .RE
769
+ .SS pipod restore
770
+ .RS 2
771
+ .nf
772
+ Usage: pipod restore [pod…] [\-\-all] [\-\-yes]
773
+
774
+ Bring archived pods back by id, short ref (p\-…), or name\. Restoring a host
775
+ restores the co\-located pods archived with it\. `pipod attach` then starts the
776
+ pod; a workspace in cold storage takes longer the bigger it is\.
777
+
778
+ Options:
779
+ \-a, \-\-all Restore every archived pod (cannot be combined with pod refs)
780
+ \-y, \-\-yes Skip the \-\-all confirmation
781
+ .fi
782
+ .RE
783
+ .SS pipod gc
784
+ .RS 2
785
+ .nf
786
+ Usage: pipod gc [\-\-delete] [\-\-yes]
787
+
788
+ List the archived and failed pods that can be deleted for good; \-\-delete deletes
789
+ them\. (The server stops idle pods and moves stopped workspaces to cold storage on
790
+ its own schedule; that never deletes anything\.)
791
+
792
+ Options:
793
+ \-\-delete Permanently delete the reclaimable pods
794
+ \-y, \-\-yes Delete without a confirmation prompt
795
+ .fi
796
+ .RE
797
+ .SS pipod doctor
798
+ .RS 2
799
+ .nf
800
+ Usage: pipod doctor [\-\-template <name|id>]
801
+
802
+ Check each layer a launch depends on: account auth, server reachability and
803
+ version, organization membership and roles, secret references, and the
804
+ server\-resolved settings bundle chain for this directory\. Works while signed
805
+ out to diagnose auth problems\. Exits non\-zero when a layer fails\.
806
+
807
+ Options:
808
+ \-\-template <name|id> Plan the checked launch with this template
809
+ .fi
810
+ .RE
811
+ .SS pipod update
812
+ .RS 2
813
+ .nf
814
+ Usage: pipod update [\-\-dry\-run]
815
+
816
+ Upgrade pi pod itself: a registry install updates to the latest published
817
+ version; a git checkout pulls its upstream and rebuilds\.
818
+
819
+ Options:
820
+ \-\-dry\-run Report what an update would do without changing anything
821
+ .fi
822
+ .RE
823
+ .SH FILES
824
+ .RS 2
825
+ .nf
826
+ ~/\.pi\-pod/auth\.json this machine's sign\-in (pipod login)
827
+ ~/\.pi\-pod/config\.json this machine's preferences, and the config of your
828
+ user layer (pipod\-config(5))
829
+ ~/\.pi/agent/ your Pi files, the rest of your user layer:
830
+ settings\.json, models\.json, mcporter\.json,
831
+ subagents\.json, agents/
832
+ ~/\.pi\-pod/org/ the organization layer's source: config\.json,
833
+ init\.sh, bake\.sh, pi/, env
834
+ ~/\.pi\-pod/secrets/ dotenv files for pipod secrets sync
835
+ ~/\.pi\-pod/jobs/ your job files
836
+ \|\.pi\-pod/config\.json a project's config and its template pin
837
+ \|\.pi\-pod/init\.sh runs in each of the project's new pods
838
+ \|\.pi\-pod/bake\.sh built into the project's pod image
839
+ \|\.pi\-pod/env the project's secret values; never committed
840
+ \|\.pi\-pod/env\.example the names of the project's secrets; committed
841
+ \|\.pi\-pod/jobs/ the project's job files
842
+ \|\.pi/ the project's Pi files, as in ~/\.pi/agent/
843
+ .fi
844
+ .RE
845
+ .SH ENVIRONMENT
846
+ .RS 2
847
+ .nf
848
+ PI_POD_ACCOUNT_URL the server pipod login uses with no \-\-server and no
849
+ previous session
850
+ PI_POD_ISSUER the OIDC issuer pipod login uses, for a server too old
851
+ to publish its own
852
+ PI_POD_SERVER_URL set in every pod: pipod there signs in with the pod's
853
+ PI_POD_SERVER_TOKEN own token, which reaches only the pods it launched
854
+ VISUAL, EDITOR the editor for pipod settings edit
855
+ NO_COLOR plain output without color
856
+ .fi
857
+ .RE
858
+ .SH SEE ALSO
859
+ .P
860
+ pipod\-config(5), https://github.com/pi-pod/pipod and docs/self\-host\.md there for running
861
+ a server\.