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
Metadata
Release files for specsync 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| specsync-0.1.0.tar.gz | 10.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| specsync-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.2 kB
Release files / specsync-0.1.0.tar.gz
| Download URL | specsync-0.1.0.tar.gz |
|---|---|
| Size | 10.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7c48ec38870dfe7bb09b71039b05926a5a20620b1961e18fb465e5f0e30ec4d4
|
|
BLAKE2b-256 checksum How to use checksums |
7a3488b3c96a9cfe727836eaadd98e5cb05b6b67d2c12b5d0f699fd264297332
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.22
|
Release files / specsync-0.1.0-py3-none-any.whl
| Download URL | specsync-0.1.0-py3-none-any.whl |
|---|---|
| Size | 15.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
95aa25efd94ac127ca29ee02d352f8ebdf807614b636f7b383c93ebd6f8212dc
|
|
BLAKE2b-256 checksum How to use checksums |
b3a2037c04d3bf48de38aabd6d0fdea2020653f8efd77b487a085402b75dee51
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.22
|