procedure-cli 0.1.13 → 0.1.14

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 (42) hide show
  1. package/dist/steps/build-test.js +1 -1
  2. package/dist/steps/build-test.js.map +1 -1
  3. package/dist/steps/product-context.js +1 -1
  4. package/dist/steps/product-context.js.map +1 -1
  5. package/dist/steps/project-info.js +1 -1
  6. package/dist/steps/project-info.js.map +1 -1
  7. package/package.json +5 -1
  8. package/.claude/settings.local.json +0 -27
  9. package/.env.example +0 -2
  10. package/AGENTS.md +0 -134
  11. package/CLAUDE.md +0 -138
  12. package/CODE-FIXED.md +0 -252
  13. package/CODE-REVIEW.md +0 -558
  14. package/config/defaults.json +0 -8
  15. package/config/powerline-config.json +0 -52
  16. package/config/stacks/typescript-node.json +0 -15
  17. package/docs/GIAI-THICH-CLAUDE-MD.md +0 -206
  18. package/docs/PRD.md +0 -141
  19. package/docs/USER-STORIES.md +0 -324
  20. package/src/app.tsx +0 -213
  21. package/src/cli.tsx +0 -19
  22. package/src/components/banner.tsx +0 -23
  23. package/src/components/gutter-line.tsx +0 -16
  24. package/src/components/guttered-select.tsx +0 -231
  25. package/src/components/step-indicator.tsx +0 -32
  26. package/src/components/timeline.tsx +0 -57
  27. package/src/lib/fs.ts +0 -23
  28. package/src/lib/git.ts +0 -41
  29. package/src/lib/powerline.ts +0 -48
  30. package/src/lib/template.ts +0 -161
  31. package/src/lib/types.ts +0 -70
  32. package/src/providers/openai.ts +0 -5
  33. package/src/providers/zai.ts +0 -7
  34. package/src/steps/architecture.tsx +0 -72
  35. package/src/steps/build-test.tsx +0 -114
  36. package/src/steps/generation.tsx +0 -176
  37. package/src/steps/powerline.tsx +0 -254
  38. package/src/steps/product-context.tsx +0 -269
  39. package/src/steps/project-info.tsx +0 -183
  40. package/src/steps/stack-style.tsx +0 -304
  41. package/src/theme.ts +0 -15
  42. package/tsconfig.json +0 -17
@@ -1,183 +0,0 @@
1
- import React, { useState, useEffect } from "react";
2
- import { Text, useInput } from "ink";
3
- import { TextInput } from "@inkjs/ui";
4
- import { GutterLine } from "../components/gutter-line.js";
5
- import { GutteredSelect } from "../components/guttered-select.js";
6
- import type { WizardAnswers } from "../lib/types.js";
7
- import { C } from "../theme.js";
8
-
9
- interface Props {
10
- onComplete: (answers: Partial<WizardAnswers>) => void;
11
- }
12
-
13
- type Step = "projectName" | "description" | "packageManager" | "license";
14
-
15
- const STEP_ORDER: Step[] = [
16
- "projectName",
17
- "description",
18
- "packageManager",
19
- "license",
20
- ];
21
-
22
- const PACKAGE_MANAGER_OPTIONS = [
23
- { label: "npm", value: "npm" },
24
- { label: "pnpm", value: "pnpm" },
25
- { label: "bun", value: "bun" },
26
- { label: "yarn", value: "yarn" },
27
- ];
28
-
29
- const LICENSE_OPTIONS = [
30
- { label: "MIT — Permissive, allows commercial use", value: "MIT" },
31
- { label: "ISC — Simplified MIT, minimal restrictions", value: "ISC" },
32
- { label: "Apache-2.0 — Permissive with patent protection", value: "Apache-2.0" },
33
- { label: "GPL-3.0 — Copyleft, requires source disclosure", value: "GPL-3.0" },
34
- { label: "Unlicense — Public domain, no restrictions", value: "Unlicense" },
35
- ];
36
-
37
- export default function ProjectInfo({ onComplete }: Props) {
38
- const [stepIndex, setStepIndex] = useState(0);
39
- const [answers, setAnswers] = useState<Record<string, string>>({});
40
- const [error, setError] = useState("");
41
- const [liveInput, setLiveInput] = useState("");
42
-
43
- const currentStep = STEP_ORDER[stepIndex]!;
44
- const isFirst = stepIndex === 0;
45
-
46
- // Reset live input when navigating to a different field
47
- useEffect(() => {
48
- setLiveInput("");
49
- }, [stepIndex]);
50
-
51
- const isSelectStep = currentStep === "packageManager" || currentStep === "license";
52
-
53
- useInput((input, key) => {
54
- if (key.shift && key.tab && stepIndex > 0) {
55
- setStepIndex((i) => i - 1);
56
- setError("");
57
- } else if (key.tab && !key.shift && !isSelectStep) {
58
- // Tab only advances text steps — select steps require an explicit Enter selection
59
- const val = liveInput.trim() || answers[currentStep] || "";
60
- if (!val) {
61
- setError(
62
- currentStep === "projectName"
63
- ? "Project name is required"
64
- : "Description is required"
65
- );
66
- return;
67
- }
68
- setError("");
69
- const next = { ...answers, [currentStep]: val };
70
- setAnswers(next);
71
- setStepIndex((i) => i + 1);
72
- }
73
- });
74
-
75
- function advance(key: string, value: string) {
76
- const next = { ...answers, [key]: value };
77
- setAnswers(next);
78
- setError("");
79
-
80
- if (stepIndex < STEP_ORDER.length - 1) {
81
- setStepIndex(stepIndex + 1);
82
- } else {
83
- onComplete(next as unknown as Partial<WizardAnswers>);
84
- }
85
- }
86
-
87
- function handleTextSubmit(value: string) {
88
- const val = value.trim();
89
- if (!val) {
90
- setError(
91
- currentStep === "projectName"
92
- ? "Project name is required"
93
- : "Description is required"
94
- );
95
- return;
96
- }
97
- advance(currentStep, val);
98
- }
99
-
100
- function handleSelectChange(key: string) {
101
- return (value: string) => {
102
- advance(key, value);
103
- };
104
- }
105
-
106
- // Render completed fields
107
- const completed = STEP_ORDER.slice(0, stepIndex).map((key) => (
108
- <GutterLine key={key}>
109
- <Text color={C.overlay1}>
110
- {key === "projectName" && `Project name: ${answers[key]}`}
111
- {key === "description" && `Description: ${answers[key]}`}
112
- {key === "packageManager" && `Package manager: ${answers[key]}`}
113
- {key === "license" && `License: ${answers[key]}`}
114
- </Text>
115
- </GutterLine>
116
- ));
117
-
118
- return (
119
- <>
120
- {completed}
121
-
122
- {currentStep === "projectName" && (
123
- <>
124
- <GutterLine>
125
- <Text bold>Project name: </Text>
126
- <TextInput placeholder="..." onChange={setLiveInput} onSubmit={handleTextSubmit} />
127
- </GutterLine>
128
- <GutterLine>
129
- <Text color={C.overlay1}>{"Tab next Enter confirm"}</Text>
130
- </GutterLine>
131
- </>
132
- )}
133
-
134
- {currentStep === "description" && (
135
- <>
136
- <GutterLine>
137
- <Text bold>One-line description: </Text>
138
- <TextInput placeholder="..." onChange={setLiveInput} onSubmit={handleTextSubmit} />
139
- </GutterLine>
140
- <GutterLine>
141
- <Text color={C.overlay1}>{"Shift+Tab prev Tab next Enter confirm"}</Text>
142
- </GutterLine>
143
- </>
144
- )}
145
-
146
- {currentStep === "packageManager" && (
147
- <>
148
- <GutterLine>
149
- <Text bold>Package manager:</Text>
150
- </GutterLine>
151
- <GutteredSelect
152
- options={PACKAGE_MANAGER_OPTIONS}
153
- onChange={handleSelectChange("packageManager")}
154
- />
155
- <GutterLine>
156
- <Text color={C.overlay1}>{"Shift+Tab prev ↑↓ move Enter select"}</Text>
157
- </GutterLine>
158
- </>
159
- )}
160
-
161
- {currentStep === "license" && (
162
- <>
163
- <GutterLine>
164
- <Text bold>License:</Text>
165
- </GutterLine>
166
- <GutteredSelect
167
- options={LICENSE_OPTIONS}
168
- onChange={handleSelectChange("license")}
169
- />
170
- <GutterLine>
171
- <Text color={C.overlay1}>{"Shift+Tab prev ↑↓ move Enter select"}</Text>
172
- </GutterLine>
173
- </>
174
- )}
175
-
176
- {error && (
177
- <GutterLine>
178
- <Text color={C.red}>{error}</Text>
179
- </GutterLine>
180
- )}
181
- </>
182
- );
183
- }
@@ -1,304 +0,0 @@
1
- import React, { useState } from "react";
2
- import { Text } from "ink";
3
- import { GutterLine } from "../components/gutter-line.js";
4
- import { GutteredSelect, GutteredMultiSelect } from "../components/guttered-select.js";
5
- import type { WizardAnswers } from "../lib/types.js";
6
- import { C } from "../theme.js";
7
-
8
- interface Props {
9
- onComplete: (answers: Partial<WizardAnswers>) => void;
10
- }
11
-
12
- type Mode = "quickstart" | "advanced";
13
- type AdvancedStep = "language" | "framework" | "codeStyle";
14
-
15
- // ─── Presets ────────────────────────────────────────────────────────────────
16
-
17
- interface Preset {
18
- label: string;
19
- description: string;
20
- answers: Partial<WizardAnswers>;
21
- }
22
-
23
- const PRESETS: Record<string, Preset> = {
24
- "typescript-node": {
25
- label: "TypeScript + Node.js",
26
- description: "CLI tools, backend APIs, npm packages",
27
- answers: {
28
- language: "TypeScript",
29
- framework: "Node.js",
30
- codeStyle: [
31
- "TypeScript strict mode, ESM imports",
32
- "camelCase for variables, PascalCase for types",
33
- "stdlib → external → internal import ordering",
34
- "Return errors, don't throw",
35
- ],
36
- buildCommand: "tsc",
37
- testCommand: "node --test",
38
- typecheckCommand: "tsc --noEmit",
39
- lintCommand: "eslint src/",
40
- prCommand: "npm run typecheck && npm run test",
41
- },
42
- },
43
- "nextjs-fullstack": {
44
- label: "Next.js Full-Stack",
45
- description: "SaaS apps, marketing sites, SSR/SSG",
46
- answers: {
47
- language: "TypeScript",
48
- framework: "Next.js",
49
- codeStyle: [
50
- "TypeScript strict mode",
51
- "camelCase for variables, PascalCase for components",
52
- "Server components by default, client components only when needed",
53
- "Co-locate components with their routes",
54
- ],
55
- buildCommand: "next build",
56
- testCommand: "vitest",
57
- typecheckCommand: "tsc --noEmit",
58
- lintCommand: "next lint",
59
- prCommand: "npm run typecheck && npm run lint",
60
- },
61
- },
62
- "react-spa": {
63
- label: "React SPA",
64
- description: "Dashboards, admin panels, SPAs",
65
- answers: {
66
- language: "TypeScript",
67
- framework: "React",
68
- codeStyle: [
69
- "TypeScript strict mode",
70
- "Functional components only, no class components",
71
- "Prefer functional patterns, immutability",
72
- "camelCase for variables, PascalCase for components",
73
- ],
74
- buildCommand: "vite build",
75
- testCommand: "vitest",
76
- typecheckCommand: "tsc --noEmit",
77
- lintCommand: "eslint src/",
78
- prCommand: "npm run typecheck && npm run test",
79
- },
80
- },
81
- "python-fastapi": {
82
- label: "Python + FastAPI",
83
- description: "AI/ML backends, REST APIs, data services",
84
- answers: {
85
- language: "Python",
86
- framework: "FastAPI",
87
- codeStyle: [
88
- "Type hints on all functions and class attributes",
89
- "Black formatting, 88 char line length",
90
- "Pydantic models for request/response schemas",
91
- "Return errors explicitly, avoid bare exceptions",
92
- ],
93
- buildCommand: "python -m py_compile src/",
94
- testCommand: "pytest",
95
- typecheckCommand: "mypy .",
96
- lintCommand: "ruff check .",
97
- prCommand: "mypy . && pytest",
98
- },
99
- },
100
- "go-service": {
101
- label: "Go HTTP Service",
102
- description: "High-perf APIs, microservices",
103
- answers: {
104
- language: "Go",
105
- framework: "net/http",
106
- codeStyle: [
107
- "gofmt enforced, no exceptions",
108
- "Errors are values — always handle, never ignore",
109
- "Table-driven tests with t.Run subtests",
110
- "Keep interfaces small, accept interfaces return structs",
111
- ],
112
- buildCommand: "go build ./...",
113
- testCommand: "go test ./...",
114
- typecheckCommand: "go vet ./...",
115
- lintCommand: "golangci-lint run",
116
- prCommand: "go vet ./... && go test ./...",
117
- },
118
- },
119
- "react-native-expo": {
120
- label: "React Native + Expo",
121
- description: "Cross-platform mobile apps (iOS + Android)",
122
- answers: {
123
- language: "TypeScript",
124
- framework: "React Native",
125
- codeStyle: [
126
- "TypeScript strict mode",
127
- "Functional components with hooks",
128
- "StyleSheet.create for styles, no inline objects",
129
- "Platform-specific code via Platform.select or .ios.tsx / .android.tsx",
130
- ],
131
- buildCommand: "expo build",
132
- testCommand: "jest",
133
- typecheckCommand: "tsc --noEmit",
134
- lintCommand: "eslint .",
135
- prCommand: "npm run typecheck && npm run test",
136
- },
137
- },
138
- };
139
-
140
- const QUICKSTART_OPTIONS = [
141
- ...Object.entries(PRESETS).map(([value, preset]) => ({
142
- label: preset.label,
143
- value,
144
- description: preset.description,
145
- })),
146
- {
147
- label: "Configure manually →",
148
- value: "advanced",
149
- description: "Choose language, framework, and code style",
150
- },
151
- ];
152
-
153
- // ─── Advanced options ────────────────────────────────────────────────────────
154
-
155
- const LANGUAGE_OPTIONS = [
156
- { label: "TypeScript", value: "TypeScript", description: "Typed JavaScript, strict mode recommended" },
157
- { label: "JavaScript", value: "JavaScript", description: "Dynamic, runs everywhere" },
158
- { label: "Python", value: "Python", description: "Readable, great ecosystem for AI/ML & web" },
159
- { label: "Go", value: "Go", description: "Fast compilation, built-in concurrency" },
160
- { label: "Rust", value: "Rust", description: "Memory-safe systems programming" },
161
- { label: "Java", value: "Java", description: "Enterprise-grade, JVM ecosystem" },
162
- { label: "Ruby", value: "Ruby", description: "Developer happiness, Rails ecosystem" },
163
- { label: "PHP", value: "PHP", description: "Web-native, Laravel & WordPress" },
164
- { label: "Swift", value: "Swift", description: "Apple platforms, type-safe" },
165
- { label: "Kotlin", value: "Kotlin", description: "Modern JVM, Android-first" },
166
- ];
167
-
168
- const FRAMEWORK_OPTIONS = [
169
- { label: "Node.js", value: "Node.js", description: "JS/TS server runtime" },
170
- { label: "React", value: "React", description: "Component-based UI library" },
171
- { label: "Next.js", value: "Next.js", description: "Full-stack React framework" },
172
- { label: "Vue", value: "Vue", description: "Progressive UI framework" },
173
- { label: "Svelte", value: "Svelte", description: "Compile-time UI framework" },
174
- { label: "Express", value: "Express", description: "Minimal Node.js web framework" },
175
- { label: "Fastify", value: "Fastify", description: "Fast Node.js web framework" },
176
- { label: "Django", value: "Django", description: "Batteries-included Python web" },
177
- { label: "Flask", value: "Flask", description: "Lightweight Python web" },
178
- { label: "Rails", value: "Rails", description: "Convention-over-config Ruby web" },
179
- ];
180
-
181
- const CODE_STYLE_OPTIONS = [
182
- { label: "Strict mode", value: "Strict mode", description: "TypeScript strict, ESLint strict" },
183
- { label: "camelCase / PascalCase", value: "camelCase for variables, PascalCase for types", description: "Standard JS/TS naming" },
184
- { label: "ESM imports", value: "ESM imports, no CommonJS require", description: "Modern module syntax" },
185
- { label: "Import ordering", value: "stdlib → external → internal import ordering", description: "Grouped imports" },
186
- { label: "Return errors, don't throw", value: "Return errors, don't throw", description: "Explicit error handling" },
187
- { label: "Functional style", value: "Prefer functional patterns", description: "Pure functions, immutability" },
188
- { label: "No any type", value: "No any type, use unknown", description: "Strict type safety" },
189
- { label: "JSDoc comments", value: "JSDoc for public APIs", description: "Documentation standard" },
190
- ];
191
-
192
- /** Suggest frameworks based on selected languages */
193
- function getFrameworkPreselect(languages: string[]): string[] {
194
- const langSet = new Set(languages.map((l) => l.toLowerCase()));
195
- const preselect: string[] = [];
196
- if (langSet.has("typescript") || langSet.has("javascript")) preselect.push("Node.js");
197
- if (langSet.has("python")) preselect.push("Django");
198
- if (langSet.has("ruby")) preselect.push("Rails");
199
- return preselect;
200
- }
201
-
202
- // ─── Component ───────────────────────────────────────────────────────────────
203
-
204
- export default function StackStyle({ onComplete }: Props) {
205
- const [mode, setMode] = useState<Mode>("quickstart");
206
- const [advancedStep, setAdvancedStep] = useState<AdvancedStep>("language");
207
- const [selectedLanguages, setSelectedLanguages] = useState<string[]>([]);
208
- const [selectedFrameworks, setSelectedFrameworks] = useState<string[]>([]);
209
-
210
- // ── QuickStart ──
211
- if (mode === "quickstart") {
212
- return (
213
- <>
214
- <GutterLine>
215
- <Text bold>Select a preset:</Text>
216
- </GutterLine>
217
- <GutteredSelect
218
- options={QUICKSTART_OPTIONS}
219
- onChange={(val) => {
220
- if (val === "advanced") {
221
- setMode("advanced");
222
- return;
223
- }
224
- const preset = PRESETS[val];
225
- if (preset) onComplete(preset.answers);
226
- }}
227
- />
228
- </>
229
- );
230
- }
231
-
232
- // ── Advanced ──
233
- if (advancedStep === "language") {
234
- return (
235
- <>
236
- <GutterLine>
237
- <Text color={C.overlay1}>Mode: manual configuration</Text>
238
- </GutterLine>
239
- <GutterLine>
240
- <Text bold>Programming languages:</Text>
241
- </GutterLine>
242
- <GutteredMultiSelect
243
- options={LANGUAGE_OPTIONS}
244
- allowCustom
245
- customPlaceholder="e.g. Elixir, Zig, C++"
246
- onSubmit={(values) => {
247
- setSelectedLanguages(values);
248
- setAdvancedStep("framework");
249
- }}
250
- />
251
- </>
252
- );
253
- }
254
-
255
- if (advancedStep === "framework") {
256
- return (
257
- <>
258
- <GutterLine>
259
- <Text color={C.overlay1}>Languages: {selectedLanguages.join(", ")}</Text>
260
- </GutterLine>
261
- <GutterLine>
262
- <Text bold>Frameworks:</Text>
263
- </GutterLine>
264
- <GutteredMultiSelect
265
- options={FRAMEWORK_OPTIONS}
266
- initialSelected={getFrameworkPreselect(selectedLanguages)}
267
- allowCustom
268
- customPlaceholder="e.g. Hono, Remix, Astro"
269
- onSubmit={(values) => {
270
- setSelectedFrameworks(values);
271
- setAdvancedStep("codeStyle");
272
- }}
273
- />
274
- </>
275
- );
276
- }
277
-
278
- // codeStyle step
279
- return (
280
- <>
281
- <GutterLine>
282
- <Text color={C.overlay1}>Languages: {selectedLanguages.join(", ")}</Text>
283
- </GutterLine>
284
- <GutterLine>
285
- <Text color={C.overlay1}>Frameworks: {selectedFrameworks.join(", ")}</Text>
286
- </GutterLine>
287
- <GutterLine>
288
- <Text bold>Code style conventions:</Text>
289
- </GutterLine>
290
- <GutteredMultiSelect
291
- options={CODE_STYLE_OPTIONS}
292
- allowCustom
293
- customPlaceholder="e.g. tabs over spaces, max 80 chars"
294
- onSubmit={(values) => {
295
- onComplete({
296
- language: selectedLanguages.join(", "),
297
- framework: selectedFrameworks.join(", "),
298
- codeStyle: values,
299
- });
300
- }}
301
- />
302
- </>
303
- );
304
- }
package/src/theme.ts DELETED
@@ -1,15 +0,0 @@
1
- /**
2
- * Catppuccin Mocha palette — https://catppuccin.com/palette
3
- * Use these constants for all terminal colors. Never use named terminal
4
- * colors (cyan, green, red…) — hex values render consistently across terminals.
5
- */
6
- export const C = {
7
- mauve: '#cba6f7', // active step, current focus
8
- green: '#a6e3a1', // completed steps, success
9
- sapphire: '#74c7ec', // section headers, accent
10
- teal: '#94e2d5', // secondary accent (custom option)
11
- red: '#f38ba8', // errors
12
- peach: '#fab387', // warnings
13
- overlay1: '#7f849c', // gutter lines, dim text, hints
14
- overlay0: '#6c7086', // pending steps, very dim
15
- } as const;
package/tsconfig.json DELETED
@@ -1,17 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "Node16",
5
- "moduleResolution": "Node16",
6
- "strict": true,
7
- "esModuleInterop": true,
8
- "skipLibCheck": true,
9
- "outDir": "dist",
10
- "rootDir": "src",
11
- "jsx": "react-jsx",
12
- "declaration": true,
13
- "sourceMap": true
14
- },
15
- "include": ["src"],
16
- "exclude": ["node_modules", "dist"]
17
- }