Kotoba

Where to start

What Kotoba isWho she is and where she runs, in one page
InstallingOne package, two commands
First runA key, a model, her first words
The approval gateHow she asks before she acts
The two voice modesLocal voice, or the agent tunnel
The soul fileChange who she is
RoadmapWhat grows next, and what was cut on purpose

Or a section

↑↓ move openesc close124 pages
All pages

Contributing and reference10 of 12

Versioning, the changelog, and how a release is meant to work

About 3 minutes to read

On this page

Where the version number really comes from

One place:

python
# api/src/kotoba/__init__.py
__version__ = "0.10.0"

Everything else reads it or is checked against it.

Where a version appearsHow it gets there
api/pyproject.tomldynamic = ["version"], resolved by version = { attr = "kotoba.__version__" }
package.jsonwritten by hand, and pinned by a test to equal kotoba.__version__
api/src/kotoba/web/kotoba-build.jsonstamped by scripts/build_web.py at build time
A git tagchecked against kotoba.__version__ by the release workflow

api/tests/test_packaged_data.py holds package.json and the package to the same number, because two version strings for one release with nothing comparing them means the interface can name a version the wheel has never heard of. api/tests/test_the_wheel_carries_the_web_ui.py refuses a build stamped for a different version. Both were run: they pass.

To bump the version, change __init__.py and package.json together. Nothing else.

The numbering

Versions start at 0.10.

  • A fix or a small addition moves the last number: 0.10.1, 0.10.2.
  • A release that changes how Kotoba behaves for you moves the middle one.
  • The leading zero stays until the shape of Kotoba stops moving; a 1 will be a promise about that.
  • Anything that changes behaviour says so in the changelog in plain words before it says so in a number.

Read the middle number as ten, not as one: 0.1 and 0.10 are different versions and 0.10 is the later of the two. The third number is not decoration either — Python normalises 0.010 to 0.10, so a version written with a stray zero publishes as a release that already exists.

The changelog

CHANGELOG.md, newest first, with an ## Unreleased section at the top. Add your entry there in the same pull request as the change, in the same plain register the rest of the file uses: what it does for the person using Kotoba, not which function you renamed.

At the time of writing, ## Unreleased says Nothing yet, and ## 0.10.0 — the first release is the only entry.

What a release is written to do

This has never been done. No tag has been pushed from this tree, release.yml has never been executed, and nothing has been published to PyPI from it. What follows is what the workflow file says, not a procedure anyone has walked.

Pushing a tag matching v* is meant to trigger three jobs:

build — install Node and Python 3.13, npm ci, python scripts/build_web.py, then check that the tag and kotoba.__version__ agree, then run the entire test suite, then the packaged-UI test with KOTOBA_REQUIRE_WEB=1, then python -m build --outdir dist ./api. The distributions go up as an artifact.

A release is the one moment a green suite is not optional: the version number it spends cannot be spent again, and nothing else links that workflow to the one that runs on a push.

publish — uploads to PyPI using Trusted Publishing, so there is no API token stored anywhere. The job carries id-token: write and runs in a pypi environment. Trusted Publishing has to be configured once on the PyPI project before the first release can go through, and nothing in this repository records whether that has been done.

attach — uploads the same distributions to the GitHub release, with the GitHub CLI rather than a third-party action, because that job can write to the repository.

Both download steps and the publish action are pinned by commit SHA, not by tag: a moving tag is somebody else's decision about what runs with your write permission. The jobs that only read stay on major tags.

Supported versions

SECURITY.md states it in one line: the latest release. Older versions get no backports — the fix is the upgrade.

What ships in a release

One distribution, kotoba-companion, on PyPI. The import name, the command and the companion are all kotoba; only the distribution name differs, because kotoba on the index is somebody else's library.

The wheel carries:

  • the package under api/src/kotoba/
  • the personality file, its templates and the skills, as package data
  • the terminal's face art
  • the compiled web UI under kotoba/web/ — which the build backend refuses to omit or to ship stale
  • LICENSE and THIRD_PARTY_NOTICES.md

Install extras pick the rest:

bash
pip install "kotoba-companion[server,voice,cli,web,mcp]"

There is no other channel. No winget manifest, no Homebrew formula, no published container image.