agent-md-generator 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.
- package/README.md +152 -0
- package/dist/cli.mjs +456 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# agent.md generator
|
|
2
|
+
|
|
3
|
+
> Twelve questions. Four minutes. A production-grade AGENT.md your AI assistants will read before every keystroke.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
A focused web app that guides you through a 4-step editorial flow and generates a complete, project-specific `AGENT.md` (or `CLAUDE.md`) powered by DeepSeek.
|
|
8
|
+
|
|
9
|
+
**[Live demo](https://agent-md-generator.edwinfom.dev)** · **Built by [Edwin Fom](https://github.com/Edwinfom00)**
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
Most developers use AI coding assistants without giving them any context about the project. The result: the AI writes code that doesn't match your conventions, introduces dependencies you didn't want, and ignores constraints you care about.
|
|
16
|
+
|
|
17
|
+
`AGENT.md` is a spec file you place at the root of your repo. AI assistants like Kiro, Cursor, Claude, and Copilot read it before every response. This app generates one for you in under 5 minutes.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## The flow
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
Step 01 · Identity → project name, type, description
|
|
25
|
+
Step 02 · Tech Stack → languages, frameworks, AI providers
|
|
26
|
+
Step 03 · Architecture → folder structure, coding conventions, UI style
|
|
27
|
+
Step 04 · Constraints → hard rules, development philosophy, extra context
|
|
28
|
+
↓
|
|
29
|
+
Review → Generate → Download
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Each step has a live preview pane on the right that shows the AGENT.md being built in real time.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Tech stack
|
|
37
|
+
|
|
38
|
+
- **Next.js 16** — App Router, server components
|
|
39
|
+
- **TypeScript** — strict mode
|
|
40
|
+
- **Tailwind CSS v4** — utility-first, custom design tokens
|
|
41
|
+
- **Vercel AI SDK** — `generateText` for the generation call
|
|
42
|
+
- **DeepSeek** (`deepseek-chat`) — the LLM that writes the spec
|
|
43
|
+
- **react-icons** — icon set (Remix Icons)
|
|
44
|
+
- **Instrument Serif** + **Geist** + **JetBrains Mono** — typography
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Getting started
|
|
49
|
+
|
|
50
|
+
### Prerequisites
|
|
51
|
+
|
|
52
|
+
- Node.js >= 20
|
|
53
|
+
- A [DeepSeek API key](https://platform.deepseek.com/)
|
|
54
|
+
|
|
55
|
+
### Install
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
cd apps/agent-md-generator
|
|
59
|
+
npm install
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Configure
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
cp .env.local.example .env.local
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Edit `.env.local`:
|
|
69
|
+
|
|
70
|
+
```env
|
|
71
|
+
DEEPSEEK_API_KEY=sk-your-key-here
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Run
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm run dev
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Open [http://localhost:3000](http://localhost:3000).
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Project structure
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
src/
|
|
88
|
+
app/
|
|
89
|
+
page.tsx ← entry point (renders WizardShell)
|
|
90
|
+
layout.tsx ← root layout, fonts
|
|
91
|
+
globals.css ← Tailwind v4 + design tokens
|
|
92
|
+
api/
|
|
93
|
+
generate/route.ts ← POST /api/generate — calls DeepSeek
|
|
94
|
+
components/
|
|
95
|
+
ui/
|
|
96
|
+
AppHeader.tsx ← top navigation bar
|
|
97
|
+
AppFooter.tsx ← step navigation (back / continue)
|
|
98
|
+
StepRail.tsx ← 4-step progress indicator
|
|
99
|
+
PreviewPane.tsx ← live AGENT.md preview (right column)
|
|
100
|
+
wizard/
|
|
101
|
+
WizardShell.tsx ← main state machine (questions → review → output)
|
|
102
|
+
QuestionField.tsx ← renders text / textarea / select / multiselect
|
|
103
|
+
ReviewStep.tsx ← summary of all answers before generation
|
|
104
|
+
GeneratingScreen.tsx ← loading state during DeepSeek call
|
|
105
|
+
output/
|
|
106
|
+
ResultScreen.tsx ← generated file viewer + download buttons
|
|
107
|
+
lib/
|
|
108
|
+
cn.ts ← clsx + tailwind-merge utility
|
|
109
|
+
questions.ts ← all 12 questions, options, dependency rules
|
|
110
|
+
buildPrompt.ts ← constructs the DeepSeek prompt from answers
|
|
111
|
+
types/
|
|
112
|
+
index.ts ← shared TypeScript types
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Design system
|
|
118
|
+
|
|
119
|
+
The design follows an editorial aesthetic inspired by the `_prototype/` folder:
|
|
120
|
+
|
|
121
|
+
| Token | Value |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `--color-paper` | `#F1ECE2` — warm off-white background |
|
|
124
|
+
| `--color-ink` | `#141413` — near-black text |
|
|
125
|
+
| `--color-cobalt` | `#2536D6` — primary accent (blue) |
|
|
126
|
+
| `--color-ink-mute` | `#6B665B` — secondary text |
|
|
127
|
+
| `--font-serif` | Instrument Serif — headings, titles |
|
|
128
|
+
| `--font-mono` | JetBrains Mono — labels, code, metadata |
|
|
129
|
+
| `--font-sans` | Geist — body text, UI |
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Output
|
|
134
|
+
|
|
135
|
+
The generator produces two downloadable files with identical content:
|
|
136
|
+
|
|
137
|
+
- `AGENT.md` — for Kiro, Cursor, and most AI coding assistants
|
|
138
|
+
- `CLAUDE.md` — for Claude (Anthropic's naming convention)
|
|
139
|
+
|
|
140
|
+
Place either file at the root of your project repository.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## No data stored
|
|
145
|
+
|
|
146
|
+
All answers stay in the browser. The only network call is the DeepSeek API request from the server route — your answers are sent to DeepSeek to generate the spec, then discarded. Nothing is logged or persisted.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
MIT © [Edwin Fom](https://github.com/Edwinfom00)
|
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// cli/index.ts
|
|
4
|
+
import * as p2 from "@clack/prompts";
|
|
5
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
6
|
+
import { resolve } from "path";
|
|
7
|
+
|
|
8
|
+
// src/lib/questions.ts
|
|
9
|
+
var QUESTIONS = [
|
|
10
|
+
{
|
|
11
|
+
id: "project_name",
|
|
12
|
+
step: 1,
|
|
13
|
+
category: "Identity",
|
|
14
|
+
question: "What is the name of your project?",
|
|
15
|
+
hint: "This will be the main title of your AGENT.md",
|
|
16
|
+
type: "text",
|
|
17
|
+
placeholder: "e.g. MyApp, Preflight, DeutschFlow...",
|
|
18
|
+
required: true
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: "project_type",
|
|
22
|
+
step: 1,
|
|
23
|
+
category: "Identity",
|
|
24
|
+
question: "What type of project is this?",
|
|
25
|
+
hint: "This defines the overall architecture and conventions",
|
|
26
|
+
type: "select",
|
|
27
|
+
required: true,
|
|
28
|
+
options: [
|
|
29
|
+
{ value: "web_app", label: "Web Application", description: "Next.js, React, Vue, SvelteKit..." },
|
|
30
|
+
{ value: "mobile_app", label: "Mobile Application", description: "React Native, Expo, Flutter..." },
|
|
31
|
+
{ value: "vscode_extension", label: "VS Code Extension", description: "TypeScript, VS Code API..." },
|
|
32
|
+
{ value: "npm_package", label: "npm Package / Library", description: "TypeScript library, SDK, CLI..." },
|
|
33
|
+
{ value: "api_backend", label: "API / Backend", description: "Express, Fastify, NestJS, Hono..." },
|
|
34
|
+
{ value: "fullstack", label: "Full-Stack Application", description: "Frontend + Backend in one repo" },
|
|
35
|
+
{ value: "cli_tool", label: "CLI Tool", description: "Command-line application" },
|
|
36
|
+
{ value: "other", label: "Other", description: "Something else entirely" }
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: "mobile_platforms",
|
|
41
|
+
step: 1,
|
|
42
|
+
category: "Identity",
|
|
43
|
+
question: "What mobile platforms will you target?",
|
|
44
|
+
hint: "Affects build config, testing setup, and platform-specific code conventions",
|
|
45
|
+
type: "select",
|
|
46
|
+
required: false,
|
|
47
|
+
dependsOn: { questionId: "project_type", value: "mobile_app" },
|
|
48
|
+
options: [
|
|
49
|
+
{ value: "ios_only", label: "iOS only", description: "Target Apple devices only" },
|
|
50
|
+
{ value: "android_only", label: "Android only", description: "Target Android devices only" },
|
|
51
|
+
{ value: "both", label: "iOS + Android", description: "Cross-platform for both" }
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: "npm_distribution",
|
|
56
|
+
step: 1,
|
|
57
|
+
category: "Identity",
|
|
58
|
+
question: "How will your package be distributed?",
|
|
59
|
+
hint: "Affects build output, bundler config, and import conventions",
|
|
60
|
+
type: "select",
|
|
61
|
+
required: false,
|
|
62
|
+
dependsOn: { questionId: "project_type", value: "npm_package" },
|
|
63
|
+
options: [
|
|
64
|
+
{ value: "esm_only", label: "ESM only", description: "Modern ESM-only package" },
|
|
65
|
+
{ value: "cjs_esm", label: "CommonJS + ESM", description: "Dual-format for broad compatibility" },
|
|
66
|
+
{ value: "browser_node", label: "Browser + Node.js", description: "Universal package for both environments" }
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: "project_description",
|
|
71
|
+
step: 1,
|
|
72
|
+
category: "Identity",
|
|
73
|
+
question: "Describe your project in 2-3 sentences.",
|
|
74
|
+
hint: "What does it do? Who is it for? What problem does it solve?",
|
|
75
|
+
type: "textarea",
|
|
76
|
+
placeholder: "e.g. Preflight is a VS Code extension that helps developers ship cleaner code by detecting debug statements, tracking TODOs with deadlines, and generating AI-powered commit messages...",
|
|
77
|
+
required: true
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: "tech_stack",
|
|
81
|
+
step: 2,
|
|
82
|
+
category: "Tech Stack",
|
|
83
|
+
question: "What is your primary tech stack?",
|
|
84
|
+
hint: "Select all that apply to your project",
|
|
85
|
+
type: "multiselect",
|
|
86
|
+
required: true,
|
|
87
|
+
options: [
|
|
88
|
+
{ value: "typescript", label: "TypeScript" },
|
|
89
|
+
{ value: "javascript", label: "JavaScript" },
|
|
90
|
+
{ value: "react", label: "React" },
|
|
91
|
+
{ value: "nextjs", label: "Next.js" },
|
|
92
|
+
{ value: "react_native", label: "React Native" },
|
|
93
|
+
{ value: "expo", label: "Expo" },
|
|
94
|
+
{ value: "tailwind", label: "Tailwind CSS" },
|
|
95
|
+
{ value: "nodejs", label: "Node.js" },
|
|
96
|
+
{ value: "python", label: "Python" },
|
|
97
|
+
{ value: "go", label: "Go" },
|
|
98
|
+
{ value: "rust", label: "Rust" },
|
|
99
|
+
{ value: "prisma", label: "Prisma" },
|
|
100
|
+
{ value: "supabase", label: "Supabase" },
|
|
101
|
+
{ value: "vercel_ai", label: "Vercel AI SDK" },
|
|
102
|
+
{ value: "zustand", label: "Zustand" },
|
|
103
|
+
{ value: "zod", label: "Zod" }
|
|
104
|
+
]
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: "ai_features",
|
|
108
|
+
step: 2,
|
|
109
|
+
category: "Tech Stack",
|
|
110
|
+
question: "Does your project use AI / LLM features?",
|
|
111
|
+
type: "select",
|
|
112
|
+
required: true,
|
|
113
|
+
options: [
|
|
114
|
+
{ value: "yes_core", label: "Yes \u2014 AI is a core feature", description: "The app is built around AI capabilities" },
|
|
115
|
+
{ value: "yes_secondary", label: "Yes \u2014 AI is a secondary feature", description: "AI enhances some features but is not the core" },
|
|
116
|
+
{ value: "no", label: "No AI features", description: "Pure logic, no LLM integration" }
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: "ai_providers",
|
|
121
|
+
step: 2,
|
|
122
|
+
category: "Tech Stack",
|
|
123
|
+
question: "Which AI providers will you use?",
|
|
124
|
+
hint: "Select all that apply",
|
|
125
|
+
type: "multiselect",
|
|
126
|
+
required: false,
|
|
127
|
+
dependsOn: { questionId: "ai_features", value: ["yes_core", "yes_secondary"] },
|
|
128
|
+
options: [
|
|
129
|
+
{ value: "openai", label: "OpenAI" },
|
|
130
|
+
{ value: "anthropic", label: "Anthropic (Claude)" },
|
|
131
|
+
{ value: "deepseek", label: "DeepSeek" },
|
|
132
|
+
{ value: "google", label: "Google Gemini" },
|
|
133
|
+
{ value: "ollama", label: "Ollama (local)" },
|
|
134
|
+
{ value: "model_agnostic", label: "Model-agnostic (any provider)" }
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: "python_framework",
|
|
139
|
+
step: 2,
|
|
140
|
+
category: "Tech Stack",
|
|
141
|
+
question: "Which Python framework are you using?",
|
|
142
|
+
hint: "Determines routing, ORM, and project structure conventions",
|
|
143
|
+
type: "select",
|
|
144
|
+
required: false,
|
|
145
|
+
dependsOn: { questionId: "tech_stack", value: "python" },
|
|
146
|
+
options: [
|
|
147
|
+
{ value: "django", label: "Django", description: "Full-stack web framework with ORM" },
|
|
148
|
+
{ value: "fastapi", label: "FastAPI", description: "Modern async API framework" },
|
|
149
|
+
{ value: "flask", label: "Flask", description: "Lightweight WSGI microframework" },
|
|
150
|
+
{ value: "none", label: "No framework", description: "Pure Python / scripts" }
|
|
151
|
+
]
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
id: "folder_structure",
|
|
155
|
+
step: 3,
|
|
156
|
+
category: "Architecture",
|
|
157
|
+
question: "Describe your folder structure.",
|
|
158
|
+
hint: "List the main folders and what they contain. The AI will use this to enforce conventions.",
|
|
159
|
+
type: "textarea",
|
|
160
|
+
placeholder: `src/
|
|
161
|
+
app/ <- Next.js App Router pages
|
|
162
|
+
components/ <- reusable UI components
|
|
163
|
+
lib/ <- utilities and helpers
|
|
164
|
+
types/ <- TypeScript types
|
|
165
|
+
hooks/ <- custom React hooks`,
|
|
166
|
+
required: true
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: "coding_conventions",
|
|
170
|
+
step: 3,
|
|
171
|
+
category: "Architecture",
|
|
172
|
+
question: "What are your most important coding conventions?",
|
|
173
|
+
hint: "Rules the AI must always follow when writing code for this project",
|
|
174
|
+
type: "multiselect",
|
|
175
|
+
required: true,
|
|
176
|
+
options: [
|
|
177
|
+
{ value: "no_any", label: "No TypeScript any", description: "Strict typing, use unknown instead" },
|
|
178
|
+
{ value: "no_comments", label: "No code comments", description: "Code must be self-documenting" },
|
|
179
|
+
{ value: "functional", label: "Functional components only", description: "No class components" },
|
|
180
|
+
{ value: "server_components", label: "Prefer Server Components", description: "Use client components only when needed" },
|
|
181
|
+
{ value: "named_exports", label: "Named exports only", description: "No default exports" },
|
|
182
|
+
{ value: "small_files", label: "Small focused files", description: "One responsibility per file" },
|
|
183
|
+
{ value: "no_overengineering", label: "No overengineering", description: "Build the simplest thing that works" },
|
|
184
|
+
{ value: "modular", label: "Modular architecture", description: "Clear separation of concerns" },
|
|
185
|
+
{ value: "error_handling", label: "Explicit error handling", description: "Always handle errors gracefully" },
|
|
186
|
+
{ value: "env_secrets", label: "No secrets in frontend", description: "API keys only in server/env" }
|
|
187
|
+
]
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
id: "ui_style",
|
|
191
|
+
step: 3,
|
|
192
|
+
category: "Architecture",
|
|
193
|
+
question: "What is the UI style and tone?",
|
|
194
|
+
hint: "How should the interface feel?",
|
|
195
|
+
type: "multiselect",
|
|
196
|
+
required: false,
|
|
197
|
+
dependsOn: { questionId: "project_type", value: ["web_app", "mobile_app", "fullstack"] },
|
|
198
|
+
options: [
|
|
199
|
+
{ value: "modern", label: "Modern & minimal" },
|
|
200
|
+
{ value: "playful", label: "Playful & friendly" },
|
|
201
|
+
{ value: "premium", label: "Premium & polished" },
|
|
202
|
+
{ value: "dark", label: "Dark theme first" },
|
|
203
|
+
{ value: "accessible", label: "Accessibility first" },
|
|
204
|
+
{ value: "mobile_first", label: "Mobile first" },
|
|
205
|
+
{ value: "pixel_perfect", label: "Pixel-perfect from designs" }
|
|
206
|
+
]
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
id: "constraints",
|
|
210
|
+
step: 4,
|
|
211
|
+
category: "Constraints",
|
|
212
|
+
question: "What are the hard constraints for this project?",
|
|
213
|
+
hint: "Things the AI must NEVER do in this project",
|
|
214
|
+
type: "multiselect",
|
|
215
|
+
required: true,
|
|
216
|
+
options: [
|
|
217
|
+
{ value: "no_db", label: "No database", description: "Use local state or files only" },
|
|
218
|
+
{ value: "no_auth", label: "No authentication", description: "No login or user accounts" },
|
|
219
|
+
{ value: "no_new_deps", label: "No new dependencies without approval", description: "Ask before adding packages" },
|
|
220
|
+
{ value: "no_telemetry", label: "No telemetry or tracking", description: "No analytics or user tracking" },
|
|
221
|
+
{ value: "no_breaking_changes", label: "No breaking API changes", description: "Maintain backward compatibility" },
|
|
222
|
+
{ value: "offline_first", label: "Offline first", description: "Must work without internet" },
|
|
223
|
+
{ value: "lightweight", label: "Keep it lightweight", description: "Minimize bundle size" },
|
|
224
|
+
{ value: "no_class_components", label: "No class components" }
|
|
225
|
+
]
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
id: "dev_philosophy",
|
|
229
|
+
step: 4,
|
|
230
|
+
category: "Constraints",
|
|
231
|
+
question: "What is your development philosophy?",
|
|
232
|
+
hint: "How should the AI approach building features?",
|
|
233
|
+
type: "select",
|
|
234
|
+
required: true,
|
|
235
|
+
options: [
|
|
236
|
+
{ value: "mvp_first", label: "MVP first, iterate later", description: "Build the smallest useful version, then improve" },
|
|
237
|
+
{ value: "production_grade", label: "Production-grade from day one", description: "Build it right the first time" },
|
|
238
|
+
{ value: "teachable", label: "Teachable & approachable", description: "Code should be easy to understand and explain" },
|
|
239
|
+
{ value: "performance", label: "Performance first", description: "Optimize for speed and efficiency" }
|
|
240
|
+
]
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
id: "extra_context",
|
|
244
|
+
step: 4,
|
|
245
|
+
category: "Constraints",
|
|
246
|
+
question: "Any additional context or special instructions?",
|
|
247
|
+
hint: "Anything else the AI should know \u2014 edge cases, specific patterns, important decisions already made...",
|
|
248
|
+
type: "textarea",
|
|
249
|
+
placeholder: "e.g. This project uses the Vercel AI SDK for all LLM calls. The API keys are stored in .env.local and never exposed to the client. The app is deployed on Vercel...",
|
|
250
|
+
required: false
|
|
251
|
+
}
|
|
252
|
+
];
|
|
253
|
+
function isQuestionVisible(question, answers) {
|
|
254
|
+
if (!question.dependsOn) return true;
|
|
255
|
+
const { questionId, value } = question.dependsOn;
|
|
256
|
+
const answer = answers[questionId];
|
|
257
|
+
if (!answer) return false;
|
|
258
|
+
if (Array.isArray(value)) {
|
|
259
|
+
if (Array.isArray(answer)) return value.some((v) => answer.includes(v));
|
|
260
|
+
return value.includes(answer);
|
|
261
|
+
}
|
|
262
|
+
if (Array.isArray(answer)) return answer.includes(value);
|
|
263
|
+
return answer === value;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// src/lib/buildPrompt.ts
|
|
267
|
+
function getLabel(questionId, value) {
|
|
268
|
+
const question = QUESTIONS.find((q) => q.id === questionId);
|
|
269
|
+
if (!question?.options) return Array.isArray(value) ? value.join(", ") : value;
|
|
270
|
+
if (Array.isArray(value)) {
|
|
271
|
+
return value.map((v) => question.options?.find((o) => o.value === v)?.label ?? v).join(", ");
|
|
272
|
+
}
|
|
273
|
+
return question.options.find((o) => o.value === value)?.label ?? value;
|
|
274
|
+
}
|
|
275
|
+
function buildPrompt(answers) {
|
|
276
|
+
const projectName = answers["project_name"] ?? "My Project";
|
|
277
|
+
const projectType = getLabel("project_type", answers["project_type"] ?? "");
|
|
278
|
+
const description = answers["project_description"] ?? "";
|
|
279
|
+
const mobilePlatforms = answers["mobile_platforms"] ? getLabel("mobile_platforms", answers["mobile_platforms"]) : null;
|
|
280
|
+
const npmDistribution = answers["npm_distribution"] ? getLabel("npm_distribution", answers["npm_distribution"]) : null;
|
|
281
|
+
const techStack = getLabel("tech_stack", answers["tech_stack"] ?? []);
|
|
282
|
+
const pythonFramework = answers["python_framework"] ? getLabel("python_framework", answers["python_framework"]) : null;
|
|
283
|
+
const aiFeatures = getLabel("ai_features", answers["ai_features"] ?? "no");
|
|
284
|
+
const aiProviders = answers["ai_providers"] ? getLabel("ai_providers", answers["ai_providers"]) : "None";
|
|
285
|
+
const folderStructure = answers["folder_structure"] ?? "";
|
|
286
|
+
const conventions = getLabel("coding_conventions", answers["coding_conventions"] ?? []);
|
|
287
|
+
const uiStyle = answers["ui_style"] ? getLabel("ui_style", answers["ui_style"]) : "Not specified";
|
|
288
|
+
const constraints = getLabel("constraints", answers["constraints"] ?? []);
|
|
289
|
+
const devPhilosophy = getLabel("dev_philosophy", answers["dev_philosophy"] ?? "");
|
|
290
|
+
const extraContext = answers["extra_context"] ?? "";
|
|
291
|
+
return `You are an expert software architect. Generate a complete, detailed, and production-quality AGENT.md file for the following project.
|
|
292
|
+
|
|
293
|
+
The AGENT.md is a comprehensive engineering README that will be used by AI coding assistants (like Claude, GPT-4, Kiro, Cursor) to understand the project deeply and write code that perfectly matches the project's conventions, architecture, and constraints.
|
|
294
|
+
|
|
295
|
+
The output must be a single Markdown document. It must be thorough, specific, and actionable \u2014 not generic. Every section should contain real, project-specific content.
|
|
296
|
+
|
|
297
|
+
Use the DeutschFlow AGENT.md and Preflight AGENT.md as structural references for quality and depth. Match that level of detail.
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
PROJECT INFORMATION:
|
|
302
|
+
|
|
303
|
+
Project Name: ${projectName}
|
|
304
|
+
Project Type: ${projectType}${mobilePlatforms ? `
|
|
305
|
+
Mobile Platforms: ${mobilePlatforms}` : ""}${npmDistribution ? `
|
|
306
|
+
Package Distribution: ${npmDistribution}` : ""}
|
|
307
|
+
Description: ${description}
|
|
308
|
+
|
|
309
|
+
Tech Stack: ${techStack}${pythonFramework ? `
|
|
310
|
+
Python Framework: ${pythonFramework}` : ""}
|
|
311
|
+
AI Features: ${aiFeatures}
|
|
312
|
+
AI Providers: ${aiProviders}
|
|
313
|
+
|
|
314
|
+
Folder Structure:
|
|
315
|
+
${folderStructure}
|
|
316
|
+
|
|
317
|
+
Coding Conventions: ${conventions}
|
|
318
|
+
UI Style: ${uiStyle}
|
|
319
|
+
Hard Constraints: ${constraints}
|
|
320
|
+
Development Philosophy: ${devPhilosophy}
|
|
321
|
+
${extraContext ? `
|
|
322
|
+
Additional Context:
|
|
323
|
+
${extraContext}` : ""}
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
Generate the AGENT.md with these sections (adapt section names to fit the project):
|
|
328
|
+
|
|
329
|
+
1. A header introducing the AI assistant's role for this specific project
|
|
330
|
+
2. Project Identity (name, vision, what makes it unique)
|
|
331
|
+
3. Core Product Principles (what it does and does NOT do)
|
|
332
|
+
4. Important Constraints (VERY IMPORTANT section \u2014 hard rules)
|
|
333
|
+
5. Tech Stack (with specific versions/choices and why)
|
|
334
|
+
6. Folder Structure (with role of each folder/file)
|
|
335
|
+
7. Architecture Guidelines (patterns, naming conventions, component rules)
|
|
336
|
+
8. Coding Conventions (with \u2705 CORRECT and \u274C INCORRECT examples where useful)
|
|
337
|
+
9. TypeScript Rules (if applicable)
|
|
338
|
+
10. Feature Implementation Rules (step-by-step process)
|
|
339
|
+
11. Development Philosophy
|
|
340
|
+
12. Decision Making & Clarifications
|
|
341
|
+
13. Communication Style
|
|
342
|
+
14. Final Reminder
|
|
343
|
+
|
|
344
|
+
Rules for the output:
|
|
345
|
+
- Be specific to THIS project, not generic
|
|
346
|
+
- Use real code examples that match the tech stack
|
|
347
|
+
- Include \u2705 CORRECT / \u274C INCORRECT examples for important rules
|
|
348
|
+
- Use tables where they add clarity
|
|
349
|
+
- Keep the tone direct and professional
|
|
350
|
+
- No filler content \u2014 every sentence must be actionable
|
|
351
|
+
- The document should be long enough to be genuinely useful (aim for 600-1000 lines)
|
|
352
|
+
- Output ONLY the Markdown content, no preamble, no explanation`;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// cli/generate.ts
|
|
356
|
+
import { createDeepSeek } from "@ai-sdk/deepseek";
|
|
357
|
+
import { generateText } from "ai";
|
|
358
|
+
async function callDeepSeek(apiKey, prompt) {
|
|
359
|
+
const deepseek = createDeepSeek({ apiKey });
|
|
360
|
+
const { text: text2 } = await generateText({
|
|
361
|
+
model: deepseek("deepseek-chat"),
|
|
362
|
+
prompt,
|
|
363
|
+
temperature: 0.3,
|
|
364
|
+
maxOutputTokens: 8e3
|
|
365
|
+
});
|
|
366
|
+
return text2;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// cli/prompts.ts
|
|
370
|
+
import * as p from "@clack/prompts";
|
|
371
|
+
async function promptQuestion(question) {
|
|
372
|
+
const message = question.hint ? `${question.question}
|
|
373
|
+
${question.hint}` : question.question;
|
|
374
|
+
switch (question.type) {
|
|
375
|
+
case "text":
|
|
376
|
+
case "textarea":
|
|
377
|
+
return p.text({
|
|
378
|
+
message,
|
|
379
|
+
placeholder: question.placeholder,
|
|
380
|
+
validate: question.required ? (v) => v.trim() === "" ? "This field is required." : void 0 : void 0
|
|
381
|
+
});
|
|
382
|
+
case "select":
|
|
383
|
+
return p.select({
|
|
384
|
+
message,
|
|
385
|
+
options: (question.options ?? []).map((o) => ({
|
|
386
|
+
value: o.value,
|
|
387
|
+
label: o.label,
|
|
388
|
+
hint: o.description
|
|
389
|
+
}))
|
|
390
|
+
});
|
|
391
|
+
case "multiselect":
|
|
392
|
+
return p.multiselect({
|
|
393
|
+
message,
|
|
394
|
+
options: (question.options ?? []).map((o) => ({
|
|
395
|
+
value: o.value,
|
|
396
|
+
label: o.label,
|
|
397
|
+
hint: o.description
|
|
398
|
+
})),
|
|
399
|
+
required: question.required
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// cli/index.ts
|
|
405
|
+
function loadEnvLocal() {
|
|
406
|
+
const envPath = resolve(process.cwd(), ".env.local");
|
|
407
|
+
if (!existsSync(envPath)) return;
|
|
408
|
+
const lines = readFileSync(envPath, "utf-8").split("\n");
|
|
409
|
+
for (const line of lines) {
|
|
410
|
+
const trimmed = line.trim();
|
|
411
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
412
|
+
const eqIndex = trimmed.indexOf("=");
|
|
413
|
+
if (eqIndex === -1) continue;
|
|
414
|
+
const key = trimmed.slice(0, eqIndex).trim();
|
|
415
|
+
const val = trimmed.slice(eqIndex + 1).trim().replace(/^["']|["']$/g, "");
|
|
416
|
+
if (!process.env[key]) process.env[key] = val;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
async function main() {
|
|
420
|
+
loadEnvLocal();
|
|
421
|
+
console.clear();
|
|
422
|
+
p2.intro(" agent-md-generator ");
|
|
423
|
+
const apiKey = process.env["DEEPSEEK_API_KEY"];
|
|
424
|
+
if (!apiKey) {
|
|
425
|
+
p2.cancel(
|
|
426
|
+
"DEEPSEEK_API_KEY is not set. Add it to .env.local or export it in your shell."
|
|
427
|
+
);
|
|
428
|
+
process.exit(1);
|
|
429
|
+
}
|
|
430
|
+
const answers = {};
|
|
431
|
+
for (const question of QUESTIONS) {
|
|
432
|
+
if (!isQuestionVisible(question, answers)) continue;
|
|
433
|
+
const value = await promptQuestion(question);
|
|
434
|
+
if (p2.isCancel(value)) {
|
|
435
|
+
p2.cancel("Cancelled.");
|
|
436
|
+
process.exit(0);
|
|
437
|
+
}
|
|
438
|
+
if (value !== void 0 && (typeof value !== "string" || value !== "")) {
|
|
439
|
+
answers[question.id] = value;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
const s = p2.spinner();
|
|
443
|
+
s.start("Generating your AGENT.md with DeepSeek...");
|
|
444
|
+
try {
|
|
445
|
+
const content = await callDeepSeek(apiKey, buildPrompt(answers));
|
|
446
|
+
const outputPath = resolve(process.cwd(), "AGENT.md");
|
|
447
|
+
writeFileSync(outputPath, content, "utf-8");
|
|
448
|
+
s.stop("Done!");
|
|
449
|
+
p2.outro(`AGENT.md written to ${outputPath}`);
|
|
450
|
+
} catch (err) {
|
|
451
|
+
s.stop("Generation failed.");
|
|
452
|
+
p2.cancel(err instanceof Error ? err.message : "Unknown error");
|
|
453
|
+
process.exit(1);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-md-generator",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Generate production-grade AGENT.md files for your project via an interactive terminal wizard.",
|
|
5
|
+
"keywords": ["agent", "ai", "claude", "cursor", "kiro", "copilot", "cli", "generator"],
|
|
6
|
+
"homepage": "https://agent-md-generator.edwinfom.dev",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/Edwinfom00/agent-md-generator"
|
|
10
|
+
},
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"author": "Edwin Fom",
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=20"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist/cli.mjs",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"bin": {
|
|
21
|
+
"agent-md-generator": "./dist/cli.mjs"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"dev": "next dev",
|
|
25
|
+
"build": "next build",
|
|
26
|
+
"build:cli": "tsup",
|
|
27
|
+
"cli": "node ./dist/cli.mjs",
|
|
28
|
+
"start": "next start",
|
|
29
|
+
"lint": "eslint"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@ai-sdk/deepseek": "^2.0.35",
|
|
33
|
+
"@upstash/ratelimit": "^2.0.8",
|
|
34
|
+
"@upstash/redis": "^1.38.0",
|
|
35
|
+
"ai": "^6.0.184",
|
|
36
|
+
"clsx": "^2.1.1",
|
|
37
|
+
"framer-motion": "^12.39.0",
|
|
38
|
+
"lucide-react": "^1.16.0",
|
|
39
|
+
"next": "16.2.6",
|
|
40
|
+
"react": "19.2.4",
|
|
41
|
+
"react-dom": "19.2.4",
|
|
42
|
+
"react-icons": "^5.6.0",
|
|
43
|
+
"react-markdown": "^10.1.0",
|
|
44
|
+
"remark-gfm": "^4.0.1",
|
|
45
|
+
"tailwind-merge": "^3.6.0",
|
|
46
|
+
"@clack/prompts": "^0.9.1"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@tailwindcss/postcss": "^4",
|
|
50
|
+
"@types/node": "^20",
|
|
51
|
+
"@types/react": "^19",
|
|
52
|
+
"@types/react-dom": "^19",
|
|
53
|
+
"eslint": "^9",
|
|
54
|
+
"eslint-config-next": "16.2.6",
|
|
55
|
+
"tailwindcss": "^4",
|
|
56
|
+
"typescript": "^5",
|
|
57
|
+
"tsup": "^8.5.0"
|
|
58
|
+
}
|
|
59
|
+
}
|