This repository was archived by the owner on Sep 18, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 52
feat: deprecate Slice Machine and redirect to the Prismic CLI #1779
Merged
angeloashmore
merged 18 commits into
main
from
claude/slice-machine-deprecation-plan-2hfx4v
Sep 17, 2026
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
0131720
feat: deprecate Slice Machine and redirect to the Prismic CLI
claude 0364a0c
test(init): disable telemetry in the bin tests through XDG_CONFIG_HOME
claude a2779d1
refactor(init): simplify the deprecation bin and its tests
claude b8040ed
ci: remove the deprecate workflow
claude bfd475e
docs: use backtick fences in the README note
claude a1c617f
feat(init): let users continue with --force
claude 977011e
docs(init): reword the --force guidance
claude 6180a49
fix(init): accept the equals form of --force
claude 711f75d
docs(init): lead with the Type Builder and cut the message down
claude d2a37b5
docs(init): say who decides on --force
claude ee569f5
docs(init): say the --force caveat in plain words
claude 194df24
docs(init): say what --force does
claude a9e73e0
docs(init): soften the opening line
claude d9f1e00
docs(init): name the command that replaces this one
claude 67b7178
docs(init): restore full sentences around the commands
claude 3ae8db5
feat(start): allow hiding the deprecation notice
claude 2721214
docs(start): match the init message and name the opt-out
claude 2b5e5ce
fix(init): stop telemetry from failing a forced run
claude File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,31 +1,97 @@ | ||
| #!/usr/bin/env node | ||
|
|
||
| import semver from "semver"; | ||
| import { readFileSync } from "node:fs"; | ||
| import { fileURLToPath } from "node:url"; | ||
| import { dirname, join } from "node:path"; | ||
| import chalk from "chalk"; | ||
|
|
||
| const __dirname = dirname(fileURLToPath(import.meta.url)); | ||
| const pkg = JSON.parse( | ||
| readFileSync(join(__dirname, "../package.json"), "utf8"), | ||
| ); | ||
| // Slice Machine is deprecated. Every run says so. Without `--force` the run | ||
| // stops here; with it, the original CLI takes over. | ||
|
|
||
| const requiredVersion = pkg.engines.node; | ||
| import { createRequire } from "node:module"; | ||
| import { setTimeout } from "node:timers/promises"; | ||
| import { parseArgs } from "node:util"; | ||
|
|
||
| if (!requiredVersion) { | ||
| throw new Error("Missing engines.node in package.json."); | ||
| } | ||
| // The manager's ES build has directory imports Node rejects; use CommonJS. | ||
| const require = createRequire(import.meta.url); | ||
| const { createSliceMachineManager } = require("@slicemachine/manager"); | ||
| const pkg = require("../package.json"); | ||
|
|
||
| const { values } = parseArgs({ | ||
| args: process.argv.slice(2), | ||
| options: { | ||
| repository: { type: "string", short: "r" }, | ||
| force: { type: "boolean" }, | ||
| }, | ||
| strict: false, | ||
| allowPositionals: true, | ||
| }); | ||
| // The previous parser also accepted `-r=<name>`. | ||
| const repository = | ||
| typeof values.repository === "string" | ||
| ? values.repository.replace(/^=/, "") | ||
| : undefined; | ||
| // `--force=true` parses as a string, so accept both spellings. | ||
| const forced = values.force === true || values.force === "true"; | ||
|
|
||
| const prismicInit = repository | ||
| ? `npx prismic init --repo ${repository}` | ||
| : "npx prismic init"; | ||
| const slicemachineInit = repository | ||
| ? `npx @slicemachine/init --repository ${repository} --force` | ||
| : "npx @slicemachine/init --force"; | ||
|
|
||
| process.stderr.write( | ||
| forced | ||
| ? `Slice Machine is deprecated. Continuing because --force was passed. | ||
|
|
||
| The @slicemachine/init command is replaced by prismic init, which models content in the Type Builder: | ||
|
|
||
| ${prismicInit} | ||
|
|
||
| Docs: https://prismic.io/docs/cli | ||
| ` | ||
| : `Slice Machine is deprecated. The @slicemachine/init command is replaced by prismic init, which models content in the Type Builder: | ||
|
|
||
| ${prismicInit} | ||
|
|
||
| const currentVersion = process.version; | ||
| --force sets up a project with the deprecated Slice Machine. It is not recommended: | ||
|
|
||
| if (!semver.satisfies(currentVersion, requiredVersion)) { | ||
| console.warn( | ||
| chalk.yellow( | ||
| `⚠️ Warning: You are using Node.js ${currentVersion}, but this tool requires ${requiredVersion}.\n` + | ||
| ` Some features may not work correctly. Please upgrade your Node.js version.\n`, | ||
| ), | ||
| ); | ||
| ${slicemachineInit} | ||
|
|
||
| Working with an AI agent? Install the Prismic skill so it knows the current workflow: | ||
|
|
||
| npx skills add --global --yes prismicio/skills | ||
|
|
||
| Docs: https://prismic.io/docs/cli | ||
| Existing Slice Machine projects: https://prismic.io/docs/slice-machine | ||
| `, | ||
| ); | ||
|
|
||
| try { | ||
| const manager = createSliceMachineManager(); | ||
| await manager.telemetry.initTelemetry({ | ||
| appName: pkg.name, | ||
| appVersion: pkg.version, | ||
| }); | ||
| const tracked = manager.telemetry | ||
| .track({ | ||
| event: "command:init:deprecation", | ||
| repository, | ||
| forced, | ||
| }) | ||
| // A forced run does not await this, so it must handle its own | ||
| // rejection. An unhandled one would take the process down. | ||
| .catch(() => undefined); | ||
| // A forced run has the rest of the command to deliver the event. | ||
| if (!forced) { | ||
| await Promise.race([tracked, setTimeout(3000)]); | ||
| } | ||
| } catch { | ||
| // Telemetry never blocks the message. | ||
| } | ||
|
|
||
| if (!forced) { | ||
| process.exit(1); | ||
| } | ||
|
|
||
| import("../dist/cli.cjs"); | ||
| // The CLI parses its own flags and rejects unknown ones, so hide `--force`. | ||
| process.argv = process.argv.filter( | ||
| (argument) => argument !== "--force" && !argument.startsWith("--force="), | ||
| ); | ||
| await import("../dist/cli.cjs"); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| telemetry=false |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| import { expect, it } from "vitest"; | ||
| import { fileURLToPath } from "node:url"; | ||
| import { execa } from "execa"; | ||
|
|
||
| const BIN = fileURLToPath( | ||
| new URL("../bin/slicemachine-init.js", import.meta.url), | ||
| ); | ||
|
|
||
| // The manager reads the user-level `.prismicrc` from `XDG_CONFIG_HOME`. The | ||
| // fixture's file disables telemetry so tests never reach Segment. | ||
| const XDG_CONFIG_HOME = fileURLToPath( | ||
| new URL("./__fixtures__/telemetry-disabled/", import.meta.url), | ||
| ); | ||
|
|
||
| const HALT = `Slice Machine is deprecated. The @slicemachine/init command is replaced by prismic init, which models content in the Type Builder: | ||
|
|
||
| npx prismic init | ||
|
|
||
| --force sets up a project with the deprecated Slice Machine. It is not recommended: | ||
|
|
||
| npx @slicemachine/init --force | ||
|
|
||
| Working with an AI agent? Install the Prismic skill so it knows the current workflow: | ||
|
|
||
| npx skills add --global --yes prismicio/skills | ||
|
|
||
| Docs: https://prismic.io/docs/cli | ||
| Existing Slice Machine projects: https://prismic.io/docs/slice-machine`; | ||
|
|
||
| const FORCED = `Slice Machine is deprecated. Continuing because --force was passed. | ||
|
|
||
| The @slicemachine/init command is replaced by prismic init, which models content in the Type Builder: | ||
|
|
||
| npx prismic init | ||
|
|
||
| Docs: https://prismic.io/docs/cli`; | ||
|
|
||
| const runBin = (args: string[]) => { | ||
| return execa(process.execPath, [BIN, ...args], { | ||
| env: { XDG_CONFIG_HOME }, | ||
| reject: false, | ||
| }); | ||
| }; | ||
|
|
||
| it.each([ | ||
| [], | ||
| ["--help"], | ||
| ["-h"], | ||
| ["--version"], | ||
| ["-v"], | ||
| ["--starter", "nextjs-starter-prismic-minimal"], | ||
| ["--no-push"], | ||
| ["--unknown-flag"], | ||
| ["--repository"], | ||
| ["--force=false"], | ||
| ])( | ||
| "prints the message to stderr and exits with code 1 (%j)", | ||
| async (...args) => { | ||
| const result = await runBin(args); | ||
|
|
||
| expect(result.exitCode).toBe(1); | ||
| expect(result.stdout).toBe(""); | ||
| expect(result.stderr).toBe(HALT); | ||
| }, | ||
| ); | ||
|
|
||
| it.each([ | ||
| ["--repository", "my-repo"], | ||
| ["--repository=my-repo"], | ||
| ["-r", "my-repo"], | ||
| ["-r=my-repo"], | ||
| ["--no-push", "--repository", "my-repo", "--starter", "foo"], | ||
| ])("carries the repository name into --repo (%j)", async (...args) => { | ||
| const result = await runBin(args); | ||
|
|
||
| expect(result.exitCode).toBe(1); | ||
| expect(result.stdout).toBe(""); | ||
| expect(result.stderr).toBe( | ||
| HALT.replace( | ||
| " npx prismic init\n", | ||
| " npx prismic init --repo my-repo\n", | ||
| ).replace( | ||
| "npx @slicemachine/init --force", | ||
| "npx @slicemachine/init --repository my-repo --force", | ||
| ), | ||
| ); | ||
| }); | ||
|
|
||
| // `--force` hands off to the CLI, which is built into `dist/`. The unit tests | ||
| // run before that build, so these assert the notice, not the handoff. Every | ||
| // case passes a flag the CLI answers on its own so no run waits for input. | ||
| it.each([ | ||
| ["--force", "--version"], | ||
| ["--version", "--force"], | ||
| ["--force", "--help"], | ||
| ["--force", "--no-push", "--starter", "foo", "--version"], | ||
| ["--force=true", "--version"], | ||
| ])("prints the notice and continues with --force (%j)", async (...args) => { | ||
| const result = await runBin(args); | ||
|
|
||
| expect(result.stderr.startsWith(FORCED)).toBe(true); | ||
| expect(result.stderr).not.toContain("add --force"); | ||
| }); | ||
|
|
||
| it.each([ | ||
| ["--force", "--repository", "my-repo", "--version"], | ||
| ["--force", "-r=my-repo", "--version"], | ||
| ])("carries the repository name into the notice (%j)", async (...args) => { | ||
| const result = await runBin(args); | ||
|
|
||
| expect( | ||
| result.stderr.startsWith( | ||
| FORCED.replace("npx prismic init", "npx prismic init --repo my-repo"), | ||
| ), | ||
| ).toBe(true); | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.