GenOffice is an open-source, AI-native office suite built on Electron: a word processor, a spreadsheet editor, a presentation builder, and a PDF viewer, tabbed together under one shell. Five apps share one promise underneath them: file-format fidelity. Open a .docx, .xlsx, or .pptx, make your edits, and everything you didn't touch comes back byte-identical. GenOffice parses the original file, tracks only the blocks you change, and splices narrow patches back into the source XML on save; the rest of the archive is copied through untouched.
Every app carries the same AI panel: block-level editing with version history in Docs, a tool-calling agent over the live workbook in Sheets, and a constrained layout-scripting agent in Slides that edits presentations through a fixed set of validated primitives rather than free-form code. All three share two packages under the hood: agent-core for the tool-calling loop, and ai-provider for talking to whichever model backend is configured.
That last part is the hook for this article. ai-provider already speaks plain OpenAI-compatible HTTP. Out of the box, GenOffice points it at Genspark. Point it at Token Station instead, and nothing about the apps changes: only where the tokens come from.
Why run it on Token Station
Genspark works the moment you sign in, and that's the right default. But it's one account, one model roster, and a credit balance you refill on Genspark's terms. Token Station changes the shape of that relationship in two ways that matter for a desktop app you run every day.
| Genspark (default) | Token Station | |
|---|---|---|
| Account / credit | Single account, single credit pool | Pay-as-you-go, no monthly or annual contract |
| Models | Roster fixed by the integration | 250+ models across 25+ providers, pick per task |
| Pricing | Credits tied to a Genspark plan | One key, provider rates, zero markup |
Pay-as-you-go, not a contract. Token Station has no subscription tier. Register free, no card required, and a $1 credit lands in your balance immediately. From there you pay provider rates on the models you actually call, nothing recurring and nothing to cancel. Some models, like NVIDIA NIM, cost nothing at all.
Freedom to choose the model. A gateway account isn't pinned to one vendor's lineup. Run GenOffice Docs on Claude for long-form editing, switch Sheets to a cheaper model for routine formula work, and point Slides at whichever image-capable model fits the deck, all through the same key and the same OpenAI-style endpoint, with no separate signup per provider.
Because Token Station speaks the same OpenAI-compatible wire format GenOffice's custom provider slot already expects, wiring it in is a routing change, not a rewrite.
Setup: patch your GenOffice checkout
These are the actual changes that route GenOffice's AI traffic to Token Station instead of Genspark. Apply them to your own fork or branch; nothing here depends on a specific GenOffice release.
1. Install prerequisites and confirm the baseline build runs
You'll need Node.js and npm on your machine.
git clone <your-fork-url> genoffice
cd genoffice
npm install
npm run dev
Confirm the shell launches and the AI panel opens normally. At this point it runs on Genspark by default, with no sign-in prompt unless you actually send a message while logged out.
2. Add an environment-driven override to the shared provider package
packages/ai-provider already defines a custom provider: any OpenAI-compatible baseUrl / apiKey / model. Add a small function that fills it in from an environment variable, the same pattern the codebase already uses for Genspark's own key (GSK_API_KEY).
packages/ai-provider/src/providers.ts
export const TOKEN_STATION_BASE_URL = 'https://models.bytefuture.ai/v1'
const TOKEN_STATION_DEFAULT_MODEL = 'anthropic/claude-opus-4-8'
export function applyTokenStationEnvOverride(
settings: AiSettings,
env: NodeJS.ProcessEnv = process.env,
): AiSettings {
const apiKey = env.TOKEN_STATION_API_KEY
if (!apiKey) return settings
return {
provider: 'custom',
providers: {
...settings.providers,
custom: {
apiKey,
model: env.TOKEN_STATION_MODEL || TOKEN_STATION_DEFAULT_MODEL,
baseUrl: TOKEN_STATION_BASE_URL,
},
},
}
}
Export it from the package's index.ts alongside defaultAiSettings and resolveAiSettings.
3. Stop each app from forcing Genspark, and apply the override
Docs, Sheets, and Slides each register an ai:get-settings IPC handler that hard-resets the provider on every read. Remove that line and call the new override instead. Same shape in all three files:
apps/docs/src/main/docs-main.ts (mirrored in apps/slides/src/main/ai-ipc.ts and apps/sheets/src/main/sheets-main.ts)
// before
ipcMain.handle('ai:get-settings', (): AiSettings => {
const stored = readJson<Partial<AiSettings> & LegacyAiSettings>(SETTINGS_PATH(), {})
const settings = resolveAiSettings(stored, defaultAiSettings())
settings.provider = 'genspark' // ← delete this
return settings
})
// after
ipcMain.handle('ai:get-settings', (): AiSettings => {
const stored = readJson<Partial<AiSettings> & LegacyAiSettings>(SETTINGS_PATH(), {})
return applyTokenStationEnvOverride(resolveAiSettings(stored, defaultAiSettings()))
})
Sheets' handler looks slightly different in two harmless ways: it takes an IPC channel constant instead of a string literal, and calls a sessionFor(event) check first. The substance is identical: delete the forced-genspark line, call the new override.
4. Get a key and point the environment at it
Register at Token Station, grab an API key from the dashboard, then set it as a persistent environment variable and restart your terminal (environment variables only apply to processes launched afterward).
# Windows (PowerShell)
[Environment]::SetEnvironmentVariable("TOKEN_STATION_API_KEY", "gw_...", "User")
# macOS / Linux — add to your shell profile
export TOKEN_STATION_API_KEY=gw_...
Optional: set TOKEN_STATION_MODEL to any Token Station provider/model id (for example openai/gpt-5.5) to override the default. Relaunch GenOffice: chat, editing, and planning across Docs, Sheets, and Slides now all run on Token Station. Slides' one-shot deck generation is the one feature that needs an additional patch, in step 5.
5. One more patch for Slides' deck generation
Slides' generate_deck/regenerate_slide tools originally called a Genspark-only cloud endpoint directly, bypassing the provider system entirely. They need their own patch, in three parts. If you're only routing Docs and Sheets, you can stop at step 4.
apps/slides/src/renderer/ai/slides-skill.ts: add two optional fields to the DeckAccess interface: a sync aiProvider() getter, and a composePageElements() method that returns a validated element list instead of an HTML marker. Then gate both tools on the active provider instead of a hard Genspark-only check:
const useCloud = cloudAvailable
&& (access.aiProvider?.() ?? 'genspark') === 'genspark'
if (!useCloud) {
// fall back to runLocalDeckGeneration() / runLocalRegenerateSlide()
}
apps/slides/src/renderer/ai/local-deck-gen.ts (new file): the module that actually does the composing: asks the configured provider for each page's layout as JSON (shapes, text boxes, charts, images), validates it, and builds it with the same add_shape / add_text_box / add_chart / insert_web_image primitives the app's own agent tools already use.
apps/slides/src/renderer/ai/AiPanel.tsx: wire the two new DeckAccess fields to the same request path generateStyleSkill/planDeckOutline already use. This piece is easy to miss: without it, aiProvider stays undefined and the gate above silently falls back to Genspark.
aiProvider: () => settingsRef.current.provider,
composePageElements: async (args) => {
const { system, user } = buildPageComposePrompt(args)
const r = await runLlmOnce(system, user, undefined, true, args.signal)
if (!r.ok || !r.text) return { ok: false, error: r.error ?? tGlobal('aiErrEmptyOutput') }
return parsePageElementsJson(r.text, args.canvasW, args.canvasH)
},
Known limits of the local path, v1: it's append-only, new pages clone the current last slide, and "replace whole deck" isn't supported yet. Local regenerate_slide also replaces content elements only; background and theme inheritance are left untouched, unlike the cloud version.
See it running
Three short demos, one per app, all running on Token Station.
Where to learn more
- Token Station: pricing & signup
- Token Station: full model catalog
- GenOffice: source on GitHub
- GenOffice: contributing guide
Sign up at models.bytefuture.ai ($1 in free credit, no card required), export TOKEN_STATION_API_KEY, and relaunch GenOffice. One key, one endpoint, every model your Docs, Sheets, and Slides sessions need.