boxyard 0.2.1
Add your description here
Requires Python: >=3.11

# boxyard

A CLI tool for managing and syncing folders ("boxes") across local and remote storage using [rclone](https://rclone.org/). Track metadata, organize boxes into groups, and keep everything in sync with conflict detection.

## Install

```bash
pip install boxyard
# or
uv pip install boxyard
```

Requires [rclone](https://rclone.org/downloads/) to be installed and configured.

## Quick start

```bash
# Initialize boxyard (creates config and data directories)
boxyard init

# Create a new box from an existing folder
boxyard new ~/projects/my-project

# Sync a box to remote storage
boxyard sync my-project

# Check sync status
boxyard yard-status

# List all boxes
boxyard list
```

## What it does

Boxyard manages folders (called "boxes") that you want to keep synced between your local machine and remote storage (S3, SFTP, or any rclone-supported backend).

Each box has:
- **Data** (`data/`) - the actual folder contents
- **Metadata** (`boxmeta.toml`) - name, groups, storage location, creation info
- **Config** (`conf/`) - optional per-box configuration that controls how data is synced
- **Sync records** - track what's been synced and when, enabling conflict detection

### The `conf/` folder

Each box can optionally have a `conf/` folder containing rclone filter files that customize which files are included or excluded when syncing the box's data:

- `.rclone_include` - only sync files matching these patterns
- `.rclone_exclude` - skip files matching these patterns (if absent, the global default exclude list is used)
- `.rclone_filters` - combined include/exclude filter rules

During sync, the `conf/` folder is synced *before* the data, ensuring filter rules are up-to-date before they're applied. This means filter rules travel with the box across remotes -- if you want a box to always exclude `.venv/` or only include `*.csv`, put that in its `conf/` folder and it will apply everywhere the box is synced.

Boxes are identified by a unique ID (`{timestamp}_{subid}`, e.g. `20251122_143022_a7kx9`) and organized into groups via symlinks.

## Commands

| Command | Description |
|---------|-------------|
| `init` | Initialize boxyard config and data directories |
| `new` | Create a new box from a folder |
| `sync` | Sync a box with remote storage |
| `multi-sync` | Sync multiple boxes concurrently |
| `list` | List all boxes |
| `box-status` | Show sync status of a box |
| `yard-status` | Show sync status of all boxes |
| `include` | Include a remote box in the local store |
| `exclude` | Exclude a box from the local store (keeps remote) |
| `delete` | Delete a box locally and/or remotely |
| `rename` | Rename a box locally, remotely, or both |
| `copy` | Copy a remote box to a local path without including it |
| `force-push` | Force push a local folder to a box's remote |
| `add-to-group` | Add a box to a group |
| `remove-from-group` | Remove a box from a group |
| `path` | Get the local path of a box |
| `which` | Identify which box a path belongs to |

## Configuration

Config file: `~/.config/boxyard/config.toml`

```toml
default_storage_location = "my-remote"
boxyard_data_path = "~/.boxyard"
user_boxes_path = "~/boxes"
user_box_groups_path = "~/box-groups"

[storage_locations.my-remote]
storage_type = "rclone"
store_path = "boxyard"
```

Storage locations are defined as rclone remotes. Boxyard uses its own rclone config at `~/.config/boxyard/boxyard_rclone.conf`.

## Directory layout

```
~/.config/boxyard/
    config.toml              # Main config
    boxyard_rclone.conf      # rclone config for remotes

~/.boxyard/
    local_store/{remote}/    # Local copies of box data
    sync_records/            # Per-box sync state
    locks/                   # File locks for concurrent operations

~/boxes/                     # Symlinks to box data folders
~/box-groups/                # Group symlinks (e.g. ~/box-groups/work/my-project)
```

## Development

Boxyard uses [nblite](https://github.com/lukastk/nblite) for notebook-first development. Source files in `src/boxyard/` are autogenerated -- edit the `.pct.py` files in `pts/` instead.

```bash
uv sync                  # Install dependencies
nbl export --reverse     # Sync pts -> nbs (after editing .pct.py files)
nbl export               # Export nbs -> src/boxyard/
pytest src/tests/        # Run tests
```

## License

MIT