Run a Ranla command
arc_ranlaRun one of Ranla's commands in this account. command is " ", such as "campaign list" or "page propose", and input holds its fields. "help " lists a noun's commands with every field. A command that needs sign-off does nothing yet: it comes back with pendingApproval, and arc_approve with its messageId applies it. For strategy, or anything that needs Ranla's judgement or research, use arc_message.
Commands:
ad: list, set — an ad's copy. list {campaignId, adId} is each ad's headlines and descriptions word for word (pins, Google's rating), its ad group's keywords and Quality Score, and Ranla's copy changes to it in 30 days (applied when, or a card waiting): read it before quoting or rewriting copy and to confirm a change went in. set {adId, headlines, descriptions, replaceHeadlines, replaceDescriptions, pins: [{text, pinnedField}], replace, moveKeywords, newAdGroupName, rationale} adds or replaces lines (the card shows old → new); with moveKeywords and newAdGroupName it moves those keywords into their own ad group with this copy
ad-account-assets: pause — pause {resourceNames} pauses account-level sitelinks, callouts and snippets, a card
ad-campaign: checklist, create, diagnostics, list, search-history, set, terms — a Google Ads Search campaign (never email). list {days} is each campaign's spend, clicks, conversions, serving status, impression share, whole served life (history), bidding with biddingRecommendation, searchPartners and landingPages. terms {campaignId, limit} is what people typed in the last 90 days and which terms cost money without converting. search-history {days, contains, campaignId, includeHistory, limit} is up to 365 days across every campaign ever run, split by campaign. diagnostics is why a campaign is not spending, as findings each with the card that fixes it (low_quality_score, launch_checklist, primary_conversion_unrelated, conversion_feed, conversion_not_biddable). checklist {campaignId} is the launch checklist, pass/warn/fail per setting. create {finalUrl, dailyBudgetCents, countries, languages, locationType, name, planItemId, plannedFrom, replaceActionId, adGroups: [{name, keywords: [{text, matchType}], maxCpcCents}], negativeKeywords, headlines, descriptions, path1, path2, sitelinks, callouts, structuredSnippets, maxCpcCents, biddingStrategy, cpcCeilingCents, targetCpaCents, searchPartners, accountDailyCapCents, budgetChanges} plans a new Search campaign for one landing page as a plan card (created PAUSED); it runs the launch checklist and fills what is not given with the account's defaults (presence targeting, the copy's language, Google Search only, safe shared lists, starter negatives), and puts any FAIL on the card. set {campaignId, rationale, and one change: status paused|enabled, dailyBudgetCents (founderRequested, accountDailyCapCents), strategy (cpcCeilingCents, targetCpaCents), maxCpcCents (adGroupIds; Manual CPC only), searchPartners, locationType and languages, sitelinks / callouts / structuredSnippets (removeAccountSitelinks, accountSitelinkMode), ads: [{adId, path1, path2}]} changes one setting of a live campaign, a card; it answers with what each card will change
ad-conversion: set, verify — Google Ads conversion actions. set {conversionActionId, primary: true|false, rationale} makes one primary or secondary, a card. verify {signupUrl} checks conversion tracking end to end (snippet live, click ids carried to signup, signups arriving, Google Ads accepts an upload) and raises one card only when a check fails, with the fixes
ad-group: add — add {campaignId, name, keywords: [{text, matchType}], headlines, descriptions, finalUrl, path1, path2, maxCpcCents, rationale} adds an ad group with its own ad, a card
ad-history: list, set — what each campaign, conversion action and shared negative list in the ad account was for: current (the offer sold today), legacy (an offer or goal that no longer exists) or other_product. Evidence reads leave out legacy and other_product and say so; removed and long-paused campaigns and removed or hidden conversion actions are legacy until the founder says otherwise. list {type}. set {items: [{type, id, label, note}], founderSaid} stores what the founder said; without founderSaid it stores Ranla's own reading (never over the founder's labels), no card
ad-keyword: add, set — a keyword in a live campaign. add {campaignId, adGroupId, text, matchType: EXACT|PHRASE|BROAD, rationale}, a card. set {keyword (its text) or criterionId, campaignId, status: paused|enabled|removed, rationale}, or {keyword or criterionId, toCampaignId, toAdGroup or toAdGroupId, rationale} to move it (the destination's only ad group when it has one), a card; removed cannot be undone
ad-negative: add, leaks — campaign negative keywords. add {campaignId, text, matchType, rationale} for one, or {campaignId, terms, matchType, rationale} for a list (a new campaign's starter list needs no search data), one card; founderRequested marks the founder's own ask and any clash with converting searches or the campaign's keywords goes on the card as a note. leaks {campaignId} runs the search-term leak review and puts up one card with the negatives for searches judged not buyers, each checked against the campaign's own keywords, plus a pause card for a keyword that mostly buys non-buyers
ad-plan: discard, edit, list, request-approval, show, withdraw — Search campaigns Ranla proposed that are not in Google Ads yet. list {status: proposed|applied|failed|rejected|all, limit, offset} returns total and says whether each has an approval card waiting (awaitingApproval). show {actionId}. edit {actionId, name, dailyBudgetCents, finalUrl, searchPartners, biddingStrategy, cpcCeilingCents, targetCpaCents, countries, languages, locationType, sitelinks, callouts, structuredSnippets, sharedNegativeLists: ["list name"], changes: [{op: remove_keyword|add_keyword|set_headline|set_description|set_paths|set_max_cpc|add_ad_group|remove_ad_group|add_negative|remove_negative, adGroup, text, matchType, index, path1, path2, maxCpcCents, keywords, headlines, descriptions}]}; index is 1-based (1 is the first line) and empty text removes that line; a negative is created with the campaign; sharedNegativeLists attaches the account's shared negative lists at create (each checked against the plan's keywords). Every edit is saved and re-runs the launch checklist; FAIL lines come back as notes for the founder and go on the card. Change a plan with edit rather than proposing a second plan for the same landing page. request-approval {actionId} puts the approval card up again for a plan with none; approving it creates that plan paused. discard {actionId, reason} drops a plan. withdraw {actionId, reason} takes back any pending paid proposal
ads: keywords, landers, spend, sync — the ad account. spend {days} is total spend next to verified conversions. landers {dailyBudgetCents, countries} recommends landing pages to build first, from real search demand. keywords {terms, campaignId, countries} prices exact terms, or a live campaign's own keywords: monthly searches, competition, top-of-page bid low/high. sync {action: status|sync_segment|stop_segment|map_goal, segment, goal, conversionAction} is what goes back to Google Ads; a segment upload is a card
aeo: competitors, refresh, run, setup, sources, status — AI search: what ChatGPT, Perplexity, Gemini, Claude and Google AI say about us. status {days: 7|14|28|90, engine} is visibility, share of voice and how the answers describe us; read enabled and chats before quoting. competitors {days, engine}. sources {days, engine, gapOnly, domain} is which pages the engines read. run asks every engine now. setup {tracking: true|false, engines: chatgpt|perplexity|gemini|claude|google_ai_mode|google_ai_overview, cadence: daily|weekly, country, language, maxActivePrompts, brandNames}: send only what changes; turning it on or spending more is a card. refresh {job: suggest_prompts|fixes|readiness|volumes|fanout, topic, count} runs one of the desk jobs now
aeo-fanout: list, set — a Google search the engines run before answering (best X, X reviews, X alternatives), checked weekly. list {gapsOnly, status: active|dismissed|all} is our position and the lists that name us. set {queryIds, status: active|dismissed}: dismissed is no longer checked, active is checked again
aeo-fix: do, list, pitch, set — a thing to do about the AI answers. list {status: open|done|snoozed|dismissed, kind}, biggest first. set {actionId, status: done|snoozed|dismissed|open, snoozeDays} returns it before and after. do {actionIds or all, pageTypes} does them: page fixes go to the SEO desk, listings come back to draft the asks. pitch {actionId, type: pitch|listing, to, subject, body, why} drafts the founder’s outreach for a get_listed or review_site fix, a card; they send it
aeo-prompt: add, ask, delete, get, list, set, suggest — a buyer question tracked in AI search. list {status: active|suggested|paused|all, days, engine}, lowest visibility first. get {promptId, day, engine} is what each engine answered. set {promptIds, status: active|paused|dismissed|suggested, stage, topic, tags, text} changes them and returns each before and after; active is tracked (asked on every scheduled run, metered), a card. add {prompts: short questions built on a real search, fromFounder: true only when the founder gave these exact questions, topic, stage}; your own go in as suggestions with their demand looked up. suggest {topic, count} proposes new ones as suggestions. ask {promptIds} asks every engine now (at most 5, metered), a card. delete {promptIds} drops them with their answers and history, a card
aeo-topic: delete — delete {topic: its name}; its prompts stay, ungrouped
affiliate: add-coupon, add-link, approve, delete, get, import, invite, list, login-link, reactivate, reject, remove-coupon, remove-link, rename-link, suspend, update — a partner in the affiliate program; affiliate is their id or email. list {status, campaign, q, days}. get {affiliate} is their links and codes. invite {emails, campaign}. approve, reject {affiliate, reason}, reactivate {affiliate}. suspend {affiliate, reason} and delete {affiliate} are cards. update {affiliate, campaign, changes: {notes, tags, commissionOverride: {commissionType, commissionBps}, …}, clear}. add-link {affiliate, token, destinationUrl}. rename-link {affiliate, token}. remove-link {affiliate, link}, a card. add-coupon {affiliate, code}. remove-coupon {affiliate, coupon}, a card. login-link {affiliate} emails them a sign-in link. import {csv, campaign}. Never their payout or tax details
affiliate-campaign: archive, create, default, list, restore, update — commission rules partners earn under, never an email campaign. list. create {changes: {name, commissionType, commissionBps, commissionDuration, cookieDays, holdDays, …}, makeDefault, stripeCouponId}. update {campaign, changes, clear, stripeCouponId}. default, archive {campaign, moveAffiliatesTo}, restore {campaign}
affiliate-commission: add, list, reverse — the ledger. list {status, affiliate}. add {affiliate, amountCents, currency, description, earnedNow}. reverse {commissionId, reason, note}
affiliate-payout: cancel, draft, list, mark-paid, revert, skip — payout runs. list, or list {runId} for its payouts. draft {currency, affiliateIds} puts the founder's approval card up; only they approve. cancel {runId}, skip {runId, affiliate} before approval. mark-paid {payoutId, reference} when they paid by hand. revert {payoutId}
affiliate-program: domain-add, domain-remove, domain-verify, email, live, pause, settings, status — status {days} first on any affiliate question: numbers per currency, top partners, what waits on the founder, setup gaps. settings {changes: {portalHeadline, minPayoutCents, payoutSchedule, payoutMethods, blockSelfReferrals, …}, clear}. live (the first go-live is a card), pause. email {kind, subject, body, enabled, reset} is one partner email. domain-add {domain}, domain-verify, domain-remove (a card). Auto-pay, its cap and the payout keys are the founder's: no command
affiliate-referral: approve, attribute, clear-flag, import-invoices, list, reassign, reject — people a partner sent. list {status, flagged, affiliate, q}. attribute {affiliate, email or stripeCustomerId, importInvoices} only when the founder names both. approve, reject, clear-flag, import-invoices {referralId}. reassign {referralId, affiliate} moves a referral and its unpaid commissions to another partner
affiliate-resource: add, list, remove, reorder, update — what partners see in the portal. list. add {title, kind, url or body}. update {resourceId, …}. remove {resourceId}, a card. reorder {ids}
analytics: act, list — list {days, limit}. act {source: posthog|amplitude|mixpanel, events}
approval-rule: add, list, remove — the kinds of change the founder always approves. list. add {key} is a card. remove {key}
attribute: inspect, instrument — instrument {repoFullName, attributeKey, type, whenSet, backfill, revisePullRequest}. To change an open PR you opened, revise it: the same attribute with revisePullRequest (its number) and the change in whenSet — never a second PR
audience: list
audit: read, retest, scan — the technical site audit. read {url} is the latest scan, one page in full with url. scan runs it again. retest {url} re-tests one page's speed
automation: delete, draft, events, get, list, runs, set, suggest, test — a lifecycle flow, one object in any status (draft, active, paused). list. get {id} opens it on the canvas. set {id, name, trigger, steps} changes those fields and returns them before and after; on an active flow it is a card and the flow stays active. set {id, status: active} turns it on, a card; set {id, status: paused} turns it off. suggest {automationId, change: add_step|edit_step|remove_step|pause, label, why, step, index, forAutomationId} puts one change on the flow, drawn dashed, for the founder to accept or reject; nothing changes until they accept. test {automationId, to, mode: dry_run}. events is the lifecycle event names the brief names
background-job: clear, list, retry, stop — list: your jobs, running and finished, and every pull request you opened in any repo (open, merged or closed). stop {jobId}. clear {jobId}. retry {jobId, fix, note} only when the founder asks
brain: check, fallback, remove, show, use — what Ranla thinks with: Included or the workspace's own model key. show. use {choice}. fallback {on}: think on Included when the key fails. check {provider} after the founder fixed a key. remove {provider}, a card. Keys are added only in Settings › Ranla's brain or the CLI, never in chat
brand: get, update — update {section: profile|voice|product|competitors|style|pov|kit|competitor|product_context, purpose, audience, tone}. Kit is the logo corner
brief: get, update — update {icp, antiIcp, oneLiner, valueProposition, websiteUrl}
campaign: delete, draft, evaluation, get, list, performance, replies, resync, schedule, set, test — an email send, one object in any status (draft, scheduled, sending, paused, sent, cancelled). list {status, query} finds them. get {campaignId} is the whole campaign: sender, audience, category, goal, schedule, and each variant's subject, preheader and body (markdown, its blocks with their ids, or its html). set {campaignId, …} changes any field and returns each one before and after: name, audience, fromName, fromEmail, replyTo, category, templateId, goalId, holdoutFraction, hypothesis, primaryMetric, variants: [{key, subject, preheader, bodyMarkdown, templateVariables}], removeVariantKeys; subject and preheader on their own are one variant's (variantKey, else the first), whatever its body is made of; a body laid out in blocks changes with edits: [{op: set_text|set_image|set_button|insert|delete, blockId, …}] on variantKey, or html replaces the whole email; status: paused|cancelled|declined|resumed with reason (declined is the founder's no, kept as their preference; resumed restarts sends, a card). A change to a campaign that is scheduled, sending or paused is a card. draft {name, audience: {listIds or segmentIds}, fromName, fromEmail, variants: [{subject, bodyMarkdown}], category: newsletter|product}; optional hypothesis, primaryMetric: conversion_rate|reply_rate|click_rate, and retrievalId + dispositions to record the learnings used; a play on a pattern adds patternId. test {campaignId, email} sends one test; without email it goes to the founder
cms: changes, confirm-map, discard, draft, inventory, map, mappings, publish, read, revert, status — the founder's CMS (WordPress), for a site not in a repo. status is what is connected and what the site runs on. inventory {collection, search}. read {url} or {id, collection}. map {collection} proposes how a written page fills that collection's fields (background), then confirm-map {collection} is the founder's card; nothing is drafted into an unconfirmed collection. draft {pageActionId, collection} puts an SEO page there as a draft, checked as rendered. publish {changeId} is the card; it goes live on their yes. revert {changeId} puts it back. discard {changeId}. changes lists them
codebase: access, activity, get, read, research, search — research {repo}. access {reason}
comms: get, update — update {midweekPingCap, quietMode, pingDelivery, routes: {needs_you, broke, done, digest}, nudgeEveryDays, maxNudges}. routes sends one kind of message its own way; null puts that kind back on pingDelivery
connection: request, skip — request {slot, reason}. skip {slot}
contact: delete, export, get, import, resubscribe, save, unsubscribe, verification, verify — get {contacts}. save {contacts, firstName, lastName, attributes}. unsubscribe {contacts}. resubscribe {contacts}. delete {contacts}. import {attachmentId, csv}. export. verify {list | segment | everyone}, a card: checks addresses can receive email. verification {list | segment | everyone}
creative: propose — propose {preset, template, headline, backgroundMode: stock|generate|library, sizePack, backgroundAssetId, generatePrompt}
document: list
domain: add, apply-dns, list, remove, settings, verify — sending domains. list. add {domain}. verify {domain} checks DNS. apply-dns {domain, provider: cloudflare|godaddy|vercel} writes the records, a card. settings {domain, openTracking, clickTracking, tlsMode, inboundEnabled}. remove {domain}, a card
email: find, resend — the send log. find {search, status}. resend {emailId}, a card
event: instrument, list — instrument {eventName, triggerDescription, repoFullName, revisePullRequest}. Pass the event name; it checks whether that name is already ingested. To change an open PR you opened, revise it: the same event with revisePullRequest (its number) and the change in triggerDescription — never a second PR
file: read — read {id, offset} reads more of an attached file
follow-up: cancel, list, reschedule, schedule
funnel: get — get {days}: sign-ups, trials and paid as separate steps (one per conversion goal), each counted once per person with the workspace's own team left out, and where each step's people came from. Answer every "how many sign-ups / trials / customers" and "where do sign-ups come from" from it, one number per step, never added together
goal: configure, create, delete, list, primary, update — create {name, type, eventName}. update {goal: name or id, name, eventName}. primary {goal: name or id}. configure {goal: name or id, type, valuePath, currency, attributionWindowHours}. delete {goal: name or id}
growth: get
guardrail: update — update {autopilot: off|approve_each|full, maxSendsPerDay, maxSendsPerContactPerWeek}. Ask me before every send is autopilot approve_each
heartbeat: run — run checks every signal now, within the working mode
idea: create, delete, list — create {title, note}. delete {ideaId} for good, a card
identify: instrument — instrument {repoFullName, callSiteHint}
image: delete, list, stock-import, stock-search — list is the Library. stock-search {query, orientation}. stock-import {photoId}. delete {imageId}, a card
inbox: archive, dismiss-draft, edit-draft, mark-read, mark-unread, read, reply, save-draft, send-draft, unarchive — read {view: inbox|unread|archived|all, search, offset, limit, messageId, before}. reply {messageIds, body, subject, to}, a card. archive, unarchive, mark-read, mark-unread {messageIds}. save-draft {messageIds, body, subject} leaves a reply for the founder, no card. edit-draft {replyId, body}. send-draft {replyId, body}, a card. dismiss-draft {replyId}
install: show
integration: disconnect, settings, test — a connected integration: github|slack|search_console|posthog|amplitude|mixpanel|stripe|cloudflare|godaddy|vercel|twilio|gtm|google_ads|cursor|claude. settings {integration, …}. test {integration}. disconnect {integration}, a card
job: get, run, update — update {kind: occasion_scan|performance_review, hour, enabled, timezone, dayOfWeek}. run {kind}
learning: list, write — write {retrievalId, sourceEvaluationId, evidenceIds, statement, dispositions}. A bad evidence id comes back with the valid ones
list: add, create, delete, list, remove, update — create {name}. add {list: name or id, contacts}. remove {list: name or id, contacts}. update {list: name or id, name, description}. delete {list: name or id}
mac-run: get, list — code work the founder's own coding agent ran on their Mac (Run on your Mac). list {status, limit}, with each run's files and first changed lines. get {runId, steps, diff} is what it did step by step, the whole diff, and the approved task it ran: what a run changed, or whether it matches what was approved, is read there, never guessed
needs-you: approve-safe, groups — groups: what waits, by kind, and which kinds are safe in bulk. approve-safe {ids} raises a card; spend, sends and posts stay one by one
negative-list: list, set — the account's shared negative lists. list {sharedSetId, name, offset} is every term with the live keywords it blocks and the 90-day searches it matched. set {campaignId, sharedSetId, attach: true|false, rationale} attaches or detaches a list (a clash with the campaign's keywords is refused unless founderRequested), or {sharedSetId, add, remove, move: [{text, matchType, campaignIds, reason}], rationale} changes its terms; a card
note: create, delete, update — create. delete {id}
onsite-message: delete, draft, get, list, update — banners and modals for anonymous visitors. list shows views, clicks and dismissals. get {id}. draft {name, headline, body, display: banner|modal, status: draft|active, path_prefix, page_rules, frequency: every_page_until_dismiss|once_per_session|once, cta_mode: link|email_capture, cta_label, cta_url, show_trigger: immediate|exit_intent|scroll|delay}. update {id, status: draft|active|paused|ended, headline, body, …}: active shows it, paused or ended stops it. delete {id}
onsite-theme: get, update — the brand tokens every banner and modal uses. get. update {primary_color, background_color, text_color, font_family: system|serif|mono, border_radius_px, logo_asset_id}
opportunity: decide, list — decide {opportunityId, status, reason, campaignId}
page: check, find, get, research, screenshots, set, ship — an SEO page, one object in any status (plan, draft, approved, live, declined). find {status: open|live|declined|all, search, limit, offset} lists them with their actionId, status and url. get {actionId} is the whole page: plan, draft, questions, research. set {actionId, url, move, title, h1, description, body, edits: [{find, replace}], status: approved|declined|live|open, liveUrl, reason, answers: [{n, answer}]} changes any of those fields and returns each one before and after; a live page edited reopens as a draft. research runs the writer: without actionId {foundationNew: {query, pageType, pitch} or foundationImprove: {existingUrl, query, pageType, pitch}, opportunityKey, plan} researches a new page or an improvement; {actionId, note} rewrites a draft from the founder's words; {actionId, fresh: true, direction} researches it again. check {actionId, apply, only} fact-checks a draft against the vendors' own pages; apply: true makes its fixes as edits. screenshots {actionId, pages: [{url, shows}]}. ship {actionId, agent} builds it where their code runs (their Mac, or Cursor/Claude in the cloud), a card; agent ranla builds a free tool
paid: audit — the paid self-audit. audit runs it on every live Search campaign in the background (launch checklist, search-term leaks, ceilings, conversion upload health, keywords in the wrong campaign, account-level template assets, economics), raises the cards and posts one pass / warn / fail report in the Paid conversation. audit {campaignId} reads one campaign now and raises nothing
pattern: list, off, on — early behaviour that predicts converting to paid or early churn here, with its evidence: a correlation, never a cause. list is each outcome and every pattern. list {patternId, limit, offset} is one pattern, its later checks and who matches it now. on turns the weekly scan on, a card. off stops it and clears the matches
person: inspect — inspect {email, days} returns that person's recent events
plan: create, list, update — create {name}. update {itemId, status: raw|proposed|approved|scheduled|sent|skipped|dismissed, title, scheduledFor, campaignId}. Nothing sent yet is status skipped
product: read
rank: list — who is worth asking
reddit: activity, check, citations, rankings, scan, status, strategy — the Reddit desk. status first on any Reddit question: on or off, mode, posture, caps, what is watched, the accounts. activity is the last seven days. rankings is which Reddit threads Google shows for our keywords. citations is which threads ChatGPT, Perplexity and Google AI cite. scan finds new threads now. check {check: rankings|ai_citations|post_ideas|watchlist|karma|rewrite_for_own_account}. strategy {enabled, mode: watch|draft|autopilot, posture: founder|burner|fleet|any, opportunityMode: strict|balanced|volume, disclose, maxCommentsPerDay, maxPostsPerWeek, goal, icp, voiceNotes, brandNames, syncFromBrand: fill|overwrite}: send only what changes; autopilot or a higher cap is a card
reddit-account: list, update — list is karma, warmth, warming and who can post. update {username, action: watch|set_kind|warming|remove, kind, warming: true|false}: warming switches warming replies on or off
reddit-draft: delete, get, list, post, set — a reply or post written for Reddit. list {status: draft|approved|scheduled|posted|rejected|failed|any, kind: comment|post|any, subreddit}. get {draftId} is the text, its checks and its thread. set {draftId, body, title, status: rejected|draft|posted, postedUrl, reason} returns each field before and after; posted records one they posted by hand; a new body on a reply already posted fixes it on Reddit in place, behind a card. delete {draftId}, a card. post {draftId, account} posts it to Reddit, always behind a card; an approved draft is one going out
reddit-idea: add, draft, list, update — post ideas. list {status: open|drafted|posted|dismissed|any}. add {subreddit, title, kind: question|story|guide|comparison|showcase|ama, angle, reason, keyword, outline}. draft {ideaId, tone, instruction} writes the post as a draft. update {ideaId, status: dismissed|open}
reddit-lead: list, update — people who asked for what we do. list {status: new|contacted|replied|converted|dismissed|any}. update {leadId, status, note, reason, messageSubject, messageBody, rewriteMessage}
reddit-thread: get, list, reply, set — a thread worth answering. list {status: new|drafted|approved|posted|dismissed|saved|ai_cited|any, lane, subreddit, minRelevance, limit}, best first. get {threadId} is the thread, its top comments, its score and every draft for it. set {threadId, status: dismissed|open, reason, saved} returns it before and after: dismissed takes it out of the inbox, open puts it back, saved is the founder's bookmark. reply {threadId, tone: helpful_expert|casual_founder|community_member, posture, instruction} writes a reply as a draft with its safety checks; nothing posts
reddit-watch: add-keyword, add-subreddit, edit — what the desk watches. add-subreddit {name, risk: low|medium|high, reason}. add-keyword {text, kind: keyword|competitor|brand|question}. edit {keywords: [{text, action: remove|pause|resume|edit, kind}], subreddits: [{name, action, risk, rulesNote}], clearInbox}
repo: inspect, list, select, set, task — the GitHub repos Ranla works in. list is the repos, each one's pull request base, and whether code reading is on. set changes one thing a call: {repos} replaces the list (a card); {reading: false} turns code reading off (on is codebase access, the founder's yes); {repo, branch} is the branch her pull requests target. select {reason} shows the founder a picker. inspect {repo} is a deep read of a repo (minutes, no PR). task {handoff: {type, id}} runs an approved page, title/H1/description change, SEO action or AI-search fix from its stored task, the approved text word for word; {title, brief, freeForm: true} for code work none of those covers. {title, brief, pullRequest} puts a change on one of your own open pull requests (the founder reviewed it and asked for changes): it starts from that PR's branch and adds to it, no new PR; Mac only. It goes where their code runs (Run on your Mac, or Cursor/Claude in the cloud), a card
revenue: assume, churn, get — get is MRR, paying customers (logos: distinct customers with a paid subscription) next to paying subscriptions (add-ons count separately), LTV at the entry price and at ARPU, CAC, and
economics: the churn, LTV and target CAC every paid figure uses, each with its source. churn is logo and MRR churn by month for 12 months per currency and tier, the trailing-90-day rate, and one-off events. assume {monthlyChurnPct, ltvCents, targetCacCents, highValueMrrCents, highValuePlanPattern, note} stores figures the founder states; they then win everywhereroutine: add, delete, list, run, set — the founder's own recurring asks (every Friday, tell me X). add {title, prompt: what to do each run in their words, cadence, dayOfWeek, dayOfMonth, hour, timezone} is a card: each run uses credits; at most 5 on. list. set {id, enabled, title, prompt, schedule fields}. run {id} now. delete {id}
segment: create, delete, get, list, preview, reach, recount, update — create {name, description, definition: {kind: filter, match: all|any, conditions: [{type: attribute|event|engagement|list|rank|pattern, path, operator, value}]}}; a pattern condition is {type: pattern, patternId, operator: in|not_in}. preview {definition} counts it first. reach {listIds, segmentIds, category} is who a send would reach
seo: authority, cadence, competitors, inspect, intel, lift, opportunities, performance, plan, structure — search. plan {refresh} is what to rank for, a reason per page; call it first when they say let us do SEO or ask what to write. performance is Search Console clicks, impressions and queries for 28 days. structure {section: summary|pages|money|spokes|coverage|all} is the money-keyword map and the next pages. opportunities {include: proposed|refused|both}. competitors. authority is the link profile. lift is fixes priced in extra clicks. intel queues the competitor pass. inspect {url} is everything known about one live page. cadence {perApproval: 1-10, perRollingMonth: 1-40} reads or sets how many new pages one approval and a rolling month may carry (default 3 and 8); only when the founder asks, a card
seo-action: list, send, set — an item on the SEO Actions queue. list is open work by value, and apart from it what was set aside. set {key, status: done|snoozed|ignored|open, days, note} returns it before and after. send {key}: a technical fix (audit:…) to where their code runs (their Mac or a cloud agent), brief traced from the repo, or a fix to pages the site already has (existing:…), a card. removePages: true only after they said to remove the pages that fix takes off the site
set: add, approve, check, create, data, deliver, pause, quote, resume, sample, status, stop — a set of pages from one template and a list of items. create {name, pageType, patternQuery with {item}, template: {sections, differentiator, cta}, items or fromBrand, pathPattern, batchCap 1-25}. add {setId, items or fromBrand}. data {item, points: [{kind: price|limit|screenshot|feature|source, value, sourceUrl}]} — a page is not written until the item has 4 facts that appear on their https source pages. A screenshot point is that page text, not an image. sample writes 3. check compares the drafts and pauses the set when they are too alike. quote is the credit total. approve is one card for the next batch (10 unless batchCap is lower, never more than 25). deliver {agent: cursor|claude} sends the finished pages to that coding agent as one pull request, and stops at a card. pause, resume, stop. status reads it. Hired accounts only
setup: code-runs, coding-agent, connection, first-look, get, home-layout, pet, pr-bar, share-first-look, start, status, test-email — start {repoFullName, kind}. home-layout {order, hidden}. first-look {siteUrl, retry}. connection {slot, skip}. pet {pet} sets their own pet in the Ranla view (none is the plane; no pet reads it). code-runs {detail} sets how much of a run on their Mac they see in the conversation (no detail reads it). pr-bar {prBar: show|hide} sets whether they see the pull request bar above the conversation (no prBar reads it). coding-agent {subfolder | clear} sets the folder inside their linked repo that is their site, for a repo with several sites: use it when the founder names a folder ('there's a movement marketing folder'), with subfolder exactly as listed (no subfolder reads what is set and the folders listed). The repo and which repo stay theirs, in Settings. Confirm in one line: Set to apps/x in owner/repo; run the task again. test-email sends the setup test email to the founder
site: colors, research — research {url}
suppression: add, add-unverifiable, check, remove — the do-not-email list. check {emails}. add {emails, reason, scope: newsletter|product|all, attachmentId}. remove {emails, scope}, a card. add-unverifiable: everyone an address check found can't receive email, a card
team: cancel-invite, invite, list, unlink-slack — list. invite {email}, a card. cancel-invite {id}. unlink-slack {id}
template: create, delete, get, list, publish, set, starters, suggest, test — an email template, one object (draft or published). list. get {template_id}. set {templateId, subject, preheader, html, text, design, variables, name, alias, category: transactional|product|newsletter, unsubscribeEnabled} changes those fields and returns them before and after; content changes go into the draft, and mail keeps sending the published version until publish {templateId} makes the draft live (republishing a template that sends is a card). suggest {templateId, label, why, op, blockId, …} puts one edit in their editor as a tracked change for the founder to accept or reject; nothing changes until they accept. starters lists the starter catalog. create {name, format: blocks|html, html}, or {starter, name} from a starter. test {templateId, to}. delete {templateId}, a card
testimonial: add, edit, list, restore, retire, revoke, use — a quote from the founder's own user, with their written yes. list {status, testimonialId} first: the switch, counts, and quotes; an id gives its consent record. add {quote, personName, email, title, company, attribution, consentEvidence} is a card and needs their written yes. use {testimonialId} puts a collection-page submission (pending) into use, a card. edit {testimonialId, attribution, showCompany, logoUrl, quote}: naming them less applies now; a trimmed quote (cuts only, ... for middle cuts) goes back to them as an ask. retire, restore, revoke {testimonialId}. Repeat a quote exactly; never reword one
testimonial-request: accept, edit, find, list, send, skip — an ask for a testimonial. list {status, requestId}: default open. send {requestId} is a card. edit {requestId, subject, body} before it goes; the quote stays word for word and nothing is offered in exchange. skip {requestId}. accept {requestId, quote, attribution, title, company} records an unclear reply as a yes, a card. find looks for new praise and moments now
testimonial-settings: off, on, set — on (a card), off. set {askFoundPraise, askMoments, autoSend, fromName, fromEmail, defaultAttribution, collectEnabled, collectHeadline}; autoSend on is a card; collectEnabled opens the hosted page users leave a quote on
testimonial-widget: create, end, list, pause, resume, start, update — quotes on the founder's own site, with a holdout. list {widgetId}: lift on signups and paid, withheld until 14 days; only proven is a result. create {name, layout, pagePath, testimonialIds, maxQuotes, holdoutFraction} returns the embed code. update {widgetId, …}. start {widgetId} is a card. pause, resume, end {widgetId}
tracker-move: check, done, later, reopen — the task to move a Google Tag Manager tracker into their site code. check looks at their site for the tracker in its own code (a consent loader counts) and closes the task when it is there. done is the founder saying they did it: checked at once, and the task leaves Needs you either way. later is Not now. reopen puts it back
tracking: get, install, verify — get is the tracker for their site code, and the task for their coding agent. verify checks pageviews. install puts it in Google Tag Manager, only when they cannot edit their site code
traffic: breakdown, efforts, summary — summary. breakdown {dimension: path|channel|referrer|country|device}. efforts. Its conversions add every goal together: never quote them as sign-ups (funnel get)
url: read
webhook: list, remove, test — list. test {webhookId, event}. remove {webhookId}, a card. Adding one stays in Webhooks
working-mode: update — update {mode: off|watch|own, checkEveryMinutes, maxConcurrentMissions, maxMissionsPerDay, maxProposalsPerDay, autoReplyMode: off|draft|send, pausedRoles, askFirstChannels, …}: how Ranla works unasked. watch is notice and tell; own is start work. askFirstChannels is the full list of channels held at Ask first under Autopilot
workspace: timezone, update — timezone {timezone}. update {workspaceName, firstName, lastName, username}
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| input | No | The command's fields. | |
| command | Yes | "<noun> <verb>", or "help <noun>". | |
| threadId | No | Ranla thread to record it in (from arc_ensure_thread). Optional. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| next | No | What to do with the pending approval | |
| noun | No | For help <noun>: the noun | |
| result | No | What the command returned: content (any JSON, shaped by the command), plus steps and artifact when it has them | |
| commands | No | For help <noun>: each verb's input schema | |
| pendingApproval | No | Set when the command needs sign-off. It does nothing until arc_approve. |