@rolino/cli
v0.10.0
Published
Agent-friendly command-line interface for Rolino
Maintainers
Readme
@rolino/cli
The rolino command-line interface for people, scripts, and coding agents.
Its stable machine mode keeps result data on stdout and diagnostics on stderr.
Network requests go through @rolino/sdk, which uses the Node.js native
fetch implementation; the CLI does not depend on Axios or another HTTP
client package.
Installation
The supported installation keeps the CLI independent from MCP:
npm install --global @rolino/cliUsers who need local STDIO MCP will install both packages explicitly:
npm install --global @rolino/cli @rolino/mcpThe default rolino setup mcp mode checks the selected Rolino instance. It
uses hosted Streamable HTTP when the instance advertises it. This mode does
not need @rolino/mcp. If remote MCP is not available, the command uses local
STDIO and explains how to install the separate MCP package. Rolino never
downloads or installs MCP silently.
Initial commands:
rolino auth login
rolino auth status
rolino auth logout
rolino setup mcp --client codex [--transport auto|http|stdio] [--scope user|project]
rolino setup mcp --client claude-code [--transport auto|http|stdio] [--scope user|project]
rolino whoami
rolino projects create --name NAME [--type PRODUCT|SERVICE|PERSONAL|COMPANY] [--website URL] [--description TEXT] [--idempotency-key KEY] --yes
rolino projects list [--limit 50] [--cursor ID]
rolino projects show PROJECT_ID
rolino backlinks targets list --project PROJECT_ID
rolino backlinks targets add --project PROJECT_ID --url URL --label LABEL
rolino backlinks discover --project PROJECT_ID --limit 20
rolino backlinks runs get --project PROJECT_ID --run RUN_ID
rolino backlinks prospects list --project PROJECT_ID [--stage STAGE]
rolino backlinks prospects get --project PROJECT_ID --prospect PROSPECT_ID
rolino backlinks prospects approve --project PROJECT_ID --prospect PROSPECT_ID --expected-version VERSION
rolino backlinks contacts research --project PROJECT_ID --prospect PROSPECT_ID
rolino backlinks contacts list --project PROJECT_ID
rolino backlinks contacts export --project PROJECT_ID --format csv
rolino backlinks outreach update --project PROJECT_ID --prospect PROSPECT_ID --file DRAFT.json --expected-version VERSION
rolino backlinks verify --project PROJECT_ID --prospect PROSPECT_ID --url PUBLIC_URL --expected-version VERSION
rolino media list --project PROJECT_ID [--type IMAGE|VIDEO] [--query TEXT] [--limit 50] [--cursor ID]
rolino media upload FILE_PATH --project PROJECT_ID --yes
rolino posts create --project PROJECT_ID --caption TEXT [--platform INSTAGRAM|TIKTOK|YOUTUBE|BLUESKY|LINKEDIN|GOOGLE_BUSINESS_PROFILE] [--media ASSET_ID] --yes
rolino posts update POST_ID --project PROJECT_ID --expected-version VERSION [--caption TEXT] [--platform INSTAGRAM|TIKTOK|YOUTUBE|BLUESKY|LINKEDIN|GOOGLE_BUSINESS_PROFILE] [--media ASSET_ID] [--clear-platforms] [--clear-media] --yes
rolino posts list --project PROJECT_ID [--limit 50] [--cursor ID] [--status STATUS]
rolino posts show POST_ID --project PROJECT_ID
rolino posts readiness POST_ID --project PROJECT_ID
rolino posts schedule preview POST_ID --project PROJECT_ID --expected-version VERSION --at ISO_DATE --timezone IANA_TIMEZONE
rolino posts schedule execute POST_ID --project PROJECT_ID --expected-version VERSION --at ISO_DATE --timezone IANA_TIMEZONE --confirmation-token TOKEN [--idempotency-key KEY]
rolino posts publish preview POST_ID --project PROJECT_ID --expected-version VERSION --platform INSTAGRAM|TIKTOK|YOUTUBE|BLUESKY|LINKEDIN|GOOGLE_BUSINESS_PROFILE
rolino posts publish execute POST_ID --project PROJECT_ID --expected-version VERSION --platform INSTAGRAM|TIKTOK|YOUTUBE|BLUESKY|LINKEDIN|GOOGLE_BUSINESS_PROFILE --confirmation-token TOKEN [--idempotency-key KEY]
rolino integrations health --project PROJECT_ID
rolino integrations delivery-options --project PROJECT_ID --provider TIKTOK|LINKEDIN
rolino calendar list --project PROJECT_ID [--from ISO_DATE --to ISO_DATE] [--limit 50] [--cursor CURSOR]
rolino seo opportunities list --project PROJECT_ID [--limit 20] [--cursor CURSOR] [--kind KIND] [--impact HIGH|MEDIUM|LOW]
rolino seo opportunities show OPPORTUNITY_ID --project PROJECT_ID
rolino seo reports list --project PROJECT_ID [--limit 10] [--cursor CURSOR] [--status COMPLETE|PARTIAL]
rolino seo reports show REPORT_ID --project PROJECT_ID
rolino blog destinations providers --project PROJECT_ID
rolino blog destinations list --project PROJECT_ID
rolino blog destinations deliveries --project PROJECT_ID [--article ARTICLE_ID]
rolino blog images generate ARTICLE_ID --project PROJECT_ID --revision REVISION_ID
rolino blog images upload ARTICLE_ID FILE --project PROJECT_ID --revision REVISION_ID --alt-text TEXT
rolino blog images review ARTICLE_ID IMAGE_ID --project PROJECT_ID --decision APPROVED|REJECTED --expected-version VERSION [--alt-text TEXT]
rolino blog approve preview ARTICLE_ID --project PROJECT_ID --revision REVISION_ID
rolino blog approve execute ARTICLE_ID --project PROJECT_ID --revision REVISION_ID --confirmation-token TOKEN --idempotency-key KEY --yes
rolino blog schedule preview ARTICLE_ID --project PROJECT_ID --revision REVISION_ID --at ISO --timezone IANA [--destination ID...]
rolino blog schedule execute ARTICLE_ID --project PROJECT_ID --revision REVISION_ID --at ISO --timezone IANA --confirmation-token TOKEN --idempotency-key KEY --yes
rolino blog schedule cancel preview ARTICLE_ID --project PROJECT_ID
rolino blog schedule cancel execute ARTICLE_ID --project PROJECT_ID --confirmation-token TOKEN --idempotency-key KEY --yes
rolino doctorInteractive login uses standard OAuth Authorization Code with PKCE S256. It
opens the configured Rolino instance, requests the exact `/api/v1` resource,
uses the fixed `http://127.0.0.1:48391/oauth/callback` redirect, and obtains
explicit workspace approval.
The approval screen always includes identity and workspace reads and lets the
user independently opt into project creation, draft writing, confirmed
scheduling, confirmed immediate publishing, and read-only SEO Intelligence.
The SEO option explains that it permits reading opportunities, evidence,
complete tasks, and weekly reports. It cannot run analysis or change SEO settings.
Opportunity detail prints the exact decision, selected format, target,
deliverables, research, safe URLs, separate topic-relevance and action-readiness
confidence, limitations, and no-publish rules. A Ready
task can request complete final deliverables for review. A Research task must
select only RESEARCH_TASK, compare all reasonable formats without a preferred
final format, and return VALIDATED with a complete next task or REJECTED
with evidence. It cannot create a final draft in the same action.
Optional permissions start off,
and existing credentials never gain a newly selected permission. Revoke and
reauthorize an existing connection to grant project creation or seo:read.
Existing grants never receive seo:read automatically. OAuth tokens never
pass through a browser URL. The CLI stores a short-lived access token and a
rotating refresh token by host, issuer, client, and resource in the
operating-system configuration directory. It does not read or migrate the old
interactive credential, so the first use after this cutover requires sign-in;
ROLINO_CONFIG_DIR overrides that location. auth logout revokes the calling
workspace grant and OAuth refresh token before deleting its local copy.
The terminal waits five minutes for browser approval. If that request expires,
close the old approval page and run rolino auth login again; refreshing the
page cannot restart the closed loopback listener.
setup mcp checks /api/v1/meta and prefers hosted Streamable HTTP when it is
available. Remote setup writes the /mcp URL and OAuth mode, does not start a
local MCP process, and does not reuse rolino auth login. For Codex, it leaves
OAuth client registration and the loopback callback to Codex so Codex can use
Rolino's advertised Client ID Metadata Document support. Run codex mcp login
rolino after remote Codex setup. Use --transport http to
require remote MCP or --transport stdio to require the local package and its
shared CLI OAuth session. The command previews the exact token-free
configuration and asks before changing anything. User scope is the default.
Codex configuration is written to CODEX_HOME/config.toml or
~/.codex/config.toml; Claude Code user scope is applied through its official
CLI. Project scope writes .codex/config.toml or .mcp.json in the current
directory. Existing file-backed configuration is backed up with a
.rolino-backup suffix. Use --dry-run to preview in scripts and --yes to
provide explicit non-interactive consent; --agent never implies consent.
An orphan Rolino-managed marker left by an earlier removal is repaired without
changing unrelated Codex settings.
Draft creation and update never schedule or publish. Updates change only the
fields supplied; omitted media, destinations, captions, and provider settings
are preserved. Both require interactive
confirmation or --yes; non-interactive and agent-mode calls fail before an
HTTP request unless --yes is present. Retries use --idempotency-key (the
request ID by default), and updates require the current --expected-version
shown by posts show so stale automation cannot overwrite a newer edit.
Media uploads use the deployment's existing local, S3-compatible, or
Cloudflare R2 storage. The CLI validates the local file, requests a short-lived
signed upload, streams the file directly to storage, and registers the reusable
asset only after the stored size and content type match. Rolino derives image
dimensions and video duration from bounded reads of the stored object rather
than trusting caller metadata. Uploading requires
interactive confirmation or --yes and never creates or schedules a post.
YouTube drafts require exactly one stored video and explicit settings. Supply
--youtube-title, --youtube-category-id, --youtube-privacy, and
--youtube-made-for-kids yes|no; repeat --youtube-tag as needed. Optional
flags include --youtube-caption, --youtube-synthetic-media, and
--no-youtube-notify-subscribers. The YouTube caption override is the video
description; otherwise Rolino uses the shared caption. For example:
rolino posts create --project PROJECT_ID --caption "Launch description" --platform YOUTUBE --media VIDEO_ASSET_ID --youtube-title "Launch video" --youtube-category-id 22 --youtube-privacy PRIVATE --youtube-made-for-kids no --youtube-tag launch --yesGoogle may restrict uploads from unaudited API projects to Private. Rolino does
not infer audit approval from configuration. posts publish preserves the
chosen Public, Unlisted, or Private visibility and does not create a schedule.
A future posts schedule delivery must target Public; confirmed scheduling
starts its private resumable upload immediately so processing can finish before
the target time.
TikTok drafts require account-specific choices. Refresh them immediately before preparing the draft:
rolino integrations delivery-options --project PROJECT_ID --provider TIKTOKFor direct publishing, pass the exact returned visibility and explicit yes/no
choices for comments, duet, stitch, commercial content, own-brand promotion,
third-party promotion, and AI-generated content. Use --tiktok-mode inbox for
a mobile inbox handoff. Add --tiktok-settings-reviewed only after reviewing
those fresh choices; it is deliberately separate from --yes, which confirms
the Rolino draft write. Editing TikTok caption, media, destinations, or its
override clears the prior settings review.
Bluesky drafts can be text-only or include up to four stored JPEG, PNG, or WebP
images. Use --bluesky-caption for a destination-specific override of up to
300 graphemes:
rolino posts create --project PROJECT_ID --caption "Shared launch" --platform BLUESKY --bluesky-caption "Launch day 🦋" --yesLinkedIn drafts can be text-only, include up to ten stored JPEG/PNG images, or
contain exactly one stored MP4 without mixing images and video. Native video
must be 75 KB to 500 MB and 3 seconds to 30 minutes. Refresh the connected
member and server policy before preparing the draft, and use
--linkedin-caption for a destination override:
rolino integrations delivery-options --project PROJECT_ID --provider LINKEDIN
rolino posts create --project PROJECT_ID --caption "Shared launch" --platform LINKEDIN --linkedin-caption "Launch day for our LinkedIn network" --media IMAGE_ASSET_ID --yes
rolino posts create --project PROJECT_ID --caption "Product demo" --platform LINKEDIN --media VIDEO_ASSET_ID --yesThe connected OAuth member is the author; the developer app's associated Company Page is not a publishing target. Native video publish and schedule execution remains in preparation until LinkedIn confirms upload and processing. If final post creation has an unknown outcome, inspect that member's LinkedIn feed before retrying.
Google Business Profile drafts can be text-only or include one stored JPEG or
PNG image with a stable public URL. Use --google-business-profile-caption
for a destination override of up to 1,500 characters:
rolino posts create --project PROJECT_ID --caption "Store update" --platform GOOGLE_BUSINESS_PROFILE --google-business-profile-caption "Visit us to see what is new." --media IMAGE_ASSET_ID --yesRolino owns the schedule and publishes only a standard update to the location selected in Integrations. The CLI cannot select a location or enable the provider. If a create result is unknown, inspect the selected Business Profile before you try again.
Project creation also requires interactive confirmation or --yes. It
atomically saves a project and its paired brand, but does not start research,
connect accounts, schedule posts, or publish. A fresh CLI invocation generates
a fresh request ID and therefore a fresh default idempotency key. To retry the
same logical creation across invocations, pass the original request ID or an
explicit stable value through --idempotency-key.
Scheduling is intentionally two-step. posts schedule preview validates the
exact time, timezone, current post version, readiness, and live provider health,
then returns a five-minute one-time confirmation. posts schedule execute
must repeat the same values and adds an idempotency key; the server rechecks
everything before atomically consuming the confirmation and scheduling. For
scripts, prefer ROLINO_CONFIRMATION_TOKEN over placing the short-lived token
in process arguments. Neither --agent nor any client-side flag bypasses the
server confirmation.
When YouTube is selected, the preview states whether confirmed execution starts
or resumes early private preparation. A schedule execution may return
PENDING with phase REMOTE_SCHEDULE_CONFIRMATION after the upload completes
while YouTube acknowledges the requested Public publish time. The video remains
private, no second publish action is required, and the same idempotency key is
safe to replay.
Immediate publishing uses the same server-enforced pattern. posts publish
preview validates the current version, exact destination set, readiness, live
provider health, and retry safety without publishing. posts publish execute
must repeat those values with the one-time confirmation and an idempotency key.
A successful execute durably queues the selected destinations for immediate
delivery; Rolino's worker performs provider calls and reconciles ambiguous
network results so an unsafe retry cannot duplicate a post. Use
ROLINO_CONFIRMATION_TOKEN for scripts instead of putting the token in process
arguments. YouTube remains PREPARING while its resumable upload and provider
processing are incomplete. The preview identifies the delivery as IMMEDIATE,
shows the exact visibility, and confirms that no schedule will be created; only
provider-confirmed visibility becomes published.
The CLI cannot enable YouTube, Bluesky, LinkedIn, or Google Business Profile, or infer provider approval. Those are server-side deployment controls. Self-hosted operators should complete the YouTube operations guide and Bluesky operations guide, LinkedIn operations guide and the Google Business Profile operations guide before live testing.
Configuration is read from ROLINO_URL, ROLINO_TOKEN, ROLINO_CONFIG_DIR,
ROLINO_OUTPUT, ROLINO_TIMEOUT, and the short-lived
ROLINO_CONFIRMATION_TOKEN, with non-secret command options for base
URL, output, timeout, and request correlation. ROLINO_TOKEN takes precedence
over saved credentials. Piped stdout defaults to JSON; --agent adds stable
next-command suggestions. Timeouts accept integer milliseconds or values such
as 500ms, 15s, and 1m.
Stable exit codes:
| Code | Meaning | | ---: | --- | | 0 | Success | | 1 | Unexpected CLI failure | | 2 | Usage/configuration error | | 3 | Authentication required or expired | | 4 | Permission or scope denied | | 5 | Resource unavailable or not found | | 6 | Conflict or stale version | | 7 | Validation failure | | 8 | Rate limited | | 9 | Rolino server failure | | 10 | Network failure | | 11 | Timeout | | 12 | User cancelled |
Support, security, and license
Stable releases are published only after the maintainer approves the release gate. Report bugs through the Rolino issue tracker and security issues through the repository's security policy.
@rolino/cli is available under the MIT License.
Agent-first Blog Studio setup
Authorize the optional blog:manage capability separately from Blog reading,
draft writing, and approved-revision publishing. Existing credentials never
gain it automatically. Start every setup with:
rolino --agent blog setup status --project PROJECT_IDThe blog site, blog plan, blog article, blog connection, and
blog destinations command groups mirror the versioned API. Use these safe
publishing reads before setup or publication:
rolino --agent blog destinations providers --project PROJECT_ID
rolino --agent blog destinations list --project PROJECT_ID
rolino --agent blog destinations deliveries --project PROJECT_ID
rolino --agent blog destinations deliveries --project PROJECT_ID --article ARTICLE_IDThe provider catalog requires blog:manage. It returns only providers enabled
for the workspace, safe capabilities, and official documentation. Destination
and delivery-attempt reads require blog:read. They omit draft content,
prompts, evidence, secrets, and raw provider responses. A returned remote URL
is not proof that a queued or failed delivery is live.
Mutations require a stable idempotency key. Connection provisioning also requires preview, explicit confirmation, and execute. A first successful execute can return a delivery token or webhook secret once; save it only in server-side environment configuration. Replays do not reveal it again. Blog publication remains the separate approved exact revision preview/execute workflow.
Blog image commands require blog:write; they cannot approve an article or
publish it. Image upload reads only the path in the command, accepts JPEG, PNG,
or WebP, and keeps its signed upload URL and storage key private. Approving an
exact revision and image bundle requires the independent blog:approve
capability and cannot publish. Scheduling, rescheduling, or canceling a future
publication requires the independent blog:publish capability and does not
grant approval.
Active-plan editorial calendar commands also require blog:write:
rolino --agent blog plan cadence preview --project PROJECT_ID --plan PLAN_ID --weekdays 1,3,5 --expected-plan-version VERSION
rolino --agent blog plan cadence apply --project PROJECT_ID --plan PLAN_ID --weekdays 1,3,5 --expected-plan-version VERSION --expected-schedule-digest DIGEST --confirmation-token TOKEN --idempotency-key KEY --yesPreview a cadence change first and show every date change and locked item. Apply only
the unchanged preview values. These commands do not change scheduledPublishAt and never schedule, publish,
or unpublish an article. Image generation already accepts optional direction
with blog images generate --editorial-brief TEXT (maximum 500 characters).
Approval, schedule, and cancellation execution bind the short-lived token from
the matching preview and a stable idempotency key. Human output requires
--yes. JSON mode does not prompt, but it still requires the confirmation
token and idempotency key. A safe replay uses the same exact input and key.
Use this order for complete Blog work:
- Read setup status and current article or plan state.
- Ask for any missing website, cadence, destination, and access level.
- Import and plan through durable jobs, then poll instead of retrying blindly.
- Present evidence before accepting a plan item unless the user already authorized that exact bounded action.
- Create or update one immutable revision with catalog-backed links.
- Generate or upload one approved image, review it, and verify alt text.
- Without
blog:approve, stop and ask the user to approve in Rolino. - With
blog:approve, preview and execute the unchanged exact bundle with confirmation and a stable idempotency key. - Without
blog:publish, stop after approval. - With
blog:publish, preview and execute unchanged immediate publication or scheduling with a stable idempotency key. - Poll delivery attempts and verify the live remote URL; queued is not published.
- After any content or image change, restart from approval preview.
Existing delivery recovery
rolino --agent posts recovery check POST_ID --project PROJECT_ID --provider YOUTUBE
rolino --agent posts recovery preview POST_ID --project PROJECT_ID --expected-version VERSION --action ATTACH --video-id VIDEO_ID
rolino --agent posts recovery execute POST_ID --project PROJECT_ID --expected-version VERSION --action ATTACH --video-id VIDEO_ID --idempotency-key STABLE_KEY --yesShow the preview to the user and obtain approval before execute. Set ROLINO_CONFIRMATION_TOKEN to the returned token, or use --confirmation-token. Keep the video ID, action, version, and publication time unchanged. Use the same idempotency key when retrying an uncertain execution.
For RESUME, supply either --at ISO_DATE or --publish-now. Attachment cannot set a publication time. ATTACHED links the video without publishing it; check delivery next. QUEUED is not confirmation of publication. Checks require posts:write; resume also requires posts:schedule or posts:publish. Unknown delivery requires manual review, not another upload. posts show displays stored post and processing IDs plus a safe YouTube Studio link.
Bluesky
Run rolino integrations delivery-options --project PROJECT_ID --provider BLUESKY for account health, image limits, and the owner connection path. Use posts schedule cancel preview POST_ID --project PROJECT_ID --expected-version VERSION, then posts schedule cancel execute with the same IDs/version, --idempotency-key KEY, --yes, and ROLINO_CONFIRMATION_TOKEN. This returns a future untouched schedule to Draft. Delivery that may have started requires a delivery check. See docs/agent-platform/bluesky.md in the repository.
Bluesky workflows also support image alt text, confirmed deletion of untouched drafts (posts:delete), and confirmed account disconnection (integrations:disconnect). These permissions are optional and independent. See the complete workflow map.
Multiple publishing accounts
Use saved connection IDs from integration health, not account names. A draft's destinations array can select several accounts on the same network. Each item contains integrationId, provider, and optional captionOverride, tiktokSettings, and youtubeSettings. A null caption override uses the shared caption. Provide YouTube settings for every YouTube account. TikTok choices and consent belong to each account.
Do not combine destinations with legacy platforms or provider-level settings. A legacy provider-only request is accepted only when its account is unambiguous. The server returns a selection error otherwise. Missing or changed account identity never selects a replacement account.
Saved post destinations have their own id. Use these destination IDs for publish destinationIds and recovery destinationId; they are different from connection integrationId. Preview, version, confirmation token, and selected destination IDs must remain unchanged when confirming. A pending schedule response can contain several destinations, each with its own mutationId. Wait for each account's confirmed result.
These contracts are staged with the multi-account database migrations. Deploy the server and worker with the same schema before using them. Existing remote receipts remain attached to their saved accounts. No live provider acceptance test is implied by local contract tests.
For draft create/update, pass --accounts-file accounts.json. The file contains the array itself:
[
{ "integrationId": "saved-toronto-connection", "provider": "BLUESKY", "captionOverride": "Toronto opens at eight." },
{ "integrationId": "saved-ottawa-connection", "provider": "BLUESKY", "captionOverride": null }
]Replace these example IDs with saved IDs. Publish preview/execute accepts repeated --destination <saved-destination-id>. Recovery accepts one --destination. Integration health, delivery options, and disconnect accept --account <integration-id>. Use the normal explicit confirmation options for writes; a file does not authorize a write by itself.
