cohere-db 1.0.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 +383 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +104 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/generate.d.ts +21 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +131 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/handoff.d.ts +16 -0
- package/dist/commands/handoff.d.ts.map +1 -0
- package/dist/commands/handoff.js +334 -0
- package/dist/commands/handoff.js.map +1 -0
- package/dist/commands/init.d.ts +11 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +28 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/show.d.ts +10 -0
- package/dist/commands/show.d.ts.map +1 -0
- package/dist/commands/show.js +123 -0
- package/dist/commands/show.js.map +1 -0
- package/dist/commands/validate.d.ts +10 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +167 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/commands/watch.d.ts +10 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +74 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/extractors/drizzle.d.ts +63 -0
- package/dist/extractors/drizzle.d.ts.map +1 -0
- package/dist/extractors/drizzle.js +251 -0
- package/dist/extractors/drizzle.js.map +1 -0
- package/dist/extractors/firebase.d.ts +40 -0
- package/dist/extractors/firebase.d.ts.map +1 -0
- package/dist/extractors/firebase.js +192 -0
- package/dist/extractors/firebase.js.map +1 -0
- package/dist/extractors/index.d.ts +68 -0
- package/dist/extractors/index.d.ts.map +1 -0
- package/dist/extractors/index.js +346 -0
- package/dist/extractors/index.js.map +1 -0
- package/dist/extractors/mongodb.d.ts +45 -0
- package/dist/extractors/mongodb.d.ts.map +1 -0
- package/dist/extractors/mongodb.js +201 -0
- package/dist/extractors/mongodb.js.map +1 -0
- package/dist/extractors/mysql.d.ts +62 -0
- package/dist/extractors/mysql.d.ts.map +1 -0
- package/dist/extractors/mysql.js +173 -0
- package/dist/extractors/mysql.js.map +1 -0
- package/dist/extractors/postgres.d.ts +48 -0
- package/dist/extractors/postgres.d.ts.map +1 -0
- package/dist/extractors/postgres.js +141 -0
- package/dist/extractors/postgres.js.map +1 -0
- package/dist/extractors/prisma.d.ts +72 -0
- package/dist/extractors/prisma.d.ts.map +1 -0
- package/dist/extractors/prisma.js +262 -0
- package/dist/extractors/prisma.js.map +1 -0
- package/dist/extractors/sqlite.d.ts +51 -0
- package/dist/extractors/sqlite.d.ts.map +1 -0
- package/dist/extractors/sqlite.js +150 -0
- package/dist/extractors/sqlite.js.map +1 -0
- package/dist/generators/templates.d.ts +104 -0
- package/dist/generators/templates.d.ts.map +1 -0
- package/dist/generators/templates.js +1516 -0
- package/dist/generators/templates.js.map +1 -0
- package/package.json +79 -0
- package/templates/claude.md +176 -0
- package/templates/constraints.md +222 -0
- package/templates/context/session-context.example.json +48 -0
- package/templates/context/session-context.schema.json +129 -0
- package/templates/cursor.md +154 -0
- package/templates/decisions/decision-template.md +138 -0
- package/templates/edge-cases.md +164 -0
- package/templates/handoffs/handoff-template.md +132 -0
- package/templates/memory/checkpoint-patterns.md +224 -0
- package/templates/query-template.md +35 -0
- package/templates/state/CURRENT_STATE.md +117 -0
- package/templates/test-templates/edge-cases.test.md +230 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nyan Lin Maung
|
|
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,383 @@
|
|
|
1
|
+
# Cohere
|
|
2
|
+
|
|
3
|
+
> AI-powered database schema extraction and documentation generator for Claude, Cursor, and other AI coding assistants
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/cohere-db)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
## The Problem
|
|
9
|
+
|
|
10
|
+
AI coding assistants struggle with databases because they lack context about:
|
|
11
|
+
- **Schema structure** - Tables, columns, types, and constraints
|
|
12
|
+
- **Relationships** - Foreign keys, joins, and cardinalities
|
|
13
|
+
- **Data types** - Proper mapping between SQL and your ORM
|
|
14
|
+
- **Valid queries** - Common patterns and edge cases
|
|
15
|
+
|
|
16
|
+
This leads to:
|
|
17
|
+
- ā Incorrect SQL generation (wrong table/column names)
|
|
18
|
+
- ā Missing relationships (N+1 query problems)
|
|
19
|
+
- ā Type mismatches and runtime errors
|
|
20
|
+
- ā Context drift in long conversations
|
|
21
|
+
|
|
22
|
+
## The Solution
|
|
23
|
+
|
|
24
|
+
`cohere` extracts database schema information and generates AI-optimized context files:
|
|
25
|
+
- `CLAUDE.md` - Structured context for Claude Code
|
|
26
|
+
- `AGENTS.md` - Context for Cursor/Windsurf
|
|
27
|
+
- `DATABASE.md` - Human-readable schema documentation
|
|
28
|
+
- Type definitions and query templates
|
|
29
|
+
|
|
30
|
+
## Features
|
|
31
|
+
|
|
32
|
+
### šÆ Core Commands
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Initialize in your project
|
|
36
|
+
cohere init
|
|
37
|
+
|
|
38
|
+
# Generate context from your database
|
|
39
|
+
cohere generate --url "postgresql://user:pass@localhost:5432/mydb"
|
|
40
|
+
|
|
41
|
+
# Generate from ORM schema files
|
|
42
|
+
cohere generate --prisma
|
|
43
|
+
cohere generate --drizzle
|
|
44
|
+
|
|
45
|
+
# Watch for schema changes and auto-regenerate
|
|
46
|
+
cohere watch
|
|
47
|
+
|
|
48
|
+
# Validate generated context matches database
|
|
49
|
+
cohere validate
|
|
50
|
+
|
|
51
|
+
# Show current database state
|
|
52
|
+
cohere show
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### šļø Supported Databases
|
|
56
|
+
|
|
57
|
+
| Database | Status | Notes |
|
|
58
|
+
|----------|--------|-------|
|
|
59
|
+
| PostgreSQL | ā
| Full support with indexes, FKs, constraints |
|
|
60
|
+
| MySQL | ā
| Full support with InnoDB features |
|
|
61
|
+
| SQLite | ā
| Full support with PRAGMA introspection |
|
|
62
|
+
| MongoDB | ā
| Document sampling and type inference |
|
|
63
|
+
| Firebase Firestore | ā
| Collection sampling with field detection |
|
|
64
|
+
|
|
65
|
+
### š ļø Supported ORMs & Schema Tools
|
|
66
|
+
|
|
67
|
+
| Tool | Status | Notes |
|
|
68
|
+
|------|--------|-------|
|
|
69
|
+
| Prisma | ā
| Parse `schema.prisma` files |
|
|
70
|
+
| Drizzle ORM | ā
| Parse schema files |
|
|
71
|
+
| Kysely | š | Planned |
|
|
72
|
+
| TypeORM | š | Planned |
|
|
73
|
+
|
|
74
|
+
## Installation
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm install -g cohere-db
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Or use with npx:
|
|
81
|
+
```bash
|
|
82
|
+
npx cohere-db generate --url "postgresql://..."
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Quick Start
|
|
86
|
+
|
|
87
|
+
### 1. Initialize
|
|
88
|
+
```bash
|
|
89
|
+
cd my-project
|
|
90
|
+
cohere init
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 2. Generate Context
|
|
94
|
+
|
|
95
|
+
**From a Live Database:**
|
|
96
|
+
```bash
|
|
97
|
+
cohere generate --url "postgresql://localhost:5432/mydb"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**From Prisma Schema:**
|
|
101
|
+
```bash
|
|
102
|
+
cohere generate --prisma
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**From Drizzle Schema:**
|
|
106
|
+
```bash
|
|
107
|
+
cohere generate --drizzle src/db/schema.ts
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 3. Generated Files
|
|
111
|
+
|
|
112
|
+
After running `generate`, you'll have:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
.ai/
|
|
116
|
+
āāā CLAUDE.md # Claude-optimized context
|
|
117
|
+
āāā AGENTS.md # Cursor/Windsurf context
|
|
118
|
+
āāā DATABASE.md # Human-readable docs
|
|
119
|
+
āāā queries/ # Example query templates
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 4. Use with AI Tools
|
|
123
|
+
|
|
124
|
+
**Claude Code:**
|
|
125
|
+
- Claude automatically reads `.ai/CLAUDE.md` in your project root
|
|
126
|
+
|
|
127
|
+
**Cursor/Windsurf:**
|
|
128
|
+
- Add `.ai/AGENTS.md` to your `.cursorrules` or `.windsurfrules`
|
|
129
|
+
|
|
130
|
+
**Gemini CLI:**
|
|
131
|
+
- Reference `.ai/DATABASE.md` in your context
|
|
132
|
+
|
|
133
|
+
## Example Output
|
|
134
|
+
|
|
135
|
+
```markdown
|
|
136
|
+
<!-- CLAUDE.md excerpt -->
|
|
137
|
+
## Database Schema
|
|
138
|
+
|
|
139
|
+
### users
|
|
140
|
+
**Type:** table
|
|
141
|
+
**Engine:** InnoDB (MySQL)
|
|
142
|
+
|
|
143
|
+
#### Columns
|
|
144
|
+
- `id` - int, PRIMARY KEY, AUTO_INCREMENT
|
|
145
|
+
- `email` - varchar(255), UNIQUE, NOT NULL
|
|
146
|
+
- `full_name` - varchar(255), NULL
|
|
147
|
+
- `organization_id` - int, FOREIGN KEY ā organizations.id
|
|
148
|
+
- `created_at` - timestamp, DEFAULT CURRENT_TIMESTAMP
|
|
149
|
+
|
|
150
|
+
#### Indexes
|
|
151
|
+
- PRIMARY KEY (`id`)
|
|
152
|
+
- UNIQUE INDEX `idx_email` (`email`)
|
|
153
|
+
- INDEX `idx_org` (`organization_id`)
|
|
154
|
+
|
|
155
|
+
#### Foreign Keys
|
|
156
|
+
- `fk_user_org` ā organizations(id) ON DELETE CASCADE
|
|
157
|
+
|
|
158
|
+
### Relationships
|
|
159
|
+
- users ā organizations (many-to-one)
|
|
160
|
+
- users ā posts (one-to-many)
|
|
161
|
+
|
|
162
|
+
### Query Examples
|
|
163
|
+
|
|
164
|
+
**Get user with organization:**
|
|
165
|
+
\`\`\`sql
|
|
166
|
+
SELECT u.*, o.name as org_name
|
|
167
|
+
FROM users u
|
|
168
|
+
JOIN organizations o ON u.organization_id = o.id
|
|
169
|
+
WHERE u.id = ?
|
|
170
|
+
\`\`\`
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Advanced Usage
|
|
174
|
+
|
|
175
|
+
### Watch Mode
|
|
176
|
+
|
|
177
|
+
Automatically regenerate when schema changes:
|
|
178
|
+
```bash
|
|
179
|
+
cohere watch
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
This monitors:
|
|
183
|
+
- Prisma schema files
|
|
184
|
+
- Database migrations
|
|
185
|
+
- Drizzle schema files
|
|
186
|
+
|
|
187
|
+
### MongoDB Sampling
|
|
188
|
+
|
|
189
|
+
For NoSQL databases, Cohere samples documents to infer schema:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
cohere generate --url "mongodb://localhost:27017/mydb" --sample-size 1000
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Firebase/Firestore
|
|
196
|
+
|
|
197
|
+
Requires service account credentials:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
export GOOGLE_APPLICATION_CREDENTIALS="path/to/service-account.json"
|
|
201
|
+
cohere generate --firebase my-project-id
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Or provide the key directly:
|
|
205
|
+
```bash
|
|
206
|
+
cohere generate --firebase my-project-id --firebase-key service-account.json
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Validation
|
|
210
|
+
|
|
211
|
+
Ensure your generated docs match the actual database:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
cohere validate --url "postgresql://..."
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
This checks:
|
|
218
|
+
- ā
All tables documented
|
|
219
|
+
- ā
Column types match
|
|
220
|
+
- ā
Indexes present
|
|
221
|
+
- ā
Foreign keys valid
|
|
222
|
+
|
|
223
|
+
## Configuration
|
|
224
|
+
|
|
225
|
+
Create `.cohererc.json` in your project root:
|
|
226
|
+
|
|
227
|
+
```json
|
|
228
|
+
{
|
|
229
|
+
"outputDir": ".ai",
|
|
230
|
+
"databases": {
|
|
231
|
+
"development": "postgresql://localhost:5432/dev",
|
|
232
|
+
"production": "postgresql://prod-server:5432/prod"
|
|
233
|
+
},
|
|
234
|
+
"include": ["users", "posts", "comments"],
|
|
235
|
+
"exclude": ["migrations", "sessions"],
|
|
236
|
+
"watch": {
|
|
237
|
+
"enabled": true,
|
|
238
|
+
"paths": ["prisma/schema.prisma", "src/db/**/*.ts"]
|
|
239
|
+
},
|
|
240
|
+
"templates": {
|
|
241
|
+
"claude": "custom/claude-template.md"
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## CLI Reference
|
|
247
|
+
|
|
248
|
+
### `cohere init`
|
|
249
|
+
Initialize Cohere in your project
|
|
250
|
+
|
|
251
|
+
**Options:**
|
|
252
|
+
- `-u, --url <url>` - Database connection URL
|
|
253
|
+
- `-d, --dir <dir>` - Output directory (default: `.ai`)
|
|
254
|
+
|
|
255
|
+
### `cohere generate`
|
|
256
|
+
Generate context files from database or ORM
|
|
257
|
+
|
|
258
|
+
**Options:**
|
|
259
|
+
- `-u, --url <url>` - Database connection URL
|
|
260
|
+
- `--prisma [path]` - Use Prisma schema
|
|
261
|
+
- `--drizzle [path]` - Use Drizzle schema
|
|
262
|
+
- `--firebase <projectId>` - Firestore project ID
|
|
263
|
+
- `--firebase-key <path>` - Service account key path
|
|
264
|
+
- `--mongo-sample <n>` - MongoDB sample size (default: 100)
|
|
265
|
+
- `-o, --output <dir>` - Output directory
|
|
266
|
+
|
|
267
|
+
### `cohere watch`
|
|
268
|
+
Watch for schema changes and auto-regenerate
|
|
269
|
+
|
|
270
|
+
**Options:**
|
|
271
|
+
- `-u, --url <url>` - Database connection URL
|
|
272
|
+
- `--interval <ms>` - Check interval (default: 5000)
|
|
273
|
+
|
|
274
|
+
### `cohere validate`
|
|
275
|
+
Validate generated docs against database
|
|
276
|
+
|
|
277
|
+
**Options:**
|
|
278
|
+
- `-u, --url <url>` - Database connection URL
|
|
279
|
+
|
|
280
|
+
### `cohere show`
|
|
281
|
+
Display current database state
|
|
282
|
+
|
|
283
|
+
**Options:**
|
|
284
|
+
- `-u, --url <url>` - Database connection URL
|
|
285
|
+
- `--json` - Output as JSON
|
|
286
|
+
|
|
287
|
+
## Architecture
|
|
288
|
+
|
|
289
|
+
```
|
|
290
|
+
cohere/
|
|
291
|
+
āāā src/
|
|
292
|
+
ā āāā cli.ts # CLI entry point
|
|
293
|
+
ā āāā commands/ # Command implementations
|
|
294
|
+
ā ā āāā generate.ts # Schema extraction & generation
|
|
295
|
+
ā ā āāā init.ts # Project initialization
|
|
296
|
+
ā ā āāā validate.ts # Schema validation
|
|
297
|
+
ā ā āāā watch.ts # File watching
|
|
298
|
+
ā ā āāā show.ts # Display schema
|
|
299
|
+
ā āāā extractors/ # Database-specific extractors
|
|
300
|
+
ā ā āāā postgres.ts # PostgreSQL extractor
|
|
301
|
+
ā ā āāā mysql.ts # MySQL extractor
|
|
302
|
+
ā ā āāā sqlite.ts # SQLite extractor
|
|
303
|
+
ā ā āāā mongodb.ts # MongoDB extractor
|
|
304
|
+
ā ā āāā firebase.ts # Firestore extractor
|
|
305
|
+
ā ā āāā prisma.ts # Prisma schema parser
|
|
306
|
+
ā ā āāā drizzle.ts # Drizzle schema parser
|
|
307
|
+
ā āāā generators/ # Context file generators
|
|
308
|
+
ā ā āāā claude.ts # CLAUDE.md generator
|
|
309
|
+
ā ā āāā cursor.ts # AGENTS.md generator
|
|
310
|
+
ā ā āāā markdown.ts # DATABASE.md generator
|
|
311
|
+
ā āāā utils/ # Shared utilities
|
|
312
|
+
āāā templates/ # Output templates
|
|
313
|
+
āāā claude.md
|
|
314
|
+
āāā cursor.md
|
|
315
|
+
āāā queries/
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## Testing
|
|
319
|
+
|
|
320
|
+
Cohere includes comprehensive unit tests for all extractors:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
# Run all tests
|
|
324
|
+
npm test
|
|
325
|
+
|
|
326
|
+
# Run tests with coverage
|
|
327
|
+
npm run test:coverage
|
|
328
|
+
|
|
329
|
+
# Watch mode
|
|
330
|
+
npm run test:watch
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
Test coverage:
|
|
334
|
+
- ā
PostgreSQL extractor (tables, indexes, foreign keys)
|
|
335
|
+
- ā
MySQL extractor (InnoDB features)
|
|
336
|
+
- ā
SQLite extractor (PRAGMA queries)
|
|
337
|
+
- ā
MongoDB extractor (document sampling)
|
|
338
|
+
- ā
Firebase extractor (collection inference)
|
|
339
|
+
- ā
Prisma parser (schema.prisma files)
|
|
340
|
+
- ā
Drizzle parser (schema definitions)
|
|
341
|
+
|
|
342
|
+
## Contributing
|
|
343
|
+
|
|
344
|
+
Contributions are welcome! Please:
|
|
345
|
+
|
|
346
|
+
1. Fork the repository
|
|
347
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
348
|
+
3. Write tests for your changes
|
|
349
|
+
4. Ensure all tests pass (`npm test`)
|
|
350
|
+
5. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
351
|
+
6. Push to the branch (`git push origin feature/amazing-feature`)
|
|
352
|
+
7. Open a Pull Request
|
|
353
|
+
|
|
354
|
+
## Roadmap
|
|
355
|
+
|
|
356
|
+
See [ROADMAP.md](docs/ROADMAP.md) for planned features.
|
|
357
|
+
|
|
358
|
+
## FAQ
|
|
359
|
+
|
|
360
|
+
**Q: Does Cohere send data to external services?**
|
|
361
|
+
A: No. All schema extraction happens locally. Your database credentials and schema never leave your machine.
|
|
362
|
+
|
|
363
|
+
**Q: Can I use this with private/commercial databases?**
|
|
364
|
+
A: Yes. Cohere is MIT licensed and can be used commercially.
|
|
365
|
+
|
|
366
|
+
**Q: How often should I regenerate context?**
|
|
367
|
+
A: Use `cohere watch` during development. Regenerate after schema migrations in production.
|
|
368
|
+
|
|
369
|
+
**Q: Does this work with multi-tenant databases?**
|
|
370
|
+
A: Yes. Cohere extracts the schema structure. Tenant-specific data is not included.
|
|
371
|
+
|
|
372
|
+
**Q: Can I customize the output templates?**
|
|
373
|
+
A: Yes. Create custom templates in `.cohererc.json` or the `templates/` directory.
|
|
374
|
+
|
|
375
|
+
## License
|
|
376
|
+
|
|
377
|
+
MIT Ā© Cohere Team
|
|
378
|
+
|
|
379
|
+
## Acknowledgments
|
|
380
|
+
|
|
381
|
+
- [Prisma](https://prisma.io) - Inspiration for type-safe database access
|
|
382
|
+
- [Drizzle ORM](https://orm.drizzle.team) - Lightweight ORM patterns
|
|
383
|
+
- [Supabase CLI](https://supabase.com/docs/reference/cli) - CLI design patterns
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;GAIG"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Cohere CLI
|
|
4
|
+
*
|
|
5
|
+
* Generate AI-friendly database context documentation for coding assistants.
|
|
6
|
+
*/
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import { dirname, join } from 'path';
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = dirname(__filename);
|
|
11
|
+
import { Command } from 'commander';
|
|
12
|
+
import inquirer from 'inquirer';
|
|
13
|
+
import { generate } from './commands/generate.js';
|
|
14
|
+
import { init } from './commands/init.js';
|
|
15
|
+
import { validate } from './commands/validate.js';
|
|
16
|
+
import { watch } from './commands/watch.js';
|
|
17
|
+
import { handoff } from './commands/handoff.js';
|
|
18
|
+
import * as fs from 'fs';
|
|
19
|
+
const pkg = JSON.parse(fs.readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
20
|
+
const version = pkg.version;
|
|
21
|
+
const program = new Command();
|
|
22
|
+
program
|
|
23
|
+
.name('cohere')
|
|
24
|
+
.description('Generate AI-friendly database context for coding assistants')
|
|
25
|
+
.version(version);
|
|
26
|
+
// Commands
|
|
27
|
+
program
|
|
28
|
+
.command('init')
|
|
29
|
+
.description('Initialize Cohere in your project')
|
|
30
|
+
.option('-u, --url <url>', 'Database connection URL')
|
|
31
|
+
.option('-d, --dir <dir>', 'Output directory', '.ai')
|
|
32
|
+
.action(init);
|
|
33
|
+
program
|
|
34
|
+
.command('generate')
|
|
35
|
+
.description('Generate context files from database or ORM schema')
|
|
36
|
+
.option('-u, --url <url>', 'Database connection URL')
|
|
37
|
+
.option('--orm <orm>', 'ORM type (prisma, drizzle)')
|
|
38
|
+
.option('--mysql', 'Use MySQL extractor')
|
|
39
|
+
.option('--sqlite <path>', 'Use SQLite extractor with file path')
|
|
40
|
+
.option('--prisma [path]', 'Use Prisma extractor (optional path)')
|
|
41
|
+
.option('--drizzle [path]', 'Use Drizzle extractor (optional path)')
|
|
42
|
+
.option('-o, --output <dir>', 'Output directory')
|
|
43
|
+
.option('--format <format>', 'Output format (markdown, json)', 'markdown')
|
|
44
|
+
.action(generate);
|
|
45
|
+
program
|
|
46
|
+
.command('validate')
|
|
47
|
+
.description('Validate generated context against database')
|
|
48
|
+
.option('--strict', 'Fail on any mismatches')
|
|
49
|
+
.action(validate);
|
|
50
|
+
program
|
|
51
|
+
.command('watch')
|
|
52
|
+
.description('Watch for schema changes and regenerate')
|
|
53
|
+
.option('-d, --debounce <ms>', 'Debounce time in ms', '2000')
|
|
54
|
+
.action(watch);
|
|
55
|
+
program
|
|
56
|
+
.command('show')
|
|
57
|
+
.description('Show current database schema')
|
|
58
|
+
.option('-f, --format <format>', 'Output format', 'markdown')
|
|
59
|
+
.action(async (options) => {
|
|
60
|
+
const { show } = await import('./commands/show.js');
|
|
61
|
+
await show(options);
|
|
62
|
+
});
|
|
63
|
+
program
|
|
64
|
+
.command('handoff')
|
|
65
|
+
.description('Multi-agent handoff management')
|
|
66
|
+
.option('--record', 'Record current session state')
|
|
67
|
+
.option('--resume <id>', 'Resume from previous session')
|
|
68
|
+
.option('--list', 'List available sessions')
|
|
69
|
+
.option('-o, --output <dir>', 'Output directory', '.ai')
|
|
70
|
+
.option('--status <status>', 'Session status', 'in_progress')
|
|
71
|
+
.option('--agentId <id>', 'Agent identifier')
|
|
72
|
+
.action(handoff);
|
|
73
|
+
// Interactive mode
|
|
74
|
+
program
|
|
75
|
+
.command('interactive')
|
|
76
|
+
.alias('i')
|
|
77
|
+
.description('Interactive mode for quick operations')
|
|
78
|
+
.action(async () => {
|
|
79
|
+
const { action } = await inquirer.prompt([
|
|
80
|
+
{
|
|
81
|
+
type: 'list',
|
|
82
|
+
name: 'action',
|
|
83
|
+
message: 'What would you like to do?',
|
|
84
|
+
choices: [
|
|
85
|
+
{ name: 'Generate context from database', value: 'generate' },
|
|
86
|
+
{ name: 'Validate existing context', value: 'validate' },
|
|
87
|
+
{ name: 'Watch for changes', value: 'watch' },
|
|
88
|
+
{ name: 'Show schema', value: 'show' },
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
]);
|
|
92
|
+
const command = program.commands.find((c) => c.name() === action);
|
|
93
|
+
if (command) {
|
|
94
|
+
const argv = [process.argv[0], program.name(), action];
|
|
95
|
+
await command.parseAsync(argv);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
// Parse arguments
|
|
99
|
+
program.parse();
|
|
100
|
+
// Show help if no command
|
|
101
|
+
if (!process.argv.slice(2).length) {
|
|
102
|
+
program.outputHelp();
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate Command
|
|
3
|
+
* Generates CLAUDE.md and AGENTS.md from database schema
|
|
4
|
+
*/
|
|
5
|
+
interface GenerateOptions {
|
|
6
|
+
url?: string;
|
|
7
|
+
orm?: string;
|
|
8
|
+
output?: string;
|
|
9
|
+
format?: string;
|
|
10
|
+
schema?: string;
|
|
11
|
+
mysql?: boolean;
|
|
12
|
+
sqlite?: string;
|
|
13
|
+
prisma?: string;
|
|
14
|
+
drizzle?: string;
|
|
15
|
+
mongodb?: string;
|
|
16
|
+
firebaseKey?: string;
|
|
17
|
+
firebaseProject?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function generate(options: GenerateOptions): Promise<void>;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=generate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,UAAU,eAAe;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAwHtE"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate Command
|
|
3
|
+
* Generates CLAUDE.md and AGENTS.md from database schema
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import { createExtractor, UnifiedSchemaConverter } from '../extractors/index.js';
|
|
8
|
+
import { TemplateGenerator } from '../generators/templates.js';
|
|
9
|
+
export async function generate(options) {
|
|
10
|
+
const outputDir = options.output || '.ai';
|
|
11
|
+
const schemaName = options.schema || 'public';
|
|
12
|
+
console.log(`š Generating database context...`);
|
|
13
|
+
console.log(` Output directory: ${outputDir}`);
|
|
14
|
+
let extractorType = 'postgresql';
|
|
15
|
+
let connectionString = options.url || process.env.DATABASE_URL || '';
|
|
16
|
+
let schemaPath;
|
|
17
|
+
// Determine extractor type
|
|
18
|
+
if (options.mysql) {
|
|
19
|
+
extractorType = 'mysql';
|
|
20
|
+
if (!connectionString) {
|
|
21
|
+
throw new Error('MySQL connection URL required. Use --url or DATABASE_URL env var.');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
else if (options.sqlite) {
|
|
25
|
+
extractorType = 'sqlite';
|
|
26
|
+
connectionString = options.sqlite;
|
|
27
|
+
}
|
|
28
|
+
else if (options.prisma) {
|
|
29
|
+
extractorType = 'prisma';
|
|
30
|
+
schemaPath = typeof options.prisma === 'string' ? options.prisma : 'prisma/schema.prisma';
|
|
31
|
+
connectionString = 'dummy'; // Not used for Prisma
|
|
32
|
+
}
|
|
33
|
+
else if (options.drizzle) {
|
|
34
|
+
extractorType = 'drizzle';
|
|
35
|
+
schemaPath = typeof options.drizzle === 'string' ? options.drizzle : 'src/db/schema.ts';
|
|
36
|
+
connectionString = 'dummy'; // Not used for Drizzle
|
|
37
|
+
}
|
|
38
|
+
else if (options.orm === 'prisma') {
|
|
39
|
+
extractorType = 'prisma';
|
|
40
|
+
schemaPath = 'prisma/schema.prisma';
|
|
41
|
+
connectionString = 'dummy';
|
|
42
|
+
}
|
|
43
|
+
else if (options.orm === 'drizzle') {
|
|
44
|
+
extractorType = 'drizzle';
|
|
45
|
+
schemaPath = 'src/db/schema.ts';
|
|
46
|
+
connectionString = 'dummy';
|
|
47
|
+
}
|
|
48
|
+
else if (connectionString) {
|
|
49
|
+
if (connectionString.startsWith('mysql')) {
|
|
50
|
+
extractorType = 'mysql';
|
|
51
|
+
}
|
|
52
|
+
else if (connectionString.startsWith('file:') || connectionString.endsWith('.db') || connectionString.endsWith('.sqlite')) {
|
|
53
|
+
extractorType = 'sqlite';
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
extractorType = 'postgresql';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// Try to auto-detect
|
|
61
|
+
if (fs.existsSync('prisma/schema.prisma')) {
|
|
62
|
+
console.log('š Detected Prisma schema, using Prisma extractor...');
|
|
63
|
+
extractorType = 'prisma';
|
|
64
|
+
schemaPath = 'prisma/schema.prisma';
|
|
65
|
+
connectionString = 'dummy';
|
|
66
|
+
}
|
|
67
|
+
else if (fs.existsSync('drizzle.config.ts') || fs.existsSync('src/db/schema.ts')) {
|
|
68
|
+
console.log('š Detected Drizzle project, using Drizzle extractor...');
|
|
69
|
+
extractorType = 'drizzle';
|
|
70
|
+
schemaPath = 'src/db/schema.ts';
|
|
71
|
+
connectionString = 'dummy';
|
|
72
|
+
}
|
|
73
|
+
else if (options.mongodb || (connectionString && (connectionString.startsWith('mongodb://') || connectionString.startsWith('mongodb+srv://')))) {
|
|
74
|
+
console.log('š Detected MongoDB connection...');
|
|
75
|
+
extractorType = 'mongodb';
|
|
76
|
+
connectionString = options.mongodb || connectionString;
|
|
77
|
+
if (!connectionString) {
|
|
78
|
+
throw new Error('MongoDB connection URL required. Use --url or DATABASE_URL env var.');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else if (options.firebaseProject || process.env.GOOGLE_APPLICATION_CREDENTIALS) {
|
|
82
|
+
console.log('š Detected Firebase project...');
|
|
83
|
+
extractorType = 'firebase';
|
|
84
|
+
connectionString = 'dummy'; // Not used for Firebase
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
throw new Error('Database connection not found. Use --url, --sqlite, --prisma, --drizzle, or --mongodb.');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
console.log(`š¦ Using extractor: ${extractorType}`);
|
|
91
|
+
if (schemaPath)
|
|
92
|
+
console.log(` Schema path: ${schemaPath}`);
|
|
93
|
+
const extractor = await createExtractor(extractorType, connectionString, {
|
|
94
|
+
schemaPath,
|
|
95
|
+
projectId: options.firebaseProject,
|
|
96
|
+
serviceAccountPath: options.firebaseKey
|
|
97
|
+
});
|
|
98
|
+
let unifiedSchema;
|
|
99
|
+
try {
|
|
100
|
+
const rawSchema = await extractor.extract();
|
|
101
|
+
rawSchema.databaseType = extractorType;
|
|
102
|
+
rawSchema.schemaName = rawSchema.schemaName || schemaName;
|
|
103
|
+
rawSchema.source = rawSchema.source || schemaPath || connectionString;
|
|
104
|
+
// Convert to unified format using generic convert
|
|
105
|
+
unifiedSchema = UnifiedSchemaConverter.convert(rawSchema);
|
|
106
|
+
// Add source info
|
|
107
|
+
unifiedSchema.source = schemaPath || connectionString.replace(/:[^:]*@/, ':***@'); // Hide password
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
if (extractor.close) {
|
|
111
|
+
await extractor.close();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Generate and save templates
|
|
115
|
+
console.log('š Generating context files...');
|
|
116
|
+
const generator = new TemplateGenerator('templates', outputDir);
|
|
117
|
+
await generator.save(outputDir, unifiedSchema);
|
|
118
|
+
// Summary
|
|
119
|
+
console.log('\nā
Generation complete!');
|
|
120
|
+
console.log(` Tables: ${unifiedSchema.tables.length}`);
|
|
121
|
+
console.log(` Output: ${path.resolve(outputDir)}`);
|
|
122
|
+
console.log('\nš Generated files:');
|
|
123
|
+
console.log(` - ${outputDir}/CLAUDE.md`);
|
|
124
|
+
console.log(` - ${outputDir}/AGENTS.md`);
|
|
125
|
+
console.log(` - ${outputDir}/queries/`);
|
|
126
|
+
console.log('\nš” Next steps:');
|
|
127
|
+
console.log(' 1. Review the generated files');
|
|
128
|
+
console.log(' 2. Add custom business rules');
|
|
129
|
+
console.log(' 3. Commit to version control');
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=generate.js.map
|