Write once, publish

A draft lives in one plain-text file in your repository. Syndroo reads that file and publishes it to Bluesky, Threads, LinkedIn, and Mastodon, and articles to DEV.to, from your terminal.

v0.7.0-rc.1 · unpublished release candidate · live-account acceptance pending

One draft.
Multiple destinations.

Publish from one document: plain text to Bluesky and Threads, plain text from a personal LinkedIn profile, public Mastodon statuses, and public personal DEV.to articles. A request is strict JSON: content.text carries the text once and targets names each destination, with optional per-target options for the platforms that need them. An article target carries its own title and body_markdown options.

LinkedIn personal · Mastodon public · DEV.to public articles

Publish

Write a request

A request is a small JSON file you keep next to your project. content is the text and targets names where it goes.

Input fileExample

post.json

{
  "content": { "text": "One document, chosen targets." },
  "targets": [{ "provider": "bluesky" }, { "provider": "linkedin" }]
}

Preview before sending

A dry run freezes and validates the request, then stops. It is optional and read-only: no network request, no credentials resolved, no local state.

Dry runIllustrative
dry run

$ syndroo publish --input post.json --dry-run --json

Dry run · no network requests · no local stateRead the printed text and target account before continuing. Preparing a later request freezes the input it read at that moment.

Publish with intent

Publishing is two phases. Preparing freezes the content and returns a single-use approval token; executing consumes that token and sends exactly the frozen preview.

SendIllustrative
publish

$ syndroo publish --input post.json

frozen preview · one approval token · nothing sent yet

$ syndroo publish --input - < execute.json

Editing the file after preparing does not change what gets sent.The execute phase can only be read from standard input.

Inspect the result

The publish result carries an operation id. Reading it back is a read-only query, and it never contacts a platform: syndroo status --operation <operationId>.

StatusIllustrative
status

$ syndroo status --operation <operationId> --json

operationId  <operationId>
status       succeeded
per target   deliveryId · attempts · outcome
An unknown outcome is reported as unknown and is never retried automatically. Live-account acceptance is still pending for this release candidate.

Local by design

Your draft is a file on your disk. Syndroo reads it when you run it, and sends it with the credentials you already have. What happens is whatever the last command you typed did.

  • Runs as a commandInstalled by building this repository, not from a registry.
  • Direct local pathThe local CLI talks to platform APIs without a Syndroo service in between.
  • Optional self-hostingThreads workflows can run on a deployment in your own Cloudflare account.

Your workflow,
your terminal.

No dashboard, no browser tab to keep open. Edit a file, run a command, read the result. Your editor, your shell, and your own platform credentials stay in charge.

See the commands
illustrative

$ $EDITOR post.json

$ syndroo publish --input post.json --dry-run --json

dry run · no network requests · no local state

$ syndroo publish --input post.json

frozen · awaiting confirmation · posts to bluesky, linkedin

$ syndroo status --operation <operationId> --json

FAQ

Where this release candidate stands, and the questions that come up most.

Is Syndroo released yet?
Not yet. 0.7.0-rc.1 is an unpublished release candidate, and live-account acceptance is still pending. There is no registry install today, so the way to run it is to build it from source.
Which platforms does it publish to?
Five official providers. Bluesky, Threads, LinkedIn and Mastodon publish text; DEV.to publishes articles. A request carries the content once and a targets list that names the providers and, when it matters, the connection and the provider options.
Where do my credentials live?
On your machine, never in the publish request. A connection reads its credentials once, from the environment variable SYNDROO_CREDENTIALS or from a private file you own, and the local credential store keeps them after that. Publishing never re-reads the environment or the file.
What does the dry run actually do?
syndroo publish --input post.json --dry-run --json freezes and validates the request, prints the preview, then exits. It is optional and read-only: no write lock, no credentials resolved, no network request, and no local state.
What gets sent when I publish?
The content is frozen when the request is prepared. Confirming sends exactly that frozen preview, so editing the file afterwards cannot change what goes out — and a later prepare is a new request with its own identity.
Can I prepare and publish in one command?
Yes. syndroo publish --input post.json --yes --json prepares, confirms and executes in one call and prints exactly one final envelope, with no second prepared result and no approval token. Without --yes the same --json call returns the prepared result and sends nothing.
Is there a Syndroo server involved?
The local path talks to platform APIs directly from your machine. For Threads, you can deploy Syndroo's server to your own Cloudflare account, connect an account, and publish manually or from GitHub CI. The SDK remains outside this documentation.
How do I check what a run did?
syndroo status --operation <operationId> --json reports the operation and one delivery per target. A delivery is succeeded, failed with a not-applied disposition, unknown, or not sent when the target never started; an unknown write is never retried automatically.

Ready to get started

Build the release candidate from source, then publish your first post from the terminal.

v0.7.0-rc.1 · unpublished release candidate · build from source · live-account acceptance pending