Work in progress — has not been tested end-to-end in all scenarios. Issues and feedback are welcome.
A Python replacement for the Ruby voog-kit.
Manage Voog CMS site templates and design assets directly via the REST API.
Why?
- Fixes the hyphen bug — the Ruby kit silently fails to pull any layout whose
layout_namecontains hyphens, a common naming pattern. This tool calls the API directly, so every file is handled correctly. - Proper git tracking — every pull and push is automatically committed to git, giving you real diff history, easy rollback, and change detection for push.
- No Ruby required — no gem/bundle/rbenv toolchain needed. Just Python 3.11+ (stdlib only, zero dependencies). Works on Windows and macOS.
- Pull all layouts, components, CSS, JS, images and fonts in one command
- Push locally modified files back to the server (layouts + text assets)
- Conflict detection — push warns when the server has changed since your last pull
- Manifest-scoped git — only Voog-tracked files are committed; developer files are ignored
pyvoog checkcompares local files against the server without changing anythingpyvoog newcreates new layouts/assets on the server from local filespyvoog manifestinspects the remote file structure- Partial pulls:
pyvoog pull layoutsorpyvoog pull assets - Dry-run mode for both pull and push
- Multi-site support via
--siteflag
-
Clone this repo into any directory (it lives separately from your site repos):
git clone https://github.com/Robothead-eu/pyvoog.git
-
Set up a shell alias (optional but recommended):
Windows (PowerShell profile):
function pyvoog { python "C:\path\to\pyvoog\pyvoog.py" @args }
macOS / Linux (~/.bashrc or ~/.zshrc):
alias pyvoog="python ~/path/to/pyvoog/pyvoog.py"
-
Python 3.11+ must be on your PATH. Verify:
python --version
# 1. Create a new site directory
pyvoog init ./my-site --host mysite.voog.com --token YOUR_API_TOKEN
# 2. Pull everything
cd ./my-site
pyvoog pull
# 3. Edit files locally, then push changes
pyvoog push
# 4. Check sync status at any time
pyvoog checkcd /path/to/existing-site
pyvoog init --host mysite.voog.com --token YOUR_API_TOKEN
pyvoog pullInitialise a site directory.
pyvoog init --host mysite.voog.com --token abc123
pyvoog init ./my-site --host mysite.voog.com --token abc123Creates:
.voog— site config (kept out of git via.gitignore).gitignore— excludes.voogand cache files.git/— git repository (for undo/history)
Pull files from the server. The server is always the source of truth.
pyvoog pull # pull everything (layouts + assets)
pyvoog pull layouts # only .tpl files (layouts + components)
pyvoog pull assets # only CSS, JS, images, fonts
pyvoog pull --dry-run # see what would change, without writing
pyvoog pull --reset # also remove orphaned local .tpl filesAfter a successful pull, changed files are automatically committed to git. Only manifest-tracked files are staged — developer files in the same directories are left untouched.
Push locally modified files to the server.
pyvoog push # push all changed manifest-tracked files
pyvoog push layouts/page.tpl # push a specific file
pyvoog push stylesheets/main.css # push a CSS file
pyvoog push --dry-run # see what would be pushedHow push works:
- Detects changed files via
git diff HEAD - Filters to only files present in
manifest.json(developer files are ignored) - Checks the server for conflicts (
updated_atcomparison) - Uploads safe files; warns and skips conflicting ones
- Auto-commits pushed files to git
What can be pushed:
- Layouts and components (
.tplfiles) - Text assets: CSS and JavaScript files
Not supported (yet):
- Binary assets (images, fonts) — these must be uploaded via the Voog editor
Compare local files against the server without changing anything.
pyvoog check
pyvoog check --verboseReports:
- Missing — on server, not local
- Modified — local file differs from server
- Extra — local file, not on server
- In sync — matches server exactly
Fetch and display the remote file structure.
pyvoog manifest # show summary
pyvoog manifest --verbose # show full file list
pyvoog manifest --save # write manifest.json to site directoryShow site info, manifest summary, and last git commit.
pyvoog statuspyvoog help
pyvoog help pull
pyvoog help pushCreate new layouts or assets on the Voog server from local files. The file must already exist locally.
pyvoog new layouts/blog.tpl # create a new layout (defaults to content_type=page)
pyvoog new components/sidebar.tpl # create a new component
pyvoog new stylesheets/custom.css # create a new CSS asset
pyvoog new layouts/blog.tpl --type blog # override content_type for special layoutspyvoog new --all # find all local-only files, confirm, then create
pyvoog new --all --dry-run # preview what would be createdpyvoog new --list # list local files not yet on the serverHow it works:
- File type is inferred from the directory (
layouts/→ page layout,components/→ component,stylesheets/→ CSS asset, etc.) - For
--all: fetches server state, compares against local files, shows the list, and asks fory/Nconfirmation - Creates via POST to the Voog API
- Updates
manifest.jsonwith new server IDs and timestamps - Auto-commits to git
The .voog file is INI-style, compatible with the Ruby voog-kit:
[mysite.voog.com]
host=mysite.voog.com
api_token=your_api_token_here
protocol=httpsNever commit .voog — it contains your API token. The pyvoog init command adds it to .gitignore automatically.
In the Voog admin panel: Settings → Integrations → API (or similar — the exact path varies by Voog version).
You can have multiple sections in .voog and switch between them with --site:
[staging.voog.com]
host=staging.voog.com
api_token=token_a
[production.voog.com]
host=production.voog.com
api_token=token_bpyvoog pull --site staging.voog.com
pyvoog pull --site production.voog.compyvoog creates/pulls files into this structure (same as the Ruby kit):
site-dir/
├── .voog ← config (not in git)
├── .gitignore
├── manifest.json ← updated on every pull/push
├── layouts/ ← page layouts (.tpl)
├── components/ ← reusable components (.tpl)
├── stylesheets/ ← CSS files
├── javascripts/ ← JS files
├── images/ ← image assets
└── assets/ ← other assets (fonts, SVGs, etc.)
| Flag | Description |
|---|---|
--verbose / -v |
Show API calls, file writes, and git operations |
--site NAME |
Use a named .voog section (multi-site) |
--version |
Print version and exit |
cd ~/path/to/pyvoog
git pull- Keep your existing site directory as-is
- Run
pyvoog init --host your.voog.com --token YOUR_TOKENinside it - Run
pyvoog pull— all files are re-pulled reliably (including those with hyphens in filenames that the Ruby kit missed) - The Ruby kit is no longer needed
No .voog config file found
Run pyvoog init --host YOUR_HOST --token YOUR_TOKEN in your site directory.
Authentication failed (401)
Your API token in .voog is invalid or expired. Get a new one from the Voog admin panel.
HTTP 404
The site hostname in .voog is wrong. Check the host= line.
CONFLICT — server was modified after last pull
Someone edited the file on the server since your last pyvoog pull. Run pyvoog pull to sync, then re-apply your local changes.
Files with hyphens not pulling with the Ruby kit
This is a known Ruby kit bug. Use pyvoog pull instead — it calls the API directly.
Git not found
Install git or add it to your PATH. The tool still works without git — you just won't get auto-commits or change detection for push.
MIT