npx @karmaniverous/smoz init -i
npx smoz dev -p 3000
smoz
bin).-l offline
: npx smoz dev -l offline -p 3000
This mirrors the README quickstart for the fastest path to “it runs.”
npx smoz
Prints version, repo root, detected PM, and presence of key files.
Tip: you can print the CLI version directly:
npx smoz -v
npx smoz init --yes
First‑time npx note: You can also run npx @karmaniverous/smoz init -i
in an empty directory — this uses the published package and installs template dependencies so subsequent npx smoz …
commands run from your local bin.
Scaffolds a new app:
app/generated/
Options:
-t, --template <nameOrPath>
— template name (e.g., default
) or a filesystem directory--install [pm]
— install deps with npm|pnpm|yarn|bun--no-install
— skip installation (overrides -y
)-y, --yes
— no prompts--dry-run
— show actions without writingDefaults via smoz.config.json (optional):
{
"cliDefaults": {
"init": {
"template": "default",
"onConflict": "example",
"install": "auto"
},
"dev": { "local": "inline" }
}
}
npx smoz register
Scans app/functions/**
for:
lambda.ts
→ register.functions.tsopenapi.ts
→ register.openapi.tsserverless.ts
→ register.serverless.ts (non‑HTTP)One‑shot, idempotent, POSIX‑sorted, formatted when Prettier is available. For a live authoring loop that keeps registers (and OpenAPI) fresh, use smoz dev
instead of a register watcher.
npx smoz add rest/foo/get
npx smoz add step/activecampaign/contacts/getContact
npx smoz add rest/users/:id/get
Scaffold:
Paths must follow the convention under app/functions/<eventType>/...
.
Path parameters
:id
, {id}
, or [id]
:
rest/users/:id/get
, rest/users/{id}/get
, rest/users/[id]/get
.app/functions/rest/users/[id]/get/*
.basePath: 'users/{id}'
.openapi.ts
includes a path parameters array and a short “Path template” hint (e.g., /users/{id}
).Consuming path parameters (eventSchema & handler)
pathParameters
is an object before validation.export const eventSchema = z.object({
pathParameters: z.object({
id: z.string().uuid(), // or z.string().min(1)
}),
});
export const handler = fn.handler(async (event) => {
const id = event.pathParameters.id; // typed via ShapedEvent
return { ok: true } as const;
});
export const eventSchema = z.object({
pathParameters: z.object({
id: z.coerce.number().int().positive(),
}),
});
Portability
:
is not allowed in Windows paths. The CLI uses [id]
on disk and {id}
in code/docs to remain portable while staying native to API Gateway/OpenAPI.npx smoz dev
Long‑running dev loop that watches source files and runs, in order. Inline is the default local backend; use --local offline
to run serverless-offline.
register
(if enabled)openapi
(if enabled)Flags (CLI wins over config defaults; cliDefaults.dev.local
sets the default):
-r, --register
/ -R, --no-register
(default: on)-o, --openapi
/ -O, --no-openapi
(default: on)-l, --local [mode]
— inline
(default) or offline
-s, --stage <name>
— stage name (default inferred)-p, --port <n>
— port (0=random)-V, --verbose
— verbose loggingRoot version flag:
-v, --version
— print smoz
version (use --verbose
with dev
to control verbosity)Notes:
serverless offline
in a child process; when the route surface changes (register writes), the child is restarted automatically.STAGE
) and prints “Updated” vs “No changes” per task run; bursts are debounced.app/config/app.config.ts
and seeds process.env
for keys declared in your app’s global.envKeys
and stage.envKeys
, using the concrete values from stages.default.params
(global) and stages[<stage>].params
(selected stage). Existing process.env
entries are not overridden. This provides parity with provider-level env in production so handlers validate cleanly in dev.