Contributing

Developing

Running and checking each Telmoni repository on your machine: the platform with the SDKs in it, these docs, the CLI, and the agent skills.

One page for the four repositories. The gates named here are what each repository's CI runs.

The platform

telmoni/telmoni: the server, the console, the four SDKs under sdk/, the Helm chart and the compose file.

You need Rust at the version rust-toolchain.toml pins (rustup installs it on the first cargo run), Node at the version in web/.nvmrc with npm, Docker for Postgres with pgvector, ClickHouse, Redis, Mailpit and, on request, Ollama, and rsync. The console builds these docs in (The docs), so check them out beside the platform:

$ git clone https://github.com/telmoni/docs.git ../docs

For make ci you also need cargo install cargo-deny typos-cli. make doctor checks that Rust, Node and npm, Docker with Compose and a running daemon, rsync and gh are installed and that both env files and the docs beside the platform exist; it checks no versions, and not cargo-deny or typos. The SDK suites want Node 22.18, 24.11, or 26 or later, which the TypeScript suite's tsup requires though the SDK itself runs on Node 18 from 18.19, or 20.6 or later, and npm (TypeScript, after npm ci --prefix sdk/typescript), Go 1.26.10 or later, and for Python (3.10 or later) a venv: python3 -m venv sdk/python/.venv && sdk/python/.venv/bin/pip install -e "sdk/python[dev]".

$ make first-run
$ make up

make first-run runs once: it copies .env and web/.env.local from their examples, mints the service secret into both and a local TELEMETRY_KEK into .env where they are blank, installs dependencies, starts Postgres and ClickHouse and runs the migrations. make up runs the stack: Postgres, ClickHouse, Redis, Mailpit, the server on :8082 and the console on :3000. COMPOSE_PROFILES=ollama in .env starts Ollama with it, and make server-dev and make web-dev run either process alone.

ALLOW_TEST_SESSION=true also mounts POST /internal/v1/test/session, which is how the end-to-end tests sign in; a Kubernetes pod refuses to start with it.

Signing in through a provider

COMPOSE_PROFILES=oidc in .env starts Dex, an OpenID Connect provider, beside the stack at http://127.0.0.1:5556/dex, with a client for the console and two people, ada@example.com and grace@example.com, each with the password password (crates/auth/dex/dev-config.yaml). It refuses any sign-in without PKCE, as a careful provider may. Point the server at it in .env:

COMPOSE_PROFILES=oidc
AUTH_CUSTOM_CLIENT_ID=telmoni-local
AUTH_CUSTOM_CLIENT_SECRET=telmoni-local-dex-secret
AUTH_CUSTOM_ISSUER=http://127.0.0.1:5556/dex
AUTH_CUSTOM_NAME=Dex

Then make up and Continue with Dex on the sign-in page. Sign in as Ada: Grace is the end-to-end suite's stranger, whom a deployment with sign-ups closed turns away, so an account of hers in your database fails that test. The suite's web/e2e/oidc.spec.ts signs in through the same Dex — make e2e starts it — and holds the round trip, the refusal page a closed deployment answers a stranger with, and an address held to single sign-on.

.env configures the server and web/.env.local the console; their examples, .env.example and web/.env.local.example, document the variables you set there. The checks:

$ make check
$ make lint
$ make sdk-check
$ make test
$ make ci

make check is types, cargo check, fmt, clippy and rustdoc, the Rust SDK among the crates it covers; make lint is eslint; make sdk-check is the other three SDKs' suites — npm run verify for TypeScript; gofmt, go vet and go test -race for Go; ruff, mypy and pytest for Python — and cargo test -p telmoni, the Rust SDK's, which needs no database; make test starts the docker stack and waits for Postgres and ClickHouse, then runs vitest, and cargo test against the two; make ci is everything CI runs. make fmt formats the code rather than checking it.

Nothing has shipped, so there are no migration paths. Each module owns one migration under crates/<module>/migrations/, and telemetry one more for ClickHouse under crates/telemetry/clickhouse/: edit it, then make db-reset. After a change to the wire contract, make contract regenerates contract/, and web/lib/types/enums.ts and web/lib/slug.ts follow until contract.test.ts passes.

The CLI

telmoni/telmoni-cli: telmoni, the command-line client. The SDKs are the platform's, above.

You need Rust at the version rust-toolchain.toml pins and cargo install cargo-deny.

$ TELMONI_ENDPOINT=http://localhost:8082 cargo run -- login
$ cargo run -- status

The first signs in to the platform's make up, at the server, which serves the /cli lanes; the code is approved on the console, at http://localhost:3000, whose address the CLI prints rather than opens, since it is on another port. status then reports on that session, whose endpoint it saved. A debug build also reads TELMONI_ENDPOINT, TELMONI_API_KEY and TELMONI_ORG from a .env in the working directory; a release build never does.

$ cargo xtask ci

cargo xtask ci is the gate CI runs: fmt, the toolchain check, clippy, build, test, doc and cargo deny. CI lints its workflows with actionlint beside it. cargo xtask dist packages this machine's binary as dist/telmoni-<os>-<arch>.tar.gz, with its SHA256SUMS; a release is the workspace's version bumped in one commit on main: .github/workflows/release.yml waits for CI to pass on it, builds the x86_64 Linux archive, and on the owner's approval tags the commit v*, publishes the crate to crates.io and cuts the GitHub release with the archive and install.sh, a Mac building from source until its archive can be signed (ARCHITECTURE.md).

The skills

telmoni/skills: the agent skills, packaged as a plugin for Claude Code and the other agents that read them.

You need uv and Claude Code.

$ make check
$ claude --plugin-dir .

make check is the gate CI runs: it validates each skill against the Agent Skills spec, plugin.json against the Agent Plugins schema, .cursor-plugin/plugin.json against Cursor's, and the plugin and its marketplace with claude plugin validate .. CI lints its workflows with actionlint beside it. claude --plugin-dir . starts a Claude Code session with your checkout's plugin loaded. make eval runs the eval suite, each case with and without the plugin, and spends model usage; on Linux its runs need bubblewrap and socat. The repository's AGENTS.md says what a skill may say and how to test a change.

The docs

telmoni/docs: these pages, MDX under content/ that the platform's console serves at /docs with Fumadocs. The console builds them in: make book in the platform lays content/ into the console's web/content/docs, every build does it first, and make up and make web-dev keep it in step as you edit, at http://localhost:3000/docs with live reload. An image carries the pages as they stood when it was built. What a page may say is the code's business: verify every claim against the platform or the CLI before writing it.

  • A page is an .mdx file under content/, with title and description in its frontmatter; the title is also its name in the sidebar.
  • Each folder's meta.json is the reading order, and the only place that holds it: a new page goes into its folder's pages, and the ... at the end takes in the pages a console built on the platform lays over the tree. The hosted service's own pages, its legal documents and its billing page, are hosted/, which only its console lays over the book.
  • Links use the served path (/docs/integrations/webhooks), never a file path. A link from one of these pages to the hosted service's own uses its address on telmoni.com (https://telmoni.com/docs/legal/subprocessors), since a self-hosted console does not serve them.
  • Shell blocks use the console fence with a $ prompt, and show only output a host really produced.
  • Outside a code fence, a bare <flag> or {param} breaks the build, and HTML comments are invalid.
  • errors.mdx and api/field-inventory.mdx stay where they are: the platform's error_catalog.rs and field_inventory.rs tests read them from there.
$ make check

make check and typos are the gate CI runs. With the platform checked out beside these docs, make check builds the console with them, which compiles every page and fails on invalid MDX, and runs those two tests (make book-check in the platform). The same pages are served as Markdown for a model, /llms.txt (the index) and /llms-full.txt (every page), which is the corpus the console agent indexes.