SyncDocs 0.13.0-alpha.3

This is a prerelease version of SyncDocs.
dotnet tool install --global SyncDocs --version 0.13.0-alpha.3
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local SyncDocs --version 0.13.0-alpha.3
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=SyncDocs&version=0.13.0-alpha.3&prerelease
                    
nuke :add-package SyncDocs --version 0.13.0-alpha.3
                    

SyncDocs

Keep your README and docs site in sync. SyncDocs copies marked sections from your README files into your docs/ folder to help prevent documentation from going stale.

Status: early alpha, and substantially AI-written. Runs the author's own F# OSS repos daily, but behavior and flags shift between versions and rough edges are expected — your mileage may vary. Issues and PRs welcome.

How It Works

  1. You add HTML comment markers around sections in your README that should be synced.
  2. You add matching markers in your docs target files.
  3. Run syncdocs sync to copy content from README to docs, or syncdocs check in CI to catch drift.

SyncDocs discovers sync pairs by convention -- no configuration file needed.

Installation

dotnet tool install -g SyncDocs

Usage

Sync docs from READMEs

syncdocs sync

Output:

  README.md -> docs/index.md: updated
  src/MyLib/README.md -> docs/MyLib/index.md: in sync

Check sync status (CI)

syncdocs check

Exits with code 0 if everything is in sync, 1 if any pair is out of sync. Use this in CI to catch forgotten doc updates.

Marking Sections

In your README (source)

Wrap the content you want to sync with a pair of HTML comment markers:

  • Start marker: ``
  • End marker: ``

Replace SECTION-NAME with any name for your section.

For example, to sync a section called "usage", you would put this in your README:

  • Line 1: ``
  • Lines 2+: Your content (any markdown)
  • Last line: ``

Everything between the start and end markers will be copied to the matching target.

In your docs file (target)

Add matching markers where the synced content should appear. Note that the target start marker omits :start:

  • Start marker: `` (no :start)
  • End marker: ``

When you run syncdocs sync, the content between the target markers is replaced with the content from the matching source markers.

Section names

Section names can contain letters, numbers, underscores, and hyphens. They must start with a letter or underscore:

  • usage -- valid
  • getting-started -- valid
  • step_2 -- valid

Multiple sections

You can have as many synced sections as you like in a single file. Content between sections is not synced, so you can have README-only content that doesn't appear in docs.

Full-file sync

If your README has no sync markers at all, SyncDocs copies the entire file content to the target. This is useful for per-project READMEs that should be mirrored exactly in docs.

Code-Sourced Blocks (drift-proof snippets)

A README code block can be sourced from a region of a real, compiled .fs/.fsx file. The snippet then can't reference a non-existent API without breaking your build, and syncdocs check fails CI the moment the rendered snippet stops matching the code.

In your README (source)

Add a src= attribute to the start marker, pointing at a file (relative to the repo root). The region defaults to the block name; append #region-name to override it. For example, replacing START / END below with real `` HTML comment markers:

[START] sync:plugin-example:start src=examples/Foo/Snippets.fs [END]
```fsharp
(this gets regenerated from the file)
```
[START] sync:plugin-example:end [END]

In your .fs/.fsx file (the region)

Delimit the region with comment markers that reuse the same vocabulary:

// sync:plugin-example:start
let example = Foo.create "hello"
// sync:plugin-example:end

The lines between the markers (the marker lines themselves are excluded) become the block body, with the common leading indentation stripped, wrapped in a ```fsharp fence.

Live example (dogfooded)

SyncDocs uses this feature on its own README. The block below is sourced from a region of src/SyncDocs/Sync.fs, so it can never drift from the real type definitions:

type SyncMode =
    | Check
    | Apply

type SyncOutcome =
    | InSync
    | OutOfSync
    | Updated

Standalone docs (guides, not just READMEs)

Code-sourced blocks aren't limited to README pair-sources. Any markdown file under the repo root that carries a src= block — a guide like docs/writing-plugins.md, say — is refreshed and verified in place, with no docs/ target needed. So a hand-written guide can embed a snippet straight from compiled code and syncdocs check will fail the moment it drifts.

The scan skips build, VCS, and vendor directories (bin, obj, .git, .jj, node_modules, .workspaces, output, artifacts, .fsdocs), and a file that is already a pair source (such as README.md) is processed once, never twice.

How it fits the sync chain

syncdocs sync runs in two stages: first it refreshes each code-sourced block from its file region — for a README pair-source this happens before the README is propagated to docs/, so docs pick up the refreshed snippet in a single run; standalone docs are refreshed directly. Then it propagates README sources to docs/ as usual. syncdocs check reports drift (non-zero exit) if any code-sourced block is stale, and fails loudly on a missing file, a missing/duplicated region marker, or an unterminated region.

Blocks without a src= attribute behave exactly as before.

Pair Discovery Convention

SyncDocs automatically finds sync pairs based on file location:

Source Target
README.md docs/index.md
src/MyLib/README.md docs/MyLib/index.md
src/OtherTool/README.md docs/OtherTool/index.md

Both the source and target file must exist for the pair to be discovered. If only one side of a pair exists, SyncDocs prints a helpful warning telling you which file to create:

  Warning: To sync docs for MyLib, create docs/MyLib/index.md

Example Workflow

  1. Edit your README.md with the latest usage instructions.
  2. Run syncdocs sync to push changes to docs/.
  3. Commit both files.
  4. In CI, run syncdocs check to ensure nobody forgets step 2.

License

MIT

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
0.13.0-alpha.3 83 6/16/2026
0.13.0-alpha.2 114 5/26/2026
0.13.0-alpha.1 105 4/27/2026
0.12.0-alpha.3 82 4/22/2026
0.12.0-alpha.2 109 4/15/2026
0.12.0-alpha.1 84 4/13/2026
0.11.0-alpha.1 87 4/13/2026
0.10.0-alpha.3 99 4/11/2026
0.10.0-alpha.1 88 4/8/2026
0.9.0-alpha.1 74 4/8/2026
0.8.0-alpha.4 84 4/8/2026
0.8.0-alpha.3 67 4/8/2026
0.8.0-alpha.1 74 4/8/2026
0.3.0-alpha.1 87 4/7/2026
0.2.0-alpha.1 102 4/7/2026
0.1.0-alpha.1 115 4/6/2026