Terminal and platforms10 of 10
Windows today
On this page
What you actually get, and the commands that get it. Everything here is native — no WSL, no container required.
Install
pip install "kotoba-companion[server]"
kotoba doctor
kotoba setup
server is the extra you want: it brings FastAPI and uvicorn, which is what makes the web app and
kotoba serve possible. Python 3.11 or newer.
You may install [cli] as well and it will succeed — prompt_toolkit, rich and pillow all
build on Windows — but it will not give you the interactive terminal. That needs the POSIX terminal
layer, which no extra can supply. See Platform support.
The commands that work
kotoba doctor # what is missing, in the order that decides it
kotoba setup # pick a provider, hand over a key
kotoba --once "explain WAL" # one question, one answer, exit
kotoba serve # backend on 8000, web UI on 3000; one Ctrl+C stops both
kotoba serve --open # and open the browser once the web UI answers
kotoba discord # run her as a Discord bot (needs the `discord` extra)
kotoba doctor is the one to run first. It reports the platform on its first line, and the
terminal row directly under it says the interactive session cannot run here and names every route
that can.
Bare kotoba does something useful
It does not refuse:
kotoba: her interactive terminal needs the POSIX terminal layer (termios, tty), which Windows does
not have. Starting the backend and the web UI instead — your browser opens when it answers, and
Ctrl+C stops both.
Then it runs serve with the browser opener on. Somebody typed the name of the program, not the name
of a server, so what they get is her.
Without the server extra there is nothing to fall back to, and it says so instead:
kotoba: her interactive terminal needs the POSIX terminal layer (termios, tty), which Windows does
not have, and the backend that takes its place here needs the server extra:
pip install "kotoba-companion[server]"
Exit code 1. This is the one entry point whose behaviour differs by platform, which is why it says out loud which way it went.
kotoba --sessions and kotoba --settings are named rather than silently ignored — they select a
panel of a terminal that is not opening, and the web UI has its own.
kotoba serve itself is unchanged: it is a server command on every platform, so it stays quiet
unless you give it --open.
Almost no approval is remembered
This is the difference you will feel, and it is deliberate.
On a Windows host with sandbox local, every shell command shows its card, every time. There is
no plain-read exemption, no allowlist bypass, and both a (always allow this family) and t (always
allow this exact line) are withheld from the rail. A grant saved on that machine before the platform
question existed is not consulted either.
The card explains itself in one sentence:
On Windows I can't read a command line the way the shell will, so every one of them asks.
The reason: everything the gate reads a command line with is POSIX — shlex in POSIX mode, an sh
metacharacter set, a POSIX tool allowlist, / as the separator. POSIX shlex eats backslashes, so
cat C:\Users\me\.ssh\id_rsa arrives as a single token with no separator in it and reads as a
harmless file inside her workdir. And cat is a real PowerShell alias for Get-Content. Rather than
guess in a language it does not speak, it asks.
What does survive is a grant for a named family that is not a shell line — execute_code. Its
action is Python handed over under its own family name, so none of the POSIX reading was ever applied
to it. Its own dangerous-code check knows both separator styles, so a snippet reading
C:\Users\me\.kotoba\.keystore_key still draws a card under a saved grant.
The dangerous-pattern set speaks the Windows dialect, so a card can say what it is showing:
rd /s /q, Remove-Item -Recurse -Force, del C:\*, format C:, diskpart, reg delete … /f,
vssadmin delete shadows /all, iwr … | iex, Stop-Computer, Start-Process … -Verb RunAs.
If you want the low-friction path back, sandbox docker gives it to you: her commands land in a
Linux container, the POSIX reading is then the correct one, and only a dangerous command asks.
PowerShell, not cmd
When she runs a shell command it goes to PowerShell explicitly — an argv, not an inherited
interpreter. create_subprocess_shell on Windows runs whatever COMSPEC names, which is cmd.exe,
so the shell she was taught and the shell that ran matched only by luck. The command is carried as
-EncodedCommand (base64 UTF-16LE) so it reaches the interpreter byte for byte instead of being
re-parsed twice, and the interpreter is named by an absolute SYSTEMROOT path so nothing the model
writes can choose it.
Your files are kept to your account
chmod 0600 writes no ACL on Windows, so the database, the keystore's master key and every atomic
write are restricted with icacls instead — full control for one account, inherited entries dropped.
That matters most for a clone under C:\, where nothing is inherited from your user profile.
kotoba doctor's permissions row asks by doing it, on a throwaway file beside the real ones, and
tells you which way it went:
ok permissions granted to *S-1-5-21-… alone, and to nobody else
warn permissions the master key and the database are not private to this account — icacls refused …
A refused grant is a warning, never a failure: she runs perfectly well either way, and a filesystem with no ACLs at all would otherwise say "problems to fix before she runs" forever.
Colour
Windows Terminal is the comfortable choice. The classic console understands ANSI but arrives with it switched off, so Kotoba asks it to turn it on once, at startup; a console that refuses gets plain text rather than escape codes printed at you.
kotoba serve on Windows
Two children, both reachable by Ctrl+C:
npmis invoked ascmd /c npm run dev, becausenpmis reallynpm.cmdandCreateProcesswill not run a batch file.- Each child gets
CREATE_NEW_PROCESS_GROUP, so a console Ctrl+C is not delivered into it and shutdown happens once, through the parent. - Shutdown sends
CTRL_BREAK_EVENTto the group and thentaskkill /F /T /PID— endingcmd.exealone would leave the Next worker it started holding port 3000.
A wheel carries the web UI already built, so with no Node installed at all the backend serves it from
its own port at /app, and serve says which of the two it started.
What is the same as everywhere else
- ElevenLabs is required for voice. There is no local speech engine yet, on any platform.
- The database, the memory, the tools, the models, the web app and the Discord bot behave the same.
What is coming
The full interactive terminal. It is on the project's roadmap under Next: "The commands run
there now, but the interactive session does not — it needs a POSIX terminal. Making it native is a
piece of work, not a patch." Until then the web app is the full-featured surface on Windows, and
--once is the scripting one.
