A Rust CLI for syncing Markdown documents with external providers.
Initial providers:
- Google Docs
- Linear Docs
The goal is to keep .md as the local source of truth and make cross-linking between platforms easier.
dsync supports:
- sync a local
.mdfile to Google Docs and Linear, creating documents when they do not exist yet - import a Google Doc into
.md - import a Linear Doc into
.md - keep cross-links automatically updated:
- Google Docs <-> Linear
- plus the file link in Git when the file is inside a git repository
curl -fsSL https://raw.githubusercontent.com/feliperbroering/dsync/main/install.sh | bashThe installer tries to download the latest matching GitHub release for your platform first. If that asset is not available yet, it falls back to building from source with Cargo.
Useful overrides:
curl -fsSL https://raw.githubusercontent.com/feliperbroering/dsync/main/install.sh | bash -s -- --version v0.1.0
curl -fsSL https://raw.githubusercontent.com/feliperbroering/dsync/main/install.sh | DSYNC_INSTALL_DIR="$HOME/bin" bashgit clone https://github.com/feliperbroering/dsync.git
cd dsync
cargo install --path .This makes the dsync binary available in the Cargo PATH.
Once releases are published, download the executable and place it in your PATH.
GitHub Actions now validates prebuilt release archives for:
x86_64-unknown-linux-gnuaarch64-unknown-linux-gnux86_64-apple-darwinaarch64-apple-darwin
Versioning and GitHub Release orchestration are handled with release-please.
Set the API token:
export LINEAR_API_KEY="lin_api_..."The CLI currently expects a pre-issued bearer token:
export GOOGLE_ACCESS_TOKEN="ya29...."There is also a template file:
cp .env.example .envExpected minimum token scopes:
https://www.googleapis.com/auth/documentshttps://www.googleapis.com/auth/drive
Next project step: a native OAuth flow inside the CLI.
dsync ~/test/doc.md --gdoc --linearBehavior:
- if
gdocUrldoes not exist in frontmatter and--gdocis used, it creates a Google Doc - if
linearDocIdorlinearDocUrldoes not exist and--linearis used, it creates a Linear Doc - prompts interactively for:
- Drive folder ID (optional)
- Linear team/project
dsync --gdoc <GDOC_ID>dsync --linear <LINEAR_DOC_ID>Expected resulting example:
---
gdocUrl: "https://docs.google.com/document/d/<DOC_ID>/edit"
linearDocUrl: "https://linear.app/<workspace>/document/<DOC_ID>/<slug>"
linearDocId: "<DOC_ID>"
gitUrl: "https://github.com/<org>/<repo>/blob/<branch>/docs/file.md"
---The project is structured to support additional providers easily:
- Notion (future)
- Evernote (future)
- other repositories and document stores
Evolution strategy:
- abstract the provider interface
- implement read/write support for each provider
- keep cross-links and frontmatter as the stable contract
Short-term roadmap:
- Google provider with native OAuth (no manual token)
- Provider Notion
- Provider Evernote
- do not commit tokens to the repository
- use environment variables
- prefer tokens with the smallest possible scope
MIT