Document Sync
Document sync keeps local markdown folders synchronized with Postgram entities.
It is designed for notes, knowledge bases, exported docs, and git repositories
where .md files are the source of truth.
What this page covers
Section titled “What this page covers”How to sync a folder of markdown files, how to schedule sync with cron, how to pull a git repository before syncing, and what the manifest protocol does.
Core workflow
Section titled “Core workflow”- Configure the CLI:
export PGM_API_URL=http://127.0.0.1:3100export PGM_API_KEY=your-api-key- Preview a sync before uploading anything:
pgm sync ~/Documents/personal-notes --repo personal-notes --dry-run- Sync the folder:
pgm sync ~/Documents/personal-notes- Use a stable repository name when the folder name is not enough:
pgm sync ~/Documents/notes --repo notes --quietWhat gets synced
Section titled “What gets synced”pgm sync <dir> walks the directory recursively and sends only markdown files
ending in .md. Relative file paths become the document identity inside the
repository, so renaming a file is treated as one deleted document and one new
document.
The walker skips:
.git,node_modules,.obsidian, and.trash- hidden directories such as
.cache - any directory containing
.pgmignoreor.noindex
Each file is hashed locally. Postgram asks only for files whose hash is new or changed, so repeated syncs are cheap.
Scheduling with cron
Section titled “Scheduling with cron”Cron runs with a minimal environment, so set PGM_API_URL, PGM_API_KEY, and
PATH in the crontab or in the script it calls.
SHELL=/bin/zshPATH=/opt/homebrew/bin:/usr/local/bin:/usr/bin:/binPGM_API_URL=https://<your-postgram-host>PGM_API_KEY=<your-api-key>
*/15 * * * * flock -n /tmp/postgram-notes-sync.lock /path/to/sync-postgram-notes.sh >> /path/to/postgram-sync.log 2>&1The flock wrapper prevents overlapping runs when a sync takes longer than the
cron interval. If your system does not provide flock, run the script less
frequently or use the locking tool available on that host.
Git-backed markdown folder
Section titled “Git-backed markdown folder”Use a small shell script when the markdown folder is a git checkout. The script fetches the latest default branch, syncs only after a successful fast-forward, and keeps cron logs useful.
#!/usr/bin/env bashset -euo pipefail
export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"export PGM_API_URL="${PGM_API_URL:-https://<your-postgram-host>}"export PGM_API_KEY="${PGM_API_KEY:?PGM_API_KEY is required}"
REPO_DIR="${REPO_DIR:-$HOME/Documents/notes}"POSTGRAM_REPO="${POSTGRAM_REPO:-notes}"BRANCH="${BRANCH:-main}"
cd "$REPO_DIR"
git fetch --prune origin "$BRANCH"git merge --ff-only "origin/$BRANCH"
pgm sync "$REPO_DIR" --repo "$POSTGRAM_REPO" --dry-run --jsonpgm sync "$REPO_DIR" --repo "$POSTGRAM_REPO" --quietFor a cron job, call the script with any overrides inline:
PGM_API_URL=https://<your-postgram-host>PGM_API_KEY=<your-api-key>
0 * * * * REPO_DIR=/path/to/notes POSTGRAM_REPO=notes /path/to/sync-postgram-notes.sh >> /path/to/postgram-notes.log 2>&1Remove the dry-run line if you do not need a preview summary in the cron log.
Sync protocol
Section titled “Sync protocol”The CLI uses the same sync API that other clients can use directly:
POST /api/sync/diffcompares local paths and SHA-256 hashes with the server.- Batched
POST /api/sync/uploadsends only new or changed files. POST /api/sync/finalizearchives server-side documents that disappeared from the latest manifest.
Check repository state:
curl http://127.0.0.1:3100/api/sync/status/personal-notes \ -H "Authorization: Bearer $PGM_API_KEY"- Use stable
--reponames. Changing the repo name creates a separate document namespace. - Keep generated directories out of the tree or add
.pgmignoreto directories that should never be indexed. - Use
--dry-runfor safe validation before upload. - Batches are capped at 50 files or 4 MiB of markdown content to protect large payload size.
- If
PGM_API_URLpoints through a reverse proxy, make sure that proxy allows request bodies larger than the upload batch size. The bundled UI nginx proxy usesclient_max_body_size 64m; other proxies need an equivalent setting. - Keep
PGM_API_KEYout of the repository and crontab logs. Use a dedicated, minimally scoped sync key where possible.