CLI tool
withoneai/cli avatar
withoneai/cli

One CLI trades OAuth tokens for one connection key

A command-line tool to give your agents access to any app, create workflows and manage your One account.

412 stars10 forksTypeScriptLicense varies

At a glance

What is it?
withoneai/cli gives an agent authenticated access to more than 750 platforms by routing every call through One's passthrough proxy, which injects credentials and normalises responses. Install is one npx command, flows live as JSON in your repository, and the Node 18 support has one hole in it.
Who is it for?
Fit for an agent that has to touch several SaaS platforms at once and where nobody wants to maintain per-platform OAuth clients, since the credential handling, the rate limiting and the response shapes are somebody else's problem. A poor fit if you need the raw tokens yourself, or if your agent needs a platform One does not proxy, and a poor fit on Node 18 if you rely on `one sync`.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 7 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 4, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Every call goes through one passthrough proxy

The architecture is drawn as a four step chain, and the third line is the whole product:

code
Your AI Agent
    ↓
  One CLI
    ↓
  One API (api.withone.ai/v1/passthrough)
    ↓
  Gmail / Slack / Shopify / HubSpot / Stripe / ...

Every API call is routed through that passthrough rather than being sent by the CLI directly to the platform. The proxy injects the right credentials, handles rate limiting and normalises responses. What you hold instead of an OAuth token is a connection key, which is the object you pass to an action.

The scale claim is 750 or more platforms, with Gmail, Slack, Shopify, HubSpot, Stripe and Notion named as examples. What the CLI removes is stated as three things: API keys to juggle, OAuth flows to build, and request formats to memorise.

The consequence is worth being clear about, because it cuts both ways. Nothing local holds a platform credential, which is good, and nothing local holds a platform credential, which also means every action depends on the proxy being reachable and on One's normalisation matching what your agent expects.

Four commands from nothing to a sent email

The quick start is four lines, and the third one is the part that is different from writing a client by hand:

bash
one add gmail
bash
one actions find gmail "send an email" --task "email a hello to a contact"
bash
one actions execute gmail <actionId> <connectionKey> \
  -d '{"to": "[email protected]", "subject": "Hello", "body": "Sent from my AI agent"}'

The pattern is that actions are discovered rather than memorised. `one actions find` takes a platform, a natural language description and a task string, and returns actions with their documentation attached, so the agent reads the docs for the call it is about to make rather than working from a hand written schema.

Execution then takes the platform, the action identifier, the connection key and a JSON payload with `-d`. `one list` sits in the same sequence as the command that shows what you are connected to. The README describes the result as going from zero to a sent Gmail message, fully authenticated and correctly formatted, without touching a single OAuth token.

The consent page names the key and everything attached to it

Authentication happens in a browser, and the CLI is explicit about what that browser is told. The consent page names the key and tags it with where this CLI is installed: the scope, the project path, the machine, the OS user, the CLI version, the chosen harnesses, and the per-install device id unless telemetry is off.

That list is long enough to be worth reading twice. A project path and a machine name are the two entries that identify you rather than the tool, and the device id is the one that behaves like a stable identifier across runs. The opt-out named is telemetry, and the device id is the item attached to it.

The rest of the design is about reversibility. Because the consent page names the key, you can find it and revoke it from Settings to API keys rather than guessing which credential belongs to which machine. And the terminal prints exactly what will be sent before the browser opens, so the disclosure happens in the place where you can still stop.

Signing out is `one logout`, which clears credentials after a scope picker and a confirmation, so you can remove one install rather than all of them.

Node 18 works until you run one sync

The stated requirement is Node.js 18 or newer, and there is one exception with a specific cause. `one sync` additionally needs Node 20 or newer, because its local SQLite engine, `better-sqlite3`, is an optional dependency that ships prebuilt binaries only for Node 20 and above.

The failure mode is described accurately, which is rarer than it sounds. On Node 18 every other command works normally, and `one sync` reports that the engine is not installed rather than crashing or falling back to a slower path. So the tool degrades in one place and says so.

That matters because the local database is where `sync` state lives, which is what makes flows and connections usable without a network round trip. Someone on Node 18 gets a working CLI for everything else and a missing feature for that one command, and the README tells them exactly which case they are in.

The package metadata agrees on the floor: the engines field asks for Node 18 or newer, with no upper bound.

Two config scopes, and a resolution order you can print

`one init` is interactive and asks where the setup should live, and the two answers have different consequences.

Global scope writes `~/.one/config.json` and applies to every folder, which is the right choice when one workspace and one API key is all you need. Project scope writes `~/.one/projects/<slug>/config.json` under your home directory rather than in the repository, and the reason given is that secrets never land in git. That is the scope to use when different projects need different API keys, different connections or different access control.

Resolution has an order you can inspect. When you run `one` in a project it uses the project config if one exists and falls back to the global one otherwise, and `one config path` prints which config is active along with the full resolution order.

The monorepo rules are the part that will bite. The project root is the nearest ancestor with `.one/`, `.git` or `package.json`, checked in that order, and `mkdir .one` in a nested subproject makes it its own root keyed by that directory's slug. One exclusion is called out explicitly: your home directory is never treated as a project root, because `~/.one` is the CLI's own config directory and a dotfiles `.git` or a stray `package.json` in `$HOME` should not turn everything under home into one project.

Flows are JSON in your repo, and the flat layout still loads

Multi-step flows are the part that turns the CLI into something an agent can be given a task in. Actions are chained across platforms into reusable workflows, and the definition is passed inline at creation time as JSON with a key, a name, a version, typed inputs and a list of steps. Each input can be required and can carry a connection bound to a platform, which is how a single flow asks for a Stripe customer and then sends a Gmail welcome email.

On disk the layout is a directory, not a file. Workflows live at `.one/flows/<key>/flow.json`, with an optional `lib/` subfolder for `.mjs` code modules, and new flows should be created in that folder layout. Flows can be grouped into subdirectories at `.one/flows/<group>/<key>/flow.json` and referenced as `group/key`, or by the bare key when it is unique.

The old single-file layout, `.one/flows/<key>.flow.json`, is deprecated but still loads for backward compatibility, which means an existing project keeps working while new ones should not copy that shape. Flow features cover conditions, loops, while loops, parallel steps, transforms, sub-flows, pagination, bash steps and external `.mjs` modules, and `one guide flows` prints the full reference.

--auth takes the prompts out of setup entirely

Setup is designed to be driven by an agent rather than a person. Passing `--auth` makes `one init` run end to end with no terminal interaction, which the README frames as handy when an AI agent is onboarding you. It saves the key, auto-installs the One skill, and skips the connect step, leaving `one add` for later.

There are two authentication modes. `browser` opens a login window and finishes when the window closes, and `manual` takes a key, which is the headless and CI path:

bash
one init --auth browser            # opens a login window; you authenticate, the window closes — done
one init --auth manual --api-key sk_live_...   # headless / CI, no browser

The flag table around it covers the rest of the non-interactive surface. `-y` skips confirmations, `-g` writes the global config at `~/.one/config.json`, and `-p` writes the project config at `~/.one/projects/<slug>/config.json`, with scope defaulting to global. `--api-key` takes either a live or test key.

The agents supported are Claude Code, Claude Desktop, Cursor, Windsurf, Codex and Kiro, and the MCP server is installed into them automatically during init. Running `one init` again is also safe: it reports the status for the active scope and offers to update the key, install to more agents or reconfigure.

Three database engines are declared and one is explained

The package file declares more local storage than the README talks about. `pgserve` is a runtime dependency, and three more sit in optional dependencies: `@electric-sql/pglite`, `better-sqlite3` and `pg`. That is four database related entries for what the documentation describes as one local SQLite engine with a Node 20 constraint.

So the picture is a CLI that can serve or embed a Postgres locally, that can use PGlite, that can use the `pg` driver, and that can use SQLite, while the only constraint documented is the prebuilt binary limitation of `better-sqlite3`. That is not a contradiction, but it is a place where the documentation is thinner than the package.

Two other details from the same file are worth noting. The package is `@withone/cli` at version 2.1.0, marked as an ES module, with a single binary named `one` pointing at `./bin/cli.js`, and the published files are limited to `bin`, `dist`, `skills` and `profiles`, so the shipped package is small by design. There is no LICENSE file in the repository and no license field in the package file, so the terms are not stated in either place.

Editorial conclusion

Fit for an agent that has to touch several SaaS platforms at once and where nobody wants to maintain per-platform OAuth clients, since the credential handling, the rate limiting and the response shapes are somebody else's problem. A poor fit if you need the raw tokens yourself, or if your agent needs a platform One does not proxy, and a poor fit on Node 18 if you rely on `one sync`. Before the first run, read `one config path` rather than guessing which config file is active, decide global versus project scope deliberately since the choice determines where your key lives, and check the consent output, because the device id is sent unless telemetry is off.

Frequently asked questions

What does the One CLI do?

It gives an AI agent authenticated access to more than 750 platforms through a single interface, and every call is routed through One's passthrough proxy at api.withone.ai/v1/passthrough, which injects the credentials, handles rate limiting and normalizes responses. You work with a connection key and never handle raw OAuth tokens yourself.

How do I install and authenticate the One CLI?

Run npx @withone/cli@latest init, or install it globally with npm install -g @withone/cli and then run one init. Setup authenticates through a browser or takes an API key, and the MCP server is installed automatically into Claude Code, Claude Desktop, Cursor, Windsurf, Codex or Kiro. Node.js 18 or newer is required, and one sync additionally needs Node 20 or newer.

What does the One CLI send to its consent page?

The consent page names the key and tags it with the scope, project path, machine, OS user, CLI version, chosen harnesses and the per-install device id unless telemetry is off, so the key can be found and revoked from Settings to API keys. The terminal prints exactly what will be sent before the browser opens.

Official sources

  1. Issues
  2. Project website
  3. README
  4. Releases
  5. withoneai/cli on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/withoneai-cli.svg)](https://hysenlabs.com/projects/withoneai-cli)