readmeg 1.0.0 → 1.0.1

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 (3) hide show
  1. package/README.md +68 -78
  2. package/bin/readmeg.js +542 -30
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -5,27 +5,27 @@
5
5
  [![Stargazers][stars-shield]][stars-url]
6
6
  [![Issues][issues-shield]][issues-url]
7
7
  [![MIT License][license-shield]][license-url]
8
- [![LinkedIn][linkedin-shield]][linkedin-url]
8
+ [![Twitter][twitter-shield]][twitter-url]
9
9
 
10
10
  <br />
11
11
  <div align="center">
12
- <a href="https://github.com/your_username/readmeg">
13
- <img src="https://images.unsplash.com/photo-1618401471353-b98aedd07871?q=80&w=120&auto=format&fit=crop" alt="Logo" width="80" height="80">
12
+ <a href="https://github.com/iamtyroon/readme-gen">
13
+ <img src="assets/logo.png" alt="Logo" width="80" height="80">
14
14
  </a>
15
15
 
16
- <h3 align="center">readmeg</h3>
16
+ <h3 align="center">readmeg</h3>
17
17
 
18
18
  <p align="center">
19
- An AI-powered CLI tool to instantly generate beautiful, comprehensive, and professional README.md files for your repositories.
19
+ Zero-config terminal tool powered by Gemini that automatically generates comprehensive, production-grade README files for local repositories.
20
20
  <br />
21
- <a href="https://github.com/your_username/readmeg"><strong>Explore the docs »</strong></a>
21
+ <a href="https://github.com/iamtyroon/readme-gen"><strong>Explore the docs »</strong></a>
22
22
  <br />
23
23
  <br />
24
- <a href="https://github.com/your_username/readmeg">View Demo</a>
24
+ <a href="https://github.com/iamtyroon/readme-gen">View Demo</a>
25
25
  ·
26
- <a href="https://github.com/your_username/readmeg/issues">Report Bug</a>
26
+ <a href="https://github.com/iamtyroon/readme-gen/issues">Report Bug</a>
27
27
  ·
28
- <a href="https://github.com/your_username/readmeg/issues">Request Feature</a>
28
+ <a href="https://github.com/iamtyroon/readme-gen/issues">Request Feature</a>
29
29
  </p>
30
30
  </div>
31
31
 
@@ -56,27 +56,25 @@
56
56
 
57
57
  ## About The Project
58
58
 
59
- [![readmeg Screen Shot][product-screenshot]](https://github.com/your_username/readmeg)
59
+ [![Product Name Screen Shot][product-screenshot]](https://github.com/iamtyroon/readme-gen)
60
60
 
61
- Writing a high-quality README is often the most tedious part of finishing a project. `readmeg` is an interactive Command Line Interface (CLI) tool designed to automate this process. By leveraging Google's advanced Gemini generative AI models, `readmeg` analyzes your project structure, prompts you for key details, and outputs a perfectly formatted, professional `README.md` file in seconds.
61
+ Writing a comprehensive, high-quality README is often the most tedious part of finishing a project. `readmeg` solves this by automating the entire process.
62
+
63
+ By scanning your local repository structure, analyzing key manifest files (such as `package.json`, `tsconfig.json`, and `.env.example`), and leveraging the advanced contextual understanding of Google's Gemini AI, `readmeg` generates a production-grade, beautifully formatted README in seconds.
62
64
 
63
65
  Here's why you should use `readmeg`:
64
- * **Save Time**: Stop writing boilerplate markdown sections from scratch.
65
- * **Interactive Prompts**: Simple, step-by-step terminal questions guide you through defining your project's scope.
66
- * **AI-Powered**: Generates intelligent descriptions, installation steps, and usage guides based on your actual project configuration.
67
- * **Standardized Layouts**: Outputs clean markdown following industry-standard templates.
66
+ * **Zero-Config**: No complex setup or configuration files required.
67
+ * **Context-Aware**: It parses your actual codebase structure and dependencies to write accurate documentation.
68
+ * **Interactive CLI**: Prompts you for key details to customize the output to your exact needs.
69
+ * **Time-Saving**: Instantly generates standard sections like Installation, Usage, Roadmap, and License.
68
70
 
69
71
  <p align="right">(<a href="#readme-top">back to top</a>)</p>
70
72
 
71
73
  ### Built With
72
74
 
73
- This project is built using modern Node.js and TypeScript, leveraging powerful CLI and AI libraries:
74
-
75
75
  * [![Node.js][Node.js]][Node-url]
76
- * [![TypeScript][TypeScript]][TypeScript-url]
77
- * [![Google Gemini][Gemini]][Gemini-url]
78
- * [![Commander.js][Commander]][Commander-url]
79
- * [![Inquirer.js][Inquirer]][Inquirer-url]
76
+ * [![Gemini][Gemini.js]][Gemini-url]
77
+ * [![TypeScript][TypeScript.js]][TypeScript-url]
80
78
 
81
79
  <p align="right">(<a href="#readme-top">back to top</a>)</p>
82
80
 
@@ -86,69 +84,66 @@ To get a local copy up and running, follow these simple steps.
86
84
 
87
85
  ### Prerequisites
88
86
 
89
- Ensure you have Node.js installed (version 18.0.0 or higher is recommended).
90
-
91
- * npm
92
- ```sh
93
- npm install npm@latest -g
94
- ```
87
+ * **Node.js** (v18.0.0 or higher recommended)
88
+ * **Gemini API Key**: You will need an API key from Google AI Studio.
95
89
 
96
90
  ### Installation
97
91
 
98
- 1. Get a free Gemini API Key from [Google AI Studio](https://aistudio.google.com/).
99
- 2. Clone the repository:
92
+ 1. Clone the repository:
100
93
  ```sh
101
- git clone https://github.com/your_username/readmeg.git
94
+ git clone https://github.com/iamtyroon/readme-gen.git
102
95
  ```
103
- 3. Install NPM packages:
96
+ 2. Navigate to the project directory and install dependencies:
104
97
  ```sh
98
+ cd readme-gen
105
99
  npm install
106
100
  ```
107
- 4. Create a `.env` file in the root directory and add your Gemini API key:
101
+ 3. Create a `.env` file in the root directory and add your Gemini API key:
108
102
  ```env
109
- GEMINI_API_KEY=your_actual_api_key_here
103
+ GEMINI_API_KEY="YOUR_GEMINI_API_KEY"
110
104
  ```
111
- 5. Build the TypeScript files (if modifying source files):
105
+ 4. Link the package globally to use the `readmeg` command anywhere:
112
106
  ```sh
113
- npm run build
107
+ npm link
114
108
  ```
115
109
 
116
110
  <p align="right">(<a href="#readme-top">back to top</a>)</p>
117
111
 
118
112
  ## Usage
119
113
 
120
- You can run `readmeg` directly using Node.js. The CLI will guide you through an interactive prompt session to gather information about your repository before generating the markdown file.
114
+ Once installed globally, you can run `readmeg` in any local repository to generate its documentation.
121
115
 
122
- ### Running the CLI
116
+ ### Run the Generator
123
117
 
124
- To start the interactive generation process:
118
+ Navigate to the target repository where you want to generate a README and run:
125
119
  ```sh
126
- node ./bin/readmeg.js
120
+ readmeg
127
121
  ```
128
122
 
129
- To view available CLI commands and options:
123
+ ### Command Line Options
124
+
125
+ You can also view help and available options directly from the CLI:
130
126
  ```sh
131
- npm start
127
+ readmeg --help
132
128
  ```
133
129
 
134
- ### Example Interactive Flow
130
+ ### How It Works
135
131
 
136
- 1. **Project Name**: Enter the name of your project (defaults to your directory name).
137
- 2. **Description**: Provide a brief summary of what your application does.
138
- 3. **Technologies**: Select or enter the main frameworks and languages used.
139
- 4. **License**: Choose your project's license (e.g., MIT, Apache 2.0, GPL v3).
140
- 5. **Output**: The tool will call the Gemini API and write a polished `README.md` directly to your root directory.
132
+ 1. **Codebase Scan**: `readmeg` analyzes your directory tree and identifies key configuration files.
133
+ 2. **Context Extraction**: It extracts metadata, dependencies, and scripts from files like `package.json` and `.env.example`.
134
+ 3. **AI Generation**: The extracted context is sent to the Gemini API to draft a structured, professional README.md.
135
+ 4. **Output**: The generated markdown is saved directly to your workspace as `README.md`.
141
136
 
142
137
  <p align="right">(<a href="#readme-top">back to top</a>)</p>
143
138
 
144
139
  ## Roadmap
145
140
 
146
- - [ ] Add support for automatic codebase parsing (reading `package.json`, `requirements.txt`, etc.)
147
- - [ ] Provide multiple pre-designed README templates (Minimal, Detailed, API-focused)
148
- - [ ] Add support for alternative LLM providers (OpenAI, Anthropic)
149
- - [ ] Implement a dry-run mode to preview markdown in the terminal before writing to disk
141
+ - [ ] Support for additional language manifests (`Cargo.toml`, `pyproject.toml`, `go.mod`)
142
+ - [ ] Custom template selection (e.g., Minimal, Academic, Enterprise)
143
+ - [ ] Interactive terminal preview before writing to disk
144
+ - [ ] GitHub Actions integration for automated documentation updates
150
145
 
151
- See the [open issues](https://github.com/your_username/readmeg/issues) for a full list of proposed features and known issues.
146
+ See the [open issues](https://github.com/iamtyroon/readme-gen/issues) for a full list of proposed features and known issues.
152
147
 
153
148
  <p align="right">(<a href="#readme-top">back to top</a>)</p>
154
149
 
@@ -175,15 +170,15 @@ Distributed under the MIT License. See `LICENSE` for more information.
175
170
 
176
171
  ## Contact
177
172
 
178
- Your Name - [@your_twitter](https://twitter.com/your_twitter) - email@example.com
173
+ iamtyroon - [@notyroon](https://x.com/notyroon)
179
174
 
180
- Project Link: [https://github.com/your_username/readmeg](https://github.com/your_username/readmeg)
175
+ Project Link: [https://github.com/iamtyroon/readme-gen](https://github.com/iamtyroon/readme-gen)
181
176
 
182
177
  <p align="right">(<a href="#readme-top">back to top</a>)</p>
183
178
 
184
179
  ## Acknowledgments
185
180
 
186
- * [Google Gen AI SDK](https://github.com/google/generative-ai-js)
181
+ * [Google Gemini AI SDK](https://github.com/google/generative-ai-js)
187
182
  * [Commander.js](https://github.com/tj/commander.js/)
188
183
  * [Inquirer.js](https://github.com/SBoudrias/Inquirer.js/)
189
184
  * [Shields.io](https://shields.io)
@@ -191,27 +186,22 @@ Project Link: [https://github.com/your_username/readmeg](https://github.com/your
191
186
 
192
187
  <p align="right">(<a href="#readme-top">back to top</a>)</p>
193
188
 
194
- [contributors-shield]: https://img.shields.io/github/contributors/your_username/readmeg.svg?style=for-the-badge
195
- [contributors-url]: https://github.com/your_username/readmeg/graphs/contributors
196
- [forks-shield]: https://img.shields.io/github/forks/your_username/readmeg.svg?style=for-the-badge
197
- [forks-url]: https://github.com/your_username/readmeg/network/members
198
- [stars-shield]: https://img.shields.io/github/stars/your_username/readmeg.svg?style=for-the-badge
199
- [stars-url]: https://github.com/your_username/readmeg/stargazers
200
- [issues-shield]: https://img.shields.io/github/issues/your_username/readmeg.svg?style=for-the-badge
201
- [issues-url]: https://github.com/your_username/readmeg/issues
202
- [license-shield]: https://img.shields.io/github/license/your_username/readmeg.svg?style=for-the-badge
203
- [license-url]: https://github.com/your_username/readmeg/blob/master/LICENSE.txt
204
- [linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge&logo=linkedin&colorB=555
205
- [linkedin-url]: https://linkedin.com/in/your_username
206
- [product-screenshot]: https://images.unsplash.com/photo-1618401471353-b98aedd07871?q=80&w=600&auto=format&fit=crop
207
-
208
- [Node.js]: https://img.shields.io/badge/Node.js-43853D?style=for-the-badge&logo=node.js&logoColor=white
189
+ [contributors-shield]: https://img.shields.io/github/contributors/iamtyroon/readme-gen.svg?style=for-the-badge
190
+ [contributors-url]: https://github.com/iamtyroon/readme-gen/graphs/contributors
191
+ [forks-shield]: https://img.shields.io/github/forks/iamtyroon/readme-gen.svg?style=for-the-badge
192
+ [forks-url]: https://github.com/iamtyroon/readme-gen/network/members
193
+ [stars-shield]: https://img.shields.io/github/stars/iamtyroon/readme-gen.svg?style=for-the-badge
194
+ [stars-url]: https://github.com/iamtyroon/readme-gen/stargazers
195
+ [issues-shield]: https://img.shields.io/github/issues/iamtyroon/readme-gen.svg?style=for-the-badge
196
+ [issues-url]: https://github.com/iamtyroon/readme-gen/issues
197
+ [license-shield]: https://img.shields.io/github/license/iamtyroon/readme-gen.svg?style=for-the-badge
198
+ [license-url]: https://github.com/iamtyroon/readme-gen/blob/main/LICENSE
199
+ [twitter-shield]: https://img.shields.io/badge/-Twitter-black.svg?style=for-the-badge&logo=x&colorB=555
200
+ [twitter-url]: https://x.com/notyroon
201
+ [product-screenshot]: assets/readmeg_scrnshot.png
202
+ [Node.js]: https://img.shields.io/badge/Node.js-6DA55F?style=for-the-badge&logo=node.js&logoColor=white
209
203
  [Node-url]: https://nodejs.org/
210
- [TypeScript]: https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge&logo=typescript&logoColor=white
211
- [TypeScript-url]: https://www.typescriptlang.org/
212
- [Gemini]: https://img.shields.io/badge/Google%20Gemini-8E75C2?style=for-the-badge&logo=googlegemini&logoColor=white
213
- [Gemini-url]: https://deepmind.google/technologies/gemini/
214
- [Commander]: https://img.shields.io/badge/Commander.js-black?style=for-the-badge&logo=commander
215
- [Commander-url]: https://github.com/tj/commander.js/
216
- [Inquirer]: https://img.shields.io/badge/Inquirer.js-red?style=for-the-badge&logo=npm
217
- [Inquirer-url]: https://github.com/SBoudrias/Inquirer.js/
204
+ [Gemini.js]: https://img.shields.io/badge/Gemini%20AI-8E75C2?style=for-the-badge&logo=googlegemini&logoColor=white
205
+ [Gemini-url]: https://ai.google.dev/
206
+ [TypeScript.js]: https://img.shields.io/badge/TypeScript-3178C6?style=for-the-badge&logo=typescript&logoColor=white
207
+ [TypeScript-url]: https://www.typescriptlang.org/
package/bin/readmeg.js CHANGED
@@ -11,6 +11,7 @@ import { Command } from "commander";
11
11
  import inquirer from "inquirer";
12
12
  import { GoogleGenAI } from "@google/genai";
13
13
  import dotenv from "dotenv";
14
+ import { execSync } from "child_process";
14
15
 
15
16
  // Load local .env configurations if present
16
17
  dotenv.config();
@@ -20,10 +21,17 @@ const program = new Command();
20
21
  program
21
22
  .name("readmeg")
22
23
  .description("Automatically generate comprehensive production-grade README.md files for your local directory repositories using Gemini.")
23
- .version("1.0.0")
24
+ .version("1.0.1")
24
25
  .option("-k, --api-key <key>", "Provide your Gemini API key manually")
25
26
  .option("-o, --output <file>", "Define custom output file path", "README.md")
26
27
  .option("-n, --non-interactive", "Run directly without interactive menu loop", false)
28
+ .option("-i, --include <files...>", "Explicitly include specific files or directories for scanning")
29
+ .option("-u, --github-user <username>", "Provide your GitHub username manually")
30
+ .option("-r, --repo-url <url>", "Provide your GitHub repository URL manually")
31
+ .option("-t, --twitter <url>", "Provide your Twitter Profile URL manually")
32
+ .option("-l, --linkedin <url>", "Provide your LinkedIn Profile URL manually")
33
+ .option("--logo <path>", "Path to the project logo image")
34
+ .option("--screenshot <path>", "Path to the project screenshot image")
27
35
  .parse(process.argv);
28
36
 
29
37
  const options = program.opts();
@@ -38,7 +46,6 @@ const IGNORED_DIRS = new Set([
38
46
  "venv",
39
47
  "env",
40
48
  ".aistudio",
41
- "assets",
42
49
  ".next",
43
50
  ".svelte-kit",
44
51
  ".nuxt",
@@ -58,7 +65,24 @@ const MANIFEST_NAMES = new Set([
58
65
  "pom.xml",
59
66
  "build.gradle",
60
67
  "composer.json",
61
- "setup.py"
68
+ "setup.py",
69
+ "tsconfig.json",
70
+ "jsconfig.json",
71
+ "vite.config.js",
72
+ "vite.config.ts",
73
+ "webpack.config.js",
74
+ "next.config.js",
75
+ "next.config.mjs",
76
+ "next.config.ts",
77
+ "nuxt.config.js",
78
+ "nuxt.config.ts",
79
+ "svelte.config.js",
80
+ "tailwind.config.js",
81
+ "tailwind.config.ts",
82
+ "Makefile",
83
+ "CMakeLists.txt",
84
+ ".env.example",
85
+ ".env.sample"
62
86
  ]);
63
87
 
64
88
  const SNIPPET_NAMES = new Set([
@@ -74,6 +98,181 @@ const SNIPPET_NAMES = new Set([
74
98
  "App.js"
75
99
  ]);
76
100
 
101
+ const SOURCE_EXTENSIONS = new Set([
102
+ ".js", ".jsx", ".ts", ".tsx",
103
+ ".py",
104
+ ".go",
105
+ ".rs",
106
+ ".java",
107
+ ".cpp", ".c", ".h", ".hpp",
108
+ ".cs",
109
+ ".rb",
110
+ ".php",
111
+ ".sh",
112
+ ".swift",
113
+ ".kt"
114
+ ]);
115
+
116
+ function isTestOrMockFile(relPath) {
117
+ const lowerPath = relPath.toLowerCase().replace(/\\/g, "/");
118
+ return (
119
+ lowerPath.includes("/test/") ||
120
+ lowerPath.includes("/tests/") ||
121
+ lowerPath.includes("/spec/") ||
122
+ lowerPath.includes("/specs/") ||
123
+ lowerPath.includes("/mock/") ||
124
+ lowerPath.includes("/mocks/") ||
125
+ lowerPath.includes("/__tests__/") ||
126
+ lowerPath.includes("/__mocks__/") ||
127
+ lowerPath.includes("test.") ||
128
+ lowerPath.includes("spec.") ||
129
+ lowerPath.endsWith(".test") ||
130
+ lowerPath.endsWith(".spec")
131
+ );
132
+ }
133
+
134
+ function getAutoSelectedSnippets(snippets) {
135
+ const entryKeywords = ["index", "main", "app", "server", "cli", "run", "start", "config"];
136
+ const scored = snippets.map(s => {
137
+ let score = 0;
138
+ const nameLower = s.name.toLowerCase();
139
+
140
+ if (SNIPPET_NAMES.has(s.name)) {
141
+ score += 100;
142
+ }
143
+ if (!s.relativePath.includes("/") && !s.relativePath.includes("\\")) {
144
+ score += 50; // Root level
145
+ }
146
+ if (entryKeywords.some(kw => nameLower.includes(kw))) {
147
+ score += 30;
148
+ }
149
+ // Files in src/, lib/, bin/, etc. (closer to root is better)
150
+ const depth = s.relativePath.split(/[/\\]/).length - 1;
151
+ score -= depth * 5; // Deeper files have lower priority
152
+
153
+ return { snippet: s, score };
154
+ });
155
+
156
+ // Sort in descending order of score
157
+ scored.sort((a, b) => b.score - a.score);
158
+
159
+ // Select top 20 snippets
160
+ const maxAutoSelect = 20;
161
+ return scored.slice(0, maxAutoSelect).map(item => item.snippet.relativePath);
162
+ }
163
+
164
+ function getExplicitIncludes(includeOption) {
165
+ if (!includeOption) return [];
166
+ const rawArray = Array.isArray(includeOption) ? includeOption : [includeOption];
167
+ const result = [];
168
+ for (const item of rawArray) {
169
+ if (typeof item === 'string') {
170
+ const splitItems = item.split(',').map(s => s.trim()).filter(Boolean);
171
+ result.push(...splitItems);
172
+ }
173
+ }
174
+ return result;
175
+ }
176
+
177
+ function processExplicitFile(filePath, rootPath, result) {
178
+ try {
179
+ const absolutePath = path.resolve(rootPath, filePath);
180
+ if (!fs.existsSync(absolutePath)) {
181
+ console.warn(`\x1b[33m[Warning] Explicitly included file not found: ${filePath}\x1b[0m`);
182
+ return;
183
+ }
184
+ const stats = fs.statSync(absolutePath);
185
+ if (!stats.isFile()) return;
186
+
187
+ const relativePath = path.relative(rootPath, absolutePath);
188
+ const item = path.basename(absolutePath);
189
+ const ext = path.extname(item).toLowerCase();
190
+ const content = fs.readFileSync(absolutePath, "utf-8");
191
+
192
+ // Add to language list
193
+ if (ext === ".ts" || ext === ".tsx") result.languages.add("TypeScript");
194
+ else if (ext === ".js" || ext === ".jsx") result.languages.add("JavaScript");
195
+ else if (ext === ".py") result.languages.add("Python");
196
+ else if (ext === ".go") result.languages.add("Go");
197
+ else if (ext === ".rs") result.languages.add("Rust");
198
+ else if (ext === ".java") result.languages.add("Java");
199
+ else if (ext === ".cpp" || ext === ".c" || ext === ".h" || ext === ".hpp") result.languages.add("C/C++");
200
+ else if (ext === ".cs") result.languages.add("C#");
201
+ else if (ext === ".rb") result.languages.add("Ruby");
202
+ else if (ext === ".php") result.languages.add("PHP");
203
+ else if (ext === ".swift") result.languages.add("Swift");
204
+ else if (ext === ".kt" || ext === ".kts") result.languages.add("Kotlin");
205
+ else if (ext === ".sh") result.languages.add("Shell");
206
+
207
+ if (MANIFEST_NAMES.has(item)) {
208
+ if (!result.manifests.some(m => m.relativePath === relativePath)) {
209
+ result.manifests.push({ relativePath, name: item, content: content.substring(0, 10000) });
210
+ }
211
+ } else if (ext === ".md") {
212
+ if (!result.markdowns.some(m => m.relativePath === relativePath)) {
213
+ result.markdowns.push({ relativePath, name: item, content });
214
+ }
215
+ } else {
216
+ if (!result.snippets.some(s => s.relativePath === relativePath)) {
217
+ result.snippets.push({ relativePath, name: item, content });
218
+ }
219
+ }
220
+ } catch (err) {
221
+ console.error(`\x1b[31m[Error] Failed to process explicit file '${filePath}': ${err.message}\x1b[0m`);
222
+ }
223
+ }
224
+
225
+ function processExplicitPath(inputPath, rootPath, result) {
226
+ try {
227
+ const absolutePath = path.resolve(rootPath, inputPath);
228
+ if (!fs.existsSync(absolutePath)) {
229
+ console.warn(`\x1b[33m[Warning] Explicit path not found: ${inputPath}\x1b[0m`);
230
+ return;
231
+ }
232
+ const stats = fs.statSync(absolutePath);
233
+ if (stats.isDirectory()) {
234
+ const relPath = path.relative(rootPath, absolutePath);
235
+ scanDirectoryFiles(absolutePath, relPath, result);
236
+ } else if (stats.isFile()) {
237
+ processExplicitFile(absolutePath, rootPath, result);
238
+ }
239
+ } catch (err) {
240
+ console.error(`\x1b[31m[Error] Failed to process explicit path '${inputPath}': ${err.message}\x1b[0m`);
241
+ }
242
+ }
243
+ function getGitRemoteInfo() {
244
+ try {
245
+ const remoteUrl = execSync("git remote get-url origin", { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
246
+ if (remoteUrl) {
247
+ let repoUrl = "";
248
+ let username = "";
249
+ let repoName = "";
250
+
251
+ if (remoteUrl.startsWith("git@")) {
252
+ const match = remoteUrl.match(/git@[^:]+:([^/]+)\/(.+?)(?:\.git)?$/);
253
+ if (match) {
254
+ username = match[1];
255
+ repoName = match[2];
256
+ repoUrl = `https://github.com/${username}/${repoName}`;
257
+ }
258
+ } else if (remoteUrl.startsWith("http")) {
259
+ const urlObj = new URL(remoteUrl);
260
+ const pathParts = urlObj.pathname.split("/").filter(Boolean);
261
+ if (pathParts.length >= 2) {
262
+ username = pathParts[0];
263
+ repoName = pathParts[1].replace(/\.git$/, "");
264
+ repoUrl = `https://${urlObj.host}/${username}/${repoName}`;
265
+ }
266
+ }
267
+ return { repoUrl, username, repoName };
268
+ }
269
+ } catch (_) {}
270
+ return null;
271
+ }
272
+
273
+
274
+
275
+
77
276
  // 1. Traverse directory to form visual path layout
78
277
  function buildTreeString(currentPath, prefix = "") {
79
278
  try {
@@ -126,7 +325,7 @@ function scanDirectoryFiles(currentPath, relativePath, result) {
126
325
  try {
127
326
  const items = fs.readdirSync(currentPath);
128
327
  for (const item of items) {
129
- if (IGNORED_DIRS.has(item) || item.startsWith(".")) continue;
328
+ if (IGNORED_DIRS.has(item) || (item.startsWith(".") && item !== ".env.example" && item !== ".env.sample")) continue;
130
329
 
131
330
  const itemPath = path.join(currentPath, item);
132
331
  const itemRelPath = relativePath ? path.join(relativePath, item) : item;
@@ -142,11 +341,33 @@ function scanDirectoryFiles(currentPath, relativePath, result) {
142
341
  else if (ext === ".py") result.languages.add("Python");
143
342
  else if (ext === ".go") result.languages.add("Go");
144
343
  else if (ext === ".rs") result.languages.add("Rust");
344
+ else if (ext === ".java") result.languages.add("Java");
345
+ else if (ext === ".cpp" || ext === ".c" || ext === ".h" || ext === ".hpp") result.languages.add("C/C++");
346
+ else if (ext === ".cs") result.languages.add("C#");
347
+ else if (ext === ".rb") result.languages.add("Ruby");
348
+ else if (ext === ".php") result.languages.add("PHP");
349
+ else if (ext === ".swift") result.languages.add("Swift");
350
+ else if (ext === ".kt" || ext === ".kts") result.languages.add("Kotlin");
351
+ else if (ext === ".sh") result.languages.add("Shell");
352
+
353
+ const isImage = [".png", ".jpg", ".jpeg", ".svg", ".gif"].includes(ext);
354
+ if (isImage) {
355
+ const lowerName = item.toLowerCase();
356
+ if (lowerName.includes("logo")) {
357
+ result.detectedLogos.push(itemRelPath);
358
+ }
359
+ if (lowerName.includes("screenshot") || lowerName.includes("scrnshot") || lowerName.includes("preview")) {
360
+ result.detectedScreenshots.push(itemRelPath);
361
+ }
362
+ }
145
363
 
146
- if (MANIFEST_NAMES.has(item)) {
364
+ const isManifest = MANIFEST_NAMES.has(item);
365
+ const isSnippetCandidate = (SNIPPET_NAMES.has(item) || SOURCE_EXTENSIONS.has(ext)) && !isTestOrMockFile(itemRelPath);
366
+
367
+ if (isManifest) {
147
368
  const content = fs.readFileSync(itemPath, "utf-8").substring(0, 10000);
148
369
  result.manifests.push({ relativePath: itemRelPath, name: item, content });
149
- } else if (SNIPPET_NAMES.has(item) && stats.size < 12000) {
370
+ } else if (isSnippetCandidate && stats.size < 40000) {
150
371
  const content = fs.readFileSync(itemPath, "utf-8");
151
372
  result.snippets.push({ relativePath: itemRelPath, name: item, content });
152
373
  } else if (ext === ".md" && item.toLowerCase() !== "readme.md" && stats.size < 15000) {
@@ -169,7 +390,7 @@ const showBanner = () => {
169
390
  | | \\ \\ __/ (_| | (_| | | | | \\___|\\__, |
170
391
  |_| \\_\\___|\\__,_|\\__,_|_| |_| |___/
171
392
  \x1b[0m`);
172
- console.log(` \x1b[45m\x1b[37m ReadMeg — Interactive CLI v1.0.0 \x1b[0m Powered by Google Gemini AI\n`);
393
+ console.log(` \x1b[45m\x1b[37m ReadMeg — Interactive CLI v1.0.1 \x1b[0m Powered by Google Gemini AI\n`);
173
394
  };
174
395
 
175
396
  async function main() {
@@ -210,11 +431,20 @@ async function main() {
210
431
  manifests: [],
211
432
  snippets: [],
212
433
  markdowns: [],
213
- languages: new Set()
434
+ languages: new Set(),
435
+ detectedLogos: [],
436
+ detectedScreenshots: []
214
437
  };
215
438
 
216
439
  scanDirectoryFiles(activeCwd, "", scanResult);
217
440
 
441
+ if (options.include) {
442
+ const includes = getExplicitIncludes(options.include);
443
+ for (const inc of includes) {
444
+ processExplicitPath(inc, activeCwd, scanResult);
445
+ }
446
+ }
447
+
218
448
  let projectType = "Unknown Project Core";
219
449
  if (scanResult.manifests.some(m => m.name === "package.json")) projectType = "Node.js (JavaScript/TypeScript)";
220
450
  else if (scanResult.manifests.some(m => m.name === "requirements.txt" || m.name === "pyproject.toml")) projectType = "Python";
@@ -224,10 +454,38 @@ async function main() {
224
454
  console.log(`\x1b[32mSuccessfully mapped codebase structure as:\x1b[0m ${projectType}`);
225
455
  console.log(`Tree Depth loaded. Captured manifests: ${scanResult.manifests.map(m => m.name).join(", ") || "None"}\n`);
226
456
 
227
- // CLI Selection Loop states
228
457
  let selectedManifestPaths = scanResult.manifests.map(m => m.relativePath);
229
- let selectedSnippetPaths = scanResult.snippets.map(s => s.relativePath);
458
+ let selectedSnippetPaths = getAutoSelectedSnippets(scanResult.snippets);
230
459
  let selectedMarkdownPaths = scanResult.markdowns.map(md => md.relativePath);
460
+
461
+ if (options.include) {
462
+ const includes = getExplicitIncludes(options.include);
463
+ for (const inc of includes) {
464
+ try {
465
+ const absPath = path.resolve(activeCwd, inc);
466
+ if (fs.existsSync(absPath) && fs.statSync(absPath).isFile()) {
467
+ const relPath = path.relative(activeCwd, absPath);
468
+ if (scanResult.snippets.some(s => s.relativePath === relPath) && !selectedSnippetPaths.includes(relPath)) {
469
+ selectedSnippetPaths.push(relPath);
470
+ }
471
+ if (scanResult.manifests.some(m => m.relativePath === relPath) && !selectedManifestPaths.includes(relPath)) {
472
+ selectedManifestPaths.push(relPath);
473
+ }
474
+ if (scanResult.markdowns.some(md => md.relativePath === relPath) && !selectedMarkdownPaths.includes(relPath)) {
475
+ selectedMarkdownPaths.push(relPath);
476
+ }
477
+ }
478
+ } catch (_) {}
479
+ }
480
+ }
481
+ const gitInfo = getGitRemoteInfo() || {};
482
+ let githubUsername = options.githubUser || gitInfo.username || "";
483
+ let githubRepoUrl = options.repoUrl || gitInfo.repoUrl || "";
484
+ let twitterUrl = options.twitter || "";
485
+ let linkedinUrl = options.linkedin || "";
486
+ let logoPath = options.logo || (scanResult.detectedLogos[0] || "");
487
+ let screenshotPath = options.screenshot || (scanResult.detectedScreenshots[0] || "");
488
+
231
489
  let addGuidelines = [];
232
490
  let customInstructions = "";
233
491
  let chosenModel = "gemini-3.5-flash";
@@ -237,9 +495,10 @@ async function main() {
237
495
  while (true) {
238
496
  const listChoices = [
239
497
  { name: "View scanned File Tree diagram", value: "view_tree" },
498
+ { name: "Configure project metadata (GitHub, Twitter, LinkedIn)", value: "project_metadata" },
240
499
  { name: "Select configuration manifest files to analyze", value: "select_manifests" },
241
500
  { name: "Select code snippet guides to inspect", value: "select_snippets" },
242
- { name: "Select reference markdown files to inspect", value: "select_markdowns" },
501
+ { name: "Select files to inspect", value: "select_files" },
243
502
  { name: "Select supplementary layout headings", value: "select_headings" },
244
503
  { name: "Enter custom text highlight instructions", value: "custom_notes" },
245
504
  { name: "GENERATE README DOCUMENT RIGHT NOW", value: "trigger_gen" },
@@ -270,6 +529,56 @@ async function main() {
270
529
  continue;
271
530
  }
272
531
 
532
+ if (activeChoice === "project_metadata") {
533
+ const metadataAnswers = await inquirer.prompt([
534
+ {
535
+ type: "input",
536
+ name: "username",
537
+ message: "Enter GitHub Username / Organisation:",
538
+ default: githubUsername
539
+ },
540
+ {
541
+ type: "input",
542
+ name: "repoUrl",
543
+ message: "Enter GitHub Repository URL:",
544
+ default: githubRepoUrl
545
+ },
546
+ {
547
+ type: "input",
548
+ name: "twitter",
549
+ message: "Enter Twitter Profile URL (optional):",
550
+ default: twitterUrl
551
+ },
552
+ {
553
+ type: "input",
554
+ name: "linkedin",
555
+ message: "Enter LinkedIn Profile URL (optional):",
556
+ default: linkedinUrl
557
+ },
558
+ {
559
+ type: "input",
560
+ name: "logo",
561
+ message: "Enter Project Logo Path (optional):",
562
+ default: logoPath
563
+ },
564
+ {
565
+ type: "input",
566
+ name: "screenshot",
567
+ message: "Enter Project Screenshot Path (optional):",
568
+ default: screenshotPath
569
+ }
570
+ ]);
571
+
572
+ githubUsername = metadataAnswers.username.trim();
573
+ githubRepoUrl = metadataAnswers.repoUrl.trim();
574
+ twitterUrl = metadataAnswers.twitter.trim();
575
+ linkedinUrl = metadataAnswers.linkedin.trim();
576
+ logoPath = metadataAnswers.logo.trim();
577
+ screenshotPath = metadataAnswers.screenshot.trim();
578
+ console.log("\x1b[32m✔ Project metadata updated.\x1b[0m\n");
579
+ continue;
580
+ }
581
+
273
582
  if (activeChoice === "select_manifests") {
274
583
  if (scanResult.manifests.length === 0) {
275
584
  console.log("\x1b[33mWarning: No manifest files (package.json, requirements.txt, setup.py, Cargo.toml etc) found to check.\x1b[0m\n");
@@ -308,22 +617,83 @@ async function main() {
308
617
  continue;
309
618
  }
310
619
 
311
- if (activeChoice === "select_markdowns") {
312
- if (scanResult.markdowns.length === 0) {
313
- console.log("\x1b[33mWarning: No reference markdown files (.md) found to check. Add some customized docs first!\x1b[0m\n");
314
- continue;
315
- }
316
- const markdownAsk = await inquirer.prompt([
620
+ if (activeChoice === "select_files") {
621
+ const subChoices = [
622
+ { name: "Check / Select files to inspect", value: "select" },
623
+ { name: "Add custom file or directory path...", value: "add" },
624
+ { name: "Go back to Main Menu", value: "back" }
625
+ ];
626
+ const subMenu = await inquirer.prompt([
317
627
  {
318
- type: "checkbox",
319
- name: "paths",
320
- message: "Check markdown documents to inject as key architectural sources:",
321
- choices: scanResult.markdowns.map(md => ({ name: md.relativePath, value: md.relativePath, checked: selectedMarkdownPaths.includes(md.relativePath) })),
628
+ type: "select",
629
+ name: "action",
630
+ message: "Select Files to Inspect Choose a management action:",
631
+ choices: subChoices,
322
632
  loop: false
323
633
  }
324
634
  ]);
325
- selectedMarkdownPaths = markdownAsk.paths;
326
- console.log(`\x1b[32m✔ Reference markdown files updated. Total: ${selectedMarkdownPaths.length}\x1b[0m\n`);
635
+
636
+ if (subMenu.action === "back") {
637
+ continue;
638
+ }
639
+
640
+ if (subMenu.action === "add") {
641
+ const addAsk = await inquirer.prompt([
642
+ {
643
+ type: "input",
644
+ name: "path",
645
+ message: "Enter the custom file or directory path to scan and inspect:"
646
+ }
647
+ ]);
648
+ const customPath = addAsk.path.trim();
649
+ if (customPath) {
650
+ processExplicitPath(customPath, activeCwd, scanResult);
651
+ try {
652
+ const absPath = path.resolve(activeCwd, customPath);
653
+ if (fs.existsSync(absPath)) {
654
+ if (fs.statSync(absPath).isFile()) {
655
+ const relPath = path.relative(activeCwd, absPath);
656
+ const ext = path.extname(relPath).toLowerCase();
657
+ if (MANIFEST_NAMES.has(path.basename(relPath))) {
658
+ if (!selectedManifestPaths.includes(relPath)) selectedManifestPaths.push(relPath);
659
+ } else if (ext === ".md") {
660
+ if (!selectedMarkdownPaths.includes(relPath)) selectedMarkdownPaths.push(relPath);
661
+ } else {
662
+ if (!selectedSnippetPaths.includes(relPath)) selectedSnippetPaths.push(relPath);
663
+ }
664
+ }
665
+ console.log(`\x1b[32m✔ Successfully scanned and added path: ${customPath}\x1b[0m\n`);
666
+ }
667
+ } catch (err) {
668
+ console.error(`\x1b[31m[Error] Failed to resolve path: ${err.message}\x1b[0m\n`);
669
+ }
670
+ }
671
+ }
672
+
673
+ if (subMenu.action === "select") {
674
+ const choices = scanResult.markdowns.map(md => ({
675
+ name: md.relativePath,
676
+ value: md.relativePath,
677
+ checked: selectedMarkdownPaths.includes(md.relativePath)
678
+ }));
679
+
680
+ if (choices.length === 0) {
681
+ console.log("\x1b[33mNo reference files currently loaded. Choose 'Add custom file or directory path...' to add one.\x1b[0m\n");
682
+ continue;
683
+ }
684
+
685
+ const selectAsk = await inquirer.prompt([
686
+ {
687
+ type: "checkbox",
688
+ name: "paths",
689
+ message: "Check files to inject as key architectural sources:",
690
+ choices,
691
+ loop: false
692
+ }
693
+ ]);
694
+ selectedMarkdownPaths = selectAsk.paths;
695
+ console.log(`\x1b[32m✔ Reference files updated. Total: ${selectedMarkdownPaths.length}\x1b[0m\n`);
696
+ }
327
697
  continue;
328
698
  }
329
699
 
@@ -402,12 +772,12 @@ The document MUST strictly follow this exact outline and formatting sequence:
402
772
 
403
773
  1. Top Anchors & Shields:
404
774
  - Add a top anchor: \`<a name="readme-top"></a>\` at the absolute beginning of the file.
405
- - Centered shields/badges using raw Markdown with stylish links: Contributors, Forks, Stargazers, Issues, License, LinkedIn. Specify reference URL identifiers at the absolute bottom of the file (e.g. \`[contributors-shield]: ...\`).
775
+ - Centered shields/badges using raw Markdown with stylish links: Contributors, Forks, Stargazers, Issues, License, and (if provided) LinkedIn and Twitter. Specify reference URL identifiers at the absolute bottom of the file (e.g. \`[contributors-shield]: ...\`).
406
776
  - Put badges cleanly on top.
407
777
 
408
778
  2. Project Logo & Headers (Centered):
409
779
  - Leave space for logo using \`<br />\` and then a centered div block containing:
410
- - An image tag targeting a generic logo placeholder (or repository logo) with dimensions 80x80. Use "https://images.unsplash.com/photo-1618401471353-b98aedd07871?q=80&w=120&auto=format&fit=crop" as a source placeholder if no logo is found.
780
+ - An image tag targeting the repository logo with dimensions 80x80. If a Logo Path is provided under Project Metadata, use it as the image src (e.g., \`assets/logo.png\`). If not provided, search the provided project structure (e.g., assets/, images/, or root) for any logo image file (like \`logo.png\`, \`logo.svg\`, \`logo.jpg\`, \`assets/logo.png\`). If found, use that file path as the src. If no logo file exists in the repository, use the unsplash placeholder URL: "https://images.unsplash.com/photo-1618401471353-b98aedd07871?q=80&w=120&auto=format&fit=crop".
411
781
  - A centered \`<h3 align="center">Project Title</h3>\`
412
782
  - A short, descriptive project subtitle.
413
783
  - Links to Explore the Docs, View Demo, Report Bug, Request Feature centering on appropriate URLs.
@@ -417,7 +787,7 @@ The document MUST strictly follow this exact outline and formatting sequence:
417
787
 
418
788
  4. About the Project:
419
789
  - Place a section title \`## About The Project\` with a paragraph detailing what issues the library solves and why.
420
- - Provide a placeholder screenshot element (\`[![Product Name Screen Shot][product-screenshot]](https://example.com)\`).
790
+ - Provide a screenshot element (\`[![Product Name Screen Shot][product-screenshot]](https://example.com)\`). If a Screenshot Path is provided under Project Metadata, ensure the \`[product-screenshot]\` reference at the bottom resolves to that file path (e.g., \`assets/screenshot.png\`). If not provided, search the project structure for any screenshot image file (like \`screenshot.png\`, \`screenshot.jpg\`, \`assets/screenshot.png\`). If found, ensure the \`[product-screenshot]\` reference at the bottom resolves to that file path (e.g., \`assets/screenshot.png\`). If no screenshot file is found, resolve the reference to the unsplash placeholder: "https://images.unsplash.com/photo-1618401471353-b98aedd07871?q=80&w=600&auto=format&fit=crop".
421
791
  - Add a \`### Built With\` subsection with raw shields list linking to core framework technologies identified in the manifests or languages (e.g. Next.js, React, Python, Go, Rust, etc., with shields like \`* [![React][React.js]][React-url]\`).
422
792
  - Add \`<p align="right">(<a href="#readme-top">back to top</a>)</p>\` at the end of this and ALL subsequent major sections.
423
793
 
@@ -449,6 +819,22 @@ The document MUST strictly follow this exact outline and formatting sequence:
449
819
 
450
820
  ${addGuidelines.length > 0 ? `Include these extra specific layout headings inside the layout: ${addGuidelines.map(sec => `- ${sec}`).join("\n")}` : ""}
451
821
 
822
+ Project Metadata for customization (use these when constructing URLs, shields, badges, and contact references):
823
+ - GitHub Username: ${githubUsername || "Not provided"}
824
+ - GitHub Repository URL: ${githubRepoUrl || "Not provided"}
825
+ - Twitter URL: ${twitterUrl || "Not provided"}
826
+ - LinkedIn URL: ${linkedinUrl || "Not provided"}
827
+ - Logo Path: ${logoPath || "Not provided"}
828
+ - Screenshot Path: ${screenshotPath || "Not provided"}
829
+
830
+ Instructions for metadata integration:
831
+ 1. Construct GitHub shields (Contributors, Forks, Stars, Issues, License) and their URL references using the provided GitHub Username and Repository name (extracted from the Repo URL).
832
+ 2. If a LinkedIn URL is provided, include a LinkedIn shield at the top (using badge image URL e.g. "https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge&logo=linkedin&colorB=555") and define its bottom link reference pointing to the LinkedIn URL. If not, omit the LinkedIn shield.
833
+ 3. If a Twitter URL is provided, include a Twitter/X shield at the top (using badge image URL e.g. "https://img.shields.io/badge/-Twitter-black.svg?style=for-the-badge&logo=x&colorB=555" or "https://img.shields.io/badge/-Twitter-black.svg?style=for-the-badge&logo=twitter&colorB=555") and define its bottom link reference pointing to the Twitter URL. If not, omit the Twitter shield.
834
+ 4. Under the Contact section, list the user's contact information using the provided Twitter and LinkedIn links.
835
+ 5. If a Logo Path is provided, use it exactly as the src of the project logo image.
836
+ 6. If a Screenshot Path is provided, ensure the bottom reference \`[product-screenshot]\` resolves to it.
837
+
452
838
  Do not write markdown block fences inside the generated readme itself unless wrapping code examples. Do not add any conversational meta-talk. Output the raw Best-README-Template markdown directly.`;
453
839
 
454
840
  const prompt = `Generate a README.md file based on the following codebase analysis:
@@ -462,6 +848,7 @@ ${snippetsBlock}
462
848
 
463
849
  ${markdownsBlock}
464
850
 
851
+ ${githubUsername || githubRepoUrl || twitterUrl || linkedinUrl || logoPath || screenshotPath ? `Project Metadata:\n- GitHub Username: ${githubUsername || "N/A"}\n- GitHub Repository: ${githubRepoUrl || "N/A"}\n- Twitter: ${twitterUrl || "N/A"}\n- LinkedIn: ${linkedinUrl || "N/A"}\n- Logo Path: ${logoPath || "N/A"}\n- Screenshot Path: ${screenshotPath || "N/A"}\n` : ""}
465
852
  ${customInstructions ? `Custom User directives:\n${customInstructions}\n` : ""}
466
853
 
467
854
  Generate the complete, polished Markdown output directly without any extra conversation.`;
@@ -597,6 +984,12 @@ async function runDirectScanAndGen() {
597
984
  console.log("Running zero-config non-interactive codebase scans...");
598
985
  const activeCwd = process.cwd();
599
986
 
987
+ const gitInfo = getGitRemoteInfo() || {};
988
+ const githubUsername = options.githubUser || gitInfo.username || "";
989
+ const githubRepoUrl = options.repoUrl || gitInfo.repoUrl || "";
990
+ const twitterUrl = options.twitter || "";
991
+ const linkedinUrl = options.linkedin || "";
992
+
600
993
  let treeBody = "";
601
994
  try {
602
995
  treeBody = buildTreeString(activeCwd);
@@ -608,16 +1001,28 @@ async function runDirectScanAndGen() {
608
1001
  const scanResult = {
609
1002
  manifests: [],
610
1003
  snippets: [],
611
- languages: new Set()
1004
+ markdowns: [],
1005
+ languages: new Set(),
1006
+ detectedLogos: [],
1007
+ detectedScreenshots: []
612
1008
  };
613
1009
 
614
1010
  try {
615
1011
  scanDirectoryFiles(activeCwd, "", scanResult);
1012
+ if (options.include) {
1013
+ const includes = getExplicitIncludes(options.include);
1014
+ for (const inc of includes) {
1015
+ processExplicitPath(inc, activeCwd, scanResult);
1016
+ }
1017
+ }
616
1018
  } catch (err) {
617
1019
  console.error(`\x1b[31mERROR: Detailed file scanning failed: ${err.message}\x1b[0m`);
618
1020
  process.exit(1);
619
1021
  }
620
1022
 
1023
+ const logoPath = options.logo || (scanResult.detectedLogos[0] || "");
1024
+ const screenshotPath = options.screenshot || (scanResult.detectedScreenshots[0] || "");
1025
+
621
1026
  const apiKey = options.apiKey || process.env.GEMINI_API_KEY;
622
1027
  if (!apiKey || !apiKey.trim()) {
623
1028
  console.error("\x1b[31mERROR: Gemini API key is missing. Run with --api-key=KEY or set the GEMINI_API_KEY environment variable.\x1b[0m");
@@ -634,25 +1039,132 @@ async function runDirectScanAndGen() {
634
1039
  }
635
1040
  });
636
1041
 
1042
+ const baseSelectedSnippets = getAutoSelectedSnippets(scanResult.snippets);
1043
+ const selectedSnippetPaths = baseSelectedSnippets.slice(0, 15);
1044
+
1045
+ if (options.include) {
1046
+ const includes = getExplicitIncludes(options.include);
1047
+ for (const inc of includes) {
1048
+ try {
1049
+ const absPath = path.resolve(activeCwd, inc);
1050
+ if (fs.existsSync(absPath) && fs.statSync(absPath).isFile()) {
1051
+ const relPath = path.relative(activeCwd, absPath);
1052
+ if (scanResult.snippets.some(s => s.relativePath === relPath) && !selectedSnippetPaths.includes(relPath)) {
1053
+ selectedSnippetPaths.push(relPath);
1054
+ }
1055
+ }
1056
+ } catch (_) {}
1057
+ }
1058
+ }
1059
+
1060
+ const filteredSnippets = scanResult.snippets.filter(s => selectedSnippetPaths.includes(s.relativePath));
1061
+
637
1062
  let manifestsBlock = "";
638
1063
  scanResult.manifests.forEach(m => {
639
- manifestsBlock += `\n--- file: ${m.relativePath} ---\n\`\`\`\n${m.content}\n\`\`\`\n`;
1064
+ manifestsBlock += `\n--- Manifest File: ${m.relativePath} ---\n\`\`\`\n${m.content}\n\`\`\`\n`;
640
1065
  });
641
1066
 
642
- const prompt = `Generate a README.md file based on the following codebase layout tree:
1067
+ let snippetsBlock = "";
1068
+ filteredSnippets.forEach(s => {
1069
+ snippetsBlock += `\n--- Code Snippet: ${s.relativePath} ---\n\`\`\`\n${s.content}\n\`\`\`\n`;
1070
+ });
1071
+
1072
+ let markdownsBlock = "";
1073
+ scanResult.markdowns.forEach(md => {
1074
+ markdownsBlock += `\n--- Reference Markdown File: ${md.relativePath} ---\n\`\`\`markdown\n${md.content}\n\`\`\`\n`;
1075
+ });
1076
+
1077
+ const systemInstruction = `Role: You are an expert technical writer and principal software architect.
1078
+ Task: Your job is to generate a comprehensive, highly polished, professional README.md file based only on the provided directory structure, project configuration files, and references, formatted EXACTLY using the Best-README-Template by @othneildrew.
1079
+
1080
+ Visual Layout / Structure Requirements (Derived from othneildrew/Best-README-Template):
1081
+ The document MUST strictly follow this exact outline and formatting sequence:
1082
+
1083
+ 1. Top Anchors & Shields:
1084
+ - Add a top anchor: \`<a name="readme-top"></a>\` at the absolute beginning of the file.
1085
+ - Centered shields/badges using raw Markdown with stylish links: Contributors, Forks, Stargazers, Issues, License, and (if provided) LinkedIn and Twitter. Specify reference URL identifiers at the absolute bottom of the file (e.g. \`[contributors-shield]: ...\`).
1086
+ - Put badges cleanly on top.
1087
+
1088
+ 2. Project Logo & Headers (Centered):
1089
+ - Leave space for logo using \`<br />\` and then a centered div block containing:
1090
+ - An image tag targeting the repository logo with dimensions 80x80. If a Logo Path is provided under Project Metadata, use it as the image src (e.g., \`assets/logo.png\`). If not provided, search the provided project structure (e.g., assets/, images/, or root) for any logo image file (like \`logo.png\`, \`logo.svg\`, \`logo.jpg\`, \`assets/logo.png\`). If found, use that file path as the src. If no logo file exists in the repository, use the unsplash placeholder URL: "https://images.unsplash.com/photo-1618401471353-b98aedd07871?q=80&w=120&auto=format&fit=crop".
1091
+ - A centered \`<h3 align="center">Project Title</h3>\`
1092
+ - A short, descriptive project subtitle.
1093
+ - Links to Explore the Docs, View Demo, Report Bug, Request Feature centering on appropriate URLs.
1094
+
1095
+ 3. Interactive Detail-TOC (Table of Contents):
1096
+ - Add a table of contents enclosed in a Collapsible Details panel (\`<details><summary>Table of Contents</summary>...\` using list elements with anchors pointing to respective sections: About The Project, Getting Started (Prerequisites, Installation), Usage, Roadmap, Contributing, License, Contact, Acknowledgments).
1097
+
1098
+ 4. About the Project:
1099
+ - Place a section title \`## About The Project\` with a paragraph detailing what issues the library solves and why.
1100
+ - Provide a screenshot element (\`[![Product Name Screen Shot][product-screenshot]](https://example.com)\`). If a Screenshot Path is provided under Project Metadata, ensure the \`[product-screenshot]\` reference at the bottom resolves to that file path (e.g., \`assets/screenshot.png\`). If not provided, search the project structure for any screenshot image file (like \`screenshot.png\`, \`screenshot.jpg\`, \`assets/screenshot.png\`). If found, ensure the \`[product-screenshot]\` reference at the bottom resolves to that file path (e.g., \`assets/screenshot.png\`). If no screenshot file is found, resolve the reference to the unsplash placeholder: "https://images.unsplash.com/photo-1618401471353-b98aedd07871?q=80&w=600&auto=format&fit=crop".
1101
+ - Add a \`### Built With\` subsection with raw shields list linking to core framework technologies identified in the manifests or languages (e.g. Next.js, React, Python, Go, Rust, etc., with shields like \`* [![React][React.js]][React-url]\`).
1102
+ - Add \`<p align="right">(<a href="#readme-top">back to top</a>)</p>\` at the end of this and ALL subsequent major sections.
1103
+
1104
+ 5. Getting Started:
1105
+ - Place \`## Getting Started\` heading.
1106
+ - Include \`### Prerequisites\` listing key runtime versions or engines with raw commands (e.g., npm or pip).
1107
+ - Include \`### Installation\` with custom sequential steps: Clone repository, Install dependencies/packages using correct package manager commands, Setup key constants/configs.
1108
+
1109
+ 6. Usage:
1110
+ - Place \`## Usage\` heading with direct code instructions, visual scripts invocation, and explanation.
1111
+
1112
+ 7. Roadmap:
1113
+ - Place \`## Roadmap\` heading highlighting future planning milestones or upcoming revisions. Use standard markdown task lists (e.g., \`- [ ] Feature 1\`).
1114
+
1115
+ 8. Contributing:
1116
+ - Place \`## Contributing\` heading detailing the exact five-step guidelines for forks, branching, commits, and pull request initiation.
1117
+
1118
+ 9. License:
1119
+ - Place \`## License\` heading highlighting the standard licensing info (e.g. MIT License).
1120
+
1121
+ 10. Contact:
1122
+ - Place \`## Contact\` heading listing author/maintainer contact points, project links, or email tags.
1123
+
1124
+ 11. Acknowledgments:
1125
+ - Place \`## Acknowledgments\` heading listing standard resources (e.g., Shields.io, select libraries, or other credits).
1126
+
1127
+ 12. Bottom Link References:
1128
+ - At the absolute bottom of the document, define ALL referenced links and shield assets used at the top and Built With section dynamically to keep the rest of the text bodies pristine (e.g., \`[contributors-shield]: ...\`).
1129
+
1130
+ Project Metadata for customization (use these when constructing URLs, shields, badges, and contact references):
1131
+ - GitHub Username: ${githubUsername || "Not provided"}
1132
+ - GitHub Repository URL: ${githubRepoUrl || "Not provided"}
1133
+ - Twitter URL: ${twitterUrl || "Not provided"}
1134
+ - LinkedIn URL: ${linkedinUrl || "Not provided"}
1135
+ - Logo Path: ${logoPath || "Not provided"}
1136
+ - Screenshot Path: ${screenshotPath || "Not provided"}
1137
+
1138
+ Instructions for metadata integration:
1139
+ 1. Construct GitHub shields (Contributors, Forks, Stars, Issues, License) and their URL references using the provided GitHub Username and Repository name (extracted from the Repo URL).
1140
+ 2. If a LinkedIn URL is provided, include a LinkedIn shield at the top (using badge image URL e.g. "https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge&logo=linkedin&colorB=555") and define its bottom link reference pointing to the LinkedIn URL. If not, omit the LinkedIn shield.
1141
+ 3. If a Twitter URL is provided, include a Twitter/X shield at the top (using badge image URL e.g. "https://img.shields.io/badge/-Twitter-black.svg?style=for-the-badge&logo=x&colorB=555" or "https://img.shields.io/badge/-Twitter-black.svg?style=for-the-badge&logo=twitter&colorB=555") and define its bottom link reference pointing to the Twitter URL. If not, omit the Twitter shield.
1142
+ 4. Under the Contact section, list the user's contact information using the provided Twitter and LinkedIn links.
1143
+ 5. If a Logo Path is provided, use it exactly as the src of the project logo image.
1144
+ 6. If a Screenshot Path is provided, ensure the bottom reference \`[product-screenshot]\` resolves to it.
1145
+
1146
+ Do not write markdown block fences inside the generated readme itself unless wrapping code examples. Do not add any conversational meta-talk. Output the raw Best-README-Template markdown directly.`;
1147
+
1148
+ const prompt = `Generate a README.md file based on the following codebase analysis:
643
1149
 
644
1150
  Project Structure:
645
1151
  ${treeBody}
646
1152
 
647
1153
  ${manifestsBlock}
648
1154
 
1155
+ ${snippetsBlock}
1156
+
1157
+ ${markdownsBlock}
1158
+
1159
+ ${githubUsername || githubRepoUrl || twitterUrl || linkedinUrl || logoPath || screenshotPath ? `Project Metadata:\n- GitHub Username: ${githubUsername || "N/A"}\n- GitHub Repository: ${githubRepoUrl || "N/A"}\n- Twitter: ${twitterUrl || "N/A"}\n- LinkedIn: ${linkedinUrl || "N/A"}\n- Logo Path: ${logoPath || "N/A"}\n- Screenshot Path: ${screenshotPath || "N/A"}\n` : ""}
1160
+
649
1161
  Generate the complete, polished Markdown output directly without any extra conversation.`;
650
1162
 
651
1163
  const response = await ai.models.generateContent({
652
1164
  model: "gemini-3.5-flash",
653
1165
  contents: prompt,
654
1166
  config: {
655
- systemInstruction: "You are an expert technical writer. Write a comprehensive, polished production-ready README.md file directly.",
1167
+ systemInstruction,
656
1168
  temperature: 0.2
657
1169
  }
658
1170
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "readmeg",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Zero-config terminal tool powered by Gemini that automatically generates comprehensive, production-grade README files for local repositories.",
5
5
  "type": "module",
6
6
  "bin": {