@runcontext/cli 0.3.2 → 0.3.4
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 +108 -0
- package/dist/index.js +109 -11
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Eric Kittelson
|
|
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,108 @@
|
|
|
1
|
+
# @runcontext/cli
|
|
2
|
+
|
|
3
|
+
CLI for [ContextKit](https://github.com/erickittelson/ContextKit) — AI-ready metadata governance over OSI.
|
|
4
|
+
|
|
5
|
+
**Your data already has a schema. ContextKit gives it meaning.**
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Global install
|
|
11
|
+
npm install -g @runcontext/cli
|
|
12
|
+
|
|
13
|
+
# Or per-project
|
|
14
|
+
npm install -D @runcontext/cli
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Point at any database — interactive wizard does the rest
|
|
21
|
+
context setup
|
|
22
|
+
|
|
23
|
+
# Or step by step
|
|
24
|
+
context introspect --db duckdb://warehouse.duckdb
|
|
25
|
+
context enrich --target silver --apply
|
|
26
|
+
context tier
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Commands
|
|
30
|
+
|
|
31
|
+
### Core Workflow
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
context setup # Interactive wizard — database to metadata in one flow
|
|
35
|
+
context introspect # Scan a database → scaffold Bronze-level OSI metadata
|
|
36
|
+
context enrich --target silver # Auto-enrich metadata toward a target tier
|
|
37
|
+
context lint # Run 37 lint rules against context files
|
|
38
|
+
context fix --write # Auto-fix lint issues where possible
|
|
39
|
+
context build # Compile context files → emit manifest JSON
|
|
40
|
+
context tier [model] # Show Bronze/Silver/Gold scorecard
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Exploration
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
context explain <name> # Look up any model, term, or owner
|
|
47
|
+
context rules # List all lint rules with tier, severity, fixability
|
|
48
|
+
context validate-osi <file> # Validate a single OSI file against the schema
|
|
49
|
+
context verify # Check metadata accuracy against a live database
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Serving
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
context serve --stdio # Start MCP server over stdio (for Claude, Cursor, etc.)
|
|
56
|
+
context serve --http --port 3000 # Start MCP server over HTTP
|
|
57
|
+
context site # Generate a static documentation site
|
|
58
|
+
context dev # Watch mode — re-lint on file changes
|
|
59
|
+
context init # Scaffold a new project structure
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## The Tier System
|
|
63
|
+
|
|
64
|
+
| Tier | What it means | How to get there |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| **Bronze** | Discoverable — described, owned, classified | `context introspect` |
|
|
67
|
+
| **Silver** | Trusted — lineage, glossary, sample values, trust status | `context enrich --target silver` |
|
|
68
|
+
| **Gold** | AI-Ready — semantic roles, golden queries, guardrails, business rules | Human curation + `context enrich --target gold` |
|
|
69
|
+
|
|
70
|
+
## Database Support
|
|
71
|
+
|
|
72
|
+
| Adapter | Connection |
|
|
73
|
+
|---|---|
|
|
74
|
+
| DuckDB | `--db duckdb://path/to/file.duckdb` |
|
|
75
|
+
| PostgreSQL | `--db postgres://user:pass@host:5432/db` |
|
|
76
|
+
|
|
77
|
+
## MCP Server
|
|
78
|
+
|
|
79
|
+
Expose your metadata to AI agents:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# For Claude Code / Cursor
|
|
83
|
+
context serve --stdio
|
|
84
|
+
|
|
85
|
+
# For multi-agent setups
|
|
86
|
+
context serve --http --port 3000
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Add to `.claude/mcp.json`:
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"mcpServers": {
|
|
94
|
+
"contextkit": {
|
|
95
|
+
"command": "npx",
|
|
96
|
+
"args": ["@runcontext/cli", "serve", "--stdio"]
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Full Documentation
|
|
103
|
+
|
|
104
|
+
See the [ContextKit repository](https://github.com/erickittelson/ContextKit) for complete docs, file structure, tier requirements, and examples.
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
MIT
|
package/dist/index.js
CHANGED
|
@@ -1201,15 +1201,14 @@ var siteCommand = new Command10("site").description("Build a static documentatio
|
|
|
1201
1201
|
// src/commands/serve.ts
|
|
1202
1202
|
import { Command as Command11 } from "commander";
|
|
1203
1203
|
import chalk12 from "chalk";
|
|
1204
|
-
var serveCommand = new Command11("serve").description("Start the MCP server (stdio transport)").option("--context-dir <path>", "Path to context directory").action(async (opts) => {
|
|
1204
|
+
var serveCommand = new Command11("serve").description("Start the MCP server (stdio or HTTP transport)").option("--context-dir <path>", "Path to context directory").option("--http", "Serve over HTTP instead of stdio").option("--port <number>", "HTTP port (default: 3000)", "3000").option("--host <address>", "HTTP host (default: 0.0.0.0)", "0.0.0.0").action(async (opts) => {
|
|
1205
1205
|
try {
|
|
1206
|
-
let
|
|
1206
|
+
let mcpModule;
|
|
1207
1207
|
try {
|
|
1208
|
-
|
|
1209
|
-
startServer = mcpModule.startServer;
|
|
1208
|
+
mcpModule = await import("@runcontext/mcp");
|
|
1210
1209
|
} catch {
|
|
1211
1210
|
}
|
|
1212
|
-
if (!
|
|
1211
|
+
if (!mcpModule) {
|
|
1213
1212
|
console.log(
|
|
1214
1213
|
chalk12.yellow(
|
|
1215
1214
|
"MCP server is not available. Install @runcontext/mcp to enable this command."
|
|
@@ -1217,11 +1216,24 @@ var serveCommand = new Command11("serve").description("Start the MCP server (std
|
|
|
1217
1216
|
);
|
|
1218
1217
|
process.exit(1);
|
|
1219
1218
|
}
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1219
|
+
if (opts.http) {
|
|
1220
|
+
const startServerHttp = mcpModule.startServerHttp;
|
|
1221
|
+
const port = parseInt(opts.port, 10);
|
|
1222
|
+
console.log(chalk12.blue(`Starting MCP server (HTTP on port ${port})...`));
|
|
1223
|
+
await startServerHttp({
|
|
1224
|
+
contextDir: opts.contextDir,
|
|
1225
|
+
rootDir: process.cwd(),
|
|
1226
|
+
port,
|
|
1227
|
+
host: opts.host
|
|
1228
|
+
});
|
|
1229
|
+
} else {
|
|
1230
|
+
const startServer = mcpModule.startServer;
|
|
1231
|
+
console.log(chalk12.blue("Starting MCP server (stdio transport)..."));
|
|
1232
|
+
await startServer({
|
|
1233
|
+
contextDir: opts.contextDir,
|
|
1234
|
+
rootDir: process.cwd()
|
|
1235
|
+
});
|
|
1236
|
+
}
|
|
1225
1237
|
} catch (err) {
|
|
1226
1238
|
console.error(formatError(err.message));
|
|
1227
1239
|
process.exit(1);
|
|
@@ -2444,7 +2456,93 @@ ${failingSection}
|
|
|
2444
2456
|
|
|
2445
2457
|
**Bronze (7):** descriptions, owner, security, grain, table_type
|
|
2446
2458
|
**Silver (+6):** trust, 2+ tags, glossary linked, lineage, refresh, 2+ sample_values
|
|
2447
|
-
**Gold (+
|
|
2459
|
+
**Gold (+24):** semantic_role on ALL fields, metric aggregation/additive, 1+ guardrail, 3+ golden queries, 1+ business rule, 1+ hierarchy, 1+ default_filter, trust=endorsed, contactable owner, 1+ relationship, description \u226550 chars, ai_context (no TODO), 1+ business_context, version, field descriptions not lazy, glossary definitions substantive, lineage references real sources, grain statements specific, ai_context filled in, 3+ relationships (models with 3+ datasets), 1+ computed metric, 3+ glossary terms (models with 5+ datasets)
|
|
2460
|
+
|
|
2461
|
+
## How to Reach Gold: Curation Recipes
|
|
2462
|
+
|
|
2463
|
+
### Metrics (gold/metrics-defined)
|
|
2464
|
+
|
|
2465
|
+
Inspect computed views in the database. Any calculated column is a candidate metric.
|
|
2466
|
+
|
|
2467
|
+
\`\`\`sql
|
|
2468
|
+
-- Find computed columns in views
|
|
2469
|
+
SELECT column_name, data_type
|
|
2470
|
+
FROM information_schema.columns
|
|
2471
|
+
WHERE table_name LIKE 'vw_%' AND data_type IN ('DOUBLE', 'FLOAT', 'INTEGER', 'BIGINT', 'DECIMAL');
|
|
2472
|
+
\`\`\`
|
|
2473
|
+
|
|
2474
|
+
For each computed column (e.g., \`opportunity_score\`, \`shops_per_10k\`, \`demand_signal_pct\`):
|
|
2475
|
+
1. Query it to understand what it measures
|
|
2476
|
+
2. Add it to the model's \`metrics[]\` array in the OSI YAML
|
|
2477
|
+
3. Include the SQL expression, aggregation type (SUM/AVG), and a human description
|
|
2478
|
+
4. Mark whether it's additive (can be summed across dimensions)
|
|
2479
|
+
|
|
2480
|
+
Example:
|
|
2481
|
+
\`\`\`yaml
|
|
2482
|
+
metrics:
|
|
2483
|
+
- name: opportunity_score
|
|
2484
|
+
expression:
|
|
2485
|
+
dialects:
|
|
2486
|
+
- dialect: DuckDB
|
|
2487
|
+
expression: "(population/10000)*2 + (income/50000)*2 + (10-shops_per_10k)*3 + transit*1.5 + demand*0.5"
|
|
2488
|
+
description: Composite score ranking census tracts for coffee shop viability
|
|
2489
|
+
aggregation: AVG
|
|
2490
|
+
additive: false
|
|
2491
|
+
\`\`\`
|
|
2492
|
+
|
|
2493
|
+
### Glossary Terms (gold/glossary-coverage)
|
|
2494
|
+
|
|
2495
|
+
For each key business concept your model measures, create a glossary term file.
|
|
2496
|
+
|
|
2497
|
+
Think about the terms a new analyst would need defined:
|
|
2498
|
+
- What is "supply saturation"? (> 5.0 shops per 10k people)
|
|
2499
|
+
- What is a "demand signal"? (review mentioning wait/line/crowded/busy)
|
|
2500
|
+
- What is "opportunity score"? (composite ranking formula)
|
|
2501
|
+
|
|
2502
|
+
For each term, create \`context/glossary/<term-name>.term.yaml\`:
|
|
2503
|
+
\`\`\`yaml
|
|
2504
|
+
term: supply-saturation
|
|
2505
|
+
definition: >
|
|
2506
|
+
A measure of coffee shop density per census tract. Calculated as
|
|
2507
|
+
shops per 10,000 residents. Tracts with > 5.0 are considered saturated.
|
|
2508
|
+
owner: analytics-team
|
|
2509
|
+
tags: [coffee-analytics]
|
|
2510
|
+
\`\`\`
|
|
2511
|
+
|
|
2512
|
+
Models with 5+ datasets need at least 3 glossary terms linked by shared tags or owner.
|
|
2513
|
+
|
|
2514
|
+
### Relationships (gold/relationships-coverage)
|
|
2515
|
+
|
|
2516
|
+
For each join in the SQL views, define a relationship in the OSI model.
|
|
2517
|
+
|
|
2518
|
+
\`\`\`sql
|
|
2519
|
+
-- Find joins by examining view definitions
|
|
2520
|
+
-- Look for patterns: ON table_a.col = table_b.col
|
|
2521
|
+
-- Or spatial joins: ABS(a.lat - b.lat) < threshold
|
|
2522
|
+
\`\`\`
|
|
2523
|
+
|
|
2524
|
+
For each join:
|
|
2525
|
+
\`\`\`yaml
|
|
2526
|
+
relationships:
|
|
2527
|
+
- name: business-to-tract
|
|
2528
|
+
left_dataset: yelp_business
|
|
2529
|
+
right_dataset: census_tract
|
|
2530
|
+
join_type: spatial
|
|
2531
|
+
cardinality: many-to-one
|
|
2532
|
+
description: Businesses assigned to nearest census tract within 0.02 degrees (~1 mile)
|
|
2533
|
+
\`\`\`
|
|
2534
|
+
|
|
2535
|
+
Models with 3+ datasets need at least 3 relationships.
|
|
2536
|
+
|
|
2537
|
+
### Golden Queries
|
|
2538
|
+
|
|
2539
|
+
Write 3-5 SQL queries answering common business questions. **Test each query first!**
|
|
2540
|
+
|
|
2541
|
+
\`\`\`sql
|
|
2542
|
+
-- Run the query, verify it returns sensible results, then document:
|
|
2543
|
+
SELECT geoid, tract_name, opportunity_score
|
|
2544
|
+
FROM vw_candidate_zones ORDER BY opportunity_score DESC LIMIT 10;
|
|
2545
|
+
\`\`\`
|
|
2448
2546
|
|
|
2449
2547
|
## YAML Formats
|
|
2450
2548
|
|