threadlines 0.1.4 → 0.1.5

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
@@ -14,14 +14,72 @@ Or use with npx:
14
14
  npx threadlines check
15
15
  ```
16
16
 
17
+ ## Quick Start
18
+
19
+ ### 1. Initialize Your First Threadline
20
+
21
+ ```bash
22
+ npx threadlines init
23
+ ```
24
+
25
+ This command:
26
+ - Creates a `/threadlines` directory in your project root
27
+ - Generates `threadlines/example.md` with a template threadline
28
+ - Provides instructions for setting up your API key
29
+
30
+ ### 2. Configure API Key
31
+
32
+ Create a `.env.local` file in your project root:
33
+
34
+ ```bash
35
+ THREADLINE_API_KEY=your-api-key-here
36
+ ```
37
+
38
+ **Important:** Make sure `.env.local` is in your `.gitignore` file!
39
+
40
+ For CI/CD environments, set `THREADLINE_API_KEY` as an environment variable in your platform settings.
41
+
42
+ ### 3. Edit Your Threadline
43
+
44
+ Edit `threadlines/example.md` with your coding standards, then rename it to something descriptive (e.g., `error-handling.md`).
45
+
46
+ ### 4. Run Checks
47
+
48
+ ```bash
49
+ npx threadlines check
50
+ ```
51
+
17
52
  ## Usage
18
53
 
54
+ ### Initialize Threadline Template
55
+
56
+ ```bash
57
+ threadlines init
58
+ ```
59
+
60
+ Creates a template threadline file to get you started. The command will:
61
+ - Create the `/threadlines` directory if it doesn't exist
62
+ - Generate `threadlines/example.md` with boilerplate content
63
+ - Display instructions for API key configuration
64
+
65
+ ### Check Code Against Threadlines
66
+
19
67
  ```bash
20
68
  threadlines check
21
69
  ```
22
70
 
71
+ Analyzes your git changes against all threadlines in the `/threadlines` directory.
72
+
73
+ **Options:**
74
+ - `--api-url <url>` - Override the server URL (default: http://localhost:3000)
75
+
23
76
  ## Configuration
24
- BANANA
77
+
78
+ ### Environment Variables
79
+
80
+ - `THREADLINE_API_KEY` - **Required.** Your Threadline API key for authentication
81
+ - Can be set in `.env.local` file (recommended for local development)
82
+ - Or as an environment variable (required for CI/CD)
25
83
  - `THREADLINE_API_URL` - Server URL (default: http://localhost:3000)
26
84
  - Can also be set with `--api-url` flag: `npx threadlines check --api-url http://your-server.com`
27
85
 
@@ -40,12 +40,26 @@ exports.checkCommand = checkCommand;
40
40
  const experts_1 = require("../validators/experts");
41
41
  const diff_1 = require("../git/diff");
42
42
  const client_1 = require("../api/client");
43
+ const config_1 = require("../utils/config");
43
44
  const fs = __importStar(require("fs"));
44
45
  const path = __importStar(require("path"));
45
46
  const chalk_1 = __importDefault(require("chalk"));
46
47
  async function checkCommand(options) {
47
48
  const repoRoot = process.cwd();
48
49
  console.log(chalk_1.default.blue('🔍 Threadline: Checking code against your threadlines...\n'));
50
+ // Get and validate API key
51
+ const apiKey = (0, config_1.getThreadlineApiKey)();
52
+ if (!apiKey) {
53
+ console.error(chalk_1.default.red('❌ Error: THREADLINE_API_KEY is required'));
54
+ console.log('');
55
+ console.log(chalk_1.default.yellow('To fix this:'));
56
+ console.log(chalk_1.default.white(' 1. Create a .env.local file in your project root'));
57
+ console.log(chalk_1.default.gray(' 2. Add: THREADLINE_API_KEY=your-api-key-here'));
58
+ console.log(chalk_1.default.gray(' 3. Make sure .env.local is in your .gitignore'));
59
+ console.log('');
60
+ console.log(chalk_1.default.gray('For CI/CD: Set THREADLINE_API_KEY as an environment variable in your platform settings.'));
61
+ process.exit(1);
62
+ }
49
63
  try {
50
64
  // 1. Find and validate threadlines
51
65
  console.log(chalk_1.default.gray('📋 Finding threadlines...'));
@@ -92,7 +106,8 @@ async function checkCommand(options) {
92
106
  const response = await client.review({
93
107
  threadlines: threadlinesWithContext,
94
108
  diff: gitDiff.diff,
95
- files: gitDiff.changedFiles
109
+ files: gitDiff.changedFiles,
110
+ apiKey
96
111
  });
97
112
  // 6. Display results
98
113
  displayResults(response);
@@ -94,6 +94,15 @@ async function initCommand() {
94
94
  console.log(chalk_1.default.blue('Next steps:'));
95
95
  console.log(chalk_1.default.gray(' 1. Edit threadlines/example.md with your coding standards'));
96
96
  console.log(chalk_1.default.gray(' 2. Rename it to something descriptive (e.g., error-handling.md)'));
97
+ console.log('');
98
+ console.log(chalk_1.default.yellow('⚠️ IMPORTANT: API Key Setup Required'));
99
+ console.log(chalk_1.default.white(' To use threadlines check, you need a THREADLINE_API_KEY.'));
100
+ console.log('');
101
+ console.log(chalk_1.default.white(' Create a .env.local file in your project root with:'));
102
+ console.log(chalk_1.default.gray(' THREADLINE_API_KEY=your-api-key-here'));
103
+ console.log('');
104
+ console.log(chalk_1.default.white(' Make sure .env.local is in your .gitignore file!'));
105
+ console.log('');
97
106
  console.log(chalk_1.default.gray(' 3. Run: npx threadlines check'));
98
107
  }
99
108
  catch (error) {
package/dist/index.js CHANGED
@@ -1,6 +1,51 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ var __importDefault = (this && this.__importDefault) || function (mod) {
37
+ return (mod && mod.__esModule) ? mod : { "default": mod };
38
+ };
3
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
+ // Load .env.local from project root before anything else
41
+ const dotenv_1 = __importDefault(require("dotenv"));
42
+ const path = __importStar(require("path"));
43
+ const fs = __importStar(require("fs"));
44
+ const projectRoot = process.cwd();
45
+ const envLocalPath = path.join(projectRoot, '.env.local');
46
+ if (fs.existsSync(envLocalPath)) {
47
+ dotenv_1.default.config({ path: envLocalPath });
48
+ }
4
49
  const commander_1 = require("commander");
5
50
  const check_1 = require("./commands/check");
6
51
  const init_1 = require("./commands/init");
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.getThreadlineApiKey = getThreadlineApiKey;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const dotenv_1 = __importDefault(require("dotenv"));
43
+ /**
44
+ * Loads environment variables from .env.local file in the project root
45
+ * (where the user runs the command, not the CLI package directory)
46
+ */
47
+ function loadEnvLocal() {
48
+ const projectRoot = process.cwd();
49
+ const envLocalPath = path.join(projectRoot, '.env.local');
50
+ if (fs.existsSync(envLocalPath)) {
51
+ dotenv_1.default.config({ path: envLocalPath });
52
+ }
53
+ }
54
+ /**
55
+ * Gets THREADLINE_API_KEY from environment.
56
+ * Priority: process.env.THREADLINE_API_KEY → .env.local file
57
+ */
58
+ function getThreadlineApiKey() {
59
+ // Load .env.local if it exists (doesn't override existing env vars)
60
+ loadEnvLocal();
61
+ // Check environment variable (from shell or CI/CD)
62
+ return process.env.THREADLINE_API_KEY;
63
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "threadlines",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Threadline CLI - AI-powered linter based on your natural language documentation",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -23,7 +23,7 @@
23
23
  "license": "MIT",
24
24
  "repository": {
25
25
  "type": "git",
26
- "url": "https://github.com/ngrootscholten/threadline.git",
26
+ "url": "git+https://github.com/ngrootscholten/threadline.git",
27
27
  "directory": "packages/cli"
28
28
  },
29
29
  "scripts": {
@@ -34,6 +34,7 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "commander": "^12.1.0",
37
+ "dotenv": "^16.4.7",
37
38
  "simple-git": "^3.27.0",
38
39
  "axios": "^1.7.9",
39
40
  "chalk": "^4.1.2",