@supacloud/cli 0.114.0 → 0.115.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ export {};
@@ -23,6 +23,14 @@ export interface SkillInstallSummary {
23
23
  }
24
24
  export declare function installSkill(request: InstallSkillRequest): SkillInstallSummary;
25
25
  export declare function resolveDefaultCodexSkillRoot(environment?: NodeJS.ProcessEnv, homeDirectory?: string): string;
26
+ /** Stable aliases for common Agent Skill roots; any other value remains an explicit path. */
27
+ export declare const SKILL_TARGET_ALIASES: readonly ["codex", "claude", "agents", "project"];
28
+ export type SkillTargetAlias = typeof SKILL_TARGET_ALIASES[number];
29
+ export declare function resolveSkillTargetRoot(target: string | undefined, options?: {
30
+ environment?: NodeJS.ProcessEnv;
31
+ homeDirectory?: string;
32
+ workingDirectory?: string;
33
+ }): string;
26
34
  export declare function resolveBundledSkillDirectory(moduleUrl?: string): string;
27
35
  export declare function registerAiTools(server: ToolServer): void;
28
36
  export {};
@@ -12,5 +12,5 @@ export declare const STARTER_DATABASE_CONFIG: {
12
12
  export declare const STARTER_DATABASE_SCHEMA = "import { sql } from \"drizzle-orm\";\nimport { boolean, check, integer, jsonb, pgTable, primaryKey, text, unique, uuid } from \"drizzle-orm/pg-core\";\n\n// Structure for the reviewed starter migrations. Grants/policies stay in those migrations.\nexport const application = pgTable.withRLS(\"starter_application\", {\n singleton: boolean().default(true).primaryKey(),\n projectId: text(\"project_id\").notNull(),\n tenantId: text(\"tenant_id\").notNull(),\n}, table => [\n check(\"starter_application_singleton_check\", sql`${table.singleton}`),\n check(\"starter_application_project_id_check\", sql`length(${table.projectId}) > 0`),\n check(\"starter_application_tenant_id_check\", sql`length(${table.tenantId}) > 0`),\n]);\n\nexport const reviews = pgTable.withRLS(\"starter_reviews\", {\n id: text().primaryKey(),\n ownerId: text(\"owner_id\").notNull(),\n state: text({ enum: [\"draft\", \"approved\"] }).notNull(),\n version: integer().notNull(),\n}, table => [\n check(\"starter_reviews_state_check\", sql`${table.state} IN ('draft', 'approved')`),\n check(\"starter_reviews_version_check\", sql`${table.version} > 0`),\n]);\n\nexport const members = pgTable.withRLS(\"starter_members\", {\n subject: text().primaryKey(),\n enabled: boolean().default(true).notNull(),\n canApprove: boolean(\"can_approve\").default(false).notNull(),\n storageSubject: uuid(\"storage_subject\").unique(),\n});\n\nexport const attachments = pgTable.withRLS(\"starter_attachments\", {\n reviewId: text(\"review_id\").primaryKey().references(() => reviews.id),\n artifactId: uuid(\"artifact_id\").notNull().unique(),\n ownerId: text(\"owner_id\").notNull(),\n runId: uuid(\"run_id\").notNull().unique(),\n objectPath: text(\"object_path\").notNull().unique(),\n});\n\nexport const attachmentResults = pgTable.withRLS(\"starter_attachment_results\", {\n reviewId: text(\"review_id\").notNull().references(() => reviews.id),\n version: integer().notNull(),\n artifactId: uuid(\"artifact_id\").notNull(),\n result: jsonb().$type<unknown>().notNull(),\n}, table => [\n primaryKey({ columns: [table.reviewId, table.version, table.artifactId] }),\n check(\"starter_attachment_results_version_check\", sql`${table.version} >= 2`),\n]);\n\nexport const attachmentRetries = pgTable.withRLS(\"starter_attachment_retries\", {\n runId: uuid(\"run_id\").primaryKey(),\n reviewId: text(\"review_id\").notNull().references(() => attachments.reviewId),\n previousRunId: uuid(\"previous_run_id\").notNull().unique(),\n generation: integer().notNull(),\n}, table => [\n unique(\"starter_attachment_retries_review_id_generation_key\").on(table.reviewId, table.generation),\n check(\"starter_attachment_retries_generation_check\", sql`${table.generation} > 0`),\n check(\"starter_attachment_retries_check\", sql`${table.runId} <> ${table.previousRunId}`),\n]);\n\nexport type ReviewRow = typeof reviews.$inferSelect;\nexport type NewReview = typeof reviews.$inferInsert;\n";
13
13
  export declare const STARTER_DATABASE_MODULES = "import { defineDatabaseModule } from \"@supacloud/db\";\nimport { getTableConfig } from \"drizzle-orm/pg-core\";\nimport { application, reviews, members, attachments, attachmentResults, attachmentRetries } from \"./schema\";\n\nconst backendPolicies = [\n [\"starter_backend_binding_read\", \"public.starter_application\", \"select\", [\"starter_review_http\", \"starter_review_worker\"]],\n [\"starter_backend_binding_lock\", \"public.starter_application\", \"update\", [\"starter_review_http\", \"starter_review_worker\"]],\n [\"starter_backend_binding_immutable\", \"public.starter_application\", \"update\", [\"starter_review_http\", \"starter_review_worker\"]],\n [\"starter_backend_member_read\", \"public.starter_members\", \"select\", [\"starter_review_http\", \"starter_review_worker\"]],\n [\"starter_backend_member_lock\", \"public.starter_members\", \"update\", [\"starter_review_http\", \"starter_review_worker\"]],\n [\"starter_backend_member_immutable\", \"public.starter_members\", \"update\", [\"starter_review_http\", \"starter_review_worker\"]],\n [\"starter_backend_review_read\", \"public.starter_reviews\", \"select\", [\"starter_review_http\", \"starter_review_worker\"]],\n [\"starter_backend_review_update\", \"public.starter_reviews\", \"update\", [\"starter_review_http\"]],\n [\"starter_worker_review_immutable\", \"public.starter_reviews\", \"update\", [\"starter_review_worker\"]],\n [\"starter_backend_attachment_read\", \"public.starter_attachments\", \"select\", [\"starter_review_http\", \"starter_review_worker\"]],\n [\"starter_backend_attachment_lock\", \"public.starter_attachments\", \"update\", [\"starter_review_http\", \"starter_review_worker\"]],\n [\"starter_backend_attachment_immutable\", \"public.starter_attachments\", \"update\", [\"starter_review_http\", \"starter_review_worker\"]],\n [\"starter_http_attachment_insert\", \"public.starter_attachments\", \"insert\", [\"starter_review_http\"]],\n [\"starter_worker_result_read\", \"public.starter_attachment_results\", \"select\", [\"starter_review_worker\"]],\n [\"starter_worker_result_insert\", \"public.starter_attachment_results\", \"insert\", [\"starter_review_worker\"]],\n] as const;\n\n// The module is the single live-Catalog ownership contract for starter tables.\nexport default defineDatabaseModule({\n name: \"starter\",\n tables: [application, reviews, members, attachments, attachmentResults, attachmentRetries].map(table => {\n const config = getTableConfig(table);\n return (config.schema ?? \"public\") + \".\" + config.name;\n }),\n policies: [\n ...([\n [\"starter_http_retry_read\", \"select\", \"starter_review_http\"],\n [\"starter_http_retry_insert\", \"insert\", \"starter_review_http\"],\n [\"starter_worker_retry_read\", \"select\", \"starter_review_worker\"],\n ] as const).map(([name, operation, role]) => ({\n name, table: \"public.starter_attachment_retries\", operation, roles: [role],\n source: \"migrations/005-review-task-recovery.sql\", tests: [\"tests/database-governance.sql\"],\n })),\n ...backendPolicies.map(([name, table, operation, roles]) => ({\n name, table, operation, roles: [...roles], source: \"migrations/004-review-runtime-roles.sql\",\n tests: [\"tests/database-governance.sql\"],\n })),\n {\n name: \"starter_member_read\", table: \"public.starter_members\", operation: \"select\",\n roles: [\"authenticated\"], source: \"migrations/003-review-uploads.sql\",\n tests: [\"tests/database-governance.sql\"],\n },\n {\n name: \"starter_review_read\", table: \"public.starter_reviews\", operation: \"select\",\n roles: [\"authenticated\"], source: \"migrations/003-review-uploads.sql\",\n tests: [\"tests/database-governance.sql\"],\n },\n ],\n});\n";
14
14
  export declare const STARTER_DATABASE_TEST = "-- Read-only catalog assertions; behavioral authorization tests remain separate.\nBEGIN READ ONLY;\nDO $test$\nDECLARE\n owned text[] := ARRAY['starter_application','starter_reviews','starter_members',\n 'starter_attachments','starter_attachment_results','starter_attachment_retries'];\nBEGIN\n IF (SELECT count(*) FROM pg_class c JOIN pg_namespace n ON n.oid=c.relnamespace\n WHERE n.nspname='public' AND c.relname=ANY(owned) AND c.relrowsecurity) <> 6 THEN\n RAISE EXCEPTION 'All starter tables must exist with RLS enabled';\n END IF;\n IF (SELECT count(*) FROM pg_policy p JOIN pg_class c ON c.oid=p.polrelid\n JOIN pg_namespace n ON n.oid=c.relnamespace\n WHERE n.nspname='public' AND c.relname=ANY(owned)) <> 20 THEN\n RAISE EXCEPTION 'Starter policy inventory changed; reconcile db/modules.ts';\n END IF;\n IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname IN ('starter_review_http','starter_review_worker')\n AND (rolsuper OR rolbypassrls)) THEN\n RAISE EXCEPTION 'Starter roles must not bypass row security';\n END IF;\n IF (SELECT count(*) FROM pg_roles WHERE rolname IN ('starter_review_http','starter_review_worker')) <> 2 THEN\n RAISE EXCEPTION 'Starter runtime roles are missing';\n END IF;\nEND\n$test$;\nROLLBACK;\n";
15
- export declare const STARTER_DATABASE_GUIDE = "\n## Database Source Workflow\n\nDrizzle owns table declarations and inferred row types in db/schema.ts.\nUse the existing @supacloud/db/drizzle-bun adapters for typed queries and governed\ntransactions; never replace permission, idempotency or audit checks with plain CRUD.\nOpaque JSON still needs runtime decoding.\n\nAfter installing dependencies, run `bun run db:generate` once and commit db/contracts/.\nThe default `bun run check` and build fail on stale database contracts before any\ncompiler regeneration. After an intentional source change, run db:generate again,\nreview the diff, then run check.\nThe command starter registers databaseGovernance.moduleFile = \"db/modules.ts\" and\nkeeps the default `databaseGovernance.mode = \"check\"`: compile/check/build run\nthe offline source-contract gate without a database. Use `bun run dev:integration`\nwith the CLI's explicit loopback database URL, or set databaseGovernance.mode to\n\"enforce\" with an explicitly supplied `DATABASE_URL`, to run SQL lint and live\nCatalog reconciliation. Missing connections, stale source contracts and Catalog\ndrift fail closed; no contracts or migrations are silently regenerated.\n\n- Maintain one schema-qualified function with explicit grants per db/functions/*.sql.\n- Preserve migrations/ and its existing executor/ledger. Add forward migrations only.\n- `bun run db:diff` generates Drizzle drafts under db/migration-candidates/, never\n into the deployment directory. The starter has existing SQL history, so establish\n and review a matching Drizzle baseline before promoting any draft; the first\n draft is not automatically an incremental production migration.\n- `bun run db:pull` requires an explicitly selected DATABASE_URL and writes only\n output/database-audit/drizzle-candidate/. Review candidates; never overwrite source blindly.\n- Full SQL dumps belong under the ignored output/database-audit/ directory. They are\n audit/recovery artifacts, never ordinary type, application or test inputs.\n- `bun run db:assess` explains adoption/findings without writing or connecting.\n- GraphQL/PostgREST exports remain legitimate protocol contracts. This check is not\n proof of deployed schema, effective role permissions or complete RLS equivalence.\n\nDo not introduce any/@ts-ignore to bypass a contract. Use Drizzle-inferred types,\npreserve bigint/numeric precision and decode unknown results at the boundary.\n";
15
+ export declare const STARTER_DATABASE_GUIDE = "\n## Database Source Workflow\n\nDrizzle owns table declarations and inferred row types in db/schema.ts.\nUse the existing @supacloud/db/drizzle-bun adapters for typed queries and governed\ntransactions; never replace permission, idempotency or audit checks with plain CRUD.\nOpaque JSON still needs runtime decoding.\n\nAfter installing dependencies, run `bun run db:generate` once and commit db/contracts/.\nThe default `bun run check` and build fail on stale database contracts before any\ncompiler regeneration. After an intentional source change, run db:generate again,\nreview the diff, then run check.\nThe command starter uses the default database governance module path\n`db/modules.ts` and fixes `databaseGovernance.mode = \"check\"`: compile/check/build\nrun the offline source-contract gate without a database. Use `bun run dev:integration`\nwith the CLI's explicit loopback database URL, or set databaseGovernance.mode to\n\"enforce\" with an explicitly supplied `DATABASE_URL`, to run SQL lint and live\nCatalog reconciliation. Missing connections, stale source contracts and Catalog\ndrift fail closed; no contracts or migrations are silently regenerated.\n\n- Maintain one schema-qualified function with explicit grants per db/functions/*.sql.\n- Preserve migrations/ and its existing executor/ledger. Add forward migrations only.\n- `bun run db:diff` generates Drizzle drafts under db/migration-candidates/, never\n into the deployment directory. The starter has existing SQL history, so establish\n and review a matching Drizzle baseline before promoting any draft; the first\n draft is not automatically an incremental production migration.\n- `bun run db:pull` requires an explicitly selected DATABASE_URL and writes only\n output/database-audit/drizzle-candidate/. Review candidates; never overwrite source blindly.\n- Full SQL dumps belong under the ignored output/database-audit/ directory. They are\n audit/recovery artifacts, never ordinary type, application or test inputs.\n- `bun run db:assess` explains adoption/findings without writing or connecting.\n- GraphQL/PostgREST exports remain legitimate protocol contracts. This check is not\n proof of deployed schema, effective role permissions or complete RLS equivalence.\n\nDo not introduce any/@ts-ignore to bypass a contract. Use Drizzle-inferred types,\npreserve bigint/numeric precision and decode unknown results at the boundary.\n";
16
16
  export declare function starterDatabaseFiles(): Record<string, string>;
@@ -1,4 +1,4 @@
1
1
  /** Shared reactive conventions for command, HTTP and edge starters. */
2
2
  export declare const STARTER_REACTIVE_GUIDE = "# Reactive development / \u54CD\u5E94\u5F0F\u5F00\u53D1\n\nRxJS is the default and only reactive event library in the starter ecosystem.\nOrdinary queries and business commands still use async/await. Use RxJS for\nongoing events and timing/composition, not as a new\ntransaction, retry or durable-delivery system.\n\nHost defaults:\n- In a native Angular host, use signal/resource APIs from @supacloud/app/angular\n and Angular's scheduler. Do not mix them with the legacy root signal graph.\n- In framework-neutral code, use async/await for one result and RxJS for event\n composition. Raw continuous protocols use AsyncIterable unless an existing\n RxJS/Angular boundary is the better fit. The host owns cancellation through\n an explicit signal.\n\n- Import native operators from rxjs; do not invent another event/operator library.\n- Import takeUntilAborted / toReadableStream from @supacloud/app/reactive.\n- Every subscription belongs to a request, connection, task or application owner.\n Bind the owner's AbortSignal before starting work; release it on exit.\n- toReadableStream has a bounded item buffer and fails on overflow. It is not\n an event journal. Do not silently drop durable business events or audit records.\n- Never wrap command submission in defer/retry/repeat or submit from subscribe.\n Await the existing governed command and then observe its existing receipt.\n- Do not shareReplay authenticated values globally across projects or sessions.\n- subscribe(async ...) does not await processing. Keep acknowledged task-output\n consumers on the SDK's for-await watch path; do not advance onCursor via next().\n\n## SupaCloud JS\n\nThe platform SDK is @supacloud/js, not a replacement Supabase client. Keep the\nclient from createSupaCloudClient. Database/Auth/Storage calls use client.supabase;\nplatform commands/tasks use the existing client.commands / client.tasks APIs.\nFor applications using this SDK, import observeQuery and observeTask from\n@supacloud/js/reactive. Pass the request signal to the native query builder:\n\n observeQuery(signal => client.supabase.from(\"widgets\").select(\"id\").abortSignal(signal), { signal: owner.signal })\n\nThe query result keeps data/error/count/status; non-null errors enter error().\nThe query factory runs once per subscriber. This is intended for reads, not\nreplaying writes. A PromiseLike is supported; an already-started Promise is not\nan appropriate factory. Unsubscribe aborts cooperative I/O, not committed work.\n\nSubmit a background task ONCE with the existing SDK, then observe the receipt:\n\n const task = await client.functions.invokeBackground(\"render\", { body: input });\n const progress = observeTask(task, { signal: owner.signal });\n\nUnsubscribing progress does not cancel the server task. Task read/decoder errors\nterminate observation; there is no automatic business retry. Realtime-to-polling\nfallback and project validation remain the SDK's responsibilities. Do not invent\na public.tasks table or copy service credentials into browser code.\n\nRun bun run check. Add cancellation, error, overflow and cross-owner isolation\ncoverage whenever adding streaming behavior. These APIs require the matching\nframework/SDK release or the packed candidate packages used by repository CI.\n";
3
- export declare const STARTER_REACTIVE_AGENTS = "# Application development rules\n\nRead README.md and REACTIVE.md before adding asynchronous features. If the\napplication is hosted by Angular, read the @supacloud/app/angular guidance\nbefore choosing a signal API.\nPrefer the generated contracts and existing project-bound @supacloud/js client.\nUse async/await for a single result; RxJS is the default event-composition\nlibrary. Do not introduce another reactive library without a documented special\nrequirement and equivalent lifecycle tests.\nBind subscriptions to an explicit owner and propagate cancellation to native I/O.\nNever automatically retry a write or turn observable delivery into durable ack.\nDo not bypass authorization, transactions, idempotency or audit to simplify code.\nRun bun run check; include negative and cleanup tests. Never store live credentials.\n";
3
+ export declare const STARTER_REACTIVE_AGENTS = "# Application development rules\n\nRead README.md and REACTIVE.md before adding asynchronous features. If the\napplication is hosted by Angular, read the @supacloud/app/angular guidance\nbefore choosing a signal API.\nPrefer the generated contracts and existing project-bound @supacloud/js client.\nUse async/await for a single result; RxJS is the default event-composition\nlibrary. Do not introduce another reactive library without a documented special\nrequirement and equivalent lifecycle tests.\nBind subscriptions to an explicit owner and propagate cancellation to native I/O.\nNever automatically retry a write or turn observable delivery into durable ack.\nDo not bypass authorization, transactions, idempotency or audit to simplify code.\nStart with `supacloud app context --format json` and `supacloud app doctor --format json`;\ndo not scan the whole repository first or treat generated/ as source. Apply only\nreviewed diagnostic fixes with `supacloud app fix --fix <file>`, then re-run check\nand doctor. Never weaken compiler governance to hide a diagnostic.\nRun bun run check; include negative and cleanup tests. Never store live credentials.\n";
4
4
  export declare const STARTER_REACTIVE_TEST = "import { expect, test } from \"bun:test\";\nimport { Observable } from \"rxjs\";\nimport { takeUntilAborted, toReadableStream } from \"@supacloud/app/reactive\";\n\ntest(\"the owner's signal releases reactive work exactly once\", () => {\n const owner = new AbortController();\n let starts = 0, stops = 0;\n const source = new Observable<number>(() => { starts++; return () => { stops++; }; });\n source.pipe(takeUntilAborted(owner.signal)).subscribe();\n owner.abort();\n source.pipe(takeUntilAborted(owner.signal)).subscribe();\n expect(starts).toBe(1);\n expect(stops).toBe(1);\n});\n\ntest(\"cancelled stream consumers release their subscription\", async () => {\n let stops = 0;\n const source = new Observable<number>(() => () => { stops++; });\n const stream = toReadableStream(source);\n await stream.cancel();\n expect(stops).toBe(1);\n});\n";
@@ -1,7 +1,7 @@
1
- export type StarterTemplate = "minimal" | "http" | "command" | "edge";
1
+ export type StarterTemplate = "minimal" | "command";
2
2
  export interface StarterSdkDependencies {
3
3
  "@supacloud/js": string;
4
4
  "@supabase/supabase-js": string;
5
5
  }
6
- /** Explicit recipes retain their existing layouts; new projects default to minimal. */
7
- export declare function appTemplateFiles(name: string, template: StarterTemplate, sdkDependencies?: StarterSdkDependencies): Record<string, string>;
6
+ /** New projects use the minimal layout; the command recipe is emitted separately. */
7
+ export declare function appTemplateFiles(name: string, template: "minimal", sdkDependencies: StarterSdkDependencies): Record<string, string>;
@@ -67,33 +67,28 @@ export interface AppToolArguments {
67
67
  wait?: boolean;
68
68
  timeout_seconds?: number;
69
69
  kind?: "module" | "command" | "query" | "controller" | "job" | "contract" | "resource" | "feature";
70
- template?: "minimal" | "http" | "command" | "edge";
70
+ template?: "minimal" | "command";
71
71
  name?: string;
72
72
  module?: string;
73
73
  permission?: string;
74
74
  read_permission?: string;
75
- "read-permission"?: string;
76
75
  rpc?: string;
77
76
  database_source?: string;
78
77
  database_table?: string;
79
78
  database_type?: string;
80
- "database-source"?: string;
81
- "database-table"?: string;
82
- "database-type"?: string;
83
79
  dir?: string;
84
80
  force?: boolean;
85
81
  dry_run?: boolean;
86
82
  register_in?: string;
87
- "dry-run"?: boolean;
88
- "register-in"?: string;
89
83
  root?: string;
90
84
  include?: string;
91
85
  out_dir?: string;
92
86
  strict?: boolean;
93
87
  format?: "text" | "json";
94
- json?: boolean;
95
88
  target?: string;
96
89
  fix?: string;
90
+ from_doctor?: string;
91
+ fix_index?: number;
97
92
  write?: boolean;
98
93
  /** `app dev` local profile. `fast` is local/ephemeral; `integration` requires an explicit database URL. */
99
94
  profile?: "fast" | "integration";
@@ -103,7 +98,6 @@ export interface AppToolArguments {
103
98
  watch?: boolean;
104
99
  /** Integration dev verifies an explicit loopback database before running dev:integration. */
105
100
  database_url?: string;
106
- "database-url"?: string;
107
101
  offset?: number;
108
102
  service?: string;
109
103
  search?: string;
@@ -113,7 +107,6 @@ export interface AppToolArguments {
113
107
  events?: string;
114
108
  /** `app context`: exact opaque request ID to correlate from events. */
115
109
  request_id?: string;
116
- "request-id"?: string;
117
110
  }
118
111
  export interface ToolResult {
119
112
  isError?: boolean;
@@ -131,12 +124,6 @@ declare function formatGraphText(manifest: AppManifest): string;
131
124
  declare function reverseDependencies(manifest: AppManifest, token: string): string[];
132
125
  export declare function runAppTool(request: AppToolArguments, options?: AppToolOptions): Promise<ToolResult>;
133
126
  export declare function registerAppTools(server: ToolServer, options?: AppToolOptions): void;
134
- /**
135
- * Promotes the single-entry development verbs to top-level commands so an AI or
136
- * developer does not need to remember the `app` namespace. The `app` tool and
137
- * these aliases share one implementation and one execution-policy classification.
138
- */
139
- export declare function registerAppAliases(server: ToolServer): void;
140
127
  export declare const __internal: {
141
128
  pascalName: typeof pascalName;
142
129
  camelName: typeof camelName;
@@ -10,6 +10,7 @@ export interface DbToolArguments {
10
10
  database_url?: string;
11
11
  schema?: string;
12
12
  lite?: boolean;
13
+ remote?: boolean;
13
14
  project_dir?: string;
14
15
  schema_dir?: string;
15
16
  db_major_version?: number;
@@ -23,13 +23,15 @@ interface ToolResponse {
23
23
  isError?: boolean;
24
24
  }
25
25
  export declare const deployToolSchema: {
26
+ action: Type.TOptional<Type.TEnum<"init"[]>>;
27
+ root: Type.TOptional<Type.TString>;
26
28
  ref: Type.TOptional<Type.TString>;
27
29
  cwd: Type.TOptional<Type.TString>;
28
30
  skip_build: Type.TOptional<Type.TBoolean>;
29
31
  assets_only: Type.TOptional<Type.TBoolean>;
30
32
  backend: Type.TOptional<Type.TBoolean>;
31
33
  status: Type.TOptional<Type.TString>;
32
- json: Type.TOptional<Type.TBoolean>;
34
+ format: Type.TOptional<Type.TEnum<("json" | "text")[]>>;
33
35
  };
34
36
  export declare function findDeployConfigRoot(startDirectory: string, environmentName?: string): Promise<string>;
35
37
  export declare function createBuildEnvironment(names: string[] | undefined, environmentVariables: Readonly<Record<string, string>> | undefined): {
@@ -1,6 +1,10 @@
1
1
  import { type ResolvedContext } from "../context";
2
2
  import type { ToolSchema } from "../schema";
3
- import { type ToolServer } from "../tool-server";
3
+ import { type ToolResult, type ToolServer } from "../tool-server";
4
+ export interface InitRequest {
5
+ root?: string;
6
+ format?: "text" | "json";
7
+ }
4
8
  export interface DeveloperExperienceOptions {
5
9
  cwd?: string;
6
10
  activeContext?: ResolvedContext;
@@ -13,6 +17,7 @@ interface PackageManifest {
13
17
  export declare const initToolSchema: ToolSchema;
14
18
  export declare const environmentToolSchema: ToolSchema;
15
19
  declare function outputDirectoryFor(manifest: PackageManifest): string;
20
+ export declare function initializeProject(request: InitRequest, options?: DeveloperExperienceOptions): Promise<ToolResult>;
16
21
  declare function profileNameFromFile(name: string): string | null;
17
22
  declare function statusMissing(context: ResolvedContext): string[];
18
23
  declare function deployMissing(context: ResolvedContext, application?: Record<string, unknown> | null, hasFrontend?: boolean): string[];
@@ -28,7 +28,7 @@ export interface LiteCliArgs {
28
28
  service_role?: boolean;
29
29
  force?: boolean;
30
30
  memory?: boolean;
31
- json?: boolean;
31
+ format?: "text" | "json";
32
32
  baseline?: boolean;
33
33
  production?: boolean;
34
34
  runtime_mode?: "development" | "strict";
@@ -31,7 +31,6 @@ export declare const remoteDevToolSchema: {
31
31
  delete: Type.TOptional<Type.TBoolean>;
32
32
  reload: Type.TOptional<Type.TBoolean>;
33
33
  interval_ms: Type.TOptional<Type.TNumber>;
34
- json: Type.TOptional<Type.TBoolean>;
35
34
  apply: Type.TOptional<Type.TBoolean>;
36
35
  drizzle_config: Type.TOptional<Type.TString>;
37
36
  migrations_dir: Type.TOptional<Type.TString>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supacloud/cli",
3
- "version": "0.114.0",
3
+ "version": "0.115.0",
4
4
  "description": "Project-scoped CLI for SupaCloud users",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -52,9 +52,9 @@
52
52
  "directory": "packages/cli"
53
53
  },
54
54
  "dependencies": {
55
- "@supacloud/compiler": "^0.53.1",
55
+ "@supacloud/compiler": "^0.54.0",
56
56
  "@supacloud/delivery": "0.24.0",
57
- "@supacloud/db": "0.20.3",
57
+ "@supacloud/db": "0.20.4",
58
58
  "typebox": "1.4.3"
59
59
  },
60
60
  "overrides": {
@@ -64,10 +64,10 @@
64
64
  },
65
65
  "devDependencies": {
66
66
  "@supabase/supabase-js": "2.118.0",
67
- "@supacloud/elysia": "0.37.0",
67
+ "@supacloud/elysia": "0.38.0",
68
68
  "@types/bun": "^1.4.4",
69
69
  "effect": "4.0.5",
70
- "elysia": "2.0.0-rc.0",
70
+ "elysia": "2.0.0-rc.1",
71
71
  "typescript": "^7.0.2"
72
72
  }
73
73
  }
@@ -16,7 +16,7 @@ Use `supacloud` as the project-level control surface and keep durable changes re
16
16
  supacloud status
17
17
  ```
18
18
 
19
- A missing remote project context does not block local `migration_new`, `db_diff`, or `db_reset`; it blocks remote inspection/apply until context is supplied.
19
+ A missing remote project context does not block local `app init/generate/context/check/doctor`, `migration_new`, `db_diff`, or `db_reset`; it blocks remote inspection/apply until context is supplied.
20
20
 
21
21
  2. Never place secrets, service-role keys, database URLs, passwords, or tokens in commands that will be logged, source files, migration files, or chat output.
22
22
  3. Treat schema, functions/RPC, triggers, RLS policies, indexes, grants, extensions, and seed/reference-data changes as migrations. Do not apply them through `database query`, `psql`, a dashboard SQL editor, or a raw Management API call.
@@ -39,8 +39,9 @@ and retry the unified command. Do not substitute a legacy endpoint when it fails
39
39
  The inspection and database-maintenance workflow below is not a deployment checklist.
40
40
 
41
41
  1. Classify the request using [references/command-map.md](references/command-map.md).
42
- 2. For database work, load [references/database-workflow.md](references/database-workflow.md) and choose either new-change or historical-drift reconciliation.
43
- 3. For AI-assisted database changes, first request bounded context:
42
+ 2. For application code changes, load [references/app-workflow.md](references/app-workflow.md) and use the init → context → generate → check → fix → verify loop.
43
+ 3. For database work, load [references/database-workflow.md](references/database-workflow.md) and choose either new-change or historical-drift reconciliation.
44
+ 4. For AI-assisted database changes, first request bounded context:
44
45
 
45
46
  ```bash
46
47
  supacloud db context --module_file db/modules.ts --module <module>
@@ -49,12 +50,30 @@ The inspection and database-maintenance workflow below is not a deployment check
49
50
 
50
51
  Use the returned source/test paths and ownership boundary; do not scan or
51
52
  edit the complete schema dump.
52
- 4. Prefer the smallest read-only inspection that proves current state.
53
- 5. Create or update version-controlled artifacts before remote writes.
54
- 6. Verify locally, inspect the diff, and run the narrowest relevant tests.
55
- 7. Preview remote changes with `--dry_run`.
56
- 8. Apply only within the user-authorized environment and scope.
57
- 9. Read back migration history and affected resources; report exact evidence and any remaining drift.
53
+ 5. Prefer the smallest read-only inspection that proves current state.
54
+ 6. Create or update version-controlled artifacts before remote writes.
55
+ 7. Verify locally, inspect the diff, and run the narrowest relevant tests.
56
+ 8. Preview remote changes with `--dry_run`.
57
+ 9. Apply only within the user-authorized environment and scope.
58
+ 10. Read back migration history and affected resources; report exact evidence and any remaining drift.
59
+
60
+ ## Application authoring
61
+
62
+ Use the stable local loop when creating or changing application code:
63
+
64
+ ```bash
65
+ supacloud app init --root ./orders-api --name orders-api --format json
66
+ supacloud app context --format json
67
+ supacloud app generate --kind feature --name case-approval --format json
68
+ supacloud app check --format json
69
+ supacloud app doctor --format json
70
+ supacloud app verify-plan --target <module>
71
+ ```
72
+
73
+ Read [references/app-workflow.md](references/app-workflow.md) for the full
74
+ sequence and guardrails. `app fix` previews one reviewed diagnostic repair;
75
+ `--write` applies it and requires a recheck. These local app actions do not need
76
+ remote project credentials.
58
77
 
59
78
  ## Project endpoint inspection
60
79
 
@@ -0,0 +1,52 @@
1
+ # Application authoring workflow
2
+
3
+ Load this reference when creating or changing a SupaCloud application, feature,
4
+ route, command, query, job, contract or resource. These actions are local unless
5
+ the request explicitly deploys or mutates a remote project.
6
+
7
+ ## Loop
8
+
9
+ ```bash
10
+ # 1. Create a project or inspect the existing project.
11
+ supacloud app init --root ./orders-api --name orders-api --format json
12
+ supacloud app context --format json > context.json
13
+ supacloud app doctor --format json > doctor.json
14
+
15
+ # 2. If doctor reports a preview-ready diagnostic, inspect its fix payload.
16
+ supacloud app fix --fix <reviewed-fix.json>
17
+ # Apply only after review; then re-run check and doctor.
18
+ supacloud app fix --fix <reviewed-fix.json> --write
19
+
20
+ # 3. Generate the smallest owned scaffold.
21
+ supacloud app generate --kind module --name orders --format json
22
+ supacloud app generate --kind controller --module orders --format json
23
+ supacloud app generate --kind command --module orders --name accept --format json
24
+ supacloud app generate --kind query --module orders --name list --format json
25
+ supacloud app generate --kind job --module orders --name sync-orders --format json
26
+ supacloud app generate --kind contract --module orders --name accept --format json
27
+
28
+ # 4. Verify the narrow change.
29
+ supacloud app compile
30
+ supacloud app check --format json
31
+ supacloud app verify-plan --target orders
32
+ bun test <returned-test-file>
33
+ git diff --check
34
+ ```
35
+
36
+ ## Guardrails
37
+
38
+ - Read `app context` before broad edits. Do not scan the whole repository or read
39
+ `generated/**` as the source of truth.
40
+ - Edit maintained sources, then regenerate. Never hand-edit `generated/**`.
41
+ - Keep feature code and colocated tests under the generated feature directory.
42
+ - Generate with explicit business inputs (`--permission`, `--rpc`,
43
+ `--database-source`, `--database-table`, `--database-type`) when required.
44
+ Never invent authorization, persistence or database ownership.
45
+ - `app fix` is preview-only by default. `--write` applies one reviewed fix; it
46
+ does not prove business correctness or authorize production changes.
47
+ - Use `verify-plan` and the returned focused test first. Do not default to the
48
+ full test suite unless the change crosses shared boundaries.
49
+ - Local app actions do not require Management API credentials. Remote deploy,
50
+ database and project operations still require the selected project context.
51
+ - Do not weaken compiler governance to make a diagnostic disappear. Fix the
52
+ source or report the required explicit input.
@@ -6,6 +6,12 @@ Load this reference when selecting a command surface or when a user asks an AI t
6
6
 
7
7
  | Intent | Use | Guardrail |
8
8
  | --- | --- | --- |
9
+ | Create a local application | `app init --format json` | Empty real directory; local-only, no dependency install |
10
+ | Inspect the compiled application before edits | `app context --format json` | Read the module neighborhood; do not scan the whole repository |
11
+ | Generate a module/feature/route/command/query/job/contract/resource | `app generate --kind <kind> --format json` | Explicit business inputs; never invent permissions, RPCs or database ownership |
12
+ | Diagnose or repair application diagnostics | `app doctor --format json`, `app fix --fix <fix.json>` | Fix is preview-only by default; review and recheck after `--write` |
13
+ | Focus application tests | `app verify-plan --target <module>` | Run the returned focused tests, not an unconditional full suite |
14
+ | Compile or check application artifacts | `app compile`, `app check --format json` | Generated files are outputs; fix source and regenerate, never hand-edit |
9
15
  | Deploy the bound application | `supacloud --env <name> deploy` | Use current CLI/server and application delivery configuration; never fall back to standalone target or direct frontend activation commands |
10
16
  | Inspect current project binding | `supacloud status` | Read-only; run first |
11
17
  | Inspect selected project API/Auth/Studio origins | `supacloud project endpoints` | Uses the Management API's authoritative projection; do not reconstruct domains locally |
@@ -31,13 +37,15 @@ Load this reference when selecting a command surface or when a user asks an AI t
31
37
  | Configure project gateway routes | `gateway` | Requires an admin-capable project token; inspect before write |
32
38
  | Install/upgrade/debug SupaCloud servers | `supacloud-admin` | Platform boundary; not a project CLI action |
33
39
 
34
- If `status` reports missing project context, local migration authoring may still
35
- continue. Do not attempt remote inspection, baseline, push, or resource changes
36
- until a project-scoped context is resolved.
40
+ If `status` reports missing project context, local application authoring
41
+ (`app init/generate/context/check/doctor/verify-plan`) and migration authoring may
42
+ still continue. Do not attempt remote inspection, baseline, push, deploy, or
43
+ resource changes until a project-scoped context is resolved.
37
44
 
38
45
  ## Command groups
39
46
 
40
47
  - `status`: resolved context, Management API connectivity, authentication, and project reachability.
48
+ - `app`: local application authoring and diagnostics: init, generate, dev/watch, verify-plan, compile/check, graph/explain, context, doctor and reviewed fix. Local actions do not require remote project credentials.
41
49
  - `project`: selected-project metadata, authoritative endpoint projection, health, logs, API keys/settings, background tasks, retry/cancel, DLQ, and background settings. `project list` deliberately redirects to `supacloud-admin`; cross-project enumeration is not a project CLI capability.
42
50
  - `database`: read/query, schema inspection, extensions, indexes, RLS, stats, migration push, controlled historical baseline, and SQL-file execution.
43
51
  - `supabase`: allowlisted official CLI adapter for initialization, declarative authoring, config pull, local stacks, reset/diff, explicit-DSN inspection/backup/type generation, and SupaCloud-controlled migration push.