vcspull sync

The vcspull sync command clones and updates repositories defined in your vcspull configuration. It’s the primary command for keeping your local workspace synchronized with remote repositories.

Command

Synchronize VCS repositories.

Usage

usage: vcspull sync [-h] [-f FILE] [-w DIR] [--dry-run] [--json] [--ndjson]
                    [--color {auto,always,never}] [--exit-on-error]
                    [--show-unchanged] [--summary-only] [--long]
                    [--relative-paths] [--fetch] [--offline] [-v] [--all]
                    [--include-worktrees] [--timeout SECONDS]
                    [--panel-lines N] [--log-file PATH] [--no-log-file]
                    [pattern ...]

Examples

$ vcspull sync --all
$ vcspull sync "django-*"
$ vcspull sync --dry-run --all
$ vcspull sync -f ./myrepos.yaml --all
$ vcspull sync -w ~/code myproject

Positional Arguments

repo_patterns pattern

patterns / terms of repos, accepts globs / fnmatch(3)

Default
None

Options

-f, --file FILE

path to config file (default: ~/.vcspull.yaml or ./.vcspull.yaml)

Default
None
-w, --workspace, --workspace-root DIR

filter by workspace root directory

Default
None
--dry-run, -n

preview what would be synced without making changes

Default
False
--json

output as JSON

Default
False
--ndjson

output as NDJSON (one JSON per line)

Default
False
--color

when to use colors (default: auto)

Default
auto
Choices
auto, always, never
--exit-on-error, -x

exit immediately encountering error (when syncing multiple repos)

Default
False
--show-unchanged

include repositories that are already up to date

Default
False
--summary-only

print only the plan summary line

Default
False
--long

show extended details for each repository

Default
False
--relative-paths

display repository paths relative to the workspace root

Default
False
--fetch

refresh remote tracking information before planning

Default
False
--offline

skip network access while planning (overrides --fetch)

Default
False
-v, --verbose

increase verbosity. -v opens libvcs INFO ('Updating to ...'); -vv opens libvcs DEBUG (full per-repo trace) plus extra dry-run plan detail. Default keeps libvcs at WARNING+.

Default
0
--all, -a

sync all configured repositories

Default
False
--include-worktrees

also sync configured worktrees for each repository

Default
False
--timeout SECONDS

per-repository wall-clock deadline in seconds (default: 10; env: VCSPULL_SYNC_TIMEOUT_SECONDS). Repos that exceed the deadline are skipped and the rest of the batch continues.

Default
None
Type
_positive_int_arg
--panel-lines N

live-trail panel height for streaming subprocess output above the spinner (default: 3; 0 hides; -1 unbounded; env: VCSPULL_PROGRESS_LINES). The panel collapses when each repo finishes, leaving only the permanent ✓ Synced line.

Default
None
Type
_panel_lines_arg
--log-file PATH

write a debug log to PATH (default: $TMPDIR/vcspull/debug-<ts>-<pid>.log; $TMPDIR/vcspull-test/... under pytest). The path is only printed to the terminal when a sync fails or times out, matching npm/pnpm/yarn.

Default
None
--no-log-file

disable the debug log file entirely

Default
False

Filtering repos

Running vcspull sync with no patterns syncs nothing and prints the generated help text. You always say which repositories to touch, with patterns or --all.

Sync all repos

Sync everything with the * pattern:

$ vcspull sync '*'

Depending on how your shell expands the wild card / asterisk, you may not need to quote *.

Filtering

Filter repos starting with “django-“:

$ vcspull sync 'django-*'

Multiple terms

Name several repositories exactly:

$ vcspull sync 'django-anymail' 'django-guardian'

Configuration file selection

Specify a custom config file with -f/--file:

$ vcspull sync --file ~/projects/.vcspull.yaml '*'

By default, vcspull searches for config files in:

  1. Current directory (.vcspull.yaml)

  2. Home directory (~/.vcspull.yaml)

  3. XDG config directory (~/.config/vcspull/)

Workspace filtering

Filter repositories by workspace root with -w/--workspace or --workspace-root:

$ vcspull sync --workspace ~/code/ '*'

This syncs only repositories in the specified workspace root, useful for:

  • Selective workspace updates

  • Multi-workspace setups

  • Targeted sync operations

The -w, --workspace, and --workspace-root spellings work identically:

$ vcspull sync --workspace-root ~/code/ '*'

Error handling

Repos not found in config

If a repo term has no match in your configurations, vcspull shows a warning:

$ vcspull sync non_existent_repo
No repo found in config(s) for "non_existent_repo"
$ vcspull sync non_existent_repo existing_repo
No repo found in config(s) for "non_existent_repo"
$ vcspull sync non_existent_repo existing_repo another_repo_not_in_config
No repo found in config(s) for "non_existent_repo"
No repo found in config(s) for "another_repo_not_in_config"

Sync terms act as a filter rather than a lookup, so the message is a warning — it does not stop the run, even with --exit-on-error.

Continuing past errors

When syncing multiple repositories, vcspull continues to the next repository if one fails.

Pass --exit-on-error / -x to stop the whole run at the first failing repository instead:

$ vcspull sync --exit-on-error grako django

Print traceback for errored repos:

$ vcspull --log-level DEBUG sync --exit-on-error grako django

Dry run mode

Preview what would be synchronized without making changes:

$ vcspull sync --dry-run '*'
Plan: 2 to clone (+), 0 to update (~), 2 unchanged (), 0 blocked (), 0 errors ()

~/code/
  + django-extensions  ~/code/django-extensions  missing

~/study/ai/
  + tiktoken  ~/study/ai/tiktoken  missing
Tip: run without --dry-run to apply. Use --show-unchanged to include  rows.

Use --dry-run or -n to:

  • Verify your configuration before syncing

  • Check which repositories would be updated

  • Test pattern filters

  • Preview operations in CI/CD

JSON output

Export sync operations as JSON for automation:

$ vcspull sync --dry-run --json 'flask' 'tiktoken'

Output:

[
  {
    "format_version": "1",
    "type": "operation",
    "name": "tiktoken",
    "path": "~/study/ai/tiktoken",
    "workspace_root": "~/study/ai/",
    "action": "clone",
    "detail": "missing",
    "url": "git+https://github.com/openai/tiktoken.git"
  },
  {
    "format_version": "1",
    "type": "summary",
    "clone": 1,
    "update": 0,
    "unchanged": 1,
    "blocked": 0,
    "errors": 0,
    "total": 2,
    "duration_ms": 8
  }
]

Each event emitted during the run includes:

  • format_version: Schema version of the event stream (currently "1")

  • type: "operation" for repository events, "summary" for the final summary

  • name, path, workspace_root, url: Repository metadata from your config

  • action: "clone", "update", "unchanged", "blocked", or "error"

  • detail: Short explanation of the action, when available

  • branch, ahead, behind, dirty: Working-tree state for existing checkouts

Use --json without --dry-run to capture actual sync executions—successful and failed repositories are emitted with their final state.

NDJSON output

Stream sync events line-by-line with --ndjson:

$ vcspull sync --dry-run --ndjson 'flask' 'tiktoken'
{"format_version": "1", "type": "operation", "name": "tiktoken", "path": "~/study/ai/tiktoken", "workspace_root": "~/study/ai/", "action": "clone", "detail": "missing", "url": "git+https://github.com/openai/tiktoken.git"}
{"format_version": "1", "type": "summary", "clone": 1, "update": 0, "unchanged": 1, "blocked": 0, "errors": 0, "total": 2, "duration_ms": 7}

Each line is a JSON object representing a sync event, ideal for:

  • Real-time processing

  • Progress monitoring

  • Log aggregation

Color output

Control colored output with --color:

  • --color auto (default): Use colors if outputting to a terminal

  • --color always: Always use colors

  • --color never: Never use colors

The NO_COLOR environment variable is also respected.