Model or dataset
Mininglamp-OSS/octo-cli avatar
Mininglamp-OSS/octo-cli

octo-cli: a metadata-driven REST client built for agent runtimes

Metadata-driven CLI for AI Agent Bots — 48 operations across 7 domains, structured JSON envelope I/O, zero interactive prompts.

859 stars129 forksGoApache-2.0

At a glance

What is it?
Mininglamp's Go CLI turns embedded OpenAPI 3.x specs into a command tree for AI Agent Bots, with structured JSON output and no interactive prompts. It is thin by design, and the domain table shows which parts of that surface are actually available.
Who is it for?
Adopt octo-cli if you are wiring an agent runtime to the Octo backend and want a single binary that returns parseable JSON instead of a TUI. Do not adopt it as a general-purpose HTTP client or if your target is the matter or summary domain, both of which the README marks temporarily withheld.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

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

DEEP OPEN-SOURCE ANALYSIS

The problem octo-cli solves: agents that need a CLI, not a shell

An agent runtime that shells out to a REST API has three chores: constructing the URL, holding a token, and parsing whatever comes back. Most CLIs are built for humans and make all three worse. They print tables, prompt for confirmation, and colourise output that a parser then has to strip.

octo-cli inverts that. The README states it is a thin, single-binary REST client designed for AI Agent Bots to call via exec from agent runtimes (OpenClaw, Claude Code, and similar). Every invocation emits a structured JSON envelope on stdout, errors go to stderr with a deterministic taxonomy, and there is no interactive I/O. That last property is the real product. A command that can never block on a prompt is a command an agent can call without a timeout guard around it.

The intended audience is narrow and worth stating plainly: teams operating bots inside the Octo ecosystem, where the backend services are matters and dmworkim. This is not a general HTTP tool that happens to speak JSON. It is the transport layer for one platform.

How the command tree is built from OpenAPI specs at startup

The architecture is the interesting part. The README describes the flow as OpenAPI specs (embedded) to Registry (parsed) to Service Engine (cobra commands) to Factory (DI) to Client (HTTP) to Output (envelope). The command tree is auto-registered at startup from OpenAPI 3.x specs embedded into the binary. Adding or changing an endpoint means editing a spec, not the code.

That has a concrete consequence for anyone reading the source: the Go code contains no per-endpoint handlers to review. If you want to know what message search files actually sends, the spec is the place to look, not a hand-written function. The trade-off is that the spec becomes the contract, and a malformed or under-specified spec surfaces as a broken command rather than a compile error.

Two design choices are visible in the README's key properties. First, unified gateway routing: each operation declares its complete module-qualified path and uses OCTO_API_BASE_URL, so there is no per-domain host configuration to keep in sync. Second, factory DI: internal/cmdutil.Factory is the dependency container, with no mutable package-level globals. Tests inject stubs through ConfigFunc, CredentialFunc, ClientFunc and RegistryFunc. That is a testability claim rather than a runtime one, but it explains why the binary can stay thin without becoming untestable.

The README also states the client is thin by design: all business logic lives in backend services. Validation and formatting are what remains locally. Do not expect the CLI to protect you from a semantically wrong request that the server accepts.

Installing octo-cli and authenticating as a bot

Four installation paths are documented. For Node-based agent runtimes the README gives npm install -g @mininglamp-oss/octo-cli, and notes the npm package resolves the matching platform sub-package which already contains the prebuilt binary, so install does not download binaries from GitHub. Go users can run go install github.com/Mininglamp-OSS/octo-cli/cmd/octo-cli@latest. A Homebrew tap is listed as coming soon, which means the brew install Mininglamp-OSS/tap/octo-cli line is not usable yet. Release archives and an install.sh script round out the options; the README points out that Windows archives are .tar.gz as well, since Windows 10+ ships tar.exe.

Authentication is a single environment variable. The Quick Start sets OCTO_BOT_TOKEN to a bf_ prefixed user bot token. OCTO_API_BASE_URL is optional and defaults to production, with the README showing https://im-test.deepminer.com.cn as the test example.

One local constraint is documented for search: message search requires a User Bot bf_ token or a user API key uk_ token, and an App Bot app_ token is rejected locally. That is a useful detail, because it means the failure happens before a network round trip.

The README also shows a mail flow with a policy-aware send. mail message send-intent takes --to, --subject, --text and --idempotency-key, and the server may accept the message or save a Draft depending on the mailbox's current outbound mode. Draft update replaces the entire draft: omitted cc, bcc, text, html or attachments are removed, so you must read the draft first and resend every field that should remain. That is a destructive default worth knowing before an agent edits mail.

The domain table is the honest part of the README

The repository lists operations across many domains, and the counts do not tell a simple story. docs has 32 operations, html has 20, drive has 43 plus 3 composite commands for 46 leaves, loop has 126. Then matter has 14 operations and is marked temporarily withheld while the backend API stabilizes. summary has 4 operations and is also withheld, pending the create backend referenced as Mininglamp-OSS/octo-smart-summary#181 being merged, deployed and enabled.

So a reader scanning the table for task management will find the command names documented and the domain unavailable. The Quick Start repeats the warning inline: the matter domain is temporarily withheld. This is a good-faith disclosure rather than a hidden gap, but it changes the adoption calculus. An agent that needs todos has no path through this CLI today.

The html domain carries a second caveat: it is a separate backend from docs, despite both dealing with documents. Anyone assuming a shared routing or shared identifiers between docs and html should verify that against the specs rather than the table.

Where octo-cli is the wrong tool

The thin-client design is a limitation as much as a feature. Because validation is local and business logic is remote, the CLI cannot tell you that a channel_id is wrong until the server rejects it. There is no dry-run mode described in the README, and no schema validation step documented before the request leaves the process. An agent that constructs malformed payloads gets a server error, not a local one, which costs a round trip and a retry.

The envelope is also a fixed shape. The README describes identity, data, pagination and rate-limit metadata, and a small fixed error taxonomy. If your runtime wants a different shape, you are writing a translation layer, and the jq example in the README (file download abc123 --jq '.data.url') suggests the project expects you to do exactly that for field extraction. That is fine, but it means octo-cli is not a drop-in for a generic HTTP client in a pipeline that already speaks a different format.

Finally, the withheld domains are a real boundary. If your use case depends on matter or summary, the tool is not merely immature for you, it is absent, and no configuration key changes that.

How this differs from calling the REST API directly

The obvious alternative is a generic HTTP client plus the Octo API documentation: curl, or a language SDK, with the token in a header and the JSON parsed by your own code. The difference is not capability, since octo-cli is documented as transport, validation and formatting over the same backend. The difference is what you maintain.

With a generic client, every endpoint you call is code you wrote: URL assembly, module-qualified paths, error mapping, retry semantics. With octo-cli, the path and the operation set come from the embedded specs, and the error taxonomy is fixed by the project. You trade control over the request shape for not owning the endpoint list. If the upstream API adds an operation and the spec is updated, the command appears in the next release without you writing anything. If you need behaviour the spec does not describe, you are waiting on the project.

A closer alternative for agent runtimes is a language-native SDK, which avoids the exec boundary entirely. That removes process spawn overhead and gives you typed responses instead of a JSON envelope you parse. It also means your agent runtime must be written in that language. octo-cli's single-binary, exec-based model is what makes it language-agnostic, and that is the specific thing an SDK cannot offer.

Release cadence and what the Apache-2.0 licence leaves you to decide

The release history shows v0.15.0, v0.14.0 and v0.13.0 landing roughly weekly in the weeks before the last push, with the version still below 1.0. A pre-1.0 version number is a maintenance signal: the README already documents one domain withheld for backend stabilization and another blocked on an upstream issue, so the surface can change between minor versions. Pinning a version in your agent runtime is the practical response, since the npm package resolves a platform sub-package and the Go install path uses @latest by default.

The project is licensed Apache-2.0. That permits commercial and private use and includes an explicit patent grant, and it requires that you retain the licence and notice files and state significant changes. It does not grant trademark rights. This is a description of the licence text, not legal advice; if you are redistributing the binary inside a product, have counsel read the NOTICE requirements rather than relying on a summary.

Upgrade cost is mostly the spec surface. Because commands are registered from embedded specs, a release can add operations without you touching your integration, but it can also change an operation's parameters. The README's draft update behaviour is an example of a semantic change that would bite silently: an agent that omits fields on a draft update deletes them.

Editorial conclusion

Adopt octo-cli if you are wiring an agent runtime to the Octo backend and want a single binary that returns parseable JSON instead of a TUI. Do not adopt it as a general-purpose HTTP client or if your target is the matter or summary domain, both of which the README marks temporarily withheld. Before committing, run one message send against a test base URL and confirm the envelope shape and error taxonomy match what your runtime parses.

Official sources

  1. License: Apache-2.0
  2. Mininglamp-OSS/octo-cli on GitHub
  3. Project website
  4. README
  5. Releases
Community notes

Community notes