Skip to content

Repository files navigation

Cogway

Run Codex, Claude Code and OpenCode on your own Notion AI subscription.

Cogway is a local bridge. Your coding client thinks it is talking to OpenAI or Anthropic; the bridge translates each request into a Notion AI conversation and translates the answer back into the tool calls your client expects. Nothing leaves your machine except the Notion request itself.

🚀 Quick start in 5 minutes · 🇷🇺 Русская версия · 💬 Telegram: @oxyarmor

Warning

This is an unofficial integration with Notion's private API. It authenticates with the token_v2 browser cookie, which is as sensitive as your password. Automated access is very likely against Notion's terms of service, and your account is the thing at risk. Read Limits, scaling and risk before relying on it.


Contents


How it works

┌───────────────┐   ┌──────────────┐   ┌───────────────┐
│  Codex CLI /  │   │ Claude Code  │   │   OpenCode    │
│  Codex VS Code│   │              │   │               │
└───────┬───────┘   └──────┬───────┘   └───────┬───────┘
        │ Responses        │ Messages          │ Chat Completions
        └──────────────────┼───────────────────┘
                           ▼
              ┌────────────────────────┐
              │  bridge  127.0.0.1:8765│
              │                        │
              │  planner   protocol    │  one JSON action envelope,
              │  turns     executor    │  shared by all three adapters
              │  state     sessions    │  one Notion thread per session
              │  account_pool          │  up to 10 sessions, failover
              └───────────┬────────────┘
                          │  notion-agent-cli + token_v2
                          ▼
              ┌────────────────────────┐
              │       Notion AI        │
              │ fable-5 / gpt-5.6-sol  │
              │       / opus-5         │
              └────────────────────────┘

The one thing worth understanding. Notion AI has no native tool calling. So the bridge asks the model for a JSON action envelope:

{"actions": [{"tool": "Read", "arguments": {"file_path": "src/app.py"}}]}

and converts it back into a real tool_use / function_call for your client. Your client still owns the agent loop, the approvals, the sandbox and the file edits — the bridge only supplies the thinking.

Everything else follows from that:

Piece Job
bridge/planner.py Builds the prompt, renders the tool catalog, parses and validates the actions that come back
bridge/turns.py Leases an account, continues or starts a Notion thread, fails over, maps errors
bridge/state.py Keeps one client session inside one Notion thread so history is not resent every turn
bridge/account_pool.py Round-robin over your Notion sessions, per-account cooldown, circuit breaker
bridge/*_api.py One adapter per client protocol
notion-private-api-mcp/ Optional MCP server for reading and writing Notion pages
runtime/ Optional local file/shell tools, for clients that bring none

Models available through the bridge:

Shown in your client Bridge id Codex transport id
Fable 5 (Notion) — default fable-5 gpt-5.5
GPT-5.6 Sol (Notion) gpt-5.6-sol gpt-5.6-sol
Opus 5 (Notion) opus-5 opus-5

Which of these you can actually use depends on your Notion plan. Run cogway doctor --live after installing: it sends one short request per model and tells you exactly which ones answer on your account.

Codex only accepts a fixed set of transport ids, which is why Fable travels as gpt-5.5; the bridge maps it back. Claude Code's own model ids (claude-sonnet-4-5-*, claude-opus-4-*, claude-3-5-haiku-*) are mapped automatically, so /model opus and /model sonnet both work.


Requirements

  • Node.js 18+ and Python 3.10+ on PATH
  • Git
  • A Notion account with Notion AI enabled
  • One of: Codex CLI, Codex for VS Code (openai.chatgpt), Claude Code, OpenCode

Works on Windows 10/11, Linux and macOS. No root, no systemd, no admin rights.


Install

Tip

Would rather not do this by hand? Install OpenCode. It installs independently of Cogway and runs on free models. Open this folder in it, pick a free model — DeepSeek V4 Flash, for example — and say "install this project following the instructions in AGENTS.md". The agent does everything below.

This needs plain opencode, not cogway opencode: the latter already goes through the bridge, which does not exist yet. Claude Code and Codex cannot run the install for the same reason — they have no provider until it is finished.

Three commands on every platform.

git clone https://github.com/coldvisixn/cogway.git
cd cogway
cogway setup

On Linux and macOS write ./cogway setup. If the wrapper does not run at all, node cli/index.mjs setup does exactly the same thing.

setup creates a Python virtual environment, installs dependencies, writes a .env, registers every client it can find, and starts the bridge. It never overwrites your existing editor settings — it merges into them and takes a backup first.

Then add your Notion session:

cogway login

and confirm everything is healthy:

cogway doctor --live
Windows PowerShell — same commands
git clone https://github.com/coldvisixn/cogway.git
Set-Location .\cogway
cogway setup
cogway login
cogway doctor

If node is not recognised, install Node.js from nodejs.org and reopen the terminal. If python opens the Microsoft Store, install Python from python.org with Add Python to PATH ticked.

Useful setup options
# Restrict file tools to one directory instead of your whole home folder
cogway setup --code-root ~/projects

# Only register some clients
cogway setup --clients claude,codex

# Install without starting anything
cogway setup --no-start

# Also run the optional local-tools server
cogway setup --local-tools

Optionally, start the bridge with your user session:

cogway autostart        # systemd --user, launchd, or Startup
cogway autostart --off  # undo

Getting your Notion token

cogway login walks you through this, but here it is in full:

  1. Open https://www.notion.so in a browser and sign in.
  2. Open DevTools (F12).
  3. Go to Application (Chrome/Edge) or Storage (Firefox) → Cookieshttps://www.notion.so.
  4. Find the row named token_v2 and copy its Value.
  5. Run cogway login, paste the value, press Enter, then Ctrl+Z and Enter on Windows, or Ctrl+D on Linux/macOS.

The token is read from stdin, so it never appears in your shell history or in the process list. It is stored in ~/.notionagents/notion_account.json with 0600 permissions.

Treat this value like a password. It grants full access to your Notion workspace, not just to Notion AI. Signing out of Notion in the browser invalidates it, which is also how you revoke it if it leaks.

If login reports several workspaces, name the one you want:

cogway login --space-name "My Workspace"

Using it

Claude Code

setup writes the provider settings into ~/.claude/settings.json. Restart Claude Code and check with /status that the API base URL points at 127.0.0.1. Then use it normally:

> refactor the retry logic in src/http.py and run the tests

/model opus selects Notion Opus 5, /model sonnet selects Fable 5.

Codex CLI

codex

Codex reads the managed block in ~/.codex/config.toml and uses the Notion provider automatically.

Codex for VS Code

Install the official openai.chatgpt extension, run Developer: Reload Window, open a new Codex chat and pick a Notion model. setup also applies a small idempotent compatibility patch to the extension's model picker so that Opus 5 (Notion) is listed. Rerun setup after the extension updates.

OpenCode

cogway opencode

This launches OpenCode against an isolated profile in .runtime/opencode/, so your global OpenCode configuration is left alone.


Configuration

Everything lives in one .env at the repository root. Real environment variables always win, which is how a second checkout runs beside the first. See .env.example for the annotated list.

Variable Default What it does
COGWAY_BRIDGE_HOST 127.0.0.1 Interface for the bridge. Keep it loopback: there is no authentication
COGWAY_BRIDGE_PORT 8765 Bridge port
NOTION_AGENT_HOME ~/.notionagents Where Notion sessions are stored
CODE_ROOT your home The furthest a file tool may reach
COGWAY_INFERENCE_TIMEOUT_SECONDS 180 When to give up on one Notion request and try another account
COGWAY_REASONING_EFFORT high low, medium or high
COGWAY_MAX_ACCOUNTS 10 Upper bound on loaded Notion sessions
COGWAY_LOCAL_TOOLS off Run the optional local-tools server
COGWAY_RUNTIME_PORT 8787 Port for that server
MCP_PATH_SECRET generated Required when local tools are on
COGWAY_WORKFLOW_ID empty Route inference through a specific Notion custom agent

Context and token limits

These are local settings. Raising a number here does not enlarge the real Notion model window — it only changes when your client decides to compact.

Limit Default Where
Context window reported to Codex 210,000 cli/clients.mjs, config/codex-models.json
Auto-compaction threshold 200,000 total same
Tool output budget 12,000 same
OpenCode context / output 100,000 / 40,000 cli/clients.mjs

Keep the compaction threshold below the reported window. After changing anything, rerun setup and start a fresh chat.

Images are limited to 10 per request, 20 MiB each and 50 MiB in total, and are uploaded as native Notion attachments.


Command reference

cogway setup [--code-root DIR] [--clients a,b] [--local-tools] [--no-start]
cogway login [--account auto|NAME] [--space-name NAME]
cogway logout [--account NAME | --all]
cogway start [--foreground] | stop | restart
cogway autostart [--off]
cogway status [--json]
cogway doctor [--live]
cogway update
cogway install <client...> | uninstall <client...>
cogway opencode [args...]

--live spends one Notion request per model per account; everything else is free. npm run setup, npm start, npm run status and npm run doctor are shortcuts for the same commands.

Adding more accounts never needs a name:

cogway login --account auto
cogway restart

Running several Notion accounts

The bridge can hold up to ten Notion sessions and spread new conversations across them. Add extras with:

cogway login --account account-02
cogway login --account account-03
cogway restart

Files live in ~/.notionagents/accounts/. Duplicates — same token_v2 or the same Notion user — are detected and ignored, so you cannot accidentally multiply one account.

Replacing the token of a dead account

An account whose allowance is spent, whose token expired, or which was suspended keeps occupying its slot. Point login at that same slot and the new token replaces the old one:

cogway status                          # find the disabled or cooling-down one
cogway login                           # replaces the primary session
cogway login --account account-02      # replaces that named session
cogway restart

login says which file it is about to replace before asking for the token, and the new token is checked against Notion first — if you paste a bad value the working session stays. Use --account auto only when you are adding an account: it takes the next free slot and leaves the dead one behind, and there are only ten slots.

Replacing in place is enough on its own. A new token is a different account as far as the pool is concerned, so the old cooldown and disabled flag do not follow it — the slot starts clean.

Starting over when every account is gone

If all ten slots hold dead accounts, free them and register new ones:

cogway logout                    # list what is stored
cogway logout --account account-02   # drop one
cogway logout --all              # drop all of them and the pool bookkeeping
cogway login                     # register the first new session
cogway login --account auto      # ...and each further one
cogway restart

logout on its own only lists; it never deletes without --account or --all. A name it does not recognise is an error rather than a silent no-op, so a typo cannot leave you believing a dead account is gone.

A new session picks the least recently used account and stays on it for the whole conversation, so the Notion thread is reused instead of resending history. On failure the account is put in cooldown and the request retries on the next one.

Before you scale this up, read Limits, scaling and risk. It covers where the real bottlenecks are, how rate limiting actually behaves, and the account-suspension risk you take on.


FAQ

Does this use my Notion AI subscription? Yes. Every request is a normal Notion AI conversation on your account, and counts against whatever limits your plan has.

Is it against Notion's terms of service? Very likely. You are using a private API with a session cookie, from something that is not the Notion client. Nobody has published a carve-out for this. The risk is yours and it lands on your Notion account. See docs/scaling.md.

Does my code get sent to Notion? Only what your client puts in the prompt — the same code, file contents and tool results it would send to any other provider. The bridge itself stores no conversation content: session state on disk is hashes, ids and counters only.

Which client works best? Codex has the most mature path here. Claude Code is fully supported: multiple tool calls per turn, real streaming, thread reuse. OpenCode works through the OpenAI-compatible endpoint.

Can I use it with Cline, Roo, Continue, Zed or Aider? They speak OpenAI Chat Completions or Anthropic Messages, so pointing them at http://127.0.0.1:8765/v1 will probably work. It is not tested and not supported; cogway install does not configure them.

Why not Gemini CLI or Cursor? Gemini CLI speaks Google's generateContent protocol with its own OAuth, which would need a whole separate adapter. Cursor requires a publicly reachable HTTPS endpoint and will not accept a loopback address. Neither can be supported well, so neither is claimed.

Why is one action per turn the default for Codex? It is not — the planner may return several independent actions in one envelope, and they are emitted as several output items. It only returns one when the next step genuinely depends on the previous result.

Can I run two checkouts at once? Yes. Give the second one its own .env with a different COGWAY_BRIDGE_PORT, or export the variables directly. Real environment variables override the file.

Does it work offline? No. Notion AI is the model.


Troubleshooting

Start with cogway doctor. It checks the toolchain, the configuration, your credentials and the running services, and prints the exact command to fix whatever it finds.

doctor says no .env

Run cogway setup, or copy .env.example to .env.

healthz reports configured: 0

The bridge found no usable account file. Run cogway login, then cogway restart — the pool is read once at startup.

Requests fail with authentication_error

Same cause: no valid Notion session. This is deliberately not a 503, so your client stops retrying instead of looping on an unfixable error.

An account shows cooldown

Not an installation problem. Notion rejected a request, so the bridge stops using that session for a while and moves to the next. retry_after shows the remaining seconds. If one account is permanently failing, refresh its token_v2 with cogway login --account <name>.

An account shows disabled

Its token is invalid or the account has no Notion AI access. Replace that session in place — cogway login for the primary one, cogway login --account account-02 for a named one — then cogway restart. See Replacing the token of a dead account.

AmbiguousWorkspaceError during login

The token can reach several workspaces. Retry with --space-name "Exact Workspace Name".

The models do not appear in VS Code

Confirm doctor is clean, run Developer: Reload Window, then open a new chat — an already-running Codex app-server keeps its old configuration. If only Opus is missing after an extension update, rerun setup.

Answers come back suspiciously fast and noticeably worse

Check the model aliases:

cogway doctor          # verifies them for you

~/.notionagents/models.json must map fable-5 → acai-budino-high, gpt-5.6-sol → orange-mousse, opus-5 → agave-flan. A wrong alias silently routes you to a smaller model. Do not guess replacements — rerun setup.

Port already in use

cogway stop      # stops by pid, or by port if the pid file is gone
cogway start

If something else owns the port, change COGWAY_BRIDGE_PORT in .env and rerun setup so the client configs follow.

Claude Code ignores the bridge

Check /status inside Claude Code. If the base URL is not 127.0.0.1, an ANTHROPIC_BASE_URL exported in your shell is overriding the settings file; environment variables win over settings.json.

Answers stop coming and doctor --live reports empty_text

The Notion AI allowance on that account is spent. Notion does not report this through the API — it closes the stream with no content and no error, and shows the human-readable notice ("you have used up your Notion credit") only on notion.so. Open the site to confirm.

A paid plan's allowance resets on its own schedule. The free allowance is a one-time trial and does not return — Notion offers an upgrade instead. Cogway cannot change that; it takes the account out of rotation with an escalating pause so the exhausted session is not retried every 30 seconds.

Windows SmartScreen or an antivirus blocks the start

The bridge is launched as a background process through PowerShell, which some antivirus products and SmartScreen treat as suspicious. Allow it, or add the project directory to the exclusions.

A model is listed in my editor but never answers

That model is not on your Notion plan. cogway doctor --live names the ones that are; pick one of those.

The service stops when I close the terminal

It should not — the bridge is started outside the terminal's process group. If it still happens, use cogway autostart to register it with your session manager instead.

Reading the logs

tail -f .runtime/logs/bridge.err.log      # Linux / macOS
Get-Content .runtime\logs\bridge.err.log -Wait   # Windows

Logs are structured JSON: request ids, account ids, segment numbers, selection reason (balanced, affinity, failover), durations and error codes. Prompts, tool results, cookies and images are never logged.


Development

# Bridge tests
PYTHONPATH=bridge .runtime/notion-agent-cli-venv/bin/python -m unittest discover -s bridge/tests -v

# CLI and runtime tests
node --test cli/clients.test.mjs scripts/patch-codex-webview.test.mjs
npm --prefix runtime test

# Syntax checks and release audit
npm run check
node scripts/check-public-release.mjs

Repository conventions for AI agents working on this codebase are in AGENTS.md.


Security and licence

  • The bridge binds to loopback and has no authentication. Do not expose it.
  • token_v2 is never read, printed, copied or committed by any tooling here.
  • Client configs are merged, never replaced, and backed up before writing.
  • Session state on disk contains no conversation content.

Report vulnerabilities as described in SECURITY.md. Run node scripts/check-public-release.mjs before publishing.

Source-available, not open source: read it, run the copy you were licensed, modify it for yourself — but do not redistribute or resell it. Full terms in LICENSE. The vendored notion-private-api-mcp/ is third-party code and keeps its own MIT licence.


Author and feedback

Cogway is written by @oxyarmor — the developer's Telegram channel.

That is the place for:

  • Ideas and feature requests. Which client to support next, which limit to make configurable, what the CLI should do that it does not.
  • Bug reports from real use. Especially the ones a test suite cannot find: a Notion API change, a client update that breaks the model picker, an error message that says nothing useful.
  • Release news. New versions and Notion-side breakage are announced there first, usually before the repository catches up.
  • A thank you, if it saved you an afternoon. It is read, and it is the only payment the open part of this project asks for.

👉 https://t.me/oxyarmor

About

Local bridge: run Codex, Claude Code and OpenCode on your Notion AI account. Unofficial, ToS risk.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages