threadlines 0.1.0 → 0.1.2

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
@@ -25,7 +25,61 @@ threadlines check
25
25
  - `THREADLINE_API_URL` - Server URL (default: http://localhost:3000)
26
26
  - `OPENAI_API_KEY` - Your OpenAI API key (required)
27
27
 
28
- ## Expert Files
28
+ ## Threadline Files
29
29
 
30
- Create a `/threadlines` folder in your repository with markdown files. See [Threadline Format](../../docs/EXPERT_FORMAT.md) for details.
30
+ Create a `/threadlines` folder in your repository. Each markdown file is a threadline defining a code quality standard.
31
+
32
+ ### Format
33
+
34
+ Each threadline file must have YAML frontmatter and a markdown body:
35
+
36
+ ```markdown
37
+ ---
38
+ id: unique-id
39
+ version: 1.0.0
40
+ patterns:
41
+ - "**/api/**"
42
+ - "**/*.ts"
43
+ context_files:
44
+ - "path/to/context-file.ts"
45
+ ---
46
+
47
+ # Your Threadline Title
48
+
49
+ Your guidelines and standards here...
50
+ ```
51
+
52
+ ### Required Fields
53
+
54
+ - **`id`**: Unique identifier (e.g., `sql-queries`, `error-handling`)
55
+ - **`version`**: Semantic version (e.g., `1.0.0`)
56
+ - **`patterns`**: Array of glob patterns matching files to check (e.g., `["**/api/**", "**/*.ts"]`)
57
+ - **Body**: Markdown content describing your standards
58
+
59
+ ### Optional Fields
60
+
61
+ - **`context_files`**: Array of file paths that provide context (always included, even if unchanged)
62
+
63
+ ### Example: SQL Queries with Schema Context
64
+
65
+ ```markdown
66
+ ---
67
+ id: sql-queries
68
+ version: 1.0.0
69
+ patterns:
70
+ - "**/queries/**"
71
+ - "**/*.sql"
72
+ context_files:
73
+ - "schema.sql"
74
+ ---
75
+
76
+ # SQL Query Standards
77
+
78
+ All SQL queries must:
79
+ - Reference tables and columns that exist in schema.sql
80
+ - Use parameterized queries (no string concatenation)
81
+ - Include proper indexes for WHERE clauses
82
+ ```
83
+
84
+ The `schema.sql` file will always be included as context, even if you're only changing query files.
31
85
 
@@ -52,7 +52,8 @@ async function checkCommand(options) {
52
52
  const threadlines = await (0, experts_1.findThreadlines)(repoRoot);
53
53
  console.log(chalk_1.default.green(`✓ Found ${threadlines.length} threadline(s)\n`));
54
54
  if (threadlines.length === 0) {
55
- console.log(chalk_1.default.yellow('⚠️ No valid threadlines found. Add threadline files to /threadlines folder.'));
55
+ console.log(chalk_1.default.yellow('⚠️ No valid threadlines found.'));
56
+ console.log(chalk_1.default.gray(' Run `npx threadlines init` to create your first threadline.'));
56
57
  process.exit(0);
57
58
  }
58
59
  // 2. Get git diff
@@ -0,0 +1,103 @@
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.initCommand = initCommand;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const chalk_1 = __importDefault(require("chalk"));
43
+ const TEMPLATE = `---
44
+ id: example-threadline
45
+ version: 1.0.0
46
+ patterns:
47
+ - "**/*.ts"
48
+ - "**/*.tsx"
49
+ context_files: []
50
+ ---
51
+
52
+ # Example Threadline
53
+
54
+ Describe your coding standard or convention here.
55
+
56
+ This threadline will check all TypeScript files (\`**/*.ts\` and \`**/*.tsx\`) against the guidelines you define below.
57
+
58
+ ## Guidelines
59
+
60
+ - Add your first guideline here
61
+ - Add your second guideline here
62
+ - Add examples or patterns to follow
63
+
64
+ ## Examples
65
+
66
+ \`\`\`typescript
67
+ // Good example
68
+ \`\`\`
69
+
70
+ \`\`\`typescript
71
+ // Bad example - avoid this
72
+ \`\`\`
73
+ `;
74
+ async function initCommand() {
75
+ const repoRoot = process.cwd();
76
+ const threadlinesDir = path.join(repoRoot, 'threadlines');
77
+ const exampleFile = path.join(threadlinesDir, 'example.md');
78
+ try {
79
+ // Create threadlines directory if it doesn't exist
80
+ if (!fs.existsSync(threadlinesDir)) {
81
+ fs.mkdirSync(threadlinesDir, { recursive: true });
82
+ console.log(chalk_1.default.green(`✓ Created /threadlines directory`));
83
+ }
84
+ // Check if example file already exists
85
+ if (fs.existsSync(exampleFile)) {
86
+ console.log(chalk_1.default.yellow(`⚠️ ${exampleFile} already exists`));
87
+ console.log(chalk_1.default.gray(' Edit it to create your threadline, or delete it and run init again.'));
88
+ return;
89
+ }
90
+ // Write template file
91
+ fs.writeFileSync(exampleFile, TEMPLATE, 'utf-8');
92
+ console.log(chalk_1.default.green(`✓ Created ${exampleFile}`));
93
+ console.log('');
94
+ console.log(chalk_1.default.blue('Next steps:'));
95
+ console.log(chalk_1.default.gray(' 1. Edit threadlines/example.md with your coding standards'));
96
+ console.log(chalk_1.default.gray(' 2. Rename it to something descriptive (e.g., error-handling.md)'));
97
+ console.log(chalk_1.default.gray(' 3. Run: npx threadlines check'));
98
+ }
99
+ catch (error) {
100
+ console.error(chalk_1.default.red(`\n❌ Error: ${error.message}`));
101
+ process.exit(1);
102
+ }
103
+ }
package/dist/index.js CHANGED
@@ -3,14 +3,19 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const commander_1 = require("commander");
5
5
  const check_1 = require("./commands/check");
6
+ const init_1 = require("./commands/init");
6
7
  const program = new commander_1.Command();
7
8
  program
8
- .name('threadline')
9
+ .name('threadlines')
9
10
  .description('AI-powered linter based on your natural language documentation')
10
11
  .version('0.1.0');
12
+ program
13
+ .command('init')
14
+ .description('Create a template threadline file to get started')
15
+ .action(init_1.initCommand);
11
16
  program
12
17
  .command('check')
13
- .description('Check code against your experts')
18
+ .description('Check code against your threadlines')
14
19
  .option('--api-url <url>', 'Threadline server URL', process.env.THREADLINE_API_URL || 'http://localhost:3000')
15
20
  .option('--api-key <key>', 'OpenAI API key', process.env.OPENAI_API_KEY)
16
21
  .action(check_1.checkCommand);
@@ -42,12 +42,12 @@ const REQUIRED_FIELDS = ['id', 'version', 'patterns'];
42
42
  async function findThreadlines(repoRoot) {
43
43
  const expertsDir = path.join(repoRoot, 'threadlines');
44
44
  if (!fs.existsSync(expertsDir)) {
45
- throw new Error('No /threadlines folder found. Create a /threadlines folder with your threadline markdown files.');
45
+ throw new Error('No /threadlines folder found. Run `npx threadlines init` to create your first threadline.');
46
46
  }
47
47
  const files = fs.readdirSync(expertsDir);
48
48
  const expertFiles = files.filter(f => f.endsWith('.md'));
49
49
  if (expertFiles.length === 0) {
50
- throw new Error('No threadline files found in /threadlines folder. Add .md files with threadline definitions.');
50
+ throw new Error('No threadline files found in /threadlines folder. Run `npx threadlines init` to create a template.');
51
51
  }
52
52
  const threadlines = [];
53
53
  for (const file of expertFiles) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "threadlines",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Threadline CLI - AI-powered linter based on your natural language documentation",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -45,4 +45,3 @@
45
45
  "typescript": "^5.7.2"
46
46
  }
47
47
  }
48
-