CLI
Agents and automation
Read JSON results
--json writes one JSON document to stdout. Human diagnostics go to stderr. Check success before consuming data; a completed process alone does not mean the command succeeded.
Commands return their own data under data, such as generated edits, hosted projects, or a migration report. Do not parse terminal messages for those values.
Call the CLI from code
Importing the package does not execute a command. runCli returns a result without changing process arguments, the working directory, or the exit status. Prompts and telemetry are disabled by default for library callers. Supply a logger to route diagnostics into the host CLI. The executable adapter owns JSON serialization and process exit status.
CommonJS callers on Node versions that support require(esm) can use const { runCli } = require('@c15t/cli').
For Inth or another host, use explicit project inputs and inspect the returned result. Standalone account commands delegate to the pinned Inth executable and use Inth's existing session and organization context. The runner never reads Inth credentials. Hosts that already own account operations should use the independent frontend exports below.
Reuse generation in another CLI
Install @c15t/cli@alpha in the host project. Import the generation entry point to create a framework's quickstart files without loading the interactive runner:
Both functions return { files, merge, dependencies, instructions } synchronously. files maps paths relative to the project root to the contents a project without them gets, such as .env, c15t.config.ts, next.config.ts and app/layout.tsx for next-app. They are the files of the framework's quickstart. Hosted mode writes the backend URL to .env under the framework's public env var, such as NEXT_PUBLIC_C15T_BACKEND_URL or VITE_C15T_BACKEND_URL. No other file holds the URL, and no file is a .gitignore.
merge says how to apply a file the project already has: env adds the generated KEY=value lines to an existing .env and keeps its other keys, but skips a *_C15T_BACKEND_URL line when the file already sets the matching *_INTH_PROJECT_URL, insert adds a snippet such as the privacy settings link to an existing index.html, and keep leaves the file alone. mergeFile(existing, generated, merge) applies one. Replace other existing files only when the user asks.
dependencies contains installation arguments on the CLI's release line, such as c15t@alpha from an alpha CLI or c15t@3 from a stable v3 CLI. getInstallSpecifier applies the same rule as the CLI's own installs to bare c15t package names and preserves explicit specifiers and external package names. The published source records the CLI version it shipped with, so vendored source keeps that release line. generateBoilerplateTemplate exposes the lower-level template with bare dependency names.
The host CLI owns writing files, checking existing contents and symlinks, installing dependencies, diagnostics, and authentication. These functions do not read the application, detect its framework, prompt, write files, install packages, or access the network. Use the project's provisioned backend URL for hosted mode.
runGenerateCommand accepts hosted or offline, --framework, and optional --backend-url and --scripts values. Value flags accept --flag value or --flag=value. A second argument supplies host defaults for these inputs. Without defaults, mode and framework are required. Explicit arguments override defaults; selecting offline clears an inherited backend URL. Repeated flags are rejected. parseGenerateOptions exposes the same parser without generating files. It supports the quickstart framework targets. Hosted mode requires an absolute HTTP or HTTPS URL without embedded credentials, whitespace or control characters. Offline mode rejects a backend URL. Invalid frameworks, integrations and flags, including the removed --output, throw an Error. Runner flags such as --apply, --json, and --package-source belong to the host rather than this parser.
For Node hosts that need the full CLI command metadata and actions, import { commands } from '@c15t/cli/commands' exports the same registry used by the runner. Actions accept a c15t CliContext; use runCli when you need the runner to create that context.
Frontend commands with host state
Use @c15t/cli/frontend when Inth or another host owns authentication and the selected project. The dispatcher accepts arguments after the c15t namespace and returns { command, data } synchronously:
setup and generate return the standalone file plan. The frontend dispatcher defaults to hosted mode. Supply a framework through arguments or generation.framework; no detection runs. Explicit flags override generation defaults. setup offline ignores the host's inherited backend URL, while an explicit offline --backend-url is an error.
A host can supply its already-fetched projects and current selection instead of a backend URL:
Projects use { id, name, organizationSlug?, status, url }. status is active, pending, or inactive; url is the provisioned consent backend URL. Generation resolves the selected ID or unambiguous organization/name and rejects an unavailable or invalid backend. An explicit backend URL takes precedence over the selected project.
| Command | Returned data | Host responsibility |
|---|---|---|
setup, generate | { files, dependencies, instructions } | Review and write files, handle conflicts and symlinks, install dependencies, wire the application. |
projects, projects list | { projects, selectedProject } | Fetch projects using the host's authenticated client. |
projects select <id|organization/name> | { project, selectedProject } | Persist the returned project ID and refresh the generation context. |
status | { authenticated, status, expiresAt?, origin?, selectedProject? } | Resolve session state and expiry in the host. |
status requires context.authentication with isLoggedIn and isExpired. Optional metadata is limited to expiresAt, origin, and selectedProject. It never returns access or refresh tokens. Project commands require context.projects, including an empty array when there are no projects. Missing host state is an error rather than a network request or implicit login.
The host owns prompts, project creation, login, logout, token refresh, and persistence. Selection returns data and does not update the context. These commands have no database dependencies. Codemods, self-hosting commands, and runner flags such as --apply or --json are rejected by the frontend dispatcher. The standalone Node CLI uses the same project resolver, backend URL validation, and account status logic with its own runtime adapters.
Plan and apply frontend files
Use @c15t/cli/frontend/runtime when the host needs filesystem operations and
dependency installation. It uses Node built-ins supported by scriptc 0.2.0:
The application directory must exist and contain a regular package.json.
Generation defaults to a plan without writes or installation. --plan and
--dry-run make that choice explicit. --apply creates files and requires a
host-supplied package manager or --skip-install. These flags belong to the
runtime; the pure frontend dispatcher continues to reject them. The host still
owns help, --json, working-directory options, framework detection, authentication
and application wiring.
The result contains { command, applied, created, installed, plan, recovered }.
plan contains the canonical application root, files with path, content
and exists, release-line dependencies, and instructions. Existing files
must already match, except files the plan merges: when an existing .env or
index.html lacks the generated lines, the runtime leaves it alone and adds an
instruction with the lines to add. Apply checks the reviewed files again before
writing and refuses conflicts, symlink targets and symlink ancestors, including
dangling symlinks.
The application root itself resolves to its real directory.
Files stage in .c15t-native-generation and publish with exclusive hard links.
Where hard links are unavailable, apply creates each file exclusively, so existing
files are never replaced, and records the copy's identity after writing it. A
copied file that the filesystem cannot tell apart from an identical replacement
may be removed during recovery and written again on resume. An interrupted
apply blocks further generation. Use --resume --apply with the original command
to recover and regenerate. Recovery checks every record and generated file before
removing files it published. Files it cannot prove it published, including
replacements with identical contents, stay in place. Edited generated files,
unexpected staging contents, and malformed records stop recovery for inspection.
Recovery removes generated directories only when they are empty. This supports
process interruption; it does not promise recovery from filesystem corruption or
power loss. Without a journal, recovery deletes leftover staged files and leaves
application files untouched. A partial journal with staged files requires
inspection. The Node runner's .c15t-generation.json uses its own recovery
path and cannot be resumed by this runtime.
Dependency installation runs after file apply commits. npm, pnpm, yarn, and Bun
run in the application directory with installer output on stderr. Cancellation
stops the direct installer process. Cancellation before or during installation
reports that generated files remain, and workflow errors list the created files.
Installer failure leaves generated files in
place and reports a retry command; package-manager changes to manifests, lockfiles
and node_modules do not roll back. For manual installation, use --skip-install
and the returned dependencies. planGeneration, applyGeneration,
recoverGeneration, installGenerationDependencies, and
parseGenerationWorkflowArguments expose the same steps separately.
Native dependency installation is supported on macOS and Linux. On Windows,
use --skip-install and install the returned dependencies manually. A workflow
that requests installation on Windows fails before writing application files.
Compile native frontend commands with scriptc
The published package includes dependency-free generation and frontend TypeScript sources. With scriptc 0.2.0, copy both source directories into the host's vendor directory before compilation. scriptc treats imports under node_modules as npm dependencies, so directly importing the npm entry points does not establish static native compilation.
Create scripts/vendor-c15t.mjs in the host project and run it with Node during the build:
Copy both complete directories and keep them as siblings. Preserve the source contents; NodeNext hosts may add explicit .ts or /index.ts extensions to relative import specifiers during vendoring. The frontend source imports the generation source through a relative path. Regenerate them when updating the locked @c15t/cli@alpha dependency. The published source paths exist for this build step. Generation-only hosts can copy just the generation directory.
In the host's cli.ts, route the generation subcommand to the vendored parser. This example prints the plan; integrate it with Inth's own plan/apply and installation behavior to create application files:
Build with scriptc 0.2.0 in its default static mode, without --dynamic:
Replace the example URL with the exact endpoint provisioned for the project. The result contains the generated source and release-line installation arguments. To route the frontend command set, import runFrontendCommand from ./vendor/c15t/frontend/index.ts, forward arguments after the c15t namespace, and supply the host context described above. Native verification covers hosted and offline boilerplate for all targets, generation defaults, project list/select, account status, filesystem apply, conflicts, symlinks, recovery, and release-line installer arguments. Import runGenerationWorkflow from ./vendor/c15t/frontend/runtime/index.ts to plan and apply standalone frontend files natively. Interactive application-root editing, codemods, and database migrations continue to use the Node runner.
Agent setup and v3 migration workflow
Launching Codex through the CLI is supported on macOS and Linux. On Windows,
use --plan to copy the prompt and run it in Codex manually.
Use c15t setup --codex --plan to print the setup prompt and copy it to your
clipboard without launching Codex. The prompt goes to stdout as plain text.
The copy confirmation or failure notice is diagnostic output, so
c15t setup --codex --plan > prompt.txt saves only the prompt. On Linux the
CLI tries wl-copy, xclip and xsel, then clip.exe under WSL. --dry-run
does the same. Add --json to export the prompt without clipboard access.
Launch your installed Codex CLI from the application directory:
Replace the example URL with the provisioned consent backend URL. With an Inth
connection, --project <id|name> resolves that project's backend URL.
Use either --project or --backend-url. --framework and --scripts provide
optional hints. Explicitly select offline or custom when needed. Without a
mode, the task asks the agent to confirm it with you. The prompt includes a
public inputs section only when you supply configuration.
Codex receives the default c15t v3 frontend task and named public inputs. The
agent inventories the application and its analytics, pixels and embeds, then
takes the install, upgrade or replace path. It resolves exact package versions
from the CLI's npm dist-tag, reads the version-matched bundled docs, runs the
upgrade guide's codemods, moves every tool behind consent, and verifies consent
in a browser. Docs links in the task point at the site for the CLI's release
line: https://v3.c15t.com for v3 prereleases, https://c15t.com otherwise.
It does not provision a backend or migrate a database. The prompt includes the parsed
backend URL, and setup rejects URLs containing whitespace or control
characters. Review the resulting diff and the agent's verification report
before deploying.
Launch requires an interactive terminal and a codex executable on PATH.
When Codex cannot start, setup fails with AGENT_NOT_STARTED and leaves the
project unchanged. AGENT_FAILED means Codex ran and exited unsuccessfully, so
review its edits.
The CLI inherits Codex's approval and sandbox settings; --yes does not
change them. A successful exit means the agent session ended successfully,
not that the CLI independently verified the application's behavior. Interrupting
setup stops the direct child process and leaves any edits for review.
Preview or export the complete task without launching an agent:
--dry-run also previews the task. Live agent launch rejects --json and
--non-interactive. Scaffold options such as --boilerplate, --overwrite,
--apply, --resume, and --skip-install are not supported with --codex.
Discuss styling, SSR, proxying, and other frontend preferences in the agent
session. generate retains deterministic generation and rejects --codex.
Hosts can reuse the same prompt and launcher:
createAgentSetupPlan performs no file or network operations. Its options are
mode, backendURL, framework, and scripts; it copies only those fields
into the task. Hosts keep authentication and project selection in their own
code. The module also exports DEFAULT_C15T_SETUP_PROMPT, AgentSetupOptions,
and AgentSetupPlan.
Hosts that write their own task can reuse the c15t steps alone.
createC15tSetupInstructions returns the inventory, install, upgrade and
replace paths, consent-gating rules, browser checks and handoff as Markdown,
without account or backend provisioning steps:
Its options are origin, the docs site the agent reads; distTag, the npm
dist-tag it resolves exact versions from; mode, which is hosted, offline
or custom, or omitted so the agent asks; and firstStep, the number of the
first c15t step when the host puts its own steps first. Steps refer to each
other by name, so renumbering them breaks no reference. origin and distTag
default to the CLI's release line. Invalid values throw.
createC15tIntegrationGuidance({ origin }) returns only the rules for moving
analytics, pixels, tag managers and embeds behind consent, including the
replacements for framework vendor packages such as @next/third-parties and
@nuxt/scripts. Use it to embed those rules in another prompt or skill.
A missing executable produces an installation hint;
launchAgentSetup returns the agent's exit code and rejects on caller
cancellation or launch failure. isAgentNotStartedError identifies rejections
raised before Codex ran.
For a scriptc host, vendor both source directories as described above and
import from ./vendor/c15t/frontend/agent/index.ts. The prompt and launcher
compile statically with scriptc 0.2.0 without --dynamic. This compiles the
handoff; Codex still needs its own installed executable, authentication, and
network access to perform the task.
For v3, source code and installed documentation determine the migration work. The legacy codemod collection targets v2, apart from the named use-consent-manager-to-hooks and scripts-to-integrations transforms. It does not update dependencies, convert a v2 backend configuration to v3, or migrate a database.
skills delegates to an external interactive installer and does not support JSON output. Use installed bundled docs directly when building unattended automation.
Environment-file edits in setup results contain only path, operation (create or update), and redacted: true. This also applies when either a symlink's name or its target is an environment file. Their original and proposed contents stay out of JSON output. Setup keeps the full contents internally to apply edits and restore files if generation fails.