# maxlistov.com > Personal site of Max Listov — full-stack developer and maker. It hosts the pages > and the full documentation of his open-source projects: stitchkit (a contract-first > backend framework for Bun and Node) and ccmux (persistent, self-healing Claude Code > sessions in tmux). Documentation is mirrored from the project repositories at build time. Every link below has a plain-markdown version at the same path with a `.md` suffix. ## Projects - [stitchkit](https://maxlistov.com/stitchkit.md): Contract-first backend framework for Bun and Node. Define your API once with defineContract() and get an HTTP API, MCP tools, AI-agent tools, a CLI and a fully-typed client — from a single source that cannot drift. - [ccmux](https://maxlistov.com/ccmux.md): Persistent, self-healing Claude Code sessions in tmux. One daemon per machine keeps long-running Claude Code agent sessions alive in tmux — healing crashes, restoring them on reboot and resuming the same conversation by a pinned uuid. - [stitchkit vs tRPC vs ts-rest](https://maxlistov.com/stitchkit/vs.md): how stitchkit compares to the closest alternatives. ## stitchkit documentation - [Getting started](https://maxlistov.com/stitchkit/docs/guide/getting-started.md): stitchkit turns one contract into an HTTP API, MCP tools, AI-agent tools and a typed client. This page gets a working app running; the rest of the guide goes deep on each piece. - [Contracts](https://maxlistov.com/stitchkit/docs/guide/contracts.md): A contract describes a set of operations once — method, path, schemas, scope, which transports each is exposed on. From it stitchkit derives the HTTP route, the MCP tool, the agent tool and the typed - [HTTP server](https://maxlistov.com/stitchkit/docs/guide/server.md): stitchkit serves contracts on Bun.serve() directly — no Hono, no Elysia, no Express. You bind a contract to handlers with implement(), then mount the result on createServer(). - [Typed client](https://maxlistov.com/stitchkit/docs/guide/client.md): From a contract, createClient builds a fully-typed client — one method per endpoint, arguments and result inferred from the schemas. There is no codegen step: the types come straight from the contract - [Realtime](https://maxlistov.com/stitchkit/docs/guide/realtime.md): stitchkit's realtime layer is Socket.IO — polling fallback, heartbeats, acks, a mature client. stitchkit does not ship its own WebSocket engine; it ships thin, typed wrappers over Socket.IO and a brid - [Auth & errors](https://maxlistov.com/stitchkit/docs/guide/auth-and-errors.md): stitchkit carries no domain model — it does not know what a user is. What it provides is the control flow: a scope on every endpoint, one hook that enforces it, and one error model shared by every tra - [MCP & AI agents](https://maxlistov.com/stitchkit/docs/guide/mcp-and-agents.md): The same contract that drives the HTTP API also drives AI tooling. An endpoint exposed on MCP becomes a Model Context Protocol tool — callable from Claude, Cursor and other MCP clients. An endpoint ex - [CLI](https://maxlistov.com/stitchkit/docs/guide/cli.md): The same contract that drives the HTTP API, MCP tools and agent tools also drives a command-line program. createCli turns contract methods into commands — myapp generate "a fox" --wait, myapp models l - [Multi-tenant / resource-scoped paths](https://maxlistov.com/stitchkit/docs/guide/multi-tenant.md): A walkthrough of one mainstream scenario end-to-end: a SaaS API scoped by a path segment — /tenants/:tenantId/widgets/... — where the same tenantId gates access in auth and is injected into tool calls - [Observability](https://maxlistov.com/stitchkit/docs/guide/observability.md): A request reaches your app through one of two surfaces — an HTTP route or a tool call (MCP / agent). Observability is the same question on both: what happened, how long did it take, who made it, did i - [Testing & deployment](https://maxlistov.com/stitchkit/docs/guide/testing-and-deployment.md): stitchkit's own test suite runs on bun:test. The contract makes most of an API testable without a live socket. - [Upgrading stitchkit](https://maxlistov.com/stitchkit/docs/guide/upgrading.md): How to move a consuming project from one stitchkit version to another — including across many versions at once (a project frozen on an old version, then jumped forward). The process is mechanical: sti - [API reference](https://maxlistov.com/stitchkit/docs/api/reference.md): Every public export of stitchkit, grouped by entrypoint. Each entry links to the guide page that explains it in context. Types are marked type; everything else is a value (a function, a class, a const ## stitchkit design decisions Architecture decision records — the reasoning behind the design, including reversed choices. - [ADR 0001 — Build on Bun.serve(), no HTTP framework](https://maxlistov.com/stitchkit/docs/decisions/0001-bun-serve-no-framework.md) - [ADR 0002 — A generic core: the framework carries no domain model](https://maxlistov.com/stitchkit/docs/decisions/0002-generic-core.md) - [ADR 0003 — Two context types: RuntimeContext and HandlerContext](https://maxlistov.com/stitchkit/docs/decisions/0003-two-context-types.md) - [ADR 0004 — Four lifecycle hooks instead of a middleware chain](https://maxlistov.com/stitchkit/docs/decisions/0004-lifecycle-hooks.md) - [ADR 0005 — The typed client is inferred from the contract](https://maxlistov.com/stitchkit/docs/decisions/0005-typed-client.md) - [ADR 0006 — Route groups and GET/DELETE query params](https://maxlistov.com/stitchkit/docs/decisions/0006-route-groups-query-params.md) - [ADR 0007 — MCP and agent tools from one shared pipeline](https://maxlistov.com/stitchkit/docs/decisions/0007-mcp-agent-tools.md) - [ADR 0008 — Thin wrappers over the stack you already use](https://maxlistov.com/stitchkit/docs/decisions/0008-thin-wrappers.md) - [ADR 0009 — A hand-rolled WebSocket transport](https://maxlistov.com/stitchkit/docs/decisions/0009-hand-rolled-websocket.md) - [ADR 0010 — Grow stitchkit into a fullstack framework](https://maxlistov.com/stitchkit/docs/decisions/0010-fullstack-rejected.md) - [ADR 0011 — Bun-only, published as one small package](https://maxlistov.com/stitchkit/docs/decisions/0011-bun-only-one-package.md) - [ADR 0012 — A built-in observability module](https://maxlistov.com/stitchkit/docs/decisions/0012-observability-module.md) - [ADR 0013 — Runtime-agnostic core, Bun as first-class adapter](https://maxlistov.com/stitchkit/docs/decisions/0013-runtime-agnostic-core.md) - [ADR 0014 — The tool surface carries the same contract guarantees as HTTP](https://maxlistov.com/stitchkit/docs/decisions/0014-tool-http-parity.md) - [ADR 0015 — OAuth 2.1 resource-server toolkit for MCP](https://maxlistov.com/stitchkit/docs/decisions/0015-oauth-resource-server.md) - [ADR 0016 — CLI as the fourth transport](https://maxlistov.com/stitchkit/docs/decisions/0016-cli-transport.md) - [ADR 0017 — Typed tool-path context via createToolkit](https://maxlistov.com/stitchkit/docs/decisions/0017-typed-tool-context.md) - [ADR 0018 — OpenAPI generated from the contract](https://maxlistov.com/stitchkit/docs/decisions/0018-openapi-generation.md) - [ADR 0019 — Generic native MCP tools (wait / download / upload)](https://maxlistov.com/stitchkit/docs/decisions/0019-generic-native-tools.md) - [ADR 0020 — A raw WebSocket lane composed beside Socket.IO](https://maxlistov.com/stitchkit/docs/decisions/0020-raw-websocket-lane.md) - [ADR 0021 — Endpoint meta passthrough (opaque per-endpoint metadata)](https://maxlistov.com/stitchkit/docs/decisions/0021-endpoint-meta-passthrough.md) - [ADR 0022 — Stable (service, action) identity on MethodDef](https://maxlistov.com/stitchkit/docs/decisions/0022-endpoint-identity.md) - [ADR 0023 — Range-capable file serving (serveFile)](https://maxlistov.com/stitchkit/docs/decisions/0023-range-file-serving.md) - [ADR 0024 — Scope-driven mounting (scopePrefixes)](https://maxlistov.com/stitchkit/docs/decisions/0024-scope-driven-mounting.md) - [ADR 0025 — Typed scoped client (consumed keys as args)](https://maxlistov.com/stitchkit/docs/decisions/0025-typed-scoped-client.md) - [ADR 0026 — Published stitch error-code registry](https://maxlistov.com/stitchkit/docs/decisions/0026-stitch-error-code-registry.md) - [ADR 0027 — Transport-neutral contract execution (bring-your-own transport)](https://maxlistov.com/stitchkit/docs/decisions/0027-transport-neutral-contract-execution.md) - [ADR 0028 — Revert createContractDispatcher (no adopting consumer)](https://maxlistov.com/stitchkit/docs/decisions/0028-revert-contract-dispatcher.md) - [ADR 0029 — Endpoint identity and domain dimensions on the audit event](https://maxlistov.com/stitchkit/docs/decisions/0029-audit-endpoint-identity-and-dimensions.md) - [ADR 0030 — Audit verb, sanitised error details, and complete error-code logging](https://maxlistov.com/stitchkit/docs/decisions/0030-audit-verb-and-json-error-details.md) - [ADR 0031 — Deep discriminated-union flattening for tool schemas](https://maxlistov.com/stitchkit/docs/decisions/0031-deep-union-flatten.md) - [ADR 0032 — Brand-based AppError identification (not instanceof)](https://maxlistov.com/stitchkit/docs/decisions/0032-apperror-brand-identity.md) - [ADR 0033 — Sound flatten: collision widening, discriminator support, probe parity](https://maxlistov.com/stitchkit/docs/decisions/0033-sound-flatten-collisions.md) ## ccmux documentation - [ccmux](https://maxlistov.com/ccmux/docs/readme.md): Persistent, self-healing Claude Code sessions in tmux — across a fleet of machines. - [Changelog](https://maxlistov.com/ccmux/docs/changelog.md): All notable changes to ccmux. The [Unreleased] section accumulates as work lands; bun run release X.Y.Z "notes" rolls it into a dated version section, and CI publishes the GitHub Release with that sec ## Source repositories - [stitchkit on GitHub](https://github.com/max-listov/stitchkit) - [ccmux on GitHub](https://github.com/max-listov/ccmux) ## Contact - Email: maxlistov@gmail.com - Telegram: https://t.me/MaxListov - Instagram: https://instagram.com/maxlistov - YouTube: https://youtube.com/@maxlistov