Synchronize markdown specifications between a git repo and external workspace.
Project description
SpecSync
Selective Markdown sync between your repo and any workspace folder.
SpecSync is a lightweight Python CLI that bridges your repo's ignored specs/ folder and an external workspace (e.g. an Obsidian vault, a Hugo content directory, or any notes folder).
It lets you pull only the Markdown files you choose (via frontmatter), keep them in sync in both directions, and work seamlessly with AI coding tools — so your specs stay organized without cluttering your codebase.
Features
- Frontmatter filtering – pull only notes with
expose: true(and matchingproject:if set). - Two-way sync – pull specs from workspace → repo or push changes back from repo → workspace.
- Safe by default – interactive prompts for conflicts,
--forceto skip prompts. - Flexible – works with any folder structure, not tied to Obsidian.
- Git-like workflow – familiar
pullandpushcommands.
Documentation
Quick Start
pipx install specsync
# or
uv tool install specsync
Set your workspace location using environment variables or direnv:
# Option 1: Direct export (temporary, current session only)
export SPECSYNC_WORKSPACE_ROOT="~/Documents/Obsidian"
# Option 2: Using direnv (recommended for project-specific config)
# Copy the example file and customize:
cp .envrc.example .envrc
# Edit .envrc with your workspace path, then:
direnv allow
Initialize in a repo (creates specs/ folder and updates pyproject.toml):
specsync init
Pull specs from your workspace into the repo's specs/ folder:
specsync pull
Push changes from the repo back to your workspace:
specsync push
Show current configuration:
specsync info
Configuration
SpecSync looks for configuration in this order:
- Command-line flags
- Environment variables (e.g.,
SPECSYNC_WORKSPACE_ROOT) pyproject.tomlunder[tool.specsync]
Using direnv for Local Configuration
For project-specific environment variables, create a .envrc file in your repo root:
# .envrc
export SPECSYNC_WORKSPACE_ROOT="/Users/you/Library/Mobile Documents/iCloud~md~obsidian/Documents/YourVault"
export SPECSYNC_REPO_SPECS_DIR="specs"
export SPECSYNC_PROJECT_NAME="my-project"
Then activate it:
direnv allow
Add .envrc to your .gitignore to keep local paths private:
echo ".envrc" >> .gitignore
Project Configuration
Example pyproject.toml:
[tool.specsync]
workspace_subdir = "specs" # Subdirectory in workspace
repo_specs_dir = "specs" # Directory in repo (git-ignored)
project_name = "my-project" # Optional, auto-detected if not set
[tool.specsync.filter]
require_expose = true # Only sync files with expose: true
match_project = true # Only sync files matching project name
Example Frontmatter
Mark specs for syncing with frontmatter:
---
expose: true # Required for syncing
project: my-project # Optional, must match if match_project is true
title: GPU Crash Fix
status: draft
---
# GPU Crash Investigation
...
Only notes with expose: true (and matching project when configured) are synced.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file specsync-0.1.0.tar.gz.
File metadata
- Download URL: specsync-0.1.0.tar.gz
- Upload date:
- Size: 10.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.22
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c48ec38870dfe7bb09b71039b05926a5a20620b1961e18fb465e5f0e30ec4d4
|
|
| MD5 |
eb9db603609ae47ef478c6896b043f63
|
|
| BLAKE2b-256 |
7a3488b3c96a9cfe727836eaadd98e5cb05b6b67d2c12b5d0f699fd264297332
|
File details
Details for the file specsync-0.1.0-py3-none-any.whl.
File metadata
- Download URL: specsync-0.1.0-py3-none-any.whl
- Upload date:
- Size: 15.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.22
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
95aa25efd94ac127ca29ee02d352f8ebdf807614b636f7b383c93ebd6f8212dc
|
|
| MD5 |
63b842b1581aff319f86cf4f9e624da1
|
|
| BLAKE2b-256 |
b3a2037c04d3bf48de38aabd6d0fdea2020653f8efd77b487a085402b75dee51
|