CodexaCodexa

CLI

Install source-distributed plugins and generate versioned frontend SDK packages from Codexa applications.

@codexa/core/cli has two focused workflows: it installs a plugin's source code from an exact Git ref, and it generates and installs typed frontend SDK tarballs from a Codexa application's documented routes. This is different from app.install(plugin, config), which registers an already-imported plugin object into a running app.

codexa plugin add https://github.com/Codexa-by-HQ/oauth --ref v1.0.0
codexa plugin list
codexa sdk generate ./src/app.ts --out ./generated/api-sdk --name @acme/api-sdk -V 1.0.0
codexa sdk install ./generated/api-sdk --project ../frontend -V 1.0.0

Getting the codexa command

Set the CLI up either as a global command, or scoped to one project as a deno task. The examples below use -A so both plugin installation and SDK generation/install work from the same command: plugin commands shell out to git and deno, while SDK install also shells out to your frontend package manager.

A one-time install puts codexa on your PATH, usable from any project afterward.

deno install --global -A -n codexa jsr:@codexa/core/cli
OR
deno install --global --allow-read --allow-write --allow-run=git,deno -n codexa jsr:@codexa/core/cli
codexa plugin add https://github.com/Codexa-by-HQ/oauth --ref v1.0.0

If you only use codexa plugin commands, you can narrow permissions to --allow-read --allow-write --allow-run=git,deno. SDK install needs permission to run the detected package manager, such as npm, pnpm, yarn, or bun.

Adding a plugin

codexa plugin add <github-url> --ref <tag-or-commit> [--project <directory>]
  • <github-url> must be a public https://github.com/<owner>/<repo> URL. Any other host, a private repository URL requiring auth, or a URL with extra path segments is rejected before anything is cloned.
  • --ref is required, on purpose. There is no "latest" or default branch install, every install pins an exact tag or commit, so two people running the same command get the exact same code.
  • --project points at the host project. Defaults to the current directory.

What happens during install

The repository is fetched at exactly that ref

A shallow, single-ref clone, not a full repository history, checked out into a temporary directory.

git fetch --depth 1 origin v1.0.0
git checkout --detach FETCH_HEAD

The plugin manifest is validated

The repository must contain a plugin.json at its root, and its name, version, and entrypoint must match the plugin's own deno.json exactly. A mismatch, or a missing plugin.json, fails the install before anything touches your project.

The plugin's source is copied into plugins/<id>

Copied into a staging directory first, then moved into place atomically, so a failure partway through never leaves a half-copied plugin directory behind. The .git directory from the clone is left out entirely, a symbolic link anywhere in the plugin fails the install outright, and the copy stops with an error past 10,000 files or 100 MB total, whichever comes first.

Your project's deno.json gains a workspace member

deno.json
{
  "workspace": ["./plugins/oauth"]
}

deno install and deno check run against the new plugin

Both run by default, catching a broken or incompatible plugin immediately rather than on your next deno task dev.

The install is recorded

Written to .codexa/plugins.json in your project, a plain record of what is installed, from where, and at which commit. Nothing here executes plugin code, it is purely metadata.

If any step fails, everything already changed is rolled back: deno.json, deno.lock, and .codexa/plugins.json are all restored to exactly what they were before the command ran, and any copied plugin files are removed. An interrupted or failed install never leaves your project half-changed.

The plugin.json manifest

Every installable plugin repository needs one, at its root.

Prop

Type

A real example, from the official OAuth plugin:

plugin.json
{
  "schemaVersion": 1,
  "id": "oauth",
  "name": "@codexa/oauth",
  "version": "1.0.0",
  "entrypoint": "./plugin.ts",
  "setup": "./scripts/bootstrap.ts",
  "codexaCore": ">=1.0.5 <2.0.0"
}

A plugin's own deno.json cannot define workspace-level options such as workspace, lock, nodeModulesDir, or unstable. Those belong to the host project's root config, since the plugin is installed as a member of your workspace, not a standalone project.

Listing installed plugins

codexa plugin list
oauth   @codexa/oauth@1.0.0   ./plugins/oauth

This reads .codexa/plugins.json directly. It never imports or runs any installed plugin's code, so it is safe to run against a project you have not audited yet.

After installing

The CLI's job ends once the plugin's source is on disk, a Deno workspace member, and recorded in the registry. Wiring the plugin into your running app is the normal app.install(plugin, config) call, typically from an async installer function if the plugin needs its own database or Redis connection.

main.ts
import { installOAuthPlugin } from './plugins/oauth/plugin.ts';

const app = createApp();
await installOAuthPlugin(app, { /* ... */ });

Generating a frontend SDK

The SDK commands turn only routes with options.openapi into a typed, fetch-based package. -V is required: generation writes the package and its .tgz archive inside that version's directory, while installation selects the same version and adds its tarball to the frontend package manager.

codexa sdk generate ./src/app.ts \
  --project . \
  --out ./generated/api-sdk \
  --name @acme/api-sdk \
  --client AcmeSDK \
  --base-url http://localhost:8000 \
  -V 1.0.0

codexa sdk install ./generated/api-sdk \
  --project ../frontend \
  -V 1.0.0

Use --install ../frontend on sdk generate to run both steps together. The installer detects npm, pnpm, Yarn, or Bun from the frontend lockfile; --package-manager overrides that choice. A repeated version fails safely unless --force is supplied.

See Generated SDK for route definitions, generated inputs and return values, browser initialization, per-request Next.js clients, permissions, and version upgrades.

On this page