Skip to content

Feature request: headless/print mode + SDK support for freebuff authToken (for third-party orchestrators) #947

Description

@micahcooley

Summary

Requesting two related capabilities that would make Freebuff drivable by third-party orchestrators (e.g. Koryphaios, Zed via ACP, CI runners) without a TTY:

  1. A --print / -p headless flag on the freebuff CLI (mirroring what codebuff exposes, or at least what the @codebuff/sdk exposes via handleEvent).
  2. Allowing the freebuff device-OAuth authToken to work with @codebuff/sdk's CodebuffClient so the free ad-supported account can run agents programmatically — not just interactively.

Background

Freebuff is the free, ad-supported build of Codebuff. Today the freebuff CLI is purely interactive — a TUI with no headless path. I verified this against the installed native binary (freebuff v0.0.140, ~/.config/manicode/freebuff):

  • freebuff -p / --print → error: unknown option '-p'
  • freebuff --headless → error: unknown option '--headless'
  • freebuff --json → error: unknown option '--json'
  • freebuff "do something" → no [prompt...] argument accepted (only [command] with choices ["login"])
  • piping a prompt via stdin → hangs waiting for a TTY

The codebuff (paid) CLI has more flags (--agent, --max, --plan, [prompt...]) but also lacks --print/--json — headless execution today is only available through @codebuff/sdk's CodebuffClient.run(), which requires a paid CODEBUFF_API_KEY (cb_...).

The freebuff CLI stores credentials at ~/.config/manicode/credentials.json with shape:

{ "default": { "id", "name", "email", "authToken", "fingerprintId", "fingerprintHash" } }

This authToken is a device-OAuth token, not a cb_... API key. Passing it to CodebuffClient({ apiKey }) is untested and may be rejected by the backend (different token class, fingerprint validation, ad-enforcement requirements, etc.).

Why this matters

Third-party agent orchestrators (I'm building Koryphaios) currently wrap CLI agents like Claude Code, Codex, Grok Build, Cursor, Devin, and Cline by spawning their binaries in --print/headless mode and parsing their NDJSON/JSONL event streams. Freebuff is the only major free CLI agent with no headless path at all, which means it's the only one we can't offer as a provider — even though it's the one users without paid subscriptions need most.

Freebuff's "6 one-hour sessions per day" limited mode is a usage policy, not a technical barrier — there's no reason it couldn't be enforced in a headless run too (show the ad text as a structured event, count the session, enforce the clock).

Proposed design

Option A — --print / -p on the CLI (preferred, lowest friction)

freebuff -p "refactor the auth module" --output-format stream-json --verbose
  • Emits one JSON object per line on stdout (same PrintModeEvent shape the SDK already defines: start, text, tool_call, tool_result, subagent_start, subagent_finish, error, finish, reasoning_delta).
  • Reads the initial prompt from the CLI arg or stdin.
  • Honors --cwd, --continue [id], --agent <id>.
  • No TTY required; safe for CI and subprocess spawning.
  • Ad enforcement: emit an ad event (or print ad text to stderr) before the run starts; require --ads-ack or an env var to acknowledge.

Option B — @codebuff/sdk accepts the freebuff authToken

import { CodebuffClient } from '@codebuff/sdk'
// Read from ~/.config/manicode/credentials.json instead of CODEBUFF_API_KEY
const client = new CodebuffClient({ apiKey: freebuffAuthToken, fingerprintId, ... })

This already works for paid keys — the ask is just to accept the freebuff device-OAuth token as a valid credential for run(), with the same session/ad limits enforced server-side. This is the cleanest path for orchestrators that already speak the SDK event protocol.

Option C — both

A is the universal solution (works for any subprocess-based integrator). B is the ergonomic solution for Node/TS integrators. They're complementary.

What I've already verified

  • The freebuff npm package is a thin launcher (index.js → launcher.js) that downloads a 124MB native binary to ~/.config/manicode/freebuff.
  • The native binary uses Commander.js; the freebuff flag set is intentionally stripped vs codebuff (no --agent, --max, --plan, [prompt...]).
  • The --headless and --json strings exist inside the binary but come from bundled chrome-devtools-mcp (browser-use agent), not from the CLI's own flag parser.
  • @codebuff/sdk exists, is published, and exposes CodebuffClient.run() with handleEvent: (event: PrintModeEvent) => void — exactly the streaming protocol an orchestrator needs.
  • Freebuff/Codebuff is an MCP client (consumes .codebuff/mcp.json), not an MCP server — so MCP is not a viable transport for driving it as a provider.

Related

Willing to contribute

Happy to help prototype/test either option against a real third-party orchestrator integration. I have a working provider harness for 7 other CLI agents and can validate the event-mapping end-to-end.

Activity

  1. added
    area:cliThe Codebuff/Freebuff terminal client
    bot:triagedClassified by the community triage bot
    type:featureA request for new behavior
    on Aug 19, 2026
  2. philly88r commented on Aug 30, 2026

    @philly88r

    LocalTry would like to be an early integration partner for this.\n\nWe operate a multi-tenant, provider-neutral CRM where each business can select its own primary and fallback AI model route. We would like to offer Freebuff as an explicitly user-connected option, but only through an official supported boundary that respects Freebuff's advertising, per-person session limits, privacy disclosures, and Terms.\n\nOur requirements are:\n\n- official per-user OAuth/device authorization, never pooled or shared accounts\n- a documented headless SDK or API event stream for text generation\n- revocation and health/status checks\n- tenant-isolated credentials and usage\n- explicit permission for use inside a commercial SaaS integration\n- structured errors for limits, model availability, and reauthentication\n\nWe will not use the unofficial reverse proxies or imitate the CLI gate. We can build and test the LocalTry connector as soon as an approved interface is available, and we would be glad to beta-test or contribute to the official implementation.\n\nCould the Freebuff team confirm whether the planned SDK/headless support will cover this use case, or whether an enterprise/integration agreement is the correct path? Contact: phillip@localtry.com

  3. Praket7 commented on Sep 7, 2026

    @Praket7

    I am building a third party MCP bridge for Freebuff Desktop at https://github.com/Praket7/freebuff-mcp.

    The current Desktop build exposes useful local read state through its orchestrator, including projects, threads, visible messages, and project files. Independent callers can reach the mutation routes, but they are correctly rejected with HTTP 403 because the Desktop launch authorization is held by the authorized Desktop execution path.

    The bridge does not extract, proxy, or bypass that authorization. It would be useful to have a supported local companion capability for legitimate programmatic control. A scoped local integration token, named pipe, loopback companion API, Desktop launched child MCP server, ACP endpoint, or authorized SDK would all be viable options.

    The requested interface should remain local only, use a credential separate from the Freebuff account and Desktop launch credential, support explicit pairing and revocation, and route actions through the existing thread engine so normal model eligibility, reasoning validation, usage limits, ads, notices, attachments, and account controls remain intact.

    This would allow safe interoperability with MCP clients while preserving the current Desktop security boundary.

  4. ojspace commented on Oct 3, 2026

    @ojspace

    Adding a data point from the integrator side, plus a first PR.

    What blocks third-party tools today is smaller than headless mode. Launchers, orchestrators and IDE integrations generally have two lanes:

    1. Terminal lane: open the agent's own TUI in a pane with the task already typed in. Every major agent takes the prompt as an argument (claude "<p>", codex "<p>", opencode --prompt "<p>", kilo --prompt "<p>", copilot -i "<p>", goose run --interactive --text "<p>", codebuff "<p>"). Freebuff is the only one that rejects it: the Freebuff build of cli-args.ts strips [prompt...] and only accepts login. The TUI, ads, landing screen and session limits are all untouched in this lane; the tool just cannot hand over the task, so Freebuff gets left out of the agent picker.
    2. Headless lane: claude -p --output-format stream-json, codex exec --json, or ACP over stdio. This is the lane Feature request: headless/print mode + SDK support for freebuff authToken (for third-party orchestrators) #947 and [Feature request] ACP Support #319 ask for.

    Lane 1 is a parser change with no product question attached, so I opened #1477 for it: accept [prompt...] in the Freebuff CLI, routed through the existing initialPrompt -> useChatInput -> queue -> useFreebuffChatAdmission path, so the session starts with the saved model and every ad surface renders exactly as when the user types. Parser tests 20/20; help becomes freebuff [options] [prompt...].

    For lane 2, a proposal that keeps the ad economics intact (happy to prototype whichever shape the team prefers):

    • freebuff -p "<prompt>" --output-format stream-json emitting the existing PrintModeEvent union from common/src/types/print-mode.ts as NDJSON, plus one new event type: {"type":"ad", "provider", "title", "body", "url", "impUrl"}.
    • The ad is fetched through the same buildAdAuctionRequest the dock uses (same placement names, same x-freebuff-env descriptor, same device signing), and the impression is reported the same way, so an ad shown in a host tool's transcript counts like an ad shown in the TUI. The host renders it; a tool that wants Freebuff has every reason to, since the free tier is why its users picked Freebuff. A host that drops the event gets no further turns, which the server can enforce from the missing impression.
    • Session admission is unchanged: the headless run POSTs the same session as the chat path, so daily limits, Freebucks, country and VPN checks all apply. No new credential class, no SDK API-key path.
    • ACP ([Feature request] ACP Support #319) then becomes a thin adapter over the same event stream, and Freebuff lands in Zed and every other ACP client at once, ads included.

    Enforcement, so a host cannot quietly drop the ads. The ad must be worth the same in a chat UI as in the TUI, and that cannot rest on the host's goodwill:

    • The server attaches an adToken to every ad it serves in headless mode. The next session/prompt (or the next step of the run) must carry the impression ack for that token, with the same engagement fields the TUI reports (visibleMs, viewport, exit reason). No ack, no next turn: the run ends with a structured ad_required error the host has to surface.
    • Ack timing is checked server-side: an ack that arrives before renderDelayMs has elapsed since the ad was served is treated as not shown.
    • Hosts identify themselves (clientInfo.name in ACP, --client in print mode) and the server can rate-limit or revoke a client whose ack pattern looks synthetic, exactly as it can for a modified TUI today.
    • The free tier stays free in a chat UI only while ads are on screen there; a host that wants ad-free runs is pointed at Codebuff Pro keys, which is the paid path that already exists.

    This keeps the economics identical across surfaces: one served ad, one verified impression, one turn. If the team would rather have the ad event land behind a server-side capability flag or in a different seam, say so and I will shape the PR that way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:cliThe Codebuff/Freebuff terminal clientbot:triagedClassified by the community triage bottype:featureA request for new behavior

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions