Skip to main content

Beyond Local File

Beyond Local File

Sync your local dev files across projects using symbolic links — without committing them to Git.

Table of Contents

What is this?

In real-world development, local files accumulate that are genuinely useful but shouldn't be committed to Git: HTTP client files with private environment variables, AI agent hooks and steering documents, task runner configs referencing local paths, debug logs, scratch specs. You want them in your project directory — your editor, your AI tools, your task runner all expect them there — but not in the repository.

beyond-local-file manages these files centrally and projects them into your target projects via symbolic links (or physical copies where symlinks aren't supported). It also automatically adds those links to each project's Git exclude list, so Git never sees them.

A few concrete things it handles that are hard to do with a shell script:

  • Syncing an entire directory subtree (e.g., .kiro/hooks/) into multiple projects at once
  • Copying specific files physically instead of symlinking, for tools that don't follow symlinks
  • Detecting when a physical copy is out of sync with the source, with conflict detection
  • Checking status across all managed projects at a glance (blf link check)

🎬 Quick Demo

Demo

Watch beyond-local-file in action: install from GitHub, sync files, create symlinks, and manage Git excludes automatically.

Why not GNU Stow or chezmoi?

GNU Stow and chezmoi are excellent tools for dotfiles management — organizing your personal configuration files (.bashrc, .vimrc, .gitconfig) across machines.

  • Stow uses a package-based approach with CLI parameters to create symlinks from a stow directory to $HOME.
  • chezmoi is a comprehensive dotfiles manager with templating, encryption, password manager integration, and Git-based sync across machines.

beyond-local-file is designed for a different use case: per-project development files that shouldn't be committed to Git. Instead of managing $HOME dotfiles, it syncs local dev files (HTTP client configs, AI hooks, task runner configs) across multiple projects using a centralized config.yml. It handles Git excludes automatically and supports physical copies for tools that don't follow symlinks.

Use Stow/chezmoi for: Personal dotfiles in $HOME
Use beyond-local-file for: Local dev files across multiple projects with different layouts

For a detailed comparison with use case examples, see docs/alternatives-comparison.md.

Architecture: Tool and Data Separation

beyond-local-file follows a clean separation between the tool (code) and managed projects (data):

  • The tool is the CLI application itself — installed once via uvx or uv tool install, lives in Python's site-packages, contains no user data.
  • Managed projects are your directories containing the local development files you want to share — live wherever you choose, can be version-controlled separately, independent of the tool.
# Tool (installed via uvx)
~/.local/share/uv/tools/beyond-local-file/   # managed by uv

# Managed Projects (your data, separate repository)
~/my-dev-files/
├── config.yml
├── project-a/
│   └── test.http
└── project-b/
    └── dev-config.yml

# Target Projects (where symlinks are created)
~/workspace/project-a/
└── test.http -> ~/my-dev-files/project-a/test.http

Installation

Recommended: uv tool install from PyPI

uv tool install beyond-local-file

# Update to latest version
uv tool install --upgrade beyond-local-file
# Or use the built-in upgrade command (auto-detects install method)
blf upgrade

Alternative: pipx from PyPI

pipx install beyond-local-file

# Update
pipx upgrade beyond-local-file
# Or use the built-in upgrade command (auto-detects install method)
blf upgrade

Install from GitHub (development version)

# Using uv
uv tool install git+https://github.com/xingyuli/beyond-local-file.git

# Using pipx
pipx install git+https://github.com/xingyuli/beyond-local-file.git

For development setup, see docs/development.md.

Recommended: Create an Alias

The command name beyond-local-file is long. For convenience, create an alias:

# Add to your ~/.bashrc, ~/.zshrc, or equivalent
alias blf='beyond-local-file'

This documentation uses blf in all examples.

Quick Start

  1. Create a config.yml in your managed projects directory:
project-a:
  - /Users/username/workspace/project-a
  - /Users/username/workspace/project-a-fork

project-b: /Users/username/workspace/project-b
  1. Sync symlinks:
cd ~/my-dev-files
blf link sync
  1. Check status:
blf link check

Configuration

The config.yml file maps project names to target paths. Four formats are supported:

1. Simple string — single target

project-a: /Users/username/workspace/project-a

2. Simple list — multiple targets

project-b:
  - /Users/username/workspace/project-b
  - /Users/username/workspace/project-b-fork

3. Selective subpaths — sync specific items only

project-c:
  target: /Users/username/workspace/project-c
  subpath:
    - .kiro/hooks
    - .vscode/settings.json

Only the listed subpaths are synced. Intermediate directories are created automatically.

4. Copy strategy — physical files for tool compatibility

Some tools don't recognize symlinks. Use copy: true for files that must be physical:

project-d:
  target: /Users/username/workspace/project-d
  subpath:
    - .kiro/hooks                    # symlink (default)
    - path: .kiro/steering/rules.md  # physical copy
      copy: true

Copy behavior: Bidirectional sync with conflict detection. Changes in either location are detected and can be synced.

Limitation: Copy mode only supports single files, not directories. This is intentional — symlinks remain the primary workflow.

Multiple targets: The target key accepts a string or list in all formats.

For detailed examples, see docs/configuration-reference.md.

Config File Location

By default the tool looks for config.yml in the current directory. You can override this with --config, or create ~/.blfrc to set a persistent default:

# ~/.blfrc — point to your managed-files config
config_file: ~/my-dev-files/config.yml

# Or combine personal and company configs
config_file:
  - ~/personal/config.yml
  - ~/company/config.yml

See Config File Resolution in the CLI reference for full details.

Available Commands

Command Description
blf link sync [PROJECT] Create symlinks or copies in target directories
blf link check [PROJECT] Check link status and Git excludes
blf revlink create PATH Adopt an existing file or directory into the managed workflow
blf revlink restore PATH Dissolve a managed symlink and recover the real file
blf upgrade Upgrade to the latest version (auto-detects install method)

Progress Tracking

When operations are interrupted (e.g., user chooses "Abort" during prompts), the tool displays progress information:

Operation aborted: 5/10 items processed

This helps you understand how much work was completed before the interruption.

For full option details and usage examples, see docs/cli-reference.md.

Documentation

Comprehensive documentation is available in the docs/ directory:

Important Notes

  • Symbolic links use absolute paths to ensure correct targeting from different locations
  • Only use in local development environments; do not commit symbolic links to Git
  • If you move the source file location, re-run sync
  • The tool is designed to run from your managed projects directory

Platform Support

Tested and works on macOS and Linux. Windows support is implemented but not yet tested. See docs/platform-support.md for details.

Windows should work with Developer Mode (Windows 10/11) or Administrator privileges for symlink creation. See docs/windows-support.md for setup instructions. Feedback from Windows users is welcome.

Contributing

Contributions are welcome! See docs/development.md for development setup and guidelines.

How the author uses it

I maintain two managed-project repos with beyond-local-file — one for personal GitHub projects (viclau-local-files, a private repo), one for company work. They're completely independent, each with its own config.yml, and the tool doesn't need to know about either.

The company-scoped repo's most involved config entry syncs an entire AI-assisted development environment into a backend project: Kiro hooks for code review, requirement breakdown, and weekly report generation; .qoder agent definitions, rules, and skills; .vscode settings; a Taskfile.yml with build and deploy tasks; and a structured local-file/ directory that AI agents read and write into during development. Two of the Kiro steering documents are synced with copy: true instead of as symlinks, because Kiro reads those files directly and doesn't follow symbolic links — one config option, no manual copy workflow.

The personal repo has a single entry: beyond-local-file itself. The tool manages its own development environment — a local task tracker, per-release archived changelogs, and an agentic workspace for drafts and analysis — none of it committed to the main repo.

License

MIT License — see the LICENSE file for details.

Release files for beyond-local-file 0.3.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for beyond-local-file 0.3.2
File Size Uploaded
beyond_local_file-0.3.2.tar.gz 2.8 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for beyond-local-file 0.3.2
File Interpreter ABI Platform
beyond_local_file-0.3.2-py3-none-any.whl Python 3 none any Details

Total release size: 2.9 MB

Release files / beyond_local_file-0.3.2.tar.gz

Download URL beyond_local_file-0.3.2.tar.gz
Size 2.8 MB
Tags Source
SHA-256 checksum
How to use checksums
07e35ed1548179b1929cb721c0d12073b2cff0eff42890435076a91ad4b73914
BLAKE2b-256 checksum
How to use checksums
816a4f5a9381bce5be199f2a06190ea59c46d16d6a6c3ae3076c879360afaff5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.

Transparency log

Release files / beyond_local_file-0.3.2-py3-none-any.whl

Download URL beyond_local_file-0.3.2-py3-none-any.whl
Size 59.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f04f6957c2fc6b35ec29c2ec6718e6cb9057875dcd48aecbd77f6694e10f102a
BLAKE2b-256 checksum
How to use checksums
b568614fb561220d1a56a9f51e9a60a971937c4f0730f14e57d0da88fa56acee
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.

Transparency log

Release history Release notifications | RSS feed

0.5.0

2 release files

0.4.0

2 release files

This release

0.3.2 This release

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page