Repository navigation
Feature request: headless/print mode + SDK support for freebuff authToken (for third-party orchestrators) #947
Description
Activity
- addedarea:cliThe Codebuff/Freebuff terminal clientThe Codebuff/Freebuff terminal clientbot:triagedClassified by the community triage botClassified by the community triage bottype:featureA request for new behaviorA request for new behavior
on Aug 19, 2026 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
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.
- added a commit that references this issue
on Sep 20, 2026 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:
- 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 ofcli-args.tsstrips[prompt...]and only acceptslogin. 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. - 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 existinginitialPrompt->useChatInput-> queue ->useFreebuffChatAdmissionpath, so the session starts with the saved model and every ad surface renders exactly as when the user types. Parser tests 20/20; help becomesfreebuff [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-jsonemitting the existingPrintModeEventunion fromcommon/src/types/print-mode.tsas NDJSON, plus one new event type:{"type":"ad", "provider", "title", "body", "url", "impUrl"}.- The ad is fetched through the same
buildAdAuctionRequestthe dock uses (same placement names, samex-freebuff-envdescriptor, 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
adTokento every ad it serves in headless mode. The nextsession/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 structuredad_requirederror the host has to surface. - Ack timing is checked server-side: an ack that arrives before
renderDelayMshas elapsed since the ad was served is treated as not shown. - Hosts identify themselves (
clientInfo.namein ACP,--clientin 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
adevent land behind a server-side capability flag or in a different seam, say so and I will shape the PR that way.- 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 (
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:
--print/-pheadless flag on thefreebuffCLI (mirroring whatcodebuffexposes, or at least what the@codebuff/sdkexposes viahandleEvent).authTokento work with@codebuff/sdk'sCodebuffClientso the free ad-supported account can run agents programmatically — not just interactively.Background
Freebuff is the free, ad-supported build of Codebuff. Today the
freebuffCLI is purely interactive — a TUI with no headless path. I verified this against the installed native binary (freebuffv0.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"])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'sCodebuffClient.run(), which requires a paidCODEBUFF_API_KEY(cb_...).The freebuff CLI stores credentials at
~/.config/manicode/credentials.jsonwith shape:{ "default": { "id", "name", "email", "authToken", "fingerprintId", "fingerprintHash" } }This
authTokenis a device-OAuth token, not acb_...API key. Passing it toCodebuffClient({ 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/-pon the CLI (preferred, lowest friction)freebuff -p "refactor the auth module" --output-format stream-json --verbosePrintModeEventshape the SDK already defines:start,text,tool_call,tool_result,subagent_start,subagent_finish,error,finish,reasoning_delta).--cwd,--continue [id],--agent <id>.adevent (or print ad text to stderr) before the run starts; require--ads-ackor an env var to acknowledge.Option B —
@codebuff/sdkaccepts the freebuff authTokenThis 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
freebuffnpm package is a thin launcher (index.js→launcher.js) that downloads a 124MB native binary to~/.config/manicode/freebuff.codebuff(no--agent,--max,--plan,[prompt...]).--headlessand--jsonstrings exist inside the binary but come from bundledchrome-devtools-mcp(browser-use agent), not from the CLI's own flag parser.@codebuff/sdkexists, is published, and exposesCodebuffClient.run()withhandleEvent: (event: PrintModeEvent) => void— exactly the streaming protocol an orchestrator needs..codebuff/mcp.json), not an MCP server — so MCP is not a viable transport for driving it as a provider.Related
/mcpstatus command — useful but orthogonal.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.