@horiastanxd/claude-init 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/LICENSE +21 -0
- package/README.md +223 -0
- package/dist/analyzer/code-patterns.d.ts +2 -0
- package/dist/analyzer/code-patterns.js +71 -0
- package/dist/analyzer/code-patterns.js.map +1 -0
- package/dist/analyzer/commands.d.ts +2 -0
- package/dist/analyzer/commands.js +86 -0
- package/dist/analyzer/commands.js.map +1 -0
- package/dist/analyzer/env-vars.d.ts +3 -0
- package/dist/analyzer/env-vars.js +42 -0
- package/dist/analyzer/env-vars.js.map +1 -0
- package/dist/analyzer/git-history.d.ts +2 -0
- package/dist/analyzer/git-history.js +41 -0
- package/dist/analyzer/git-history.js.map +1 -0
- package/dist/analyzer/index.d.ts +3 -0
- package/dist/analyzer/index.js +44 -0
- package/dist/analyzer/index.js.map +1 -0
- package/dist/analyzer/project-structure.d.ts +2 -0
- package/dist/analyzer/project-structure.js +95 -0
- package/dist/analyzer/project-structure.js.map +1 -0
- package/dist/analyzer/tech-stack.d.ts +2 -0
- package/dist/analyzer/tech-stack.js +141 -0
- package/dist/analyzer/tech-stack.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +129 -0
- package/dist/cli.js.map +1 -0
- package/dist/generators/agents-md.d.ts +6 -0
- package/dist/generators/agents-md.js +12 -0
- package/dist/generators/agents-md.js.map +1 -0
- package/dist/generators/claude-md.d.ts +2 -0
- package/dist/generators/claude-md.js +5 -0
- package/dist/generators/claude-md.js.map +1 -0
- package/dist/generators/copilot-instructions.d.ts +2 -0
- package/dist/generators/copilot-instructions.js +5 -0
- package/dist/generators/copilot-instructions.js.map +1 -0
- package/dist/generators/cursor-rules.d.ts +2 -0
- package/dist/generators/cursor-rules.js +5 -0
- package/dist/generators/cursor-rules.js.map +1 -0
- package/dist/generators/gemini-md.d.ts +2 -0
- package/dist/generators/gemini-md.js +5 -0
- package/dist/generators/gemini-md.js.map +1 -0
- package/dist/generators/index.d.ts +11 -0
- package/dist/generators/index.js +43 -0
- package/dist/generators/index.js.map +1 -0
- package/dist/generators/registry.d.ts +21 -0
- package/dist/generators/registry.js +108 -0
- package/dist/generators/registry.js.map +1 -0
- package/dist/generators/render.d.ts +19 -0
- package/dist/generators/render.js +58 -0
- package/dist/generators/render.js.map +1 -0
- package/dist/generators/sections.d.ts +9 -0
- package/dist/generators/sections.js +96 -0
- package/dist/generators/sections.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server.d.ts +1 -0
- package/dist/mcp-server.js +98 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/types.d.ts +84 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +53 -0
- package/dist/utils.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +13 -0
- package/dist/version.js.map +1 -0
- package/package.json +79 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Horia Stan
|
|
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,223 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# claude-init
|
|
4
|
+
|
|
5
|
+
**One command generates the AI context files for every coding assistant - from one repo scan.**
|
|
6
|
+
|
|
7
|
+
`CLAUDE.md` · `AGENTS.md` · Cursor · Windsurf · Cline · Copilot · `GEMINI.md` · Aider · Junie · Warp
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx @horiastanxd/claude-init
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
[](https://www.npmjs.com/package/@horiastanxd/claude-init)
|
|
14
|
+
[](https://github.com/horiastanxd/claude-init/actions/workflows/ci.yml)
|
|
15
|
+
[](./LICENSE)
|
|
16
|
+
[](https://nodejs.org)
|
|
17
|
+
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div align="center">
|
|
21
|
+
|
|
22
|
+

|
|
23
|
+
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Why
|
|
29
|
+
|
|
30
|
+
Every AI coding tool wants a file describing your project - and they all use a
|
|
31
|
+
different name and format. Keeping ten of them in sync by hand is busywork, and the
|
|
32
|
+
moment your stack changes they go stale.
|
|
33
|
+
|
|
34
|
+
`claude-init` scans your repo once - stack, scripts, structure, env vars, conventions,
|
|
35
|
+
git - and writes all of them in seconds. **No API key, no network, 100% local.**
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
$ npx @horiastanxd/claude-init
|
|
39
|
+
✔ Analyzed my-app (TypeScript, Next.js)
|
|
40
|
+
+ CLAUDE.md
|
|
41
|
+
+ AGENTS.md
|
|
42
|
+
+ .cursor/rules/project.mdc
|
|
43
|
+
+ .windsurf/rules/project.md
|
|
44
|
+
+ .clinerules/project.md
|
|
45
|
+
+ .github/copilot-instructions.md
|
|
46
|
+
+ GEMINI.md
|
|
47
|
+
+ CONVENTIONS.md
|
|
48
|
+
+ .junie/guidelines.md
|
|
49
|
+
+ WARP.md
|
|
50
|
+
|
|
51
|
+
Done. 10 file(s) generated.
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Supported tools
|
|
55
|
+
|
|
56
|
+
| Target (`-t`) | File written | Read by |
|
|
57
|
+
| --- | --- | --- |
|
|
58
|
+
| `claude` | `CLAUDE.md` | Claude Code |
|
|
59
|
+
| `agents` | `AGENTS.md` | OpenAI Codex, Jules, Amp, Zed, Devin, RooCode, Factory, +20 agents |
|
|
60
|
+
| `cursor` | `.cursor/rules/project.mdc` | Cursor (modern `.mdc` rules) |
|
|
61
|
+
| `windsurf` | `.windsurf/rules/project.md` | Windsurf / Codeium |
|
|
62
|
+
| `cline` | `.clinerules/project.md` | Cline, Roo Code |
|
|
63
|
+
| `copilot` | `.github/copilot-instructions.md` | GitHub Copilot |
|
|
64
|
+
| `gemini` | `GEMINI.md` | Gemini CLI |
|
|
65
|
+
| `aider` | `CONVENTIONS.md` | Aider |
|
|
66
|
+
| `junie` | `.junie/guidelines.md` | JetBrains Junie |
|
|
67
|
+
| `warp` | `WARP.md` | Warp terminal |
|
|
68
|
+
|
|
69
|
+
> [`AGENTS.md`](https://agents.md) is becoming the shared standard - one file read by
|
|
70
|
+
> a growing list of agents. `claude-init` generates it alongside each tool's native
|
|
71
|
+
> format, so you are covered both ways.
|
|
72
|
+
|
|
73
|
+
## Usage
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npx @horiastanxd/claude-init # generate everything in the current repo
|
|
77
|
+
npx @horiastanxd/claude-init ./path/to/repo # analyze a different directory
|
|
78
|
+
npx @horiastanxd/claude-init -t claude,cursor # only specific tools
|
|
79
|
+
npx @horiastanxd/claude-init --overwrite # refresh files that already exist
|
|
80
|
+
npx @horiastanxd/claude-init --dry-run # print the analysis as JSON, write nothing
|
|
81
|
+
npx @horiastanxd/claude-init list # show all targets and their paths
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
By default existing files are left untouched - re-run with `--overwrite` to refresh
|
|
85
|
+
them after your stack changes.
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
claude-init [generate] [dir] analyze a repo and write context files (default)
|
|
89
|
+
claude-init check [dir] verify files are up to date (exit 1 on drift)
|
|
90
|
+
claude-init list list supported targets
|
|
91
|
+
claude-init mcp run as an MCP server over stdio
|
|
92
|
+
|
|
93
|
+
Options:
|
|
94
|
+
-t, --targets <list> comma-separated target ids, or "all" (default: all)
|
|
95
|
+
-o, --output <dir> output directory (default: .)
|
|
96
|
+
--overwrite overwrite existing files
|
|
97
|
+
--dry-run print the analysis as JSON, write nothing
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Keep context files fresh
|
|
101
|
+
|
|
102
|
+
`claude-init check` regenerates in memory and compares against disk, exiting non-zero
|
|
103
|
+
on drift. Wire it into CI or a pre-commit hook so your context never rots.
|
|
104
|
+
|
|
105
|
+
**pre-commit** (`.git/hooks/pre-commit` or [pre-commit](https://pre-commit.com)):
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
npx @horiastanxd/claude-init check || {
|
|
109
|
+
echo "AI context files are stale - run: npx @horiastanxd/claude-init --overwrite"
|
|
110
|
+
exit 1
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**GitHub Actions:**
|
|
115
|
+
|
|
116
|
+
```yaml
|
|
117
|
+
- run: npx @horiastanxd/claude-init check
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Example output
|
|
121
|
+
|
|
122
|
+
<details>
|
|
123
|
+
<summary><code>CLAUDE.md</code> generated for a Next.js + Prisma app</summary>
|
|
124
|
+
|
|
125
|
+
```markdown
|
|
126
|
+
# my-app
|
|
127
|
+
|
|
128
|
+
A demo application.
|
|
129
|
+
|
|
130
|
+
## Stack
|
|
131
|
+
- Language: TypeScript
|
|
132
|
+
- Framework: Next.js
|
|
133
|
+
- Runtime: Node.js
|
|
134
|
+
- Package manager: pnpm
|
|
135
|
+
- Database: Prisma ORM
|
|
136
|
+
- Testing: Vitest
|
|
137
|
+
|
|
138
|
+
## Commands
|
|
139
|
+
```bash
|
|
140
|
+
pnpm install # install
|
|
141
|
+
pnpm run dev # dev
|
|
142
|
+
pnpm run test # test
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Code conventions
|
|
146
|
+
- TypeScript strict mode is enabled - keep full type safety, avoid `any`.
|
|
147
|
+
- Linter: ESLint. Run it before committing.
|
|
148
|
+
- Formatter: Prettier. Do not hand-format against it.
|
|
149
|
+
|
|
150
|
+
## Environment variables
|
|
151
|
+
Copy `.env.example` to `.env` and set:
|
|
152
|
+
- `DATABASE_URL` (**required**) - Postgres connection string
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
</details>
|
|
156
|
+
|
|
157
|
+
## MCP server
|
|
158
|
+
|
|
159
|
+
`claude-init` also runs as a [Model Context Protocol](https://modelcontextprotocol.io)
|
|
160
|
+
server, so an agent can analyze a repo and write the context files itself.
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# Claude Code
|
|
164
|
+
claude mcp add claude-init -- npx @horiastanxd/claude-init --mcp
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Tools exposed: `analyze_project`, `generate_context_files`, `check_context_files`.
|
|
168
|
+
|
|
169
|
+
## What gets detected
|
|
170
|
+
|
|
171
|
+
- **Stack** - language, framework, runtime, package manager, database, test runner, build tool
|
|
172
|
+
- **Commands** - install / dev / build / test / lint / format, plus other scripts
|
|
173
|
+
- **Structure** - a trimmed file tree, entry points, config files
|
|
174
|
+
- **Conventions** - strict mode, linter, formatter, import style, commit convention
|
|
175
|
+
- **Env vars** - parsed from `.env.example`, with inline comments as descriptions
|
|
176
|
+
- **Git** - default branch, remote, top authors, frequently changed files
|
|
177
|
+
|
|
178
|
+
Languages: JS/TS (npm, pnpm, yarn, bun), Python (pip, uv, poetry), Rust (cargo),
|
|
179
|
+
Go (modules), plus partial detection for Java, Ruby, and PHP.
|
|
180
|
+
|
|
181
|
+
## Use as a library
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
import { analyzeProject, generateClaudeMd, buildFiles } from 'claude-init';
|
|
185
|
+
|
|
186
|
+
const analysis = await analyzeProject(process.cwd());
|
|
187
|
+
const md = generateClaudeMd(analysis);
|
|
188
|
+
|
|
189
|
+
// or render every target in memory
|
|
190
|
+
for (const file of buildFiles(analysis)) {
|
|
191
|
+
console.log(file.relPath, file.content.length);
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Development
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
npm install
|
|
199
|
+
npm run dev -- --dry-run # run from source
|
|
200
|
+
npm test
|
|
201
|
+
npm run build
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Contributions welcome - adding a new tool is usually a single entry in
|
|
205
|
+
[`src/generators/registry.ts`](./src/generators/registry.ts). See
|
|
206
|
+
[CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
207
|
+
|
|
208
|
+
## Roadmap
|
|
209
|
+
|
|
210
|
+
- More tools (Zed dedicated rules, Continue, Kilo Code, Trae)
|
|
211
|
+
- Monorepo-aware generation (per-package context files)
|
|
212
|
+
- Optional LLM pass to enrich descriptions (opt-in, off by default)
|
|
213
|
+
|
|
214
|
+
Ideas and PRs welcome.
|
|
215
|
+
|
|
216
|
+
## Star History
|
|
217
|
+
|
|
218
|
+
[](https://star-history.com/#horiastanxd/claude-init&Date)
|
|
219
|
+
|
|
220
|
+
## License
|
|
221
|
+
|
|
222
|
+
[MIT](./LICENSE)
|
|
223
|
+
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { pathExists, readText, readJson } from '../utils.js';
|
|
3
|
+
export async function detectCodePatterns(projectDir) {
|
|
4
|
+
const [tsconfig, linter, formatter, commitConvention] = await Promise.all([
|
|
5
|
+
detectStrict(projectDir),
|
|
6
|
+
detectLinter(projectDir),
|
|
7
|
+
detectFormatter(projectDir),
|
|
8
|
+
detectCommitConvention(projectDir),
|
|
9
|
+
]);
|
|
10
|
+
return {
|
|
11
|
+
strict: tsconfig.strict,
|
|
12
|
+
linter,
|
|
13
|
+
formatter,
|
|
14
|
+
commitConvention,
|
|
15
|
+
importStyle: tsconfig.importStyle,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
async function detectStrict(dir) {
|
|
19
|
+
const raw = await readText(join(dir, 'tsconfig.json'));
|
|
20
|
+
if (raw === null)
|
|
21
|
+
return { strict: false, importStyle: null };
|
|
22
|
+
return {
|
|
23
|
+
strict: /"strict"\s*:\s*true/.test(raw),
|
|
24
|
+
importStyle: /"(baseUrl|paths)"\s*:/.test(raw) ? 'absolute (path aliases)' : 'relative',
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
async function detectLinter(dir) {
|
|
28
|
+
const eslint = [
|
|
29
|
+
'.eslintrc',
|
|
30
|
+
'.eslintrc.json',
|
|
31
|
+
'.eslintrc.js',
|
|
32
|
+
'.eslintrc.cjs',
|
|
33
|
+
'eslint.config.js',
|
|
34
|
+
'eslint.config.mjs',
|
|
35
|
+
];
|
|
36
|
+
for (const f of eslint) {
|
|
37
|
+
if (await pathExists(join(dir, f)))
|
|
38
|
+
return 'ESLint';
|
|
39
|
+
}
|
|
40
|
+
if (await pathExists(join(dir, 'biome.json')))
|
|
41
|
+
return 'Biome';
|
|
42
|
+
if (await pathExists(join(dir, 'ruff.toml')))
|
|
43
|
+
return 'Ruff';
|
|
44
|
+
if (await pathExists(join(dir, '.golangci.yml')))
|
|
45
|
+
return 'golangci-lint';
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
async function detectFormatter(dir) {
|
|
49
|
+
const prettier = ['.prettierrc', '.prettierrc.json', '.prettierrc.js', 'prettier.config.js'];
|
|
50
|
+
for (const f of prettier) {
|
|
51
|
+
if (await pathExists(join(dir, f)))
|
|
52
|
+
return 'Prettier';
|
|
53
|
+
}
|
|
54
|
+
if (await pathExists(join(dir, 'biome.json')))
|
|
55
|
+
return 'Biome';
|
|
56
|
+
const pkg = await readJson(join(dir, 'package.json'));
|
|
57
|
+
if (pkg?.prettier)
|
|
58
|
+
return 'Prettier';
|
|
59
|
+
if (pkg?.devDependencies?.['prettier'])
|
|
60
|
+
return 'Prettier';
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
async function detectCommitConvention(dir) {
|
|
64
|
+
const markers = ['commitlint.config.js', '.commitlintrc', '.commitlintrc.json', '.czrc'];
|
|
65
|
+
for (const f of markers) {
|
|
66
|
+
if (await pathExists(join(dir, f)))
|
|
67
|
+
return 'Conventional Commits';
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=code-patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-patterns.js","sourceRoot":"","sources":["../../src/analyzer/code-patterns.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { pathExists, readJson, detectPackageManager } from '../utils.js';
|
|
3
|
+
const EMPTY = {
|
|
4
|
+
install: null,
|
|
5
|
+
dev: null,
|
|
6
|
+
build: null,
|
|
7
|
+
test: null,
|
|
8
|
+
lint: null,
|
|
9
|
+
format: null,
|
|
10
|
+
extra: {},
|
|
11
|
+
};
|
|
12
|
+
const KNOWN_SCRIPTS = new Set([
|
|
13
|
+
'dev',
|
|
14
|
+
'start',
|
|
15
|
+
'build',
|
|
16
|
+
'test',
|
|
17
|
+
'lint',
|
|
18
|
+
'format',
|
|
19
|
+
'fmt',
|
|
20
|
+
'prepare',
|
|
21
|
+
'postinstall',
|
|
22
|
+
'prepublishonly',
|
|
23
|
+
]);
|
|
24
|
+
export async function detectCommands(projectDir) {
|
|
25
|
+
if (await pathExists(join(projectDir, 'package.json'))) {
|
|
26
|
+
return fromPackageJson(projectDir);
|
|
27
|
+
}
|
|
28
|
+
if (await pathExists(join(projectDir, 'Cargo.toml'))) {
|
|
29
|
+
return {
|
|
30
|
+
install: null,
|
|
31
|
+
dev: 'cargo run',
|
|
32
|
+
build: 'cargo build --release',
|
|
33
|
+
test: 'cargo test',
|
|
34
|
+
lint: 'cargo clippy',
|
|
35
|
+
format: 'cargo fmt',
|
|
36
|
+
extra: {},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (await pathExists(join(projectDir, 'pyproject.toml'))) {
|
|
40
|
+
const hasUv = await pathExists(join(projectDir, 'uv.lock'));
|
|
41
|
+
return {
|
|
42
|
+
install: hasUv ? 'uv sync' : 'pip install -e ".[dev]"',
|
|
43
|
+
dev: null,
|
|
44
|
+
build: null,
|
|
45
|
+
test: 'pytest',
|
|
46
|
+
lint: 'ruff check .',
|
|
47
|
+
format: 'ruff format .',
|
|
48
|
+
extra: {},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
if (await pathExists(join(projectDir, 'go.mod'))) {
|
|
52
|
+
return {
|
|
53
|
+
install: 'go mod download',
|
|
54
|
+
dev: 'go run .',
|
|
55
|
+
build: 'go build ./...',
|
|
56
|
+
test: 'go test ./...',
|
|
57
|
+
lint: 'golangci-lint run',
|
|
58
|
+
format: 'go fmt ./...',
|
|
59
|
+
extra: {},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return { ...EMPTY };
|
|
63
|
+
}
|
|
64
|
+
async function fromPackageJson(dir) {
|
|
65
|
+
const pkg = await readJson(join(dir, 'package.json'));
|
|
66
|
+
const scripts = pkg?.scripts ?? {};
|
|
67
|
+
const pm = await detectPackageManager(dir);
|
|
68
|
+
const run = (script) => `${pm} run ${script}`;
|
|
69
|
+
const has = (script) => typeof scripts[script] === 'string';
|
|
70
|
+
const formatScript = has('format') ? 'format' : has('fmt') ? 'fmt' : null;
|
|
71
|
+
const extra = {};
|
|
72
|
+
for (const key of Object.keys(scripts)) {
|
|
73
|
+
if (!KNOWN_SCRIPTS.has(key.toLowerCase()))
|
|
74
|
+
extra[key] = run(key);
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
install: pm === 'npm' ? 'npm install' : `${pm} install`,
|
|
78
|
+
dev: has('dev') ? run('dev') : has('start') ? run('start') : null,
|
|
79
|
+
build: has('build') ? run('build') : null,
|
|
80
|
+
test: has('test') ? run('test') : null,
|
|
81
|
+
lint: has('lint') ? run('lint') : null,
|
|
82
|
+
format: formatScript ? run(formatScript) : null,
|
|
83
|
+
extra,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/analyzer/commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { readText } from '../utils.js';
|
|
3
|
+
const CANDIDATES = ['.env.example', '.env.sample', '.env.template', '.env.local.example'];
|
|
4
|
+
export async function detectEnvVars(projectDir) {
|
|
5
|
+
for (const candidate of CANDIDATES) {
|
|
6
|
+
const content = await readText(join(projectDir, candidate));
|
|
7
|
+
if (content !== null)
|
|
8
|
+
return parseEnvFile(content);
|
|
9
|
+
}
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
export function parseEnvFile(content) {
|
|
13
|
+
const vars = [];
|
|
14
|
+
let pendingComment = '';
|
|
15
|
+
for (const rawLine of content.split('\n')) {
|
|
16
|
+
const line = rawLine.trim();
|
|
17
|
+
if (!line) {
|
|
18
|
+
pendingComment = '';
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (line.startsWith('#')) {
|
|
22
|
+
pendingComment = line.replace(/^#+\s*/, '');
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const eqIdx = line.indexOf('=');
|
|
26
|
+
if (eqIdx === -1)
|
|
27
|
+
continue;
|
|
28
|
+
const name = line.slice(0, eqIdx).trim().replace(/^export\s+/, '');
|
|
29
|
+
if (!name)
|
|
30
|
+
continue;
|
|
31
|
+
const value = line.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, '');
|
|
32
|
+
vars.push({
|
|
33
|
+
name,
|
|
34
|
+
example: value || null,
|
|
35
|
+
required: value === '',
|
|
36
|
+
description: pendingComment,
|
|
37
|
+
});
|
|
38
|
+
pendingComment = '';
|
|
39
|
+
}
|
|
40
|
+
return vars;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=env-vars.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-vars.js","sourceRoot":"","sources":["../../src/analyzer/env-vars.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,MAAM,UAAU,GAAG,CAAC,cAAc,EAAE,aAAa,EAAE,eAAe,EAAE,oBAAoB,CAAC,CAAC;AAE1F,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,UAAkB;IACpD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;QAC5D,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,YAAY,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,cAAc,GAAG,EAAE,CAAC;IAExB,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAE5B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,cAAc,GAAG,EAAE,CAAC;YACpB,SAAS;QACX,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC5C,SAAS;QACX,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,KAAK,KAAK,CAAC,CAAC;YAAE,SAAS;QAE3B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QACnE,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QAEvE,IAAI,CAAC,IAAI,CAAC;YACR,IAAI;YACJ,OAAO,EAAE,KAAK,IAAI,IAAI;YACtB,QAAQ,EAAE,KAAK,KAAK,EAAE;YACtB,WAAW,EAAE,cAAc;SAC5B,CAAC,CAAC;QACH,cAAc,GAAG,EAAE,CAAC;IACtB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { simpleGit } from 'simple-git';
|
|
2
|
+
const NONE = {
|
|
3
|
+
hasGit: false,
|
|
4
|
+
remoteName: null,
|
|
5
|
+
defaultBranch: null,
|
|
6
|
+
topAuthors: [],
|
|
7
|
+
hotFiles: [],
|
|
8
|
+
};
|
|
9
|
+
export async function analyzeGit(projectDir) {
|
|
10
|
+
const git = simpleGit(projectDir);
|
|
11
|
+
const isRepo = await git.checkIsRepo().catch(() => false);
|
|
12
|
+
if (!isRepo)
|
|
13
|
+
return { ...NONE };
|
|
14
|
+
const [remotes, branch, authorLog, fileLog] = await Promise.all([
|
|
15
|
+
git.getRemotes(true).catch(() => []),
|
|
16
|
+
git.revparse(['--abbrev-ref', 'HEAD']).catch(() => 'main'),
|
|
17
|
+
git.raw(['log', '--format=%an', '--no-merges', '-200']).catch(() => ''),
|
|
18
|
+
git.raw(['log', '--name-only', '--format=', '--no-merges', '-500']).catch(() => ''),
|
|
19
|
+
]);
|
|
20
|
+
return {
|
|
21
|
+
hasGit: true,
|
|
22
|
+
remoteName: remotes[0]?.refs?.fetch ?? remotes[0]?.name ?? null,
|
|
23
|
+
defaultBranch: branch.trim() || 'main',
|
|
24
|
+
topAuthors: topCounts(authorLog, 3),
|
|
25
|
+
hotFiles: topCounts(fileLog, 5),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function topCounts(log, limit) {
|
|
29
|
+
const counts = {};
|
|
30
|
+
for (const line of log.split('\n')) {
|
|
31
|
+
const key = line.trim();
|
|
32
|
+
if (!key)
|
|
33
|
+
continue;
|
|
34
|
+
counts[key] = (counts[key] ?? 0) + 1;
|
|
35
|
+
}
|
|
36
|
+
return Object.entries(counts)
|
|
37
|
+
.sort(([, a], [, b]) => b - a)
|
|
38
|
+
.slice(0, limit)
|
|
39
|
+
.map(([k]) => k);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=git-history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-history.js","sourceRoot":"","sources":["../../src/analyzer/git-history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,MAAM,IAAI,GAAY;IACpB,MAAM,EAAE,KAAK;IACb,UAAU,EAAE,IAAI;IAChB,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE,EAAE;IACd,QAAQ,EAAE,EAAE;CACb,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,UAAkB;IACjD,MAAM,GAAG,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;IAElC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;IAC1D,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;IAEhC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC9D,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;QACpC,GAAG,CAAC,QAAQ,CAAC,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC;QAC1D,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;QACvE,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;KACpF,CAAC,CAAC;IAEH,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,IAAI;QAC/D,aAAa,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,MAAM;QACtC,UAAU,EAAE,SAAS,CAAC,SAAS,EAAE,CAAC,CAAC;QACnC,QAAQ,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;KAChC,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,GAAW,EAAE,KAAa;IAC3C,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACxB,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;SAC1B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;SAC7B,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { basename, join } from 'node:path';
|
|
2
|
+
import { readJson } from '../utils.js';
|
|
3
|
+
import { detectTechStack } from './tech-stack.js';
|
|
4
|
+
import { analyzeGit } from './git-history.js';
|
|
5
|
+
import { analyzeStructure } from './project-structure.js';
|
|
6
|
+
import { detectCommands } from './commands.js';
|
|
7
|
+
import { detectEnvVars } from './env-vars.js';
|
|
8
|
+
import { detectCodePatterns } from './code-patterns.js';
|
|
9
|
+
import { TARGETS } from '../generators/registry.js';
|
|
10
|
+
/**
|
|
11
|
+
* Top-level path segments of every file we generate. Excluded from the structure
|
|
12
|
+
* tree so that running `generate` does not make a later `check` report drift.
|
|
13
|
+
*/
|
|
14
|
+
const GENERATED_SEGMENTS = [
|
|
15
|
+
...new Set(TARGETS.flatMap((t) => t.files.map((f) => f.path.split(/[\\/]/)[0]))),
|
|
16
|
+
];
|
|
17
|
+
export async function analyzeProject(projectDir) {
|
|
18
|
+
const [techStack, gitInfo, structure, commands, envVars, codePatterns, pkg] = await Promise.all([
|
|
19
|
+
detectTechStack(projectDir),
|
|
20
|
+
analyzeGit(projectDir),
|
|
21
|
+
analyzeStructure(projectDir, GENERATED_SEGMENTS),
|
|
22
|
+
detectCommands(projectDir),
|
|
23
|
+
detectEnvVars(projectDir),
|
|
24
|
+
detectCodePatterns(projectDir),
|
|
25
|
+
readJson(join(projectDir, 'package.json')),
|
|
26
|
+
]);
|
|
27
|
+
return {
|
|
28
|
+
name: pkg?.name || basename(projectDir) || 'project',
|
|
29
|
+
description: pkg?.description ?? '',
|
|
30
|
+
techStack,
|
|
31
|
+
structure,
|
|
32
|
+
commands,
|
|
33
|
+
tests: {
|
|
34
|
+
framework: techStack.testing,
|
|
35
|
+
command: commands.test,
|
|
36
|
+
coverage: Boolean(pkg?.scripts && ('coverage' in pkg.scripts || 'test:coverage' in pkg.scripts)),
|
|
37
|
+
testDir: structure.testDir,
|
|
38
|
+
},
|
|
39
|
+
envVars,
|
|
40
|
+
codePatterns,
|
|
41
|
+
gitInfo,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analyzer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAGpD;;;GAGG;AACH,MAAM,kBAAkB,GAAa;IACnC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;CAClF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,UAAkB;IACrD,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC9F,eAAe,CAAC,UAAU,CAAC;QAC3B,UAAU,CAAC,UAAU,CAAC;QACtB,gBAAgB,CAAC,UAAU,EAAE,kBAAkB,CAAC;QAChD,cAAc,CAAC,UAAU,CAAC;QAC1B,aAAa,CAAC,UAAU,CAAC;QACzB,kBAAkB,CAAC,UAAU,CAAC;QAC9B,QAAQ,CACN,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CACjC;KACF,CAAC,CAAC;IAEH,OAAO;QACL,IAAI,EAAE,GAAG,EAAE,IAAI,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,SAAS;QACpD,WAAW,EAAE,GAAG,EAAE,WAAW,IAAI,EAAE;QACnC,SAAS;QACT,SAAS;QACT,QAAQ;QACR,KAAK,EAAE;YACL,SAAS,EAAE,SAAS,CAAC,OAAO;YAC5B,OAAO,EAAE,QAAQ,CAAC,IAAI;YACtB,QAAQ,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,IAAI,CAAC,UAAU,IAAI,GAAG,CAAC,OAAO,IAAI,eAAe,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;YAChG,OAAO,EAAE,SAAS,CAAC,OAAO;SAC3B;QACD,OAAO;QACP,YAAY;QACZ,OAAO;KACR,CAAC;AACJ,CAAC"}
|