boxyard-cli
Use the Boxyard CLI to manage, find, inspect, sync, include, exclude, group, rename, or copy boxes. Use when the user asks about boxyard command usage, Boxyard config files, locating box folders, rclone-backed storage, sync status, or shell/TUI helpers.
By lukastk · 469 installs
npx skills add lukastk/boxyard --skill boxyard-cli
Source repository · Upstream listing
Boxyard CLI Skill
Use this skill when the user wants to use Boxyard, not develop Boxyard itself.
Boxyard is a Python CLI for managing and syncing folders ("boxes") across local and remote storage using rclone or local storage. A box has data, metadata, optional sync configuration, group membership, and sync records.
Where generated data should live
Generated data — including large outputs — generally belongs inside the box it relates to, not in some sibling directory chosen to dodge syncing. Do not move heavy outputs out of a box to keep it "small". The whole point of Boxyard is that syncing makes large boxes comfortable to live with: anything you don't want pushed can be excluded from sync via the box's conf/.rclone exclude / conf/.rclone filters (see "Per box sync configuration"), or the box itself can be excluded locally with boxyard exclude . Keep data colocated with its box and control sync with filters — don't fragment it to avoid sync.
Before running commands
If operating from this repository checkout, prefer:
If Boxyard is already installed in the environment, boxyard ... is also fine.
Read only commands are safe to run without confirmation: help , list , tree , path , which , box status , yard status , list groups , owner , doctor .
Ask before running commands that can modify local or remote state: init , new , sync , multi sync , sync missing meta , include , exclude , delete , rename , sync name , add to group , remove from group , add parent , remove parent , create user symlinks , copy , force push , claim , release , discard local .
Be especially careful with:
boxyard new from PATH / f PATH : moves PATH into Boxyard unless copy is supplied.
boxyard exclude : syncs first by default, then removes the local data copy.
boxyard delete : deletes a box.
boxyard sync sync setting replace force : can overwrite data depending on direction/status.
boxyard force push force : destructively overwrites remote data from a local source folder.
Configuration files and important paths
Default files and folders:
The config file controls the real locations. Important config keys:
Derived paths:
For a box with index name <box id <name :
Remote/rclone stores use this layout under the storage location's store path :
The global CLI option for non default config is:
boxyard init uses config path and data path to create a config/data directory. The shell helper honors BOXYARD CONFIG PATH ; normal Typer CLI commands should be given config when using a non default config.
DEFAULT BOX GROUPS can add default groups at runtime. It is parsed as a TOML list string, for example:
How to find where boxes are
Use these patterns first.
Find the box containing the current directory or any path
which searches every configured checkout root (including symlink resolved paths) and reports the box name, id, index name, storage location, checkout root/state, authoritative local DATA path, and inclusion state.
Get a box's data folder
boxyard path defaults to the data path. By default it filters to included boxes. Use all when you need to select from included and excluded boxes.
Get non data paths for a box
Find checkout roots and actual local paths
Never reconstruct user boxes path/<index name : a box may be in any configured root. user boxes path is permanently the root named default ; additional roots are [checkout roots.NAME] . Use:
Status markers are ● included, ○ excluded, ! root unavailable, × recorded checkout missing, and ↔ interrupted relocation. An unavailable root never falls back to default and its boxes remain in the catalog.
Common discovery commands
Group filters support boolean expressions over group names:
Other list filters:
Box selection options
Many commands accept one of:
Name matching options:
With no box / box id / box name at all, boxyard uses the box you are
standing in — anywhere under <user boxes path /<index name /... . If the cwd is
not inside a box (or the box is not a candidate for that command, e.g. an
already included box for include ), it falls back to an fzf picker over the
candidates. Commands that destroy something — delete , rename , copy ,
force push , sync name — refuse a bare invocation outright and always need
an explicit selector.
Creating boxes
Create an empty box:
Create from an existing folder, moving the folder into Boxyard:
Copy from an existing folder instead of moving it:
Clone a git repo as a new box:
Useful options:
Select local placement independently of remote storage:
exclude remembers the preferred root; include without a root reuses it. relocate is locked, local only, does no remote I/O, and is recoverable via doctor . Use adopt existing only for a pre populated destination: Boxyard verifies every source entry is identical there, preserves destination only content, then commits placement and removes the source.
Syncing
Sync one box:
Sync only selected parts:
Sync settings and direction:
Other sync commands:
Soft interruption is enabled by default for long operations: interrupt once or twice to stop after the current operation; repeated interrupts exit immediately.
Write ownership ( owner , claim , release , discard local )
A box can have a write owner : the single machine allowed to push its DATA. A box with
no owner is unrestricted , exactly as before this feature existed — so most boxes are
unowned and nothing about them changed. Ownership is recorded per box as write owner
and compared against this machine's configured machine name (configured, never derived
from the hostname, because hostnames are unreliable — one machine reports both
lukas pocket4 and pocket4 ).
If a sync is refused because another machine owns the box , there are exactly two ways
out, and the error prints both:
discard local is the destructive one, but not lossy: what it overwrites is kept under
the sync backups directory and the path is printed. Prefer steal when this machine's
copy is the one you want to keep, discard local when the remote's is.
Ownership is also enforced on three commands that bypass sync entirely and would
otherwise write to the remote unchecked: force push , rename scope remote both , and
delete . Being refused by one of these is the gate working, not a bug — resolve it with
claim / steal rather than reaching for a workaround.
Health check ( doctor )
boxyard doctor is a strictly read only health check of the machine's whole boxyard state. It never mutates or auto fixes anything, and exits 0 when healthy / 1 when there is any finding, so scripts and cron jobs can assert on it.
Agents: run boxyard doctor whenever box state looks inconsistent — e.g. a folder in user boxes path that boxyard list doesn't know about, boxyard list missing boxes that exist on another machine, group symlinks pointing nowhere, or errors mentioning boxmeta/sync records. Every finding comes with a one line hint on how to fix it; apply the hints rather than improvising.
Checks: unregistered folder (dirs in user boxes path not registered as boxes — the classic symptom of hand creating folders instead of using boxyard new ), malformed name (names that don't parse as <timestamp <subid <name ; legacy formats are accepted), broken registration (missing/invalid boxmeta.toml in the local store), duplicate box id , stale cache ( boxyard meta.json disagrees with a fresh scan), dangling symlinks (group symlinks with missing targets), group tree debris (real files in the group tree, which break create user symlinks and thereby most mutating commands), orphaned sync records , interrupted sync (sync records left incomplete — the local copy may be incomplete; re sync to recover), unknown storage location (leftovers from removed/renamed storage locations), rclone config (missing rclone binary/remote sections/default exclude file), stale meta mirror (remote boxmetas not mirrored locally — what sync missing meta would fetch; a machine where that never runs silently hides newer boxes from boxyard list ), tombstoned box (boxes deleted from another machine but still registered here), and tree orphans (parents referencing unknown box ids).
Include, exclude, copy
Include an excluded remote box locally:
Exclude a local copy while keeping the remote:
Copy a remote box to an arbitrary destination without adding it to Boxyard tracking:
Groups and hierarchy
Groups:
Parent child hierarchy:
Rename, delete, and force operations
Rename:
Sync only the name between local and remote:
Delete:
Destructive force push:
Per box sync configuration
Each box can have a conf/ folder. Boxyard syncs conf/ before data/ , so filters travel with the box.
Special files:
If conf/.rclone exclude is absent, Boxyard uses:
Default excludes include .venv/ , .pixi/ , .trunk/ , node modules/ , pycache / , and .DS Store .
Shell helper
The repo includes a zsh helper:
Default keybinding: Ctrl+G ( BOXYARD WIDGET KEY can override it). Type a partial box name, press the keybinding, and it replaces the current word with a relative path to the selected box. It uses boxyard shell helper search and fzf for multiple matches.
Direct helper examples:
Reference files in this repository
From this skill directory, the repository root is ../.. .
Read these for more context when needed:
../../README.md — high level usage and directory layout
../../src/boxyard/const.py — default paths and constants
../../src/boxyard/config.py — config model and derived paths
../../src/boxyard/ cli/main.py — command definitions
../../src/boxyard/ cli/multi sync.py — multi sync
../../src/boxyard/ models.py — box path and metadata layout
../../src/boxyard/ shell helper.py — shell helper behavior