Skip to content

Commit 48bf085

Browse files
committed
docs(cli): give the two plugin artifacts distinct nouns and rewrite "Which scaffolder?" as a two-question decision (#16484)
`plugin` names two different artifacts in this CLI and nothing said which one a reader was about to get. `os init <name> -t plugin` writes a metadata package — declarative objects another stack loads, compiled, `private: true`. `os create plugin <name>` writes a kernel code plugin — TypeScript implementing the kernel `Plugin` contract, built by `tsc`, publishable. Someone who wanted a "plugin skeleton" and reached for the nearer of the two got the wrong artifact silently. No flag and no subcommand is renamed: `-t plugin` and `os create plugin` are published surface and are spelled exactly as before. What moved is the NOUN each user-facing string uses, so the two shapes stop sharing one word. The "Which scaffolder?" guidance is now a two-question decision — metadata or kernel code, then a new project or an addition to a directory you already have — landing on exactly one of the four entry points with the reason to pick it: `npm create objectstack@latest` (equivalently `npx create-objectstack`), `os init`, `os init <name> -t plugin`, `os create plugin <name>`. `os create example` is deliberately absent; it was retired in #16483. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YFY46JydE1gMxQG1TqBcMZ
1 parent c8e5ac6 commit 48bf085

6 files changed

Lines changed: 101 additions & 27 deletions

File tree

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
"@objectstack/cli": patch
3+
---
4+
5+
docs(cli): give the two `plugin` artifacts their own nouns, and rewrite "Which scaffolder?" as a two-question decision (#16484, #15531)
6+
7+
`plugin` names two different artifacts in this CLI, and neither the help text
8+
nor the docs said which one a reader was about to get:
9+
10+
- `os init <name> -t plugin` scaffolds a **metadata package** — declarative
11+
objects another stack loads, built by `objectstack compile`, emitted
12+
`private: true`.
13+
- `os create plugin <name>` scaffolds a **kernel code plugin** — TypeScript
14+
implementing the kernel `Plugin` contract, built by `tsc`, publishable as
15+
`@objectstack/plugin-<name>`.
16+
17+
Someone who wanted a "plugin skeleton" and reached for the nearer of the two got
18+
the wrong artifact, with no failure anywhere to tell them so — the metadata
19+
package has no `Plugin` to implement, and the kernel code plugin has no
20+
declarative objects to compile.
21+
22+
**No flag and no subcommand is renamed.** `-t plugin` and `os create plugin` are
23+
published surface and are spelled exactly as before; renaming them is a separate
24+
decision, not this change. What moved is the NOUN each surface uses for the
25+
artifact, so the two shapes stop sharing one word:
26+
27+
- `os init --help` now reads `Template: app, plugin (a metadata package), empty`,
28+
and the `plugin` template describes itself as
29+
`Metadata package: declarative objects another stack loads` rather than
30+
`Reusable plugin with objects`.
31+
- `os create`'s `plugin` template describes itself as a **kernel code** plugin.
32+
33+
The "Which scaffolder?" guidance in `content/docs/deployment/cli.mdx` is now a
34+
two-question decision — *metadata or kernel code?* then *a new project, or an
35+
addition to a directory you already have?* — landing on exactly one of the four
36+
entry points, each with the reason to pick it: `npm create objectstack@latest`
37+
(equivalently `npx create-objectstack`), `os init`, `os init <name> -t plugin`,
38+
and `os create plugin <name>`. `os create example` is deliberately absent: it was
39+
retired in #16483.

content/docs/deployment/cli.mdx

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ npm create objectstack@latest my-app
2626
cd my-app
2727
```
2828

29-
This scaffolds a working project with `objectstack.config.ts`, a sample object, and all dependencies installed — plus the AI skills bundle and an `AGENTS.md` for coding agents. (`os init` is the CLI's own scaffolder for metadata-plugin skeletons and bare configs — see [below](#os-init).)
29+
This scaffolds a working project with `objectstack.config.ts`, a sample object, and all dependencies installed — plus the AI skills bundle and an `AGENTS.md` for coding agents. (`os init` is the CLI's own scaffolder for metadata-package skeletons and bare configs — see [below](#os-init).)
3030

3131
### Add more metadata
3232

@@ -80,20 +80,32 @@ predicate/schema/binding mistakes that fail silently at runtime), and `os dev --
8080

8181
Scaffolds a new ObjectStack project with configuration, TypeScript setup, and initial metadata files.
8282

83-
> **Which scaffolder?** For a new app, prefer **`npm create objectstack@latest`** — it
84-
> also derives your namespace, pins the framework packages to the current release, and
85-
> installs the AI skills bundle + `AGENTS.md`. Reach for `os init` when you want a
86-
> **bare config** in an existing directory — or a **metadata plugin**, which is only one
87-
> of the two different artifacts the word `plugin` names in this CLI.
88-
89-
**`plugin` names two artifacts. Route by the artifact you want, not by the word.**
90-
91-
| You want | Command | What it emits | Built by | Publishable? | Read next |
92-
|:---------|:--------|:--------------|:---------|:-------------|:----------|
93-
| A **metadata plugin** — declarative objects another stack loads, no kernel code | `os init <name> -t plugin` | `objectstack.config.ts` whose manifest declares `type: 'plugin'`, plus `src/objects/*.object.ts` | `objectstack compile` (its `build` script) | **No** — the emitted `package.json` is `private: true` | [`os init`](#os-init) below, and [Object Metadata](/docs/data-modeling/objects) for the objects it holds |
94-
| A **kernel code plugin** — TypeScript implementing the kernel `Plugin` contract | `os create plugin <name>` | `src/index.ts` exporting a `Plugin` with `init` / `destroy` | `tsc` (its `build` script) | **Yes** — a publishable `@objectstack/plugin-<name>` package | [`os create`](#os-create) below, then [Plugin Anatomy](/docs/plugins/anatomy) and [Plugin Development](/docs/plugins/development) |
95-
96-
Every page under [Plugins & Packages](/docs/plugins) teaches the **kernel code** plugin, so
83+
> **Which scaffolder? Two questions.**
84+
>
85+
> **1. Metadata, or kernel code?** A **metadata package** is declarative — objects
86+
> another stack loads, built by `objectstack compile`. A **kernel code plugin** is
87+
> TypeScript implementing the kernel `Plugin` contract, built by `tsc`.
88+
>
89+
> **2. A whole new project, or an addition to a directory you already have?**
90+
91+
| What you are building | Where it goes | Entry point | Why this one |
92+
|:----------------------|:--------------|:------------|:-------------|
93+
| An **application** — metadata you run | a brand-new project | **`npm create objectstack@latest <name>`** — equivalently `npx create-objectstack <name>` | Derives your namespace, pins the framework packages to the current release, and installs the AI skills bundle + `AGENTS.md`. Prefer it for anything green-field |
94+
| An **application** — metadata you run | a directory you **already have** | `os init` — or `os init -t empty` for a bare config | Writes config, TypeScript setup and starter metadata in place. Derives no namespace and installs no skills bundle |
95+
| A **metadata package** — declarative objects another stack loads, no kernel code | its own project | `os init <name> -t plugin` | The only scaffolder that emits a manifest declaring `type: 'plugin'` |
96+
| A **kernel code plugin** — TypeScript implementing the kernel `Plugin` contract | its own project, or `--in-repo` inside an ObjectStack monorepo checkout | `os create plugin <name>` | The only scaffolder that emits a `Plugin` for you to implement |
97+
98+
**The CLI spells two different artifacts `plugin`; this page does not.** The flag stays
99+
`-t plugin` and the subcommand stays `os create plugin` — what differs is the noun. A
100+
**metadata package** is what `os init -t plugin` writes; a **kernel code plugin** is what
101+
`os create plugin` writes. Route by the artifact you want, not by the word.
102+
103+
| The word `plugin` in | Names | What it emits | Built by | Publishable? | Read next |
104+
|:---------------------|:------|:--------------|:---------|:-------------|:----------|
105+
| `os init <name> -t plugin` | A **metadata package** — declarative objects another stack loads, no kernel code | `objectstack.config.ts` whose manifest declares `type: 'plugin'`, plus `src/objects/*.object.ts` | `objectstack compile` (its `build` script) | **No** — the emitted `package.json` is `private: true` | [`os init`](#os-init) below, and [Object Metadata](/docs/data-modeling/objects) for the objects it holds |
106+
| `os create plugin <name>` | A **kernel code plugin** — TypeScript implementing the kernel `Plugin` contract | `src/index.ts` exporting a `Plugin` with `init` / `destroy` | `tsc` (its `build` script) | **Yes** — a publishable `@objectstack/plugin-<name>` package | [`os create`](#os-create) below, then [Plugin Anatomy](/docs/plugins/anatomy) and [Plugin Development](/docs/plugins/development) |
107+
108+
Every page under [Plugins & Packages](/docs/plugins) teaches the **kernel code plugin**, so
97109
`os create plugin` is the scaffolder those pages mean — `os init -t plugin` will not give
98110
you a `Plugin` to implement, and `os create plugin` will not give you declarative objects
99111
to compile.
@@ -102,7 +114,7 @@ to compile.
102114
**Why the two scaffolders are deliberately separate.** Merging the `os init` and
103115
`os create` command families was measured and ruled against in
104116
[#15531](https://github.com/objectstack-ai/objectstack/issues/15531): the two commands
105-
emit two different artifacts, so collapsing a metadata plugin and a kernel code plugin
117+
emit two different artifacts, so collapsing a metadata package and a kernel code plugin
106118
under one command word would make this collision **structural** instead of merely
107119
documented — teaching the wrong artifact to everyone, human or agent, who generates a
108120
plugin from the CLI. The collision, and the misdirection this table replaces, are recorded
@@ -111,13 +123,13 @@ in [#15817](https://github.com/objectstack-ai/objectstack/issues/15817).
111123

112124
```bash
113125
os init my-app # Create with default "app" template
114-
os init my-plugin -t plugin # Create a metadata plugin project
126+
os init my-package -t plugin # Create a metadata package project
115127
os init blank -t empty # Minimal config only
116128
os init my-app --no-install # Skip dependency installation
117129
```
118130

119131
**Options:**
120-
- `-t, --template <template>` — Template: `app` (default), `plugin`, `empty`
132+
- `-t, --template <template>` — Template: `app` (default), `plugin` (a **metadata package**), `empty`
121133
- `--no-install` — Skip automatic dependency installation
122134
- `-p, --package-manager <npm|pnpm|yarn|bun>` — Package manager to use (auto-detected from the environment)
123135

@@ -126,7 +138,7 @@ os init my-app --no-install # Skip dependency installation
126138
| Template | What it creates |
127139
|----------|-----------------|
128140
| `app` | Full application with objects, barrel imports |
129-
| `plugin` | **Metadata** plugin: declarative objects, built by `objectstack compile`, `private`*not* the kernel code plugin `os create plugin` emits |
141+
| `plugin` | **Metadata package**: declarative objects, built by `objectstack compile`, `private`*not* the kernel code plugin `os create plugin` emits |
130142
| `empty` | Minimal project with just `objectstack.config.ts` |
131143

132144
#### `os dev`
@@ -1315,7 +1327,7 @@ third-party extension primitive, authored as `src/skills/<name>.skill.ts` with
13151327
#### `os create`
13161328

13171329
Scaffolds a **standalone** **kernel code** plugin project (the `Plugin` contract,
1318-
built by `tsc`, publishable; *not* the metadata plugin `os init -t plugin` emits — see
1330+
built by `tsc`, publishable; *not* the **metadata package** `os init -t plugin` emits — see
13191331
[Which scaffolder?](#os-init)) into the current directory:
13201332

13211333
```bash

content/docs/plugins/index.mdx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,20 @@ Plugins follow a strict three-phase lifecycle (`init()` → `start()` → `destr
7575

7676
## Creating a Plugin
7777

78-
The fastest way to create a plugin is with the CLI scaffolding:
78+
<Callout type="info">
79+
**Which artifact this page means.** Every plugin taught here is a **kernel code
80+
plugin** — TypeScript implementing the `Plugin` contract, built by `tsc`, published as
81+
`@objectstack/plugin-<name>`. That is what `os create plugin` scaffolds. If what you
82+
want instead is a **metadata package** — declarative objects another stack loads, with
83+
no kernel code — the scaffolder is `os init <name> -t plugin`, and
84+
[Which scaffolder?](/docs/deployment/cli#os-init) routes between the two by artifact
85+
rather than by the word `plugin`, which the CLI spells the same for both.
86+
</Callout>
87+
88+
The fastest way to create a kernel code plugin is with the CLI scaffolding:
7989

8090
```bash
81-
# Create a new plugin project in the current directory
91+
# Create a new kernel code plugin project in the current directory
8292
os create plugin my-feature
8393

8494
# This creates:

packages/cli/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ os compile
5656
| Command | Description |
5757
|---------|-------------|
5858
| `os generate <type> <name>` | Generate metadata files (alias: `os g`) |
59-
| `os create <type> [name]` | Create a new package/plugin/example from template |
59+
| `os create <type> [name]` | Scaffold a standalone **kernel code** plugin project (the `Plugin` contract, built by `tsc`) from a built-in template |
6060

6161
Available generate types: `object`, `view`, `action`, `flow`, `dashboard`, `app`, `skill`
6262

@@ -177,7 +177,9 @@ Common variables: `OS_DATABASE_URL`, `OS_DATABASE_DRIVER`,
177177

178178
### `os init`
179179

180-
- `-t, --template <template>` — Template: `app` (default), `plugin`, `empty`
180+
- `-t, --template <template>` — Template: `app` (default), `plugin` (a **metadata package**
181+
declarative objects another stack loads, *not* the kernel code plugin `os create plugin`
182+
emits), `empty`
181183
- `--no-install` — Skip dependency installation
182184

183185
### `os compile`

packages/cli/src/commands/create.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ const PLUGIN_IN_REPO_DIR = 'packages/plugins';
286286

287287
export const templates: Record<string, CreateTemplate> = {
288288
plugin: defineTemplate({
289-
description: 'Create a new ObjectStack plugin',
289+
description: 'Create a new kernel code plugin (TypeScript implementing the kernel Plugin contract)',
290290
inRepoDir: PLUGIN_IN_REPO_DIR,
291291
dirName: (name: string) => `plugin-${name}`,
292292
filesFor: (placement: ScaffoldPlacement) => {

packages/cli/src/commands/init.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ export default ${toCamelCase(namespace)}Item;
617617
},
618618

619619
plugin: {
620-
description: 'Reusable plugin with objects',
620+
description: 'Metadata package: declarative objects another stack loads',
621621
get dependencies() {
622622
return {
623623
'@objectstack/spec': pkgVersion(),
@@ -882,7 +882,18 @@ export default class Init extends Command {
882882
};
883883

884884
static override flags = {
885-
template: Flags.string({ char: 't', description: 'Template: app, plugin, empty', default: 'app' }),
885+
template: Flags.string({
886+
char: 't',
887+
// The word `plugin` names two different artifacts in this CLI and only one
888+
// of them is a template here: `-t plugin` writes a METADATA PACKAGE
889+
// (declarative objects, compiled), while `os create plugin` writes a
890+
// KERNEL CODE plugin (TypeScript implementing `Plugin`). The flag
891+
// spellings are published surface and unchanged (#16484); the nouns are
892+
// what tell the two apart. See the chooser in
893+
// content/docs/deployment/cli.mdx under `os init`.
894+
description: 'Template: app, plugin (a metadata package), empty',
895+
default: 'app',
896+
}),
886897
install: Flags.boolean({ description: 'Install dependencies', default: true, allowNo: true }),
887898
'package-manager': Flags.string({
888899
char: 'p',

0 commit comments

Comments
 (0)