Getting started
This page goes from one command to the demo workspace, then to your own project and your coding agent. All but the last section run on your own machine, with no account anywhere.
What you need
- Node 22.12 or later. Check with
node --version. - A browser on the same machine.
- For your own project: its git repository, where the
.turnkeel/folder will live.
Nothing else. Local mode keeps its database and its files in a folder, and needs no Postgres, no Docker and no account.
Start Turnkeel
npx turnkeel
This starts Turnkeel on http://127.0.0.1:4400 and opens your browser. Your data goes to ~/.turnkeel, or to the folder that TURNKEEL_DATA_DIR names. Ctrl-C stops it.
| Option | What it does |
|---|---|
--port 4500 |
Another port. TURNKEEL_PORT does the same. |
--no-open |
Opens no browser and prints the one-time address instead. |
--no-demo |
Skips the demo on the first run and asks for a workspace name instead. |
The one-time sign-in address
Local mode has no sign-in page. At each start Turnkeel makes a one-time address, and your browser opens at it. That browser gets a cookie and is you, the Owner of every workspace in this install. The address works once. A new start makes a new one, and the cookie of the start before stops working.
http://127.0.0.1:4400/api/v1/local/session?code=…
- For a second browser, press Enter in the terminal where
turnkeelruns. It prints a new address. - Turnkeel listens on the loopback address only, so other machines cannot reach it.
- Agents and the command line never use this address. They use tokens.
Local mode is for one person. It stops requests that come without the cookie or a token, but a program that runs as your user on the same machine can read the data folder. A team runs the server with sign-in, as described at the end of this page.
Look around the demo
The first run opens a demo workspace: Example Notes, a note-taking app for iOS and Android that does not exist, with invented people and agents and every tab filled in. Every page says "Demo data" beside the workspace name, and so does every figure in Money. Nothing in the demo is sent anywhere, and it has no assistant.
Start on Your turn and open each line. Its gates, listings and docs come from files bundled with the server, so they cannot be edited there.
When you are done, choose Remove demo data in the workspace menu and name your own workspace. The demo stops showing, and its rows stay in the local database. For a database with no demo rows at all, start with an empty data folder and turnkeel --no-demo.
Connect Claude Code over MCP
An agent works with a token of its own. The token sets what the agent may read and write, and in which projects. It never lets the agent approve, accept a decision, pass a gate a person must pass, publish, send or spend.
An Owner or Admin makes the token: workspace menu, Agents and tokens, create an agent, then a token with its scopes and projects. The token is shown once. In the demo, the token for the agent builder is shown on the first page instead.
Put the address and the token in the environment Claude Code runs in:
export TURNKEEL_URL=http://127.0.0.1:4400
export TURNKEEL_TOKEN=tk_…
Print the MCP configuration and add it to the project's .mcp.json. It names the server turnkeel and refers to TURNKEEL_TOKEN. The token itself is never in it.
turnkeel mcp config
Optional: add the hooks, so the Agents tab shows what each session is doing and when it needs you. The command shows the change and asks before it writes .claude/settings.local.json.
turnkeel hooks install
Cursor and Codex use the same MCP server: turnkeel mcp config --client cursor or --client codex prints their form. Agents without hooks report their sessions with the report_session tool. Agents has the scopes, the tools and the commands.
Your own project: init and sync
Create a project in the app: workspace menu, Projects, New project. Then, in your product's repository, write a starting set of files from a template:
turnkeel init --template app-launch
The other templates are saas-launch and browser-extension (Templates). Without --template, init writes turnkeel.yml, one example gate file and a docs.yml. It never overwrites a file that exists, and it sends nothing.
.turnkeel/
turnkeel.yml url, workspace, project (read by the CLI only)
gates/*.md launch gates, one file per area
listings/*.md store and profile texts to copy
docs.yml which Markdown shows under Docs
steps/*.md test-step templates
Check that turnkeel.yml names your server, the workspace's address and the project's key. Read the other files, change what does not fit, commit them, and send them with a token that has gates:sync (and docs:sync for docs):
turnkeel sync --dry-run
turnkeel sync
The first command says what would change and changes nothing. When only turnkeel.yml names the server, the CLI asks once before it sends your token there; setting TURNKEEL_URL skips the question.
From then on, edit the file and sync again, and the app follows. A change that would let an agent pass a gate a person had to pass waits until a person confirms it in the app (Launch and gates).
On your own server, in short
For a team, run the same server with Postgres and sign-in. The repository has a Dockerfile and a docker compose file, and the code opens at launch. The server reads its settings from the environment, and refuses to start, naming the variable, when one is missing or half set.
| Variable | What it sets |
|---|---|
DATABASE_URL |
Postgres |
TURNKEEL_PUBLIC_URL |
The address people and agents use. Setting it turns sign-in on. |
TURNKEEL_AUTH_SECRET |
At least 32 characters. Signs sessions and sign-in links. |
SMTP_URL, MAIL_FROM |
Mail for sign-in links and invitations. Without them, the link is written to the server log. |
S3_… |
Optional. Storage for files; without it they stay in a folder on the server. |
The first person to sign in becomes the Owner, so sign in before you give the address to anyone. Everyone after that joins by invitation. Sign-in with GitHub and Google is offered when you set their client ids; both are built and not yet verified against the providers. What local mode holds cannot be moved to a server with sign-in. Self-hosting has the rest.
The source of this page will be on GitHub when the repository opens. Something wrong or unclear? Write to us.