Usage Examples
Four concrete walkthroughs: extending the CRM through the API, running a CLI
command, using the clientos-context skill, and deploying to production.
1. Add a CRM resource end to end
The clientos domain follows one consistent pattern across all 14 files in
apps/api/src/routes/clientos/*. Using clients.ts as the reference
implementation, adding a new resource means:
- Define the table in
packages/db/src/schema-clientos.ts, inside theclientosPostgres schema, with anorgIdcolumn like every other table in that schema. - Create a route file under
apps/api/src/routes/clientos/. Each file defines:- A Zod response schema (e.g.
ClientSchema) and aserializeClient-style function to shape DB rows into API responses. - Three role tiers as
constarrays:readRoles(org:viewer+),writeRoles(org:contributor+),deleteRoles(org:admin). - One
createRoute()+ handler pair per operation (list, get, create, update, delete), each withmiddleware: [requireRole(...roles)].
- A Zod response schema (e.g.
- Enforce org scoping in the handler, not in the database: call
callerOrgIds(user)and filter every query withinArray(table.orgId, orgIds)(list/get) or verify the target org is in that list before a write (seecreateClientRoute's handling ofbody.orgId). - Emit an audit event on create/update/delete via
emitAuditEvent()— every mutatingclientosroute does this for traceability. - Mount the route on the shared router alongside the other
clientosroute modules. - Add a test — see
route-factory.test.tsin the same directory for the test harness pattern used across these routes.
The typed client in packages/api-client regenerates from the OpenAPI spec
your new createRoute() definitions produce, so apps/web picks up the new
endpoints with full type safety once you re-run codegen.
2. Run a clientos CLI command
apps/cli/src/commands/clientos/* holds 16 operator commands, invoked as
client clientos <cmd>. Unlike the API, these talk directly to Supabase with
the service-role key — a trusted local tool, not a client-facing surface.
# List clients in the local Supabase instance
client clientos list-clients
# Add a note to a client (interactive prompt for title/body/project)
client clientos add-note acme-corp
add-note looks up the client by slug, offers a project picker if the
client has active projects, and inserts the note directly into the notes
table via the CLI's Supabase client (apps/cli/src/lib/clientos/db.ts) — no
API round-trip.
3. Log client notes with the clientos-context skill
The clientos-context skill (skills/clientos-context/SKILL.md) turns
free-form client notes into structured edits across the eight markdown files
Client OS keeps per client at {CLIENTS_ROOT}/{slug}/04-llm-context/
(brief.md, current-state.md, timeline.md, promises.md,
open-tasks.md, repo-map.md, decisions.md, handoff.md).
Trigger it with phrasing like:
"Log this for acme-corp: they want a loyalty program eventually, and we decided to use Postgres over Mongo for the new integration."
The skill resolves the client slug, reads the existing eight files, routes
each fact to the file that owns that kind of information (a long-term goal
goes to brief.md; a decision goes to decisions.md as a new dated row),
and edits in place rather than appending blindly — updating an existing
promise's status instead of duplicating it, for example. It performs full
CRUD: it can also mark a promise done or remove a resolved task. The files on
disk stay the source of truth; run client clientos sync-files <slug> when
you want those changes pushed into the llm_context_files DB table.
4. Deploying to production
Once you're ready to put this in front of real users, see
Deployment for a summary of what's required — and
docs/PROD-DEPLOY.md in the repo for the full first-production-deploy
checklist covering Render, Vercel, and Supabase Cloud.