create-objectstack@16.0.0
Minor Changes
-
3f218e4: feat(create-objectstack): the blank scaffold ships the three generic connector executors by default
npm create objectstacknow generates anobjectstack.config.tsthat wires the
rest,openapi, andmcpconnector executor plugins (ADR-0022/0023/0024 +
ADR-0097) intoplugins:, alongsiderequires: ['automation']. This closes the
last authoring gap in the ADR-0097 promise that integrations are expressible
and executable as pure metadata: an author (human or AI) can now add a
declarativeconnectors:entry namingprovider: 'rest' | 'openapi' | 'mcp'
and have it materialize into a live, dispatchable connector at boot — with no
host-code edit.plugins:—new ConnectorRestPlugin(),new ConnectorOpenApiPlugin(),
new ConnectorMcpPlugin()(zero-arg = contribute the provider factory only).requires: ['automation']— the automation service performs the
materialization and owns the registry the executors register into. It is also
a hard dependency of the connector plugins, so a scaffold that lists them in
plugins:without it fails boot; automation ships transitively via
@objectstack/cli.- deps —
@objectstack/connector-rest,@objectstack/connector-openapi,
@objectstack/connector-mcp. - Security (#3055): declarative
mcpstdio transports stay denied by default —
opt in per host withnew ConnectorMcpPlugin({ declarativeStdio: ['node'] }).
Brand connectors (Slack, …) remain marketplace/opt-in.
Patch Changes
-
83e8f7d: feat(mcp): decouple the stdio auto-start switch from the HTTP surface + surface the MCP endpoint on
os devboot (#3167)The MCP HTTP surface (
/api/v1/mcp) and the long-lived stdio transport used to
share one env var:OS_MCP_SERVER_ENABLED=trueturned the HTTP surface on and
silently auto-started the stdio transport — which bridges the raw metadata service- data engine with no per-request principal (unscoped). An operator setting it to
"make sure MCP is on" got an unscoped transport as a side effect.
@objectstack/types— newresolveMcpStdioAutoStart(). Stdio auto-start is
now its own switch,OS_MCP_STDIO_ENABLED(default off);OS_MCP_SERVER_ENABLED
governs only the HTTP surface. The legacyOS_MCP_SERVER_ENABLED=truetrigger
still starts stdio for one release, flagged as deprecated.=falseis unchanged
(it only ever gated HTTP).@objectstack/mcp—MCPServerPlugin.start()gates stdio on the new switch
and logs a one-time deprecation warning when started via the legacy alias.@objectstack/cli—os devnow prints the MCP endpoint, the agent-skill
URL, and a ready-to-pasteclaude mcp addcommand on boot (gated on the HTTP
surface being on), so the "an agent operates the app it's building" loop is
discoverable at dev time.create-objectstack— the blank scaffold README documents that the app is
itself an MCP server (the serve side), distinct from the consume-side connector.
- data engine with no per-request principal (unscoped). An operator setting it to
-
3b6ef8a: Scaffolded projects ship with a
.gitignoreagain —npx create-objectstackproduced none, leavingnode_modules/and.envun-ignored for every new user.npm pack/pnpm packstrip.gitignorefrom a tarball unconditionally, at every depth. The blank template committed one atsrc/templates/blank/.gitignoreand the build faithfully copied it todist/templates/blank/.gitignore, butfiles: ["dist"]publishing dropped it on the way to the registry — so the file was present in the repo, present in every local build, and absent from all 11 files of a real scaffold. Verified against the published 15.1.1 tarball, which shipsdist/templates/blank/.dockerignoreand no.gitignore.The template is now committed as
_gitignore(a name npm does not strip) and restored to.gitignorewhen the template is copied, via aTEMPLATE_FILE_ALIASESmap in the newtemplate-copy.ts. Only.gitignoreis aliased: the strip list is.gitignoreand.npmrc, not "every dotfile" —.dockerignorepacks fine and stays literal.The restored ignore rules also cover
.env/.env.*, which they never did. The template README has users writeOS_AUTH_SECRETandOS_SECRET_KEYinto a.env, anddocker-compose.ymlcalls that file "never committed" — but only the prose said so, and.dockerignorewas the only file that listed it.A packing ratchet in
template-consistency.test.tsguards both halves: it packs the real package, scaffolds from the extracted tarball with the real copy logic, and asserts every template file lands under its intended name. Source-level assertions cannot see this class of bug — the file only vanishes at publish. -
3a8ce9d: fix(create-objectstack): the blank scaffold declares pnpm build approvals, so a fresh
pnpm installno longer exits 1 on pnpm 11pnpm 11 turned an unapproved dependency build script from a warning into a hard
error. The blank template declared no build approvals, so the very first command
a new user runs failed on any current pnpm:npx create-objectstack myapp && cd myapp && pnpm install # [ERR_PNPM_IGNORED_BUILDS] Ignored build scripts: better-sqlite3@12.11.1, esbuild@0.28.1 # exit 1The scaffold now ships a
pnpm-workspace.yamlapproving the two packages it
actually depends on building —better-sqlite3(the native sqlite driver behind
@objectstack/driver-sql) andesbuild(compilesobjectstack.config.ts).Both approval keys are present because pnpm reads them by version, and neither
alone covers the supported range:allowBuilds(a package → boolean map) — the only key pnpm 11 honors, and
understood back to pnpm 10.31.onlyBuiltDependenciesalone still errors.onlyBuiltDependencies(a list) — pnpm 10.0–10.30, which ignoreallowBuilds.
npm and yarn ignore the file, so the npm install path is unaffected. Both
packages ship prebuilt binaries, so this was an install-time hard stop rather
than a runtime defect — the project ran fine once installed.This is the #3091 failure class (in-repo settings masking what users resolve)
and was caught by the publish smoke gate added in #3100, which installs the
release candidate the way a user does — on whatever pnpm corepack hands a fresh
machine. -
809214f: Stop leaking repo-internal skills into scaffolded projects. The scaffolder (and the docs) advertised
npx skills add objectstack-ai/framework --all, and the skills CLI's--allimplies--skill '*'— which includes evenmetadata.internalskills — so repo-internal tooling like.claude/skills/dogfood-verificationlanded in every new project's.agents/skills/. All install commands are now scoped to the published catalog via the/skillssubpath (npx skills add objectstack-ai/framework/skills --all), the internal skill is additionally markedmetadata.internal: trueto hide it from interactive discovery, and a template-consistency ratchet plus a scaffold-e2e assertion keep the boundary from regressing.