proteum
v2.5.3
Published
LLM-first Opinionated Typescript Framework for web applications.
Readme
Proteum
Proteum is an LLM-first SSR / SEO / TypeScript framework for full-stack web applications.
It is built for teams that want explicit server contracts, server-first rendering, deterministic generated artifacts, and a codebase that an AI agent can inspect without reverse-engineering hidden runtime magic.
Sponsor
Proteum is sponsored by Unique Domains.
Why Proteum
Most full-stack frameworks optimize first for human convenience.
Proteum optimizes first for:
- explicit, typed, machine-readable contracts
- SSR and SEO as framework primitives
- server-first architecture with minimal client runtime
- deterministic generation instead of ambient magic
- codebases that stay explainable to humans and LLMs at the same time
Proteum combines:
- page-first SSR workflows similar to modern React meta-frameworks
- explicit controller and service layers inspired by backend frameworks
- generated manifests and contracts that make routes, services, layouts, and diagnostics easy to inspect
Core Principles
- Server-first by default. Put data loading in the page data function and keep client code focused on UI.
- Explicit request entrypoints. Routes and controllers are exported definition objects.
- Local validation. Declare controller input on
defineAction({ input, handler }); handlers receive parsedinput. - Deterministic generation. Proteum owns
.proteum/and regenerates it from source. - Explainability matters.
proteum explain,proteum doctor,proteum diagnose,proteum perf, andproteum traceexpose the framework view of your app and its live requests, and the profiler renders the same diagnostics and perf surfaces for humans in dev. - SEO is not an afterthought. Identity, routes, layouts, and SSR data are part of the app contract.
What a Proteum App Looks Like
my-app/
identity.config.ts
proteum.config.ts
.env # optional file for required local env vars
package.json
commands/
client/
pages/
_layout/
components/
islands/
services/
server/
config/
index.ts
controllers/
services/
common/
models/
router/
errors/
.proteum/
manifest.json
client/
common/
server/Important files:
identity.config.ts: typed app identity, naming, locale, and SEO-facing metadata defaults viaApplication.identity({ ... })proteum.config.ts: typed Proteum compiler and connection settings such astranspileandconnectviaApplication.setup({ ... })process.env/ optional.env:PORT,ENV_*,URL,URL_INTERNAL, any app-chosen variables referenced byproteum.config.ts, andTRACE_*environment variables loaded by the appserver/config/*.ts: plain typed config exports consumed by the explicit app bootstrapserver/index.ts: default-exporteddefineApplication({ services, router, models, commands })application graphclient/pages/**: SSR page entrypoints that default-exportdefinePageRoute({ path, options, data, render })server/controllers/**: generated API definitions that default-exportdefineController({ path, actions })commands/**: dev-only internal commands that extendCommandsserver/services/**: business logic that extendsService.proteum/**: framework-owned generated contracts and manifests
Required Proteum env vars:
ENV_NAME:localorserverENV_PROFILE:dev,testing, orprodPORT: default router portURL: canonical absolute base URL forRouter.url(..., true)URL_INTERNAL: internal absolute base URL used by SSR and connected-project server calls
If proteum.config.ts declares connect, Proteum also requires:
- one explicit
connect.<Namespace>.sourcevalue inproteum.config.ts - one explicit
connect.<Namespace>.urlInternalvalue inproteum.config.ts
Proteum does not provide defaults for required env vars. They must be defined explicitly in process.env or .env.
Use proteum explain env to see the required env vars, their allowed values, and whether each one is currently provided.
Optional trace env vars:
TRACE_ENABLETRACE_REQUESTS_LIMITTRACE_EVENTS_LIMITTRACE_CAPTURETRACE_PERSIST_ON_ERRORENABLE_PROFILER
Optional proteum.config.ts fields:
transpile: array of package names that Proteum should compile fromnode_modules/instead of treating as prebuilt vendor codeconnect: connected project namespaces that should be merged into generated controller helpers
Example:
import { Application } from 'proteum/config';
const PRODUCT_CONNECTED_SOURCE = process.env.PRODUCT_CONNECTED_SOURCE;
const PRODUCT_URL_INTERNAL = process.env.PRODUCT_URL_INTERNAL;
export default Application.setup({
transpile: ['@acme/components'],
connect: {
Product: {
source: PRODUCT_CONNECTED_SOURCE,
urlInternal: PRODUCT_URL_INTERNAL,
},
},
});Connected contract sources are provided explicitly through proteum.config.ts instead of being inferred from the namespace:
- local typed source value:
file:../product - remote runtime-only source value:
github:owner/repo?ref=<sha-or-branch>&path=proteum.connected.json
Use this for linked or workspace-local TypeScript packages that ship source files and must flow through Proteum's alias and SSR compilation pipeline.
Example: Server Bootstrap
Proteum app services and router plugins are declared explicitly through typed config exports plus a default-exported defineApplication(...) definition object.
// server/config/user.ts
import { Services, type ServiceConfig } from '@server/app';
import AppContainer from '@server/app/container';
import Router from '@server/services/router';
import Users from '@/server/services/Users';
type RouterBaseConfig = Omit<ServiceConfig<typeof Router>, 'plugins'>;
export const usersConfig = Services.config(Users, {});
export const routerBaseConfig = {
currentDomain: AppContainer.Environment.router.currentDomain,
http: {
domain: 'example.com',
port: AppContainer.Environment.router.port,
ssl: true,
upload: { maxSize: '10mb' },
},
context: () => ({}),
} satisfies RouterBaseConfig;// server/index.ts
import { defineApplication, type Application } from '@server/app';
import Router from '@server/services/router';
import SchemaRouter from '@server/services/schema/router';
import Users from '@/server/services/Users';
import * as userConfig from '@/server/config/user';
type MyAppServices = {
Users: Users;
};
type MyRouterPlugins = {
schema: SchemaRouter;
};
export type MyRouter = Router<MyApp, MyRouterPlugins>;
export interface MyApp extends Application, MyAppServices {
Router: MyRouter;
}
const createRouter = (app: MyApp): MyRouter =>
new Router<MyApp, MyRouterPlugins>(
app,
{
...userConfig.routerBaseConfig,
plugins: {
schema: new SchemaRouter({}, app),
},
},
app
);
const createServices = (app: MyApp): MyAppServices => ({
Users: new Users(app, userConfig.usersConfig, app),
});
const MyApplication = defineApplication({
services: createServices,
router: createRouter,
});
export default MyApplication;Proteum reads server/index.ts as the source of truth for installed root services and router plugins, and reads server/config/*.ts Services.config(...) exports for typed config such as service priority overrides.
Router Cache Policy
Browser cache headers are configurable per app through the optional routerBaseConfig.http.cache object. Omit it to keep Proteum's defaults.
export const routerBaseConfig = {
currentDomain: AppContainer.Environment.router.currentDomain,
http: {
domain: 'example.com',
port: AppContainer.Environment.router.port,
ssl: true,
upload: { maxSize: '10mb' },
cache: {
html: {
dynamic: {
cacheControl: 'no-store, no-cache, must-revalidate, proxy-revalidate',
surrogateControl: 'no-store',
},
static: {
cacheControl: 'public, max-age=0, must-revalidate',
surrogateControl: false,
},
},
publicAssets: {
dev: 'no-store',
versioned: 'public, max-age=31536000, immutable',
unversioned: 'public, max-age=0, must-revalidate',
},
},
},
context: () => ({}),
} satisfies RouterBaseConfig;Default public asset validators depend on the environment: dev disables ETag and Last-Modified, while non-dev enables them. Use etag: false and lastModified: false when an app needs to fully disable browser cache for /public assets.
Example: Page
Proteum pages are explicit SSR entrypoints.
import { definePageRoute } from '@common/router/definitions';
export default definePageRoute({
path: '/',
options: {
auth: false,
layout: false,
},
data: ({ Plans, Stats }) => ({
plans: Plans.getPlans(),
stats: Stats.general(),
}),
render: ({ plans, stats }) => {
return <LandingPage plans={plans} stats={stats} />;
},
});What happens here:
path,options, and errorcodemetadata are static and compiler-readable- route behavior such as
auth,layout,static, orredirectLoggedlives in the options object - every key returned from
databecomes page data - runtime app/client references are allowed only inside
dataandrender
Example: Controller
Proteum controllers are explicit request entrypoints.
import { defineAction, defineController, schema } from '@generated/server/controller';
export default defineController({
path: 'Auth',
actions: {
loginWithPassword: defineAction({
input: schema.object({
email: schema.string().email(),
password: schema.string().min(8),
}),
handler: ({ input, services, request }) => {
return services.Auth.loginWithPassword(input, request);
},
}),
},
});Controller rules:
- read request-scoped values from action context
- declare validation once with
defineAction({ input, handler }) - call business logic through
services,models, orapp - return explicit values instead of relying on ambient globals
Example: Command
Proteum commands are explicit dev-only internal entrypoints.
import { Commands } from '@server/app/commands';
export default class DiagnosticsCommands extends Commands {
public async ping() {
const { Stats } = this.services;
return {
app: this.app.identity.identifier,
domains: await Stats.general(),
};
}
}Command rules:
- files live under
commands/**/*.ts - each file default-exports a class extending
Commandsfrom@server/app/commands - methods with bodies become generated dev commands
- command path comes from the file path plus the method name
export const commandPath = 'Custom/path'can override the base path when neededcommands/tsconfig.jsonand.proteum/server/commands.d.tsgive/commandsits own dev-only alias and app typing surface- commands run only in dev contexts:
proteum command ..., the dev profiler, or dev-only__proteum/commandsendpoints
Example: Service
Proteum services keep business logic out of request handlers.
import Service from '@server/app/service';
export default class StatsService extends Service<Config, {}, MyApp, MyApp> {
public async general() {
return {
totalDomains: await this.models.SQL`SELECT COUNT(*) FROM domains`.value(),
tlds: Object.keys(this.app.Domains.tlds).length,
};
}
}Service rules:
- services extend
Service - request context should be resolved in controllers, then passed into services as explicit values
- services can use
this.services,this.models, andthis.app
Framework-Owned Generated Contracts
Proteum generates a machine-readable app description in .proteum/.
Typical generated artifacts:
.proteum/manifest.json.proteum/client/routes.ts.proteum/client/controllers.ts.proteum/client/layouts.ts.proteum/common/controllers.ts.proteum/server/commands.ts.proteum/server/routes.ts.proteum/server/controllers.ts
These files are not hand-written application code. They are deterministic outputs derived from your app source and used by the runtime, the compiler, and tooling.
This is one of Proteum's most important properties: the framework can explain what it discovered instead of asking you to guess.
CLI
Proteum ships with a compact CLI focused on the real app lifecycle:
| Command | Purpose |
| --- | --- |
| proteum dev | Start the compiler, SSR server, and hot reload loop |
| proteum refresh | Regenerate .proteum contracts and typings |
| proteum typecheck | Refresh generated typings, then run TypeScript |
| proteum lint | Run ESLint for the current app |
| proteum check | Refresh, typecheck, and lint in one command |
| proteum build --prod | Produce the production server and client bundles into bin/, with optional static or served bundle analysis |
| proteum connect | Inspect connected-project sources, env, cached contracts, and imported controllers |
| proteum doctor | Inspect manifest diagnostics |
| proteum explain | Explain routes, controllers, services, layouts, conventions, env, and connected projects |
| proteum diagnose | Combine owner lookup, diagnostics, trace data, and server logs for one concrete route or request target |
| proteum perf | Aggregate request-trace performance into hot paths, one-request waterfalls, regressions, and memory drift views |
| proteum trace | Inspect live dev-only request traces from the running SSR server |
| proteum mcp | Start, inspect, or attach to the machine-scope MCP router that routes live app reads by projectId |
| proteum command | Run a dev-only internal command locally or against a running dev server |
| proteum session | Mint a dev-only auth session token and Playwright-ready cookie payload |
| proteum e2e | Run Playwright with Proteum-managed E2E_* values instead of shell-leading env assignments |
| proteum verify | Validate targeted changed-file checks, focused owner/request/browser workflows, or the full framework reference-app pass |
| proteum init | Scaffold a new Proteum app with built-in deterministic templates |
| proteum configure agents | Interactively configure tracked Proteum instruction files and Claude aliases |
| proteum create | Scaffold a page, controller, command, route, or root service inside an app |
| proteum worktree | Create or initialize Codex worktrees with a machine-readable bootstrap marker |
Recommended daily workflow:
proteum dev
proteum refresh
proteum check
proteum verify changed --dry-run
proteum build --prod
proteum build --prod --analyze
proteum build --prod --analyze --analyze-serve --analyze-port autoOnly the bare proteum build and bare proteum dev commands print the welcome banner and include the active Proteum installation method. Any extra argument or option skips the banner. proteum dev is the only command that clears the interactive terminal before rendering its live session UI, exposes CTRL+R reload plus CTRL+C shutdown hotkeys, and prints connected app names plus successful connected /ping checks in the server-ready banner. Every proteum dev start ensures tracked Proteum instruction files contain the current managed # Proteum Instructions section and CLAUDE.md symlinks point to sibling AGENTS.md files before the dev loop begins.
Useful inspection commands:
proteum doctor
proteum doctor --contracts
proteum doctor --json
proteum connect
proteum connect --controllers
proteum connect --strict
proteum explain
proteum explain owner /api/Auth/CurrentUser
proteum explain --routes --controllers --commands
proteum explain --routes --controllers --commands --full
proteum explain --connected --controllers
proteum explain --all --full
proteum diagnose /
proteum diagnose /dashboard --port 3101
proteum perf top --since today
proteum perf request /dashboard --port 3101
proteum perf compare --baseline yesterday --target today --group-by route
proteum perf memory --since 1h --group-by controller
proteum mcp
proteum mcp status
proteum command proteum/diagnostics/ping
proteum command proteum/diagnostics/ping --port 3101
proteum session [email protected] --role ADMIN --port 3101
proteum session [email protected] --role GOD --json
proteum e2e --port 3101 --session-email [email protected] --session-role ADMIN tests/e2e/features/admin.spec.ts
proteum trace requests
proteum trace arm --capture deep
proteum trace latestUseful scaffolding commands:
proteum init my-app --name "My App"
proteum init my-app --name "My App" --dry-run --json
proteum configure agents
proteum worktree init --source /path/to/main-app
proteum worktree create /path/to/.codex/worktrees/feature --source /path/to/main-app --branch feature/name
proteum create page marketing/faq --route /faq
proteum create controller Founder/projects --method list
proteum create service Conversion/Plansproteum configure agents writes a compact managed # Proteum Instructions router plus the task-specific instruction files that router points to. Standalone mode writes root documents into the app root; monorepo mode writes shared root documents such as AGENTS.md, DOCUMENTATION.md, CODING_STYLE.md, diagnostics.md, and optimizations.md into the chosen monorepo root and keeps only app-local instruction files in the Proteum app root. For each generated AGENTS.md, it creates a sibling CLAUDE.md symlink pointing to AGENTS.md. It preserves content outside managed sections and asks before replacing directories, foreign symlinks, or unrelated files. If you decline, that path is left untouched.
Every proteum dev start runs the same idempotent instruction check. It updates missing or stale managed sections automatically and prompts only when a blocked path would need to be replaced.
proteum worktree init writes .proteum/worktree-bootstrap.json for app roots under /.codex/worktrees/. The marker records .env copy status, refresh and dependency results, runtime status, key file hashes, and the active Proteum version. proteum dev, proteum refresh, proteum runtime status, proteum verify, and MCP workflow_start block inside Codex worktrees until the marker is fresh. Run npx proteum worktree init --source <source-app-root> for a new worktree, or add --refresh when stale state is reported. PROTEUM_ALLOW_UNBOOTSTRAPPED_WORKTREE=1 bypasses the block but remains visible in runtime status, doctor, and MCP output.
proteum connect, proteum explain, proteum doctor, and proteum diagnose share the same generated manifest and contract state. proteum perf uses the same dev request-trace store as the profiler Perf tab. proteum runtime status also inspects the configured router/HMR ports and returns an exact Start Dev action, so agents do not need to curl page routes to identify port owners. proteum dev exposes the app-root MCP contract at /__proteum/mcp and ensures one managed machine MCP daemon is running; proteum mcp is the machine-scope router agents register once. Agents should start with MCP workflow_start, use offline candidates to choose the correct app root when no dev server is live, then route repeated reads by the returned live projectId. For the full diagnostics and tracing model, see docs/diagnostics.md, docs/mcp.md, and docs/request-tracing.md.
Dev Commands
Proteum includes a dev-only command surface for internal testing, debugging, and one-off execution that should not become a normal controller or route.
- commands live under
./commands/**/*.ts - each file default-exports a class extending
Commandsfrom@server/app/commands - each method is addressed by
file/path/methodName - Proteum creates
commands/tsconfig.jsonwhen the folder exists so command files inherit the server alias/type project proteum command foo/barrefreshes generated artifacts, builds the dev output, starts a temporary local dev server, runs the command, prints the result, and exitsproteum command foo/bar --port 3101runs the same command against an existingproteum devinstance- the dev profiler exposes the same command list and run action through the
Commandstab - the same profiler also exposes
Explain,Doctor, andDiagnosetabs backed by the same diagnostics contract as the CLI
Proteum itself also ships a small built-in diagnostic command at proteum/diagnostics/ping, so the command surface is never empty in dev.
Dev Sessions
Proteum includes a dev-only auth bootstrap command for browser automation, API probes, and protected-route debugging without driving the login UI.
proteum session <email>mints a session for a known user--role <role>asserts that the resolved user has the expected role before returning the session--port <port>or--url <baseUrl>targets an existingproteum devserver- without
--portor--url, Proteum starts a temporary local dev server, creates the session, prints the payload, and exits - output includes the raw token, a
Cookie:header, and a Playwright-readycookiespayload - prefer this command when an LLM or test runner needs an authenticated dev context
- do not use it when the login flow itself is what you are testing
Typical usage:
proteum session [email protected] --role ADMIN --port 3101
proteum session [email protected] --role GOD --jsonThe CLI talks to the running app over the dev-only __proteum/session/start endpoint and uses the auth service registered on the current app router. For the full guide, see docs/dev-sessions.md.
Request Tracing
Proteum includes a dev-only in-memory request trace buffer for auth, routing, controller, context, SSR, API, Prisma SQL, and render debugging.
This is separate from proteum explain and proteum doctor: tracing is live request-time data, while explain/doctor are manifest-backed structure and diagnostics. proteum perf aggregates the same trace buffer into hot-path, waterfall, compare, and memory views. When you already know the failing path and want the fastest suspect list, start with proteum diagnose; when the issue is performance, start with proteum perf; then drop into raw trace output only if needed. When an agent needs repeated trace, perf, diagnose, status, owner, or instruction-routing reads from the same running app, use machine MCP workflow_start, then pass the returned projectId to follow-up app-bound MCP tools.
When diagnosing or testing against an app, first read the default port from PORT or ./.proteum/manifest.json and check whether a server is already running there. If it is, inspect the existing traces before reproducing the issue so you can collect past errors and their context.
proteum trace requests: list the most recent request summariesproteum trace latest: show the latest captured requestproteum trace show <requestId>: inspect one trace in detailproteum trace arm --capture deep: force the next request into deep capture modeproteum trace export <requestId>: write one trace to diskproteum trace latest --url http://127.0.0.1:3010: target a non-standard dev base URL directlyproteum diagnose /dashboard --port 3101: combine owner lookup, diagnostics, trace summary, and buffered logs for one concrete pathproteum perf top --since today: rank the hottest traced paths in the selected windowproteum perf request /dashboard --port 3101: inspect one traced request with stage timings, CPU, SQL, render, and memory deltasproteum perf compare --baseline yesterday --target today --group-by route: compare regression deltas between two windowsproteum perf memory --since 1h --group-by controller: rank recent heap and RSS drift
Trace summaries include sql=<count>. Detailed trace output includes Calls and SQL sections so API/fetcher activity and Prisma queries can be inspected together.
Default behavior:
- tracing is enabled only in
profile: dev - traces live in memory and are bounded by
TRACE_REQUESTS_LIMITandTRACE_EVENTS_LIMIT - payloads are summarized, long strings are truncated, and sensitive fields such as cookies, passwords, and tokens are redacted
TRACE_PERSIST_ON_ERRORcan export crashing requests undervar/traces/proteum devremoves auto-persisted crash traces fromvar/traces/when the dev session stopsENABLE_PROFILER=truereuses the same instrumentation path to populaterequest.profilingand the routerrequest.finishedhook with a reduced request/API/SQL snapshot in any environment, without retaining finished requests in the global trace buffer unless dev trace is also enabled
Trace env example:
export TRACE_ENABLE=true
export TRACE_REQUESTS_LIMIT=200
export TRACE_EVENTS_LIMIT=800
export TRACE_CAPTURE=resolve
export TRACE_PERSIST_ON_ERROR=true
export ENABLE_PROFILER=trueCapture modes:
summary: request lifecycle plus high-signal eventsresolve: adds auth, route resolution, and controller/context stepsdeep: adds route skip reasons and deeper payload summaries for one request investigation
In the dev profiler, the request-trace tabs are now visual as well as textual: Summary, Auth, Routing, Controller, SSR, API, SQL, Errors, Diagnose, Explain, Doctor, Commands, and Cron all add focused charts over the same live contracts, while Perf remains the aggregated hot-path, breakdown, regression, and memory surface exposed by proteum perf.
The trace and perf CLIs talk to the running dev server over the dev-only __proteum/trace and __proteum/perf HTTP endpoints. Use --port for a different local port or --url when the host itself is non-standard. For the full guide, see docs/request-tracing.md.
LLM-Friendly By Design
Proteum is built so an agent can answer these questions quickly and reliably:
- What is this app called, and what are its SEO defaults?
- Which routes exist?
- Which controller handles a request?
- Which services are installed?
- Which layouts exist?
- Which diagnostics did the framework detect?
Proteum answers those questions with explicit artifacts:
identity.config.tsfor app identityproteum.config.tsfor compiler and connected-project setupPORT,ENV_*,URL,URL_INTERNAL, app-chosen connected-project config values,TRACE_*, andENABLE_PROFILERenv vars for the environment surfaceserver/index.tsfor the explicit root service graph.proteum/manifest.jsonfor machine-readable app structureproteum explainfor compact framework introspection, andproteum explain --manifestwhen the full manifest is requiredproteum doctor --jsonfor structured diagnosticsproteum doctor --contracts --jsonfor generated-artifact and manifest-owned file checksproteum explain owner <query>for fast ownership lookup over routes, controllers, files, and generated artifactsproteum diagnose <path>for a one-shot request diagnosis surfaceproteum perf top|request|compare|memoryfor request-trace performance rollupsproteum mcpfor one managed machine-scope MCP router that starts withworkflow_startand routes repeated low-token agent reads byprojectId/__proteum/mcpfrom a runningproteum devserver as the app-root runtime endpoint behind that router- the profiler
Explain,Doctor,Diagnose, andPerftabs for a human-readable view over the same diagnostics and trace-derived perf contracts proteum command ...plus the profilerCommandstab for dev-only internal executionproteum session ...for explicit authenticated dev browser or API bootstrapping without login UI automationproteum e2e ...for Playwright runs that needE2E_BASE_URL,E2E_PORT, orE2E_AUTH_TOKENwithout shell-leading env assignments
If you are an LLM or automation agent, start here:
- Use
proteum mcpas the one registered MCP server;proteum devensures the managed machine daemon is running. - Call MCP
workflow_startwithcwdor a knownprojectId; if it is ambiguous or returns offline app candidates, useproject_resolve { cwd }, choose the intended app root, follow its port-inspected next action when needed, then retryworkflow_start. - If the app root is inside
/.codex/worktrees/andworkflow_startor a guarded CLI command reports missing/stale bootstrap, run the returnednpx proteum worktree init --source <source-app-root>command before runtime reads. - Use the returned live
projectIdwith MCPruntime_status,orient,instructions_resolve,route_candidates,explain_summary,diagnose,trace_show,perf_request, andlogs_tailbefore CLI equivalents for repeated read-only app state. - Treat returned instruction previews as the allowed scope for read-only discovery and diagnostics. Read full file contents only before edits or git writes, when
fullRead/fullReadPolicyrequires it, or when compact previews are insufficient. - Use compact CLI commands for fallback,
dev,build,check,verify, migrations, E2E, and final reproducible terminal evidence. - Use
proteum diagnose,proteum perf, and compactproteum tracefor reproducible command evidence when MCP is unavailable or the terminal output itself is needed. - If machine MCP routing fails, run
proteum mcp statusandproteum runtime statusfrom the intended app root; if no live session exists, use the exact MCP offline or runtime-status next action. If the same app already responds on the configured port without live tracking, use or repair that runtime instead of starting another server. If a live session exists but runtime/MCP is unreachable, stop the listed session file first, then start dev again and retryworkflow_start. Do not run diagnose, trace, or perf reads while runtime health is unreachable, and do notcurlnormal page routes to identify port ownership. - Inspect
server/index.ts, controllers, services, or pages only after the routing/diagnostic surfaces identify the relevant owner. Do not run broad owner searches after MCP already returned the route/page/controller owner. - If the task touches a protected route or controller in dev and login UX is not the feature under test, use
proteum e2e --session-email <email> --session-role <role>for Playwright suites orproteum session <email> --role <role>before direct HTTP calls.
For implementation rules in a real Proteum app, treat the routed local AGENTS.md files plus proteum orient, compact CLI diagnostics, and MCP repeated-read surfaces as the task contract. This README is the framework overview, not the project-local instruction layer.
What Proteum Avoids
Proteum intentionally avoids several patterns that make frameworks harder to inspect and harder to trust:
- hidden runtime globals
- implicit service registration hidden behind bootstrap helpers
- implicit request state inside business services
- controller validation defined far away from the handler
- route systems that cannot be explained without reading the compiler
- generated code that hides where it came from
Real-World Shape
Proteum is already used on large application surfaces with:
- many controllers and services
- SSR landing pages and authenticated app pages
- generated controller accessors injected into page context
- build, typecheck, lint, and diagnostic workflows run from the CLI
In real apps, the common package.json scripts look like this:
{
"scripts": {
"dev": "proteum dev",
"refresh": "proteum refresh",
"typecheck": "proteum typecheck",
"check": "proteum check",
"build": "proteum build --prod",
"start": "node ./bin/server.js"
}
}Installation
Proteum currently targets:
- Node.js
>=20.19.0 - npm
>=3.10.10
Install in an app:
npm install proteumYou can bootstrap a new app with:
npx proteum init my-app --name "My App"
npx proteum init my-app --name "My App" --dry-run --jsonThen use the normal workflow:
npm install
npx proteum configure agents
npx proteum dev
npx proteum check
npx proteum build --prodMigrating To 2.5
Proteum 2.5 removes the old contextual route/controller magic. Apps migrate by replacing ambient @app imports, top-level Router.*(...) route calls, controller classes, and Application subclasses with explicit definition objects and typed runtime callback parameters.
Use the 2.5 migration guide for the full checklist.
Repository Structure
This repository is organized around the same explicit framework surface it exposes:
cli/: compiler, commands, diagnostics, and developer workflowclient/: client runtime, page registration, islands, and router behaviorserver/: controller base classes, services, runtime, and SSR server behaviorcommon/: shared router contracts, models, request/response types, and utilitiesdocs/: focused design notes and internal documentationagents/: agent-specific conventions and scaffolding used in Proteum-based projects
Status
Proteum is actively hardening its explicit model.
The direction is deliberate:
- less runtime magic
- more generated and auditable contracts
- clearer controller and service boundaries
- better SSR, SEO, and explainability defaults
- better ergonomics for both humans and AI agents
If you want a framework that treats machine-readable architecture as a first-class feature, Proteum is what this repository is building.

