Skip to content

CLI workflows

Use the CLI yourself or let your coding agent run it. Start with an authoring project to change an app, or a writable .pop document to work with its data.

Responses below use example paths and compact JSON. Versions, timings, generated IDs, installed templates and palettes vary. Larger responses are explicitly marked as excerpts. Shell commands such as cd succeed without printing a response.

Install Bun 1.4.2 or newer. To open document windows, install the pop Mac app. The examples below use bunx @hitslop/pop.

Entry point When to use it
bunx @hitslop/pop COMMAND Run the authoring CLI without a global install.
pop COMMAND After bun install -g @hitslop/pop, with Bun’s bin directory on your PATH.

Use bunx or pop for the examples below. Authoring builds, registering, browser preview, document creation and document edits run on macOS or Linux. On both platforms the CLI also renders template artwork and exports closed documents as PNG/PDF itself. Opening a window uses the installed Mac app, which need not already be running.

The npm package includes its document engine, which does that rendering. open finds the Mac app automatically in /Applications or ~/Applications.

Append --help to any command to see its arguments.

Terminal window
bunx @hitslop/pop init weekend-kit
cd weekend-kit
bun install
bun run check
bun run dev

Expected terminal responses (build-tool progress omitted):

Command Response
init weekend-kit After the brief and author questions: Created /Users/you/weekend-kit. Run bun install in that directory, then bun run dev. Then choose an agent.
cd weekend-kit No output on success.
bun install Bun’s dependency installation summary; package counts and timing vary.
bun run check svelte-check found 0 errors and 0 warnings for a valid starter.
bun run dev Disposable preview: http://localhost:5173/ (port may differ); the process stays running.

init asks what you want to build and who the author is. The agent you launch next sets the app’s title, description, and categories in pop.ts to match what it builds; you can edit them there anytime. Your description is saved in BRIEF.md alongside the checklist starter and local agent guidance.

At the end, choose which agent CLI should build your pop. The picker offers detected Codex, Claude Code, Gemini CLI, and OpenCode installations. Choose Other CLI… for Grok or another installed tool: enter its executable name or path, then its prompt option (leave blank if it accepts a positional prompt). The agent opens in the new project and is asked to read the brief and pop guidance before implementing your app. It uses its existing account, model, and permission settings.

Choose Finish without launching to work manually. If an agent fails or you cancel the launch, your project remains ready to use. No agent is installed automatically.

For an agent or script that is already running, create the project without another interactive session:

Terminal window
bunx @hitslop/pop init budget-book --yes \
--brief 'Track spending by category with a monthly summary.' \
--title 'Budget Book' \
--category finance --category personal --author Jordan \
--description 'A simple monthly spending tracker.'

Response (with your chosen destination):

Created /Users/you/budget-book. Run bun install in that directory, then bun run dev.

This invocation has no interactive questions or agent launch.

Flags set metadata explicitly; --brief and --author also skip their questions. --yes, CI, and non-interactive terminals never prompt or launch an agent. Missing values default to the directory name, productivity, Anonymous, and A pop mini app.; an omitted brief uses that description. The wizard initializes the explicit slug from the directory name: 2–64 lowercase letters or digits, separated by single hyphens. Metadata is validated before files are created, and an existing destination is never overwritten.

Read pop.ts, AGENTS.md, and BRIEF.md before editing. Preview data resets on refresh, and an invalid edit shows a diagnostic until you fix it. Vite watches source changes. Component and CSS updates preserve accepted edits; a change to pop.ts, schema.ts, commands.ts, their dependencies (including skin or artwork), or the role inventory resets disposable state.

Stop the preview, then package the app and add it to your local catalog:

Terminal window
bun run build
bun run register

Responses, respectively (additional build progress omitted):

/Users/you/weekend-kit/dist/weekend-kit.pop
/Users/you/.pop/templates/weekend-kit.pop

Build writes dist/weekend-kit.pop on macOS or Linux, with Finder artwork rendered on either platform. Register builds it the same way and adds it to the Mac app’s template catalog. Existing documents keep their app version.

From outside the project, the equivalent commands take its source directory: pop check ./weekend-kit, pop dev ./weekend-kit --port 5174 (the preview port defaults to 5173), pop build ./weekend-kit, and pop register ./weekend-kit. See create your first pop for the authoring tutorial.

In the Mac app, choose a template and select Create. For the terminal equivalent, run these commands from your authoring project:

Terminal window
bunx @hitslop/pop create --from dist/weekend-kit.pop --output "$HOME/Documents/Weekend.pop"
bunx @hitslop/pop open "$HOME/Documents/Weekend.pop"

Both commands print the same resolved path after success:

/Users/you/Documents/Weekend.pop

Create makes a new document with the template’s starting data; choose a destination that does not already exist, and .pop is added if you leave it off. Open launches it in pop. Both print the document’s path. Keep writable documents out of synced folders such as iCloud Drive.

To start from a template in the Mac app’s catalog instead, list them and pass a slug to --from:

Terminal window
bunx @hitslop/pop templates
bunx @hitslop/pop create --from weekend-kit --output "$HOME/Documents/Weekend.pop"

The templates response is a catalog object. Example excerpt:

{
"templates": [
{
"slug": "weekend-kit",
"title": "Weekend Kit",
"source": "installed",
"path": "/Users/you/.pop/templates/weekend-kit.pop"
}
]
}

The following create prints /Users/you/Documents/Weekend.pop. Run one of the two creation examples, or choose a different output path for a second copy.

templates prints each template’s slug, title, description, categories, path and source: bundled with the app, or installed by register. If you register a template with the same slug as a bundled one, the slug names yours.

For a complete numbered example with every response, follow edit installed documents. For an existing document, replace My.pop with its path and quote paths containing spaces:

Terminal window
bunx @hitslop/pop describe My.pop # fields, commands and current values (add --json for tools)
bunx @hitslop/pop call My.pop addTask --args '{"text":"Buy coffee"}'
bunx @hitslop/pop schema My.pop # the stored descriptor
bunx @hitslop/pop get My.pop # saved values
bunx @hitslop/pop apply My.pop --op '{"type":"set","path":["title"],"value":"Ready"}'
bunx @hitslop/pop batch My.pop --ops '[...]'

call runs one of the commands describe lists, as one undo step. apply takes one operation and batch an array committed all-or-nothing; both print {"ids":[...]}, the inserted row IDs. An operation is {"type":..., "path":[...]}, where type is set, clear, insert, remove, move, increment or replace. A path walks the schema from the root: field names and record keys are strings, rows are {"id":"<$id>"}, and elements of a scalar list are {"index":n}. Use row IDs, never list positions. Each kind’s merge behavior is in data and schemas.

get prints the saved value, while get --snapshot also includes the schema, the template’s colors (defaults), the version and the effective colors (theme).

A refused batch exits 1 and prints Refused ops[N] (reason): message on stderr, naming the zero-based index of the operation to fix and whether anything was applied. Successful edits are saved. On a Mac, Edit ▸ Undo can revert agent edits in the open window. If a command’s outcome is uncertain, run get before retrying. Document creation and editing work on macOS and Linux; opening a window needs the Mac app.

import writes a JSON file’s value into a document, changing only what differs. Rows are matched by $id, so rows and text that stay keep their identity, and fields the import leaves unchanged are not written at all; an open window keeps working on them. Pass --path to replace one part, such as '["rows"]':

Terminal window
bunx @hitslop/pop get Old.pop > data.json
bunx @hitslop/pop import New.pop data.json
bunx @hitslop/pop import New.pop rows.json --path '["rows"]'

Responses:

Command Response
get Old.pop > data.json JSON is written to data.json; nothing is printed in the terminal.
import New.pop data.json {"ids":[]} when no rows are inserted; inserted rows appear in ids.
import New.pop rows.json --path '["rows"]' The same {"ids":[...]} shape, with the IDs inserted by this edit.

Both documents must come from the same template, so the data fits its schema; a value that doesn’t fit is refused and nothing changes. For a document of another template, map the data to one batch of insert and set operations, giving each insert an id so a retried command is refused as a duplicate. Copy attachments with the commands below, then write their references. Edit ▸ Undo in the window reverts an import as one step.

theme get, set, reset, export and import read and change a document’s palette. Their commands and example responses are in styling.

Terminal window
bunx @hitslop/pop attachments ref ./photo.png
# Store the printed reference where the app expects it, attaching the file in the same edit.
bunx @hitslop/pop apply My.pop --attach ./photo.png \
--op '{"type":"set","path":["photo"],"value":{"id":"ATTACHMENT_ID","byteLength":48213,"name":"photo.png","mimeType":"image/png"}}'
bunx @hitslop/pop attachments list My.pop
bunx @hitslop/pop attachments export My.pop ATTACHMENT_ID \
--output ./photo-copy.png

Example responses (ATTACHMENT_ID stands for the file’s actual content hash):

Command Response
attachments ref ./photo.png {"id":"ATTACHMENT_ID","byteLength":48213,"name":"photo.png","mimeType":"image/png"}
apply My.pop --attach ./photo.png … {"ids":[]}
attachments list My.pop [{"id":"ATTACHMENT_ID","byteLength":48213,"mimeType":"image/png"}]
attachments export My.pop ATTACHMENT_ID --output ./photo-copy.png /Users/you/Documents/photo-copy.png

attachments ref prints a file’s reference (its ID, size, name and type) without reading the document. --attach on apply or batch saves the file in the same edit that stores the reference, so both succeed or neither does; repeat it for more files. Ask your agent to store the reference where the app expects it. A file nothing references any more is removed when the document closes, and a duplicate or shared copy carries only the files its document references. List shows saved attachment IDs and sizes.

Attachment export refuses existing output files and the document itself. After an uncertain edit, run get before another command.

Terminal window
bunx @hitslop/pop export My.pop --format png --output My.png
bunx @hitslop/pop export My.pop --format pdf --output My.pdf

Export saves your edits and prints the output path. Choose a new output path other than the .pop itself; an existing destination is refused. Both open and closed documents render saved data independently, using Export.svelte. Pop without this optional view refuse PNG/PDF export. PNG and selectable vector PDF use the Rust renderer. On macOS and Linux the CLI exports a closed document itself; an open one is exported by the Mac app that has it open. See icons and exports for capture layouts.

Successful exports print their resolved output paths, respectively:

/Users/you/Documents/My.png
/Users/you/Documents/My.pdf

Agent skills link to your global CLI, so they update whenever you upgrade it. Install the CLI globally, then run the interactive installer to choose skills and agents:

Terminal window
bun install -g @hitslop/pop
pop skills install

Or, from a project directory, install for all detected agents at project scope:

Terminal window
pop skills install --all --scope project

After the skill and agent selections, install prints each installed skill and its agent directories. Example excerpt:

Installed "pop-authoring"

--all prints the same installation results without selection prompts. The preceding bun install -g @hitslop/pop prints Bun’s installation summary, including the pop executable.

Skills install for every project by default (global scope); add --scope project to link them into the current project only. Select skills once, then agents once. Installation only adds or repairs selected links; deselecting an item does not remove it. Bare skills is shorthand for skills install. Global links require a global install. Project links use the project’s pinned node_modules/@hitslop/pop, including when installed through bunx.

Upgrading the global CLI updates linked skills in place. If a link breaks or points somewhere else, repair it; add --scope project for project links:

Terminal window
pop skills repair

Example repair response when a link already points to the right place:

No repairs needed [pop-authoring] (global).

A repaired link instead reports Repaired "pop-authoring" for … (global), naming its agents.

To install skills for a new agent, run skills install again.

Remove installed links explicitly. Any copy of the CLI can do this:

Terminal window
pop skills uninstall --scope project
# Remove every installed pop skill at this scope without prompts:
pop skills uninstall --all --scope project

Both uninstall forms report each removed skill and its agent directories. Example excerpt:

Removed "pop-authoring"

With nothing installed, the response is No installed skills (project). Use either interactive uninstall or --all; the second invocation will find no remaining links if the first removed everything.

The guides linked by init follow the project’s pinned node_modules/@hitslop/pop install. Upgrading that dependency updates the linked guides; upgrading the global CLI leaves them unchanged.

The Mac app and the pop package share a release version. Within a project, update its one pinned pop dependency and continue using its bun run scripts. A global CLI update does not change project dependencies. If the command protocol differs, the CLI names which installation needs updating before touching a document. Updating either installation preserves the app already saved inside every document.

Update the global CLI with bun install -g @hitslop/pop@VERSION, replacing VERSION with the matching released version. Installed agent skills point at the global CLI, so they update with it.

Interactive commands may show an update notice on stderr with that command, checked at most daily. Network failures do not fail your command. CI and piped commands skip these checks; set POP_NO_UPDATE_CHECK=1 to disable them in a terminal as well.

Terminal window
pop open --browser ./MyDocument.pop
pop open --browser

Example responses (copy and import IDs vary):

http://127.0.0.1:41238/?copy=COPY_ID#import=IMPORT_ID
Local browser host is running. Keep this terminal open; Ctrl-C stops it.

Opening the list prints http://127.0.0.1:41238. The host message appears only when this invocation starts the host; one that reuses it prints the URL and exits.

The first command opens an independent copy in desktop Google Chrome. The second opens your saved browser copies. Keep the host terminal running; Ctrl-C stops it. Later invocations reuse the same host. No account or server upload is involved.

Edits autosave in this browser profile on this device. Download .pop includes the current app, data, theme and referenced attachments for opening in the desktop client. The original file stays unchanged. Browser storage can be cleared or evicted: download copies you want to keep. Reload requires the local host to be running.

Chrome on desktop is supported. Safari, private browsing and mobile browsers remain unqualified. Hosted edit links use the separate live sharing. Fullscreen appears for apps declaring fullscreenable; Keep awake is a separate, initially off toggle.