runline ⚡

September 19, 2026 · View on GitHub

Code mode for agents.

Turn any API or host capability into a callable action. Install a plugin, write JavaScript, call actions. Code runs in a QuickJS WASM runtime with plugin globals; enable the built-in node plugin when you want filesystem, path, OS, process, crypto, shell, and fetch actions.

npm install -g runline

Quick Start

npm install -g runline
runline init
runline connection add bf --plugin brandfetch --set apiKey=xxx

runline exec 'return await brandfetch.brand.getColors({ domain: "nike.com" })'
# => [{ hex: "#E5E5E5", type: "accent" }, { hex: "#111111", type: "dark" }, ...]

All 204 built-in plugins ship bundled inside runline — no per-plugin install step. Just add a connection for the one you want to use. Agent code runs in a QuickJS runtime: each configured plugin is a top-level global, dot-chain into resource and action. Configure the built-in node plugin for host work like node.fs.readFile, node.process.execFile, node.path.join, node.crypto.hash, and node.fetch.

// agent writes this
const company = await brandfetch.brand.getCompany({ domain: "stripe.com" });
const deals = await pipedrive.deal.list({ limit: 10 });
const issue = await github.issue.create({
  owner: "acme", repo: "api",
  title: `New lead: ${company.name}`,
  body: `${deals.length} open deals`
});
return { company: company.name, issue: issue.number };

Plugins

204 built-in plugins covering popular SaaS, DevOps, productivity, image-generation APIs, and host Node capabilities. All ship with the package — no separate install needed.

Set the env var shown in the Auth column, add a connection, and go:

export GITHUB_TOKEN=ghp_xxx
runline connection add gh --plugin github --set token=$GITHUB_TOKEN
runline exec 'return await github.user.listRepos({ username: "torvalds" })'
PluginActionsResourcesAuth
actionNetwork23attendance, event, person, petition, signature, tag, personTagACTION_NETWORK_API_KEY
activeCampaign48contact, account, accountContact, contactTag, contactList, list, tag, deal, connection, ecomCustomer, ecomOrder, ecomOrderProductACTIVE_CAMPAIGN_API_URL, ACTIVE_CAMPAIGN_API_KEY
adalo5collectionADALO_APP_ID, ADALO_API_KEY
affinity16list, listEntry, person, organizationAFFINITY_API_KEY
agileCrm15contact, company, dealAGILE_CRM_SUBDOMAIN, AGILE_CRM_EMAIL, AGILE_CRM_API_KEY
airtable10base, recordAIRTABLE_TOKEN
airtop24session, window, extraction, interaction, agent, fileAIRTOP_API_KEY
apiTemplateIo4account, template, image, pdfAPI_TEMPLATE_IO_API_KEY
asana22task, subtask, taskComment, taskTag, taskProject, user, projectASANA_TOKEN
autopilot11contact, contactJourney, contactList, listAUTOPILOT_API_KEY
bambooHr11employee, employeeDocument, file, companyReportBAMBOO_HR_SUBDOMAIN, BAMBOO_HR_API_KEY
bannerbear4image, templateBANNERBEAR_API_KEY
baserow8rowBASEROW_HOST, BASEROW_TOKEN
beeminder18datapoint, charge, goal, userBEEMINDER_API_TOKEN
bitly3linkBITLY_ACCESS_TOKEN
bitwarden19collection, event, group, memberBITWARDEN_CLIENT_ID, BITWARDEN_CLIENT_SECRET
box11file, folderBOX_ACCESS_TOKEN
brandfetch5brandBRANDFETCH_API_KEY
brevo15contact, attribute, email, senderBREVO_API_KEY
bubble5objectBUBBLE_API_TOKEN, BUBBLE_APP_NAME
chargebee5customer, invoice, subscriptionCHARGEBEE_ACCOUNT_NAME, CHARGEBEE_API_KEY
circleci3pipelineCIRCLECI_API_KEY
ciscoWebex10message, meetingWEBEX_ACCESS_TOKEN
clearbit3person, companyCLEARBIT_API_KEY
clickup61checklist, checklistItem, comment, folder, goal, goalKeyResult, guest, task, taskTag, taskList, taskDependency, spaceTag, list, timeEntry, timeEntryTagCLICKUP_ACCESS_TOKEN
clockify25client, project, tag, task, timeEntry, user, workspaceCLOCKIFY_API_KEY
cloudflare4zoneCertificateCLOUDFLARE_API_TOKEN
cockpit5collection, form, singletonCOCKPIT_URL, COCKPIT_ACCESS_TOKEN
coda18table, formula, control, viewCODA_ACCESS_TOKEN
coingecko10coin, event
contentful7space, contentType, entry, asset, localeCONTENTFUL_SPACE_ID, CONTENTFUL_DELIVERY_TOKEN
convertkit16customField, form, sequence, tag, tagSubscriberCONVERTKIT_API_SECRET
copper32company, lead, opportunity, person, project, task, customerSource, userCOPPER_API_KEY, COPPER_EMAIL
cortex4analyzer, job, responderCORTEX_HOST, CORTEX_API_KEY
currents22action, instance, project, run, signature, specFile, test, testResultCURRENTS_API_KEY
customerIo9campaign, customer, event, segmentCUSTOMERIO_SITE_ID, CUSTOMERIO_TRACKING_API_KEY, CUSTOMERIO_APP_API_KEY
databricks34sql, files, genie, modelServing, catalog, table, volume, function, vectorSearchDATABRICKS_HOST, DATABRICKS_TOKEN
deepl2languageDEEPL_API_KEY
demio4event, reportDEMIO_API_KEY, DEMIO_API_SECRET
dhl1shipmentDHL_API_KEY
discord13channel, member, messageDISCORD_BOT_TOKEN, DISCORD_GUILD_ID
discourse16category, group, post, user, userGroupDISCOURSE_HOST, DISCOURSE_API_KEY
disqus4forumDISQUS_API_KEY
docker5containers, images
drift5contactDRIFT_ACCESS_TOKEN
dropbox9file, folder, searchDROPBOX_ACCESS_TOKEN
dropcontact2contactDROPCONTACT_API_KEY
egoi4contactEGOI_API_KEY
elasticsearch9document, indexELASTICSEARCH_URL
elevenlabs20dialogue, audio, history, voices, pronunciationDictionaries, models, speech, transcription, music, soundELEVENLABS_API_KEY
emelia9campaign, contactListEMELIA_API_KEY
erpnext5documentERPNEXT_HOST, ERPNEXT_API_KEY, ERPNEXT_API_SECRET
facebookGraph1requestFACEBOOK_ACCESS_TOKEN
fal8image, video, run, queueFAL_KEY
freshdesk10ticket, contactFRESHDESK_DOMAIN, FRESHDESK_API_KEY
freshservice77agent, agentGroup, announcement, asset, assetType, change, department, location, problem, product, release, requester, requesterGroup, software, ticket, agentRoleFRESHSERVICE_DOMAIN, FRESHSERVICE_API_KEY
freshworksCrm35account, appointment, contact, deal, note, salesActivity, task, searchFRESHWORKS_CRM_DOMAIN, FRESHWORKS_CRM_API_KEY
getresponse5contactGETRESPONSE_API_KEY
gett12account, place, driver, ride
ghost5postGHOST_URL, GHOST_ADMIN_API_KEY
github37file, issue, release, commit, branch, repository, review, user, organization, workflowGITHUB_TOKEN
gitlab17issue, release, repository, user, fileGITLAB_TOKEN
gmail32message, thread, draft, label, profile, alias
gong4call, userGONG_ACCESS_KEY, GONG_ACCESS_KEY_SECRET
googleAppsScript10script, project, file, version, deployment, function, process
googleCalendar22calendar, event, freeBusy, calendarList, acl, settings
googleContacts10contact, group
googleDocs44document
googleDrive47file, folder, fileFolder, drive, comment, reply, revision, changes, permission, accessProposal, about
googleImage2imageGOOGLE_API_KEY
googleSheets23spreadsheet, sheet, chart, namedRange, protectedRange, conditionalFormat, dataValidation
googleSlides7presentation, page
googleTasks12taskList, task
gotify3messageGOTIFY_URL, GOTIFY_APP_TOKEN, GOTIFY_CLIENT_TOKEN
gotowebinar20webinar, registrant, session, attendee, coorganizer, panelistGOTO_ACCESS_TOKEN, GOTO_ORGANIZER_KEY
grafana17dashboard, team, teamMember, userGRAFANA_URL, GRAFANA_API_KEY
graphql2query, introspectGRAPHQL_ENDPOINT
grist4recordGRIST_API_KEY
hackernews6article, user, all
halopsa20client, site, ticket, userHALOPSA_API_URL, HALOPSA_CLIENT_ID, HALOPSA_CLIENT_SECRET
harvest49client, project, task, contact, invoice, expense, estimate, user, timeEntry, companyHARVEST_TOKEN, HARVEST_ACCOUNT_ID
helpscout13conversation, customer, mailbox, threadHELPSCOUT_ACCESS_TOKEN
highlevel17contact, opportunity, task, calendarHIGHLEVEL_ACCESS_TOKEN, HIGHLEVEL_LOCATION_ID
homeAssistant13config, service, state, event, log, template, historyHASS_HOST, HASS_TOKEN
hubspot32contact, company, deal, ticket, contactList, engagement, formHUBSPOT_ACCESS_TOKEN
humanticAi3profileHUMANTIC_AI_API_KEY
hunter3domainSearch, emailFinder, emailVerifierHUNTER_API_KEY
intercom10contact, companyINTERCOM_ACCESS_TOKEN
iterable6event, user, userListITERABLE_API_KEY
jenkins11job, build, instanceJENKINS_URL, JENKINS_USER, JENKINS_TOKEN
jira16issue, issueComment, userJIRA_DOMAIN, JIRA_EMAIL, JIRA_API_TOKEN
keap28company, contact, contactNote, contactTag, order, product, email, fileKEAP_ACCESS_TOKEN
kobotoolbox17form, submission, hook, fileKOBOTOOLBOX_URL, KOBOTOOLBOX_TOKEN
lemlist15activity, campaign, lead, team, unsubscribe, enrichLEMLIST_API_KEY
linear89issue, comment, state, label, project, milestone, projectUpdate, view, cycle, team, initiative, user, attachment, org, webhookLINEAR_API_KEY
lingvanex1translateLINGVANEX_API_KEY
linkedin1postLINKEDIN_ACCESS_TOKEN
lonescale4list, itemLONESCALE_API_KEY
magento15customer, invoice, order, productMAGENTO_HOST, MAGENTO_ACCESS_TOKEN
mailcheck1emailMAILCHECK_API_KEY
mailchimp14member, memberTag, listGroup, campaignMAILCHIMP_API_KEY
mailerlite4subscriberMAILERLITE_API_KEY
mailgun1emailMAILGUN_API_KEY, MAILGUN_EMAIL_DOMAIN
mailjet3email, smsMAILJET_API_KEY, MAILJET_SECRET_KEY
mandrill2messageMANDRILL_API_KEY
marketstack3endOfDayData, exchange, tickerMARKETSTACK_API_KEY
matrix10account, room, message, event, roomMemberMATRIX_HOMESERVER_URL, MATRIX_ACCESS_TOKEN
mattermost19channel, message, reaction, userMATTERMOST_URL, MATTERMOST_TOKEN
mautic20company, contact, contactSegment, campaignContact, companyContact, segmentEmailMAUTIC_URL, MAUTIC_USERNAME, MAUTIC_PASSWORD
medium3post, publication, meMEDIUM_ACCESS_TOKEN
messagebird2sms, balanceMESSAGEBIRD_ACCESS_KEY
metabase10question, alert, database, metricMETABASE_URL, METABASE_SESSION_TOKEN
microsoftCalendar2calendar, event
microsoftFiles5files, folder
microsoftMail4mail
misp44attribute, event, eventTag, feed, galaxy, noticelist, object, organisation, tag, user, warninglistMISP_URL, MISP_API_KEY
mocean2sms, voiceMOCEAN_API_KEY, MOCEAN_API_SECRET
monday18board, boardColumn, boardGroup, boardItemMONDAY_API_TOKEN
monicaCrm45contact, activity, note, task, tag, journalEntry, reminder, call, conversationMONICA_API_TOKEN
msg911smsMSG91_AUTHKEY
nasa14apod, asteroidNeoFeed, asteroidNeoLookup, asteroidNeoBrowse, donki, earthAssetsNASA_API_KEY
netlify7deploy, siteNETLIFY_ACCESS_TOKEN
netscalerAdc3certificate, fileNETSCALER_URL, NETSCALER_USERNAME, NETSCALER_PASSWORD
nextcloud13file, folder, userNEXTCLOUD_WEBDAV_URL, NEXTCLOUD_USERNAME, NEXTCLOUD_PASSWORD
nocodb5rowNOCODB_HOST, NOCODB_API_TOKEN
node38fs, path, os, process, crypto, fetch
notion14block, database, page, userNOTION_API_KEY
npm5package, distTag
odoo6record, modelODOO_URL, ODOO_USERNAME, ODOO_PASSWORD
okta5userOKTA_URL, OKTA_API_TOKEN
oneSimpleApi10website, socialProfile, information, utilityONE_SIMPLE_API_TOKEN
onfleet34organization, task, worker, admin, hub, team, recipient, container, destinationONFLEET_API_KEY
openai2imageOPENAI_API_KEY
openThesaurus1synonyms
openweathermap2weatherOPENWEATHERMAP_API_KEY
oura4profile, summaryOURA_ACCESS_TOKEN
paddle9coupon, payment, plan, product, userPADDLE_VENDOR_ID, PADDLE_VENDOR_AUTH_CODE
pagerduty9incident, incidentNote, logEntry, userPAGERDUTY_API_TOKEN
parallel1searchPARALLEL_API_KEY
paypal4payout, payoutItemPAYPAL_CLIENT_ID, PAYPAL_SECRET
peekalink2linkPEEKALINK_API_KEY
phantombuster5agentPHANTOMBUSTER_API_KEY
philipsHue4lightPHILIPS_HUE_ACCESS_TOKEN, PHILIPS_HUE_USERNAME
pipedrive47activity, deal, dealProduct, file, lead, note, organization, person, productPIPEDRIVE_API_TOKEN
plaud9user, recording, transcript, summary, note
plivo3sms, mms, callPLIVO_AUTH_ID, PLIVO_AUTH_TOKEN
postbin6bin, request
posthog5alias, event, identity, trackPOSTHOG_URL, POSTHOG_API_KEY
profitwell2company, metricPROFITWELL_ACCESS_TOKEN
pushbullet4pushPUSHBULLET_ACCESS_TOKEN
pushcut1notificationPUSHCUT_API_KEY
pushover1messagePUSHOVER_API_TOKEN
quickbase8field, file, record, reportQUICKBASE_HOSTNAME, QUICKBASE_USER_TOKEN
quickbooks45bill, customer, employee, estimate, invoice, item, payment, purchase, vendorQUICKBOOKS_ACCESS_TOKEN, QUICKBOOKS_COMPANY_ID
quickchart1chart
raindrop13bookmark, collection, tag, userRAINDROP_ACCESS_TOKEN
recraft2imageRECRAFT_API_KEY
reddit10post, comment, subreddit, user
replicate2imageREPLICATE_API_TOKEN
rocketchat1chatROCKETCHAT_DOMAIN, ROCKETCHAT_USER_ID, ROCKETCHAT_AUTH_TOKEN
rundeck2jobRUNDECK_URL, RUNDECK_TOKEN
salesforce63connection, auth, limits, metadata, soql, account, contact, lead, opportunity, case, task, user, sobject
salesmate15company, activity, dealSALESMATE_SESSION_TOKEN, SALESMATE_LINKNAME
securityScorecard14company, industry, portfolio, portfolioCompany, invite, reportSECURITYSCORECARD_API_KEY
segment4identify, track, groupSEGMENT_WRITE_KEY
sendgrid10mail, contact, listSENDGRID_API_KEY
sendy6campaign, subscriberSENDY_URL, SENDY_API_KEY
sentry21event, issue, organization, project, release, teamSENTRY_TOKEN
servicenow40incident, user, userGroup, userRole, businessService, configurationItem, department, tableRecordSERVICENOW_SUBDOMAIN, SERVICENOW_USERNAME, SERVICENOW_PASSWORD
shiftAtlas35summary, graph, stage, actor, line, journey, labels, change, task, assignment, relation, binding, evidenceSHIFT_LABS_API_KEY
shiftCrm40access, account, person, pipeline, opportunity, activity, task, record, propertyDefinition, importSHIFT_CRM_API_KEY
shiftObjects8objectSHIFT_LABS_API_KEY
shiftOcr2ocrSHIFT_LABS_API_KEY
shiftPages11pageSHIFT_LABS_API_KEY
shiftTranscription7transcriptionSHIFT_LABS_API_KEY
shiftWork29project, issue, issueViewSHIFT_LABS_API_KEY
shopify10order, productSHOPIFY_SUBDOMAIN, SHOPIFY_ACCESS_TOKEN
signl42alertSIGNL4_TEAM_SECRET
slack38message, channel, reaction, user, userGroup, file, starSLACK_ACCESS_TOKEN
sms772sms, voiceSMS77_API_KEY
splunk16search, alert, report, userSPLUNK_BASE_URL, SPLUNK_AUTH_TOKEN
spotify30player, album, artist, playlist, track, library, myDataSPOTIFY_ACCESS_TOKEN
stackby4rowSTACKBY_API_KEY
steel59session, scrape, browser, screenshot, pdf, page, file, sessionFile, credential, profile, extension, captchaSTEEL_API_KEY
storyblok7content, management
strapi5entrySTRAPI_URL
strava9activitySTRAVA_ACCESS_TOKEN
stripe20balance, customer, charge, coupon, customerCard, source, token, meterEventSTRIPE_SECRET_KEY
supabase5rowSUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY
syncromsp20customer, contact, ticket, rmmAlertSYNCROMSP_SUBDOMAIN, SYNCROMSP_API_KEY
tapfiliate11affiliate, affiliateMetadata, programAffiliateTAPFILIATE_API_KEY
telegram21message, chat, callback, fileTELEGRAM_BOT_TOKEN
thehive23alert, case, observable, task, logTHEHIVE_URL, THEHIVE_API_KEY
thehiveProject37alert, case, task, observable, comment, log, page, queryTHEHIVE_URL, THEHIVE_API_KEY
todoist31task, project, section, comment, labelTODOIST_API_TOKEN
together2imageTOGETHER_API_KEY
travisci5buildTRAVISCI_API_TOKEN
trello37board, boardMember, card, cardComment, list, attachment, checklist, labelTRELLO_API_KEY, TRELLO_TOKEN
twake1messageTWAKE_API_KEY
twilio2sms, callTWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN
twist22channel, thread, comment, messageConversationTWIST_ACCESS_TOKEN
twitter8tweet, user, list, dmTWITTER_BEARER_TOKEN
typesafe7evaluate, choice, score, noul, raw, model, guideTYPESAFE_API_KEY
unleashedSoftware3salesOrder, stockOnHandUNLEASHED_API_ID, UNLEASHED_API_KEY
uplead2person, companyUPLEAD_API_KEY
uproc1processUPROC_EMAIL, UPROC_API_KEY
uptimerobot22account, monitor, alertContact, maintenanceWindow, publicStatusPageUPTIMEROBOT_API_KEY
urlscanio3scanURLSCANIO_API_KEY
vercel14whoami, project, deployment, envVERCEL_TOKEN
vero8user, eventVERO_AUTH_TOKEN
vonage1smsVONAGE_API_KEY, VONAGE_API_SECRET
wekan24board, list, card, cardComment, checklist, checklistItemWEKAN_URL, WEKAN_TOKEN
wolt20venue, menu, item, account, address, order
woocommerce15product, order, customerWOOCOMMERCE_URL, WOOCOMMERCE_CONSUMER_KEY, WOOCOMMERCE_CONSUMER_SECRET
wordpress15post, page, userWORDPRESS_URL, WORDPRESS_USERNAME, WORDPRESS_PASSWORD
xai2imageXAI_API_KEY
xero8invoice, contactXERO_ACCESS_TOKEN, XERO_TENANT_ID
yourls3urlYOURLS_URL, YOURLS_SIGNATURE
zammad22user, organization, group, ticketZAMMAD_URL, ZAMMAD_TOKEN
zendesk18ticket, user, organization, ticketFieldZENDESK_SUBDOMAIN, ZENDESK_EMAIL, ZENDESK_API_TOKEN
zoho60account, contact, deal, invoice, lead, product, purchaseOrder, salesOrder, vendor, quoteZOHO_ACCESS_TOKEN
zoom5meetingZOOM_ACCESS_TOKEN
zulip15message, stream, userZULIP_URL, ZULIP_EMAIL, ZULIP_API_KEY

Examples

# List all available actions
runline actions
# List actions only for connected services
runline actions --connected

# Get Nike's brand colors
runline exec 'return await brandfetch.brand.getColors({ domain: "nike.com" })'

# Create a GitHub issue
runline exec '
  return await github.issue.create({
    owner: "acme", repo: "api",
    title: "Bug: login broken",
    labels: ["bug", "urgent"]
  })
'

# Search Pipedrive deals
runline exec 'return await pipedrive.deal.search({ term: "Acme" })'

# Chain actions together
runline exec '
  const contact = await hubspot.contact.get({ id: "123" });
  const task = await todoist.task.create({
    content: `Follow up with ${contact.properties.firstname}`,
    priority: 4
  });
  return { contact: contact.properties.email, taskId: task.id };
'

# Discover actions from inside the runtime
runline exec 'return actions.list()'
runline exec 'return actions.list("brandfetch")'
runline exec 'return actions.find("create issue")'
runline exec 'return actions.describe("github.issue.create")'
runline exec 'return actions.check("github.issue.create", { owner: "a" })'

# Output as JSON (for agents)
runline exec 'return await github.repo.list({ owner: "torvalds" })' --json

Writing a Plugin

Plugins export a function that receives a RunlinePluginAPI and registers actions. Use TypeBox schemas by default for both connection config and action input schemas; Runline uses them for action discovery, actions.check(...), and runtime validation before execute runs.

import type { RunlinePluginAPI } from "runline";
import * as t from "typebox";

export default function orders(rl: RunlinePluginAPI) {
  rl.setName("orders");
  rl.setVersion("1.0.0");

  // Connection config — env vars override config.json values
  rl.setConnectionSchema(t.Object({
    apiKey: t.String({ env: "ORDERS_API_KEY" }),
    baseUrl: t.String({ env: "ORDERS_BASE_URL" }),
  }));

  rl.registerAction("list", {
    access: "read",
    description: "List orders for an organization",
    inputSchema: t.Object({
      orgId: t.String(),
      status: t.Optional(t.String({ description: "open, closed, or all" })),
      limit: t.Optional(t.Number()),
    }),
    async execute(input, ctx) {
      const { orgId, status, limit } = input as Record<string, unknown>;
      const url = new URL(`${ctx.connection.config.baseUrl}/orgs/${orgId}/orders`);
      if (status) url.searchParams.set("status", status as string);
      if (limit) url.searchParams.set("limit", String(limit));

      const res = await fetch(url.toString(), {
        headers: { Authorization: `Bearer ${ctx.connection.config.apiKey}` },
      });
      if (!res.ok) throw new Error(`Orders API ${res.status}: ${await res.text()}`);
      return res.json();
    },
  });

  rl.registerAction("create", {
    access: "write",
    description: "Create a new order",
    inputSchema: t.Object({
      orgId: t.String(),
      customer: t.String(),
      total: t.Number(),
    }),
    async execute(input, ctx) {
      const res = await fetch(`${ctx.connection.config.baseUrl}/orders`, {
        method: "POST",
        headers: {
          Authorization: `Bearer ${ctx.connection.config.apiKey}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify(input),
      });
      if (!res.ok) throw new Error(`Orders API ${res.status}: ${await res.text()}`);
      return res.json();
    },
  });
}

Custom plugins are discovered from the nearest project .runline/ directory first, then .runline/plugins.json, then ~/.runline/plugins, then the bundled built-ins named by configured connections. Project-local plugins win over same-named global or built-in plugins; duplicates discovered later are skipped and reported on stderr.

Supported local layouts:

.runline/plugins/orders.ts
.runline/plugins/orders.js
.runline/plugins/orders/index.ts
.runline/plugins/orders/index.js
.runline/plugins/orders/src/index.ts
.runline/plugins/orders/src/index.js
.runline/plugins/orders/package.json   # { "main": "dist/index.js" }

A package directory can also expose multiple plugins:

{
  "runline": { "plugins": ["./orders.js", "./billing.js"] }
}

plugins.json can also point at explicit plugin paths:

{
  "plugins": [{ "path": "./tools/orders.ts" }]
}

A plugin may export the default registration function shown above, or a plain plugin definition object with { name, version, actions }. ESM, TypeScript, and CommonJS object exports are supported. The function form is preferred because it validates plugin names, keeps action registration consistent, and gives authors the public RunlinePluginAPI surface.

Actions can include optional access: "read" | "write" metadata. Use read for actions that only retrieve data, and write for anything that creates, updates, deletes, sends, uploads, executes, triggers, deploys, imports, changes config, writes local files, or may otherwise affect an external system. Omit it only for legacy compatibility; built-in plugins include it.

Plugin execute handlers run outside the QuickJS runtime with full Node.js access (fetch, fs, npm dependencies available to the host process, etc). Agent code calls them through configured plugin globals. ctx.connection.config contains the resolved connection config with env var overrides applied, and ctx.updateConnection(patch) can persist refreshed credentials. Add a node connection only when you explicitly want to expose host APIs through the built-in node plugin.

Agents can inspect custom plugins from inside runline exec before calling them:

runline exec 'return actions.list("orders")'
runline exec 'return actions.find("list orders")'
runline exec 'return actions.describe("orders.list")'
runline exec 'return actions.check("orders.list", { orgId: "acme" })'
runline exec 'return await orders.list({ orgId: "acme", status: "open" })'

For debugging, run runline actions --json to see loaded actions, access metadata, and schemas. Loader failures include the plugin path and reason on stderr. A broken plugin does not stop discovery of healthy plugins in the same directory; common failures include invalid exports, invalid plugin names, malformed package.json/plugins.json, missing entrypoints, and duplicate plugin names.

See packages/runline-plugins/ for 211 real-world examples.

Sandbox

Agent code runs in a QuickJS WASM runtime:

  • Timeout — configurable, kills infinite loops
  • Memory limit — configurable, prevents OOM
  • console.log — captured and returned in result.logs
  • Plugin globals — each installed plugin is a top-level proxy (e.g. github, slack, brandfetch). Dot-chain into resource and action: github.issue.create(input)
  • Configured Node globals — when configured, the built-in node plugin exposes host-backed actions such as node.fs.readFile, node.fs.writeFile, node.path.join, node.os.info, node.process.execFile, node.crypto.hash, and node.fetch

For Agents

Every command supports --json. Use runline actions --json for full schemas with input types.

runline actions --json          # all actions with schemas
runline actions --connected --json  # only connected services
runline exec '<code>' --json    # structured { result, logs } output

SDK

import { Runline } from "runline";
import brandfetch from "runline-plugin-brandfetch";

const rl = Runline.create({
  plugins: [brandfetch],
  connections: [{ name: "bf", plugin: "brandfetch", config: { apiKey: "xxx" } }],
});

const result = await rl.execute(`
  const colors = await brandfetch.brand.getColors({ domain: "stripe.com" });
  return colors.filter(c => c.type === "accent");
`);

console.log(result.result);  // [{ hex: "#635BFF", type: "accent", brightness: 116 }]

CLI Reference

runline exec "<code>"                  # execute JS in the QuickJS runtime
runline exec -f ./script.js            # execute a file
runline actions                        # list all actions
runline actions --connected            # only actions for configured connections
runline plugin install <source>        # install from git/npm/local
runline plugin list                    # list installed plugins
runline plugin remove <name>           # remove a plugin
runline connection add <n> -p <plugin> -s key=val  # add connection
runline connection list                # list connections
runline connection remove <name>       # remove a connection
runline init                           # create .runline/ directory

Configuration

.runline/config.json:

{
  "connections": [
    { "name": "gh", "plugin": "github", "config": { "token": "ghp_xxx" } },
    { "name": "bf", "plugin": "brandfetch", "config": { "apiKey": "xxx" } }
  ],
  "timeoutMs": 30000,
  "memoryLimitBytes": 67108864
}

Env vars override config values. Plugins declare env var names in their connection schema (e.g. GITHUB_TOKEN).

Development

Runline is a bun workspace monorepo: packages/runline (library + CLI), packages/runline-plugins (204 built-in plugins, bundled into runline's dist at build time), and packages/pi-runline (pi extension that exposes runline to agents).

bun install
bun --filter runline dev -- exec 'return 1 + 2'
bun --filter runline test
bun run check

Pi integration

The pi-runline package is a pi extension that plugs runline into coding agents as a single native tool:

  • execute_runline — run JavaScript in the runline runtime. Discovery happens inside the runtime via actions.list / find / describe / check, so the agent never needs a separate listing tool.

It ships with /runline-plugins, a fuzzy multi-select picker for choosing which of the 202 plugins the agent should see, plus a guided credential prompt for the ones you enable.

pi install npm:pi-runline
# then in any pi session inside a project with .runline/
/runline-plugins

See packages/pi-runline/README.md for details.

How It Relates to dripline

dripline is query mode — SQL tables over live APIs. runline is code mode — JavaScript actions over the same APIs. Same plugin architecture, same connection config, different interface. Use dripline when you want to SELECT rows; use runline when you want to create, update, delete, or chain multiple API calls together.

License

MIT