Skip to content

GitHub markdown sync

The save_md_to_github, read_md_from_github, list_md_from_github, and update_md_status tools store content as markdown files in a linked GitHub repo. Then deploy_md_to_site pulls a file and creates a draft on a target WP or Duda site.

This separates writing (a content team push) from publishing (a design or editor team pull + deploy). See Content + Design teams for the full role split.

  • GitHub App installed via /admin/github and linked to a repo with Contents:write permission
  • One or more sites with github_repo configured in /admin/sites
  • A token whose allowed_tools includes the GitHub markdown tools

Files live at <github_path_prefix>/posts/<YYYY-MM-DD>-<slug>.md (path prefix optional, configured per site). The path is yours — the worker doesn’t enforce, just stores wherever you tell it.

Frontmatter (YAML) is required. Minimum:

---
slug: my-post-slug
title: "Post title"
type: post # or "page"
---

Common extras:

status: ready-for-design # custom workflow state
author: "Alice"
created_at: 2026-06-01
tags: [seo, plugins, marketing]
categories: [tutorials]
excerpt: "One-line summary..."
target_site_suggestion: "viper-template"
save_md_to_github
site_id="<source-site-id>"
path="posts/2026-06-01-top-5-seo-plugins.md"
markdown="---\nslug: top-5-seo-plugins\ntitle: ...\nstatus: ready-for-design\n---\n\nBody..."
message="[content] add: top 5 SEO plugins"

Returns { repo, path, sha, commit_sha, html_url }. The worker validates the frontmatter has at least slug and title.

list_md_from_github
site_id="<source-site-id>"
status="ready-for-design"
limit=20

Walks the repo tree, opens each .md to read its frontmatter, returns only files matching the filter. Slow when you have hundreds of files — narrow with path_glob if so.

read_md_from_github
site_id="<source-site-id>"
path="posts/2026-06-01-top-5-seo-plugins.md"

Returns { repo, path, sha, frontmatter, body }. Pass the sha to subsequent update calls for concurrency safety.

update_md_status
site_id="<source-site-id>"
path="posts/2026-06-01-top-5-seo-plugins.md"
patch={
"status": "deployed",
"deployments": [
{ "site_id": "viper-template", "post_id": "142", "deployed_at": "2026-06-01T10:00Z" }
]
}

Merges the patch into existing frontmatter (set a field to null to remove it). Body is preserved verbatim.

deploy_md_to_site
source_site_id="<source-site-id>"
source_path="posts/2026-06-01-top-5-seo-plugins.md"
target_site_id="<target-wp-or-duda-site>"
page_builder="gutenberg"

Dispatches by frontmatter.type (postcreate_draft, pagecreate_page_draft). For WordPress, string tags/categories are auto-resolved to integer term IDs (creates missing terms). Target must be WP or Duda — Astro targets use create_astro_route directly.

  • Path may not contain .. or absolute prefixes
  • Frontmatter must parse as YAML
  • Workflow status field is freeform — the worker doesn’t enforce a state machine