explainthisrepo 0.5.1 → 0.6.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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ExplainThisRepo
2
2
 
3
- ExplainThisRepo is a CLI that generates plain-English explanations of public GitHub repositories and local directories by analyzing project structure, README content, and high signal files.
3
+ ExplainThisRepo is a CLI that generates plain-English explanations of any codebase (GitHub repositories and local directories) by analyzing project structure, README content, and high signal files.
4
4
 
5
5
  It helps developers quickly understand unfamiliar codebases by deriving architectural explanations from real project structure and code signals, producing a clear, structured `EXPLAIN.md`.
6
6
 
package/dist/cli.js CHANGED
@@ -7,6 +7,7 @@ import path from "node:path";
7
7
  import { fileURLToPath } from "node:url";
8
8
  import { Command } from "commander";
9
9
  import ora from "ora";
10
+ import { runInit } from "./init.js";
10
11
  import { fetchRepo, fetchReadme } from "./github.js";
11
12
  import { buildPrompt, buildQuickPrompt, buildSimplePrompt } from "./prompt.js";
12
13
  import { generateExplanation } from "./generate.js";
@@ -133,9 +134,9 @@ async function main() {
133
134
  const program = new Command();
134
135
  program
135
136
  .name("explainthisrepo")
136
- .description("Explain GitHub repositories in plain English")
137
+ .description("CLI that generates plain English explanations of any codebase")
137
138
  .version(getPkgVersion(), "-v, --version", "Show version")
138
- .argument("[repository]", "GitHub repository (owner/repo or URL) or local path")
139
+ .argument("[repository]", "GitHub repository (owner/repo or URL) or local directories")
139
140
  .option("--doctor", "Run diagnostics")
140
141
  .option("--quick", "Quick summary mode")
141
142
  .option("--simple", "Simple summary mode")
@@ -155,7 +156,16 @@ Examples:
155
156
  $ explainthisrepo ./path/to/directory
156
157
  $ explainthisrepo . --stack
157
158
  $ explainthisrepo --doctor`);
159
+ program
160
+ .command("init")
161
+ .description("Initialize configuration with Gemini API key")
162
+ .action(async () => {
163
+ await runInit();
164
+ });
158
165
  program.parse(process.argv);
166
+ if (process.argv[2] === "init") {
167
+ return;
168
+ }
159
169
  const options = program.opts();
160
170
  const repository = program.args[0];
161
171
  if (options.doctor) {
@@ -173,7 +183,7 @@ Examples:
173
183
  process.exit(1);
174
184
  }
175
185
  if (!repository) {
176
- program.error("repository argument required");
186
+ program.error("repository argument required (or use `init` to set up API key)");
177
187
  }
178
188
  const local = fs.existsSync(repository);
179
189
  let owner = "";
@@ -0,0 +1,4 @@
1
+ export declare function getConfigPath(): string;
2
+ export declare function ensureConfigDir(): string;
3
+ export declare function writeConfig(contents: string): void;
4
+ export declare function readConfig(): string | null;
package/dist/config.js ADDED
@@ -0,0 +1,33 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ const CONFIG_DIR_NAME = "ExplainThisRepo";
5
+ const CONFIG_FILE_NAME = "config.toml";
6
+ export function getConfigPath() {
7
+ if (process.platform === "win32") {
8
+ const appdata = process.env.APPDATA;
9
+ if (!appdata) {
10
+ throw new Error("APPDATA environment variable is not set");
11
+ }
12
+ return path.join(appdata, CONFIG_DIR_NAME, CONFIG_FILE_NAME);
13
+ }
14
+ const xdg = process.env.XDG_CONFIG_HOME;
15
+ const base = xdg ?? path.join(os.homedir(), ".config");
16
+ return path.join(base, "explainthisrepo", CONFIG_FILE_NAME);
17
+ }
18
+ export function ensureConfigDir() {
19
+ const configPath = getConfigPath();
20
+ const dir = path.dirname(configPath);
21
+ fs.mkdirSync(dir, { recursive: true });
22
+ return configPath;
23
+ }
24
+ export function writeConfig(contents) {
25
+ const path = ensureConfigDir();
26
+ fs.writeFileSync(path, contents, { encoding: "utf-8" });
27
+ }
28
+ export function readConfig() {
29
+ const path = getConfigPath();
30
+ if (!fs.existsSync(path))
31
+ return null;
32
+ return fs.readFileSync(path, "utf-8");
33
+ }
package/dist/init.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function runInit(): Promise<void>;
package/dist/init.js ADDED
@@ -0,0 +1,45 @@
1
+ import readline from "node:readline";
2
+ import process from "node:process";
3
+ import chalk from "chalk";
4
+ import { writeConfig } from "./config.js";
5
+ const CONFIG_TEMPLATE = `[llm]
6
+ provider = "gemini"
7
+ api_key = "{api_key}"
8
+ `;
9
+ export async function runInit() {
10
+ const err = process.stderr;
11
+ err.write(chalk.yellow("WARNING: input is hidden. Paste your GEMINI_API_KEY and press Enter.\n\n"));
12
+ try {
13
+ const apiKey = (await promptHidden("Gemini API key: ")).trim();
14
+ if (!apiKey) {
15
+ err.write(chalk.red("error: API key cannot be empty\n"));
16
+ process.exit(1);
17
+ }
18
+ writeConfig(CONFIG_TEMPLATE.replace("{api_key}", apiKey));
19
+ err.write("\r");
20
+ err.write("\x1b[2K");
21
+ err.write(chalk.green("Configuration written.\n"));
22
+ process.exit(0);
23
+ }
24
+ catch {
25
+ err.write(chalk.red("\nInterrupted.\n"));
26
+ process.exit(130);
27
+ }
28
+ }
29
+ function promptHidden(label) {
30
+ const err = process.stderr;
31
+ return new Promise((resolve) => {
32
+ err.write(label);
33
+ const rl = readline.createInterface({
34
+ input: process.stdin,
35
+ output: undefined,
36
+ terminal: true,
37
+ });
38
+ rl._writeToOutput = () => { };
39
+ rl.question("", (answer) => {
40
+ rl.close();
41
+ err.write("\n");
42
+ resolve(answer);
43
+ });
44
+ });
45
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "explainthisrepo",
3
- "version": "0.5.1",
4
- "description": "A CLI developer tool to explain any GitHub repository in plain English",
3
+ "version": "0.6.1",
4
+ "description": "CLI that generates plain English explanations of any codebase",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "author": "Caleb Wodi <calebwodi33@gmail.com>",