How to Publish to Social Media from OpenCode
OpenCode can publish to social media through the Groniz Skill, remote MCP server, or CLI. It reads the source material in your project and prepares a draft. Groniz handles OAuth, per-platform formatting, scheduling,…
OpenCode can publish to social media through the Groniz Skill, remote MCP server, or CLI. It reads the source material in your project and prepares a draft. Groniz handles OAuth, per-platform formatting, scheduling, and delivery across 32+ networks.
Keep two decisions separate. First, approve the words, links, and assets. Next, have OpenCode identify the live integration, inspect its current settings, and show the complete request. Approve the external write and its publication time only after reviewing that request. Do not treat a completed draft as permission to post.
How the pieces fit together
Repository source
-> OpenCode extracts claims and links
-> OpenCode creates a channel-native draft
-> You review content and assets
-> OpenCode discovers the live Groniz schema
-> You approve publishing or scheduling
-> You verify on the destination
This workflow covers publishing. It can make a regular posting cadence easier to manage, but it cannot guarantee reach or engagement.
Prerequisites
You need:
- OpenCode in the project containing your source material.
- A Groniz account with either an API key or an authenticated local Groniz CLI session.
- At least one destination connected in Groniz.
- A source file such as
CHANGELOG.md,RELEASE.md, or an approved article. - Any media assets you intend to attach.
- An approval rule that distinguishes content approval from publication approval.
OpenCode discovers project skills from paths such as .agents/skills/<name>/SKILL.md. The Groniz Skill can therefore live with the project as part of a repeatable workflow. OpenCode can also use remote MCP servers configured under mcp. See the OpenCode skills documentation and OpenCode MCP server documentation for the client-side behavior.
Choose the OpenCode connection path
The Skill is the shortest route when OpenCode can run commands in your environment:
npx skills add groniz/groniz-cli
You can instead connect the remote MCP server in opencode.json:
{
"mcp": {
"groniz": {
"type": "remote",
"url": "https://mcp.groniz.com/mcp",
"enabled": true,
"headers": { "Authorization": "Bearer YOUR_API_KEY" },
},
},
}
Keep the real key out of committed configuration. Use your normal secret-loading setup to inject it at runtime.
The third path is the standalone native CLI:
curl -fsSL https://groniz.com/install.sh | sh
groniz auth:login
The login command uses a browser device flow. Once authenticated, OpenCode can invoke the local groniz binary.
All three paths use the same Groniz publishing layer. Pick one for the project so you can trace its authentication and failures without sorting through several setups.
Why source-first publishing works across channels
The roles stay the same across destinations. OpenCode inspects the exact release note, documentation change, or approved Markdown in the repository. Groniz exposes the current settings for the publishing account you select.
The draft still needs to suit its channel. A technical article may fit Dev.to or Hashnode. A concise progress note may work on X, while a professional reflection may belong on LinkedIn. You can use one source for several posts without copying the same text everywhere.
For the broader connector model, read Introducing Groniz Connectors. The companion guide to publishing Markdown to Dev.to and Hashnode with OpenCode covers long-form destinations. For another repo-native example, see turning a GitHub release into an X thread with Codex.
Prepare a source packet
Give OpenCode a specific set of evidence instead of the whole repository. A small social-source.md file is enough:
# Approved source
Release: v2.4.0
Audience: API users
Problem: retries previously required custom code
Change: retry policy is now configurable
Evidence: docs/retries.md and CHANGELOG.md
Link: https://example.com/releases/v2-4-0
Do not claim: lower latency or guaranteed delivery
Ask OpenCode to check every claim against the named files, flag contradictions, and omit unsupported details. A narrow engineering change should not turn into a broad marketing promise.
Reusable asset: a channel brief
Save this as .agents/social/channel-brief.md and fill it before each run:
# Channel brief
Destination:
Objective:
Reader:
Source files:
Required link:
Media files:
Tone:
One useful takeaway:
Claims that require verification:
Claims to exclude:
Publication mode: draft only | publish now | schedule
Approved publication time and timezone:
Then prompt OpenCode:
Read the source files and channel brief. Draft for the named destination,
using only supported claims. Preserve technical qualifiers. Return the draft,
a claim-to-source table, and a review checklist. Stop before any Groniz write
action. Draft approval is not publication approval.
For a release-driven post, the claim table should show whether each statement came from documentation, code, or inference. Keep inferences visible for review so they do not slip into the copy as facts.
Review the channel-native draft
Start with the substance. Check version numbers, product names, dates, links, customer claims, and limitations. Then read for the channel: inspect the opening line, paragraph length, hashtags or mentions, media crop, and whether the post makes sense without prior context.
Remove internal paths, confidential issue references, unreleased features, and invented quotes. Confirm that you have permission to use every image.
End the review with either revise or content approved. Content approval freezes the draft that can move to delivery preparation, but it does not grant permission to post.
Deliver through Groniz
For a Skill or CLI run, have OpenCode perform discovery in this order:
groniz whoami
groniz integrations:list
groniz integrations:settings <integration-id>
Treat the settings response as authoritative for required fields, current length limits, post types, and available dynamic integration tools. Invoke only the tools listed there. If the post includes media, upload each file first:
groniz upload ./approved-image.png
Use the returned .path in the post request, not the local filename or an external image URL. Then ask OpenCode to build a publish-now or scheduled request from the discovered schema. It should show the final destination, content, media paths, and time for approval. Dev.to, Hashnode, Discord, Telegram, X, and LinkedIn are supported destinations, though each has its own capabilities and settings.
For one reviewed target, the generic scheduling command is:
groniz posts:create \
-c "APPROVED_CONTENT_FOR_THIS_TARGET" \
-m "<returned-groniz-media-.path>" \
-s "2026-08-14T15:00:00Z" \
-t schedule \
-i "TARGET_INTEGRATION_ID" \
--settings '<required-settings-json>'
Replace the settings placeholder with every required value from the target's live response. The media value must be the .path returned by groniz upload. Repeat discovery for each additional destination, then build a new command with that integration's own settings. OpenCode should show every resolved command and wait for publication approval before running it.
Publication approval is the second decision. Check the account, destination, resolved content, media, settings, and ISO 8601 time. Approve either publish now or the exact scheduled time. A prior content approved decision alone does not authorize the command.
Verify delivery and handle failures
A returned post ID means that Groniz accepted the request. It does not prove that the destination published the post. Confirm the status, then open the destination URL if Groniz returns one. Check the native post's line breaks, links, media, account identity, and publication time.
When delivery fails, keep a compact record:
- Integration ID:
- Requested time/timezone:
- Source revision:
- Returned post ID:
- Error or final status:
- Settings refreshed after error: yes/no
- Retry approved by:
Refresh integrations:settings before changing the request. Common causes of failure include expired authorization, a field omitted from the live schema, content over the current limit, an unsupported post type, a media upload problem, or a timezone mistake.
Before retrying, find out whether the first request created a post or remains pending. If the outcome is unclear, keep the post ID and inspect its status instead of issuing a second write. Require new publication approval if a retry changes the content, destination, media, settings, or time.
Measure the next iteration
Use the destination's native analytics and read the replies. Record impressions or views, meaningful responses, and clicks when the destination provides them. Analytics coverage and metric definitions vary by provider, so do not combine unlike metrics into a single cross-platform score.
Compare similar posts over time. One result cannot establish the best time or a winning format, and this workflow does not provide autonomous optimization. Save the source brief, final approved draft, publication time, observations, and one editorial change to test. That gives the next OpenCode run a concrete decision instead of a vague instruction to "perform better."
To set up the publishing layer, connect an account and create an API key in Groniz Connectors.