meto-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/LICENSE +21 -0
  3. package/README.md +106 -0
  4. package/dist/cli/git.d.ts +11 -0
  5. package/dist/cli/git.d.ts.map +1 -0
  6. package/dist/cli/git.js +34 -0
  7. package/dist/cli/git.js.map +1 -0
  8. package/dist/cli/github.d.ts +35 -0
  9. package/dist/cli/github.d.ts.map +1 -0
  10. package/dist/cli/github.js +117 -0
  11. package/dist/cli/github.js.map +1 -0
  12. package/dist/cli/index.d.ts +3 -0
  13. package/dist/cli/index.d.ts.map +1 -0
  14. package/dist/cli/index.js +192 -0
  15. package/dist/cli/index.js.map +1 -0
  16. package/dist/cli/interruption.d.ts +32 -0
  17. package/dist/cli/interruption.d.ts.map +1 -0
  18. package/dist/cli/interruption.js +66 -0
  19. package/dist/cli/interruption.js.map +1 -0
  20. package/dist/cli/preflight.d.ts +44 -0
  21. package/dist/cli/preflight.d.ts.map +1 -0
  22. package/dist/cli/preflight.js +79 -0
  23. package/dist/cli/preflight.js.map +1 -0
  24. package/dist/cli/prompts.d.ts +7 -0
  25. package/dist/cli/prompts.d.ts.map +1 -0
  26. package/dist/cli/prompts.js +148 -0
  27. package/dist/cli/prompts.js.map +1 -0
  28. package/dist/cli/renderer.d.ts +45 -0
  29. package/dist/cli/renderer.d.ts.map +1 -0
  30. package/dist/cli/renderer.js +118 -0
  31. package/dist/cli/renderer.js.map +1 -0
  32. package/dist/cli/scaffold.d.ts +18 -0
  33. package/dist/cli/scaffold.d.ts.map +1 -0
  34. package/dist/cli/scaffold.js +48 -0
  35. package/dist/cli/scaffold.js.map +1 -0
  36. package/dist/cli/stacks.d.ts +40 -0
  37. package/dist/cli/stacks.d.ts.map +1 -0
  38. package/dist/cli/stacks.js +294 -0
  39. package/dist/cli/stacks.js.map +1 -0
  40. package/dist/cli/supabase.d.ts +24 -0
  41. package/dist/cli/supabase.d.ts.map +1 -0
  42. package/dist/cli/supabase.js +72 -0
  43. package/dist/cli/supabase.js.map +1 -0
  44. package/dist/cli/tree.d.ts +9 -0
  45. package/dist/cli/tree.d.ts.map +1 -0
  46. package/dist/cli/tree.js +70 -0
  47. package/dist/cli/tree.js.map +1 -0
  48. package/dist/cli/types.d.ts +33 -0
  49. package/dist/cli/types.d.ts.map +1 -0
  50. package/dist/cli/types.js +2 -0
  51. package/dist/cli/types.js.map +1 -0
  52. package/package.json +47 -0
  53. package/templates/.claude/agent-memory/lom-developer/MEMORY.md +20 -0
  54. package/templates/.claude/agent-memory/lom-pm/MEMORY.md +22 -0
  55. package/templates/.claude/agent-memory/lom-tester/MEMORY.md +18 -0
  56. package/templates/.claude/agents/developer-agent.md +56 -0
  57. package/templates/.claude/agents/pm-agent.md +72 -0
  58. package/templates/.claude/agents/tester-agent.md +62 -0
  59. package/templates/CLAUDE.md +63 -0
  60. package/templates/ai/backlog/epics.md +1 -0
  61. package/templates/ai/context/decisions.md +19 -0
  62. package/templates/ai/context/product-vision.md +19 -0
  63. package/templates/ai/context/tech-stack.md +8 -0
  64. package/templates/ai/context/test-log.md +7 -0
  65. package/templates/ai/tasks/tasks-backlog.md +1 -0
  66. package/templates/ai/tasks/tasks-done.md +1 -0
  67. package/templates/ai/tasks/tasks-in-progress.md +1 -0
  68. package/templates/ai/tasks/tasks-in-testing.md +1 -0
  69. package/templates/ai/tasks/tasks-todo.md +1 -0
  70. package/templates/ai/workflows/commit-conventions.md +10 -0
  71. package/templates/ai/workflows/definition-of-done.md +5 -0
  72. package/templates/gitignore +16 -0
  73. package/templates/src/.gitkeep +0 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,24 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/).
7
+
8
+ ## [0.1.0] - 2026-03-04
9
+
10
+ ### Added
11
+
12
+ - CLI scaffold command (`meto-cli init`) that bootstraps a structured project with methodology built in
13
+ - 10 interactive prompts collecting project brief (name, description, target users, tech stack, problem statement, success criteria, value proposition, out of scope, code conventions, output directory)
14
+ - 3 stack presets: Next.js + Supabase, React Native, Node.js CLI
15
+ - Custom stack option with free-text input
16
+ - Stack-aware Definition of Done generated per project
17
+ - Dry-run mode (`meto-cli init --dry-run`) to preview scaffold output without writing files
18
+ - Pre-flight checks: Node.js version validation (>= 18), git availability detection, write permission verification
19
+ - Git repository initialization with initial commit after scaffold
20
+ - SIGINT cleanup handler that removes partial scaffold on interruption
21
+ - Post-scaffold next steps guidance with conditional git init reminder
22
+ - Template rendering engine with token replacement (`{{TOKEN}}` format)
23
+ - File tree visualization for dry-run output
24
+ - `--help` and `--version` flags
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 iLomer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,106 @@
1
+ # Meto
2
+
3
+ > Lovable gives you an app. Meto gives you a project -- built the right way, your way.
4
+
5
+ Meto scaffolds structured software projects with built-in methodology. You describe what you want to build, and Meto bootstraps a project with a kanban board, agent definitions, product context, and coding conventions -- ready for your first Claude Code session.
6
+
7
+ <!-- TODO: Record demo GIF and replace this -->
8
+ ![demo](assets/demo.gif)
9
+
10
+ ---
11
+
12
+ ## Quick Start
13
+
14
+ ```bash
15
+ npx meto-cli init
16
+ ```
17
+
18
+ Answer a few questions about your project, and Meto generates a fully structured repository in seconds.
19
+
20
+ ---
21
+
22
+ ## What Just Happened?
23
+
24
+ After running `meto-cli init`, your new project comes pre-loaded with everything you need to start building with discipline:
25
+
26
+ - **CLAUDE.md** -- a project instruction file that Claude Code reads every session, pre-filled with your vision, stack, and conventions
27
+ - **Kanban board** -- a task pipeline (backlog, todo, in-progress, testing, done) ready for your first sprint
28
+ - **Agent definitions** -- PM, developer, and tester agents configured to follow your methodology from day one
29
+ - **Product context** -- your vision, tech stack, and decisions captured in structured files so every session starts with shared context
30
+ - **Epics and workflows** -- definition of done, commit conventions, and an epic backlog to plan against
31
+ - **Token optimized** -- generated files are optimized for token consumption with Claude Code, so every session gets more productive output per dollar spent
32
+
33
+ No more hours of manual setup. No more "I forgot to write the CLAUDE.md." It is all there from the start.
34
+
35
+ ---
36
+
37
+ ## What You Get
38
+
39
+ ```
40
+ your-project/
41
+ ├── .claude/
42
+ │ ├── agents/
43
+ │ │ ├── developer-agent.md
44
+ │ │ ├── pm-agent.md
45
+ │ │ └── tester-agent.md
46
+ │ └── agent-memory/
47
+ │ ├── meto-developer/MEMORY.md
48
+ │ ├── meto-pm/MEMORY.md
49
+ │ └── meto-tester/MEMORY.md
50
+ ├── ai/
51
+ │ ├── backlog/
52
+ │ │ └── epics.md
53
+ │ ├── context/
54
+ │ │ ├── decisions.md
55
+ │ │ ├── product-vision.md
56
+ │ │ ├── tech-stack.md
57
+ │ │ └── test-log.md
58
+ │ ├── tasks/
59
+ │ │ ├── tasks-backlog.md
60
+ │ │ ├── tasks-done.md
61
+ │ │ ├── tasks-in-progress.md
62
+ │ │ ├── tasks-in-testing.md
63
+ │ │ └── tasks-todo.md
64
+ │ └── workflows/
65
+ │ ├── commit-conventions.md
66
+ │ └── definition-of-done.md
67
+ ├── src/
68
+ ├── .gitignore
69
+ └── CLAUDE.md
70
+ ```
71
+
72
+ ---
73
+
74
+ ## Next Steps
75
+
76
+ 1. `cd your-project`
77
+ 2. Open the project in your editor
78
+ 3. Start a Claude Code session and call `@meto-pm` to populate your backlog
79
+ 4. Pick your first task and start building
80
+
81
+ ---
82
+
83
+ ## Prerequisites
84
+
85
+ | Requirement | Version | Notes |
86
+ |---|---|---|
87
+ | Node.js | >= 18 | Required to run the CLI |
88
+ | git | any | Recommended -- Meto will initialize a repository if git is available |
89
+ | Claude Code | latest | For the generated project to work with agents |
90
+
91
+ ---
92
+
93
+ ## CLI Reference
94
+
95
+ | Command | Description |
96
+ |---|---|
97
+ | `meto-cli init` | Scaffold a new structured project |
98
+ | `meto-cli init --dry-run` | Preview the generated file tree without writing to disk |
99
+ | `meto-cli --help` | Show available commands and options |
100
+ | `meto-cli --version` | Show the installed version |
101
+
102
+ ---
103
+
104
+ ## License
105
+
106
+ MIT
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Initializes a git repository in the output directory and creates
3
+ * an initial commit with all scaffolded files.
4
+ *
5
+ * Assumes the .gitignore has already been written as part of the
6
+ * template rendering step.
7
+ *
8
+ * @param outputDir - The scaffolded project directory
9
+ */
10
+ export declare function initGitRepo(outputDir: string): Promise<void>;
11
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/cli/git.ts"],"names":[],"mappings":"AAoBA;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASlE"}
@@ -0,0 +1,34 @@
1
+ import { execFile } from "node:child_process";
2
+ import { resolve } from "node:path";
3
+ /**
4
+ * Executes a git command in the specified directory.
5
+ * Returns a promise that resolves with stdout or rejects with an error.
6
+ */
7
+ function runGit(args, cwd) {
8
+ return new Promise((promiseResolve, promiseReject) => {
9
+ execFile("git", args, { cwd }, (error, stdout, stderr) => {
10
+ if (error) {
11
+ const message = stderr.trim() || error.message;
12
+ promiseReject(new Error(`git ${args[0]}: ${message}`));
13
+ return;
14
+ }
15
+ promiseResolve(stdout.trim());
16
+ });
17
+ });
18
+ }
19
+ /**
20
+ * Initializes a git repository in the output directory and creates
21
+ * an initial commit with all scaffolded files.
22
+ *
23
+ * Assumes the .gitignore has already been written as part of the
24
+ * template rendering step.
25
+ *
26
+ * @param outputDir - The scaffolded project directory
27
+ */
28
+ export async function initGitRepo(outputDir) {
29
+ const absoluteDir = resolve(outputDir);
30
+ await runGit(["init"], absoluteDir);
31
+ await runGit(["add", "-A"], absoluteDir);
32
+ await runGit(["commit", "-m", "chore(scaffold): initialize project [bootstrap]"], absoluteDir);
33
+ }
34
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/cli/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;GAGG;AACH,SAAS,MAAM,CAAC,IAAc,EAAE,GAAW;IACzC,OAAO,IAAI,OAAO,CAAC,CAAC,cAAc,EAAE,aAAa,EAAE,EAAE;QACnD,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACvD,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC;gBAC/C,aAAa,CAAC,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC;gBACvD,OAAO;YACT,CAAC;YACD,cAAc,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,SAAiB;IACjD,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAEvC,MAAM,MAAM,CAAC,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC;IACpC,MAAM,MAAM,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,CAAC;IACzC,MAAM,MAAM,CACV,CAAC,QAAQ,EAAE,IAAI,EAAE,iDAAiD,CAAC,EACnE,WAAW,CACZ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Result of the GitHub post-scaffold flow.
3
+ * Contains information about whether a repo was created and its URL.
4
+ */
5
+ export interface GitHubResult {
6
+ /** Whether a GitHub repository was successfully created. */
7
+ repoCreated: boolean;
8
+ /** The URL of the created repository, if any. */
9
+ repoUrl: string | undefined;
10
+ }
11
+ /**
12
+ * Checks whether the GitHub CLI (`gh`) is installed by running `gh --version`.
13
+ * Resolves to true if `gh` is found, false otherwise.
14
+ */
15
+ export declare function checkGhInstalled(): Promise<boolean>;
16
+ /**
17
+ * Checks whether the GitHub CLI is authenticated by running `gh auth status`.
18
+ * Resolves to true if the user is logged in, false otherwise.
19
+ */
20
+ export declare function checkGhAuthenticated(): Promise<boolean>;
21
+ /**
22
+ * Runs the post-scaffold GitHub repository creation flow.
23
+ *
24
+ * Checks for `gh` CLI installation and authentication, then optionally
25
+ * creates a new GitHub repository. Returns a result indicating whether
26
+ * a repo was created and its URL.
27
+ *
28
+ * This function is a no-op if `gitAvailable` is false (git was skipped).
29
+ *
30
+ * @param projectName - The project name (used as the repo name)
31
+ * @param outputDir - The scaffolded project directory
32
+ * @param gitAvailable - Whether git is available on the system
33
+ */
34
+ export declare function runGitHubFlow(projectName: string, outputDir: string, gitAvailable: boolean): Promise<GitHubResult>;
35
+ //# sourceMappingURL=github.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/cli/github.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,4DAA4D;IAC5D,WAAW,EAAE,OAAO,CAAC;IACrB,iDAAiD;IACjD,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAMnD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAMvD;AA6CD;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,OAAO,GACpB,OAAO,CAAC,YAAY,CAAC,CA2DvB"}
@@ -0,0 +1,117 @@
1
+ import { execFile } from "node:child_process";
2
+ import { resolve } from "node:path";
3
+ import * as p from "@clack/prompts";
4
+ /**
5
+ * Checks whether the GitHub CLI (`gh`) is installed by running `gh --version`.
6
+ * Resolves to true if `gh` is found, false otherwise.
7
+ */
8
+ export function checkGhInstalled() {
9
+ return new Promise((promiseResolve) => {
10
+ execFile("gh", ["--version"], (error) => {
11
+ promiseResolve(error === null);
12
+ });
13
+ });
14
+ }
15
+ /**
16
+ * Checks whether the GitHub CLI is authenticated by running `gh auth status`.
17
+ * Resolves to true if the user is logged in, false otherwise.
18
+ */
19
+ export function checkGhAuthenticated() {
20
+ return new Promise((promiseResolve) => {
21
+ execFile("gh", ["auth", "status"], (error) => {
22
+ promiseResolve(error === null);
23
+ });
24
+ });
25
+ }
26
+ /**
27
+ * Creates a GitHub repository using the `gh` CLI.
28
+ * Returns the repository URL on success.
29
+ *
30
+ * @param projectName - The name for the new repository
31
+ * @param visibility - Whether the repo should be "public" or "private"
32
+ * @param cwd - The local directory containing the git repo
33
+ */
34
+ function createGhRepo(projectName, visibility, cwd) {
35
+ const absoluteCwd = resolve(cwd);
36
+ const visibilityFlag = visibility === "public" ? "--public" : "--private";
37
+ return new Promise((promiseResolve, promiseReject) => {
38
+ execFile("gh", [
39
+ "repo",
40
+ "create",
41
+ projectName,
42
+ visibilityFlag,
43
+ "--source",
44
+ ".",
45
+ "--remote",
46
+ "origin",
47
+ "--push",
48
+ ], { cwd: absoluteCwd }, (error, stdout, stderr) => {
49
+ if (error) {
50
+ const message = stderr.trim() || error.message;
51
+ promiseReject(new Error(message));
52
+ return;
53
+ }
54
+ promiseResolve(stdout.trim());
55
+ });
56
+ });
57
+ }
58
+ /**
59
+ * Runs the post-scaffold GitHub repository creation flow.
60
+ *
61
+ * Checks for `gh` CLI installation and authentication, then optionally
62
+ * creates a new GitHub repository. Returns a result indicating whether
63
+ * a repo was created and its URL.
64
+ *
65
+ * This function is a no-op if `gitAvailable` is false (git was skipped).
66
+ *
67
+ * @param projectName - The project name (used as the repo name)
68
+ * @param outputDir - The scaffolded project directory
69
+ * @param gitAvailable - Whether git is available on the system
70
+ */
71
+ export async function runGitHubFlow(projectName, outputDir, gitAvailable) {
72
+ const noResult = { repoCreated: false, repoUrl: undefined };
73
+ if (!gitAvailable) {
74
+ return noResult;
75
+ }
76
+ const ghInstalled = await checkGhInstalled();
77
+ if (!ghInstalled) {
78
+ p.log.info("GitHub CLI not found. Install it to create repos from the terminal: https://cli.github.com");
79
+ return noResult;
80
+ }
81
+ const ghAuthenticated = await checkGhAuthenticated();
82
+ if (!ghAuthenticated) {
83
+ p.log.info("GitHub CLI found but not logged in. Run `gh auth login` to connect your account.");
84
+ return noResult;
85
+ }
86
+ const shouldCreate = await p.confirm({
87
+ message: "Create a GitHub repository for this project?",
88
+ initialValue: true,
89
+ });
90
+ if (p.isCancel(shouldCreate) || !shouldCreate) {
91
+ return noResult;
92
+ }
93
+ const visibility = await p.select({
94
+ message: "Repository visibility?",
95
+ options: [
96
+ { value: "private", label: "Private", hint: "only you can see it" },
97
+ { value: "public", label: "Public", hint: "anyone can see it" },
98
+ ],
99
+ });
100
+ if (p.isCancel(visibility)) {
101
+ return noResult;
102
+ }
103
+ const ghSpinner = p.spinner();
104
+ ghSpinner.start("Creating GitHub repository...");
105
+ try {
106
+ const repoUrl = await createGhRepo(projectName, visibility, outputDir);
107
+ ghSpinner.stop(`Repository created: ${repoUrl}`);
108
+ return { repoCreated: true, repoUrl };
109
+ }
110
+ catch (error) {
111
+ const message = error instanceof Error ? error.message : "Unknown error";
112
+ ghSpinner.stop(`GitHub repo creation failed: ${message}`);
113
+ p.log.warning("The project was scaffolded successfully. You can create a GitHub repo manually later.");
114
+ return noResult;
115
+ }
116
+ }
117
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/cli/github.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,192 @@
1
+ #!/usr/bin/env node
2
+ import { readFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import * as p from "@clack/prompts";
5
+ import { collectProjectBrief } from "./prompts.js";
6
+ import { InterruptionHandler } from "./interruption.js";
7
+ import { buildTokenMap, renderTemplates, resolveTemplatesDir, } from "./renderer.js";
8
+ import { runGitHubFlow } from "./github.js";
9
+ import { initGitRepo } from "./git.js";
10
+ import { runSupabaseFlow } from "./supabase.js";
11
+ import { checkWritePermission, PreflightError, runPreflightChecks, } from "./preflight.js";
12
+ import { DirectoryNotEmptyError, writeScaffold } from "./scaffold.js";
13
+ import { formatFileTree } from "./tree.js";
14
+ /**
15
+ * Resolves the absolute path to the package root directory.
16
+ * At runtime: dist/cli/index.js -> package root is ../../
17
+ */
18
+ function resolvePackageRoot() {
19
+ const currentFileUrl = new URL(import.meta.url);
20
+ const packageRoot = new URL("../../", currentFileUrl);
21
+ return decodeURIComponent(packageRoot.pathname);
22
+ }
23
+ /**
24
+ * Reads the version string from package.json at the package root.
25
+ */
26
+ async function readVersion() {
27
+ const packageJsonPath = join(resolvePackageRoot(), "package.json");
28
+ const raw = await readFile(packageJsonPath, "utf-8");
29
+ const parsed = JSON.parse(raw);
30
+ if (typeof parsed === "object" &&
31
+ parsed !== null &&
32
+ "version" in parsed &&
33
+ typeof parsed.version === "string") {
34
+ return parsed.version;
35
+ }
36
+ return "unknown";
37
+ }
38
+ /**
39
+ * Prints usage information for the CLI.
40
+ */
41
+ function printHelp() {
42
+ p.intro("meto-cli -- methodology-first project scaffolding");
43
+ p.note([
44
+ "Usage: meto-cli <command> [options]",
45
+ "",
46
+ "Commands:",
47
+ " init Scaffold a new structured project",
48
+ " init --dry-run Preview files without writing to disk",
49
+ "",
50
+ "Options:",
51
+ " --help, -h Show this help message",
52
+ " --version, -v Show the installed version",
53
+ ].join("\n"), "Help");
54
+ p.outro("Run 'meto-cli init' to get started.");
55
+ }
56
+ async function main() {
57
+ const arg = process.argv[2];
58
+ if (arg === "--help" || arg === "-h" || arg === undefined) {
59
+ printHelp();
60
+ return;
61
+ }
62
+ if (arg === "--version" || arg === "-v") {
63
+ const version = await readVersion();
64
+ p.intro(`meto-cli v${version}`);
65
+ p.outro("");
66
+ return;
67
+ }
68
+ if (arg === "init") {
69
+ const dryRun = process.argv.includes("--dry-run");
70
+ const interruption = new InterruptionHandler();
71
+ interruption.install();
72
+ p.intro("meto-cli -- methodology-first project scaffolding");
73
+ let preflight;
74
+ try {
75
+ preflight = await runPreflightChecks();
76
+ }
77
+ catch (error) {
78
+ if (error instanceof PreflightError) {
79
+ p.log.error(error.message);
80
+ }
81
+ else if (error instanceof Error) {
82
+ p.log.error(`Pre-flight check failed: ${error.message}`);
83
+ }
84
+ else {
85
+ p.log.error("An unexpected error occurred during pre-flight checks.");
86
+ }
87
+ interruption.uninstall();
88
+ process.exit(1);
89
+ }
90
+ if (!preflight.gitAvailable) {
91
+ p.log.warning("git not found -- the scaffolded project will not be initialized as a git repository.");
92
+ }
93
+ const brief = await collectProjectBrief();
94
+ const writeError = await checkWritePermission(brief.outputDirectory);
95
+ if (writeError !== undefined) {
96
+ p.log.error(writeError);
97
+ interruption.uninstall();
98
+ process.exit(1);
99
+ }
100
+ const stackLabel = brief.techStack === "custom"
101
+ ? brief.customStack
102
+ : brief.techStack;
103
+ p.note([
104
+ `Project: ${brief.projectName}`,
105
+ `Desc: ${brief.description}`,
106
+ `Users: ${brief.targetUsers}`,
107
+ `Stack: ${stackLabel}`,
108
+ `Output: ${brief.outputDirectory}`,
109
+ ].join("\n"), "Project Brief");
110
+ const s = p.spinner();
111
+ s.start("Rendering templates...");
112
+ try {
113
+ const templatesDir = resolveTemplatesDir();
114
+ const tokens = buildTokenMap(brief);
115
+ const renderedFiles = await renderTemplates(templatesDir, tokens);
116
+ if (dryRun) {
117
+ s.stop("Templates rendered (dry run).");
118
+ const filePaths = renderedFiles.map((f) => f.relativePath);
119
+ const tree = formatFileTree(filePaths);
120
+ p.note(tree, "Files that would be created");
121
+ p.log.info(`Total files: ${renderedFiles.length}`);
122
+ p.outro("Dry run complete. No files were written.");
123
+ interruption.uninstall();
124
+ return;
125
+ }
126
+ interruption.arm(brief.outputDirectory);
127
+ await writeScaffold(brief.outputDirectory, renderedFiles);
128
+ interruption.disarm();
129
+ s.stop("Scaffold generated.");
130
+ let gitInitSucceeded = false;
131
+ if (preflight.gitAvailable) {
132
+ const gitSpinner = p.spinner();
133
+ gitSpinner.start("Initializing git repository...");
134
+ try {
135
+ await initGitRepo(brief.outputDirectory);
136
+ gitSpinner.stop("Git repository initialized.");
137
+ gitInitSucceeded = true;
138
+ }
139
+ catch {
140
+ gitSpinner.stop("Git initialization failed -- skipping.");
141
+ }
142
+ }
143
+ const githubResult = await runGitHubFlow(brief.projectName, brief.outputDirectory, gitInitSucceeded);
144
+ const supabaseResult = await runSupabaseFlow(brief.techStack, brief.outputDirectory);
145
+ const nextSteps = [
146
+ `cd ${brief.outputDirectory}`,
147
+ "Open in your editor",
148
+ "Type `claude` to start a session (if Claude Code is already installed)",
149
+ "Install Claude Code if you haven't: https://docs.anthropic.com/en/docs/claude-code",
150
+ "Call @meto-pm to populate your backlog",
151
+ ];
152
+ if (githubResult.repoCreated && githubResult.repoUrl) {
153
+ nextSteps.push(`GitHub repo: ${githubResult.repoUrl}`);
154
+ }
155
+ if (brief.techStack === "nextjs-supabase") {
156
+ if (supabaseResult.initialized) {
157
+ nextSteps.push("Run `supabase start` to launch the local development stack");
158
+ }
159
+ nextSteps.push("Copy the local credentials from `supabase status` into `.env.local`");
160
+ }
161
+ if (!preflight.gitAvailable) {
162
+ nextSteps.push("Run `git init` when git is available");
163
+ }
164
+ p.note(nextSteps.join("\n"), "Next Steps");
165
+ p.outro("Done. Happy building!");
166
+ }
167
+ catch (error) {
168
+ s.stop("Failed.");
169
+ interruption.disarm();
170
+ if (error instanceof DirectoryNotEmptyError) {
171
+ p.log.error(error.message);
172
+ }
173
+ else if (error instanceof Error) {
174
+ p.log.error(`Scaffold generation failed: ${error.message}`);
175
+ }
176
+ else {
177
+ p.log.error("An unexpected error occurred during scaffold generation.");
178
+ }
179
+ interruption.uninstall();
180
+ process.exit(1);
181
+ }
182
+ interruption.uninstall();
183
+ return;
184
+ }
185
+ p.intro("meto-cli -- methodology-first project scaffolding");
186
+ p.log.error(`Unknown command: ${arg}`);
187
+ p.log.info("Run 'meto-cli --help' to see available commands.");
188
+ p.outro("");
189
+ process.exit(1);
190
+ }
191
+ main();
192
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EACL,aAAa,EACb,eAAe,EACf,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C;;;GAGG;AACH,SAAS,kBAAkB;IACzB,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IACtD,OAAO,kBAAkB,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,WAAW;IACxB,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,EAAE,EAAE,cAAc,CAAC,CAAC;IACnE,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;IACrD,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxC,IACE,OAAO,MAAM,KAAK,QAAQ;QAC1B,MAAM,KAAK,IAAI;QACf,SAAS,IAAI,MAAM;QACnB,OAAQ,MAAkC,CAAC,OAAO,KAAK,QAAQ,EAC/D,CAAC;QACD,OAAQ,MAAkC,CAAC,OAAiB,CAAC;IAC/D,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAS,SAAS;IAChB,CAAC,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;IAC7D,CAAC,CAAC,IAAI,CACJ;QACE,qCAAqC;QACrC,EAAE;QACF,WAAW;QACX,uDAAuD;QACvD,2DAA2D;QAC3D,EAAE;QACF,UAAU;QACV,4CAA4C;QAC5C,gDAAgD;KACjD,CAAC,IAAI,CAAC,IAAI,CAAC,EACZ,MAAM,CACP,CAAC;IACF,CAAC,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;AACjD,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAE5B,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QAC1D,SAAS,EAAE,CAAC;QACZ,OAAO;IACT,CAAC;IAED,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACxC,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC;QACpC,CAAC,CAAC,KAAK,CAAC,aAAa,OAAO,EAAE,CAAC,CAAC;QAChC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACZ,OAAO;IACT,CAAC;IAED,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAClD,MAAM,YAAY,GAAG,IAAI,mBAAmB,EAAE,CAAC;QAC/C,YAAY,CAAC,OAAO,EAAE,CAAC;QAEvB,CAAC,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QAE7D,IAAI,SAAS,CAAC;QACd,IAAI,CAAC;YACH,SAAS,GAAG,MAAM,kBAAkB,EAAE,CAAC;QACzC,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,IAAI,KAAK,YAAY,cAAc,EAAE,CAAC;gBACpC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7B,CAAC;iBAAM,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAClC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,4BAA4B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3D,CAAC;iBAAM,CAAC;gBACN,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;YACxE,CAAC;YACD,YAAY,CAAC,SAAS,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC;YAC5B,CAAC,CAAC,GAAG,CAAC,OAAO,CACX,sFAAsF,CACvF,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,mBAAmB,EAAE,CAAC;QAE1C,MAAM,UAAU,GAAG,MAAM,oBAAoB,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QACrE,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACxB,YAAY,CAAC,SAAS,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,UAAU,GACd,KAAK,CAAC,SAAS,KAAK,QAAQ;YAC1B,CAAC,CAAC,KAAK,CAAC,WAAW;YACnB,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;QAEtB,CAAC,CAAC,IAAI,CACJ;YACE,eAAe,KAAK,CAAC,WAAW,EAAE;YAClC,eAAe,KAAK,CAAC,WAAW,EAAE;YAClC,eAAe,KAAK,CAAC,WAAW,EAAE;YAClC,eAAe,UAAU,EAAE;YAC3B,eAAe,KAAK,CAAC,eAAe,EAAE;SACvC,CAAC,IAAI,CAAC,IAAI,CAAC,EACZ,eAAe,CAChB,CAAC;QAEF,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;QACtB,CAAC,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAElC,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,mBAAmB,EAAE,CAAC;YAC3C,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;YACpC,MAAM,aAAa,GAAG,MAAM,eAAe,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YAElE,IAAI,MAAM,EAAE,CAAC;gBACX,CAAC,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;gBAExC,MAAM,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;gBAC3D,MAAM,IAAI,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;gBAEvC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,6BAA6B,CAAC,CAAC;gBAC5C,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC;gBACnD,CAAC,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;gBACpD,YAAY,CAAC,SAAS,EAAE,CAAC;gBACzB,OAAO;YACT,CAAC;YAED,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;YACxC,MAAM,aAAa,CAAC,KAAK,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;YAC1D,YAAY,CAAC,MAAM,EAAE,CAAC;YAEtB,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;YAE9B,IAAI,gBAAgB,GAAG,KAAK,CAAC;YAC7B,IAAI,SAAS,CAAC,YAAY,EAAE,CAAC;gBAC3B,MAAM,UAAU,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;gBAC/B,UAAU,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;gBAEnD,IAAI,CAAC;oBACH,MAAM,WAAW,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;oBACzC,UAAU,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;oBAC/C,gBAAgB,GAAG,IAAI,CAAC;gBAC1B,CAAC;gBAAC,MAAM,CAAC;oBACP,UAAU,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;gBAC5D,CAAC;YACH,CAAC;YAED,MAAM,YAAY,GAAG,MAAM,aAAa,CACtC,KAAK,CAAC,WAAW,EACjB,KAAK,CAAC,eAAe,EACrB,gBAAgB,CACjB,CAAC;YAEF,MAAM,cAAc,GAAG,MAAM,eAAe,CAC1C,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,eAAe,CACtB,CAAC;YAEF,MAAM,SAAS,GAAa;gBAC1B,MAAM,KAAK,CAAC,eAAe,EAAE;gBAC7B,qBAAqB;gBACrB,wEAAwE;gBACxE,oFAAoF;gBACpF,wCAAwC;aACzC,CAAC;YAEF,IAAI,YAAY,CAAC,WAAW,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;gBACrD,SAAS,CAAC,IAAI,CAAC,gBAAgB,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC;YACzD,CAAC;YAED,IAAI,KAAK,CAAC,SAAS,KAAK,iBAAiB,EAAE,CAAC;gBAC1C,IAAI,cAAc,CAAC,WAAW,EAAE,CAAC;oBAC/B,SAAS,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;gBAC/E,CAAC;gBACD,SAAS,CAAC,IAAI,CAAC,qEAAqE,CAAC,CAAC;YACxF,CAAC;YAED,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC;gBAC5B,SAAS,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;YACzD,CAAC;YAED,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC,CAAC;YAE3C,CAAC,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAClB,YAAY,CAAC,MAAM,EAAE,CAAC;YAEtB,IAAI,KAAK,YAAY,sBAAsB,EAAE,CAAC;gBAC5C,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7B,CAAC;iBAAM,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAClC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,+BAA+B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC9D,CAAC;iBAAM,CAAC;gBACN,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;YAC1E,CAAC;YAED,YAAY,CAAC,SAAS,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,YAAY,CAAC,SAAS,EAAE,CAAC;QACzB,OAAO;IACT,CAAC;IAED,CAAC,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;IAC7D,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,oBAAoB,GAAG,EAAE,CAAC,CAAC;IACvC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;IAC/D,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,IAAI,EAAE,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Manages SIGINT cleanup during scaffold writing.
3
+ *
4
+ * When armed with an output directory, a SIGINT will remove that directory
5
+ * and print a cleanup message. When not armed, SIGINT exits cleanly
6
+ * (the default behavior from clack's prompt cancellation).
7
+ */
8
+ export declare class InterruptionHandler {
9
+ private outputDir;
10
+ private readonly boundHandler;
11
+ constructor();
12
+ /**
13
+ * Registers the SIGINT handler.
14
+ */
15
+ install(): void;
16
+ /**
17
+ * Removes the SIGINT handler.
18
+ */
19
+ uninstall(): void;
20
+ /**
21
+ * Arms the handler with the output directory that should be cleaned up
22
+ * if SIGINT is received. Call this just before scaffold writing begins.
23
+ */
24
+ arm(outputDirectory: string): void;
25
+ /**
26
+ * Disarms the handler. Call this after scaffold writing completes
27
+ * successfully so that a late SIGINT does not remove the user's project.
28
+ */
29
+ disarm(): void;
30
+ private handleInterrupt;
31
+ }
32
+ //# sourceMappingURL=interruption.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interruption.d.ts","sourceRoot":"","sources":["../../src/cli/interruption.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;;IAS1C;;OAEG;IACH,OAAO,IAAI,IAAI;IAIf;;OAEG;IACH,SAAS,IAAI,IAAI;IAIjB;;;OAGG;IACH,GAAG,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI;IAIlC;;;OAGG;IACH,MAAM,IAAI,IAAI;IAId,OAAO,CAAC,eAAe;CAmBxB"}