context101-cli 0.1.2 → 0.1.3
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 +52 -0
- package/package.json +19 -2
- package/src/main.js +2 -1
- package/src/stacks.js +16 -6
- package/src/style.js +29 -8
package/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# context101-cli
|
|
2
|
+
|
|
3
|
+
your context. every agent.
|
|
4
|
+
|
|
5
|
+
Thin self-host CLI for [Context101](https://github.com/jginorio/context101) — a wrapper around Amazon Bedrock Knowledge Bases. Self-host now; hosted later (not there yet). Alpha / trusted-team.
|
|
6
|
+
|
|
7
|
+
This is the AWS front door: init, deploy, list, destroy, config. Not a wiki app.
|
|
8
|
+
|
|
9
|
+
**`npx context101` (unscoped) is Context7's MCP — not this tool.** Use `context101-cli`.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm i -g context101-cli
|
|
15
|
+
context101 <cmd>
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
or
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx context101-cli@latest <cmd>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Commands
|
|
25
|
+
|
|
26
|
+
| Command | What it does |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| `context101 init` | write deploy-env; TTY asks to deploy |
|
|
29
|
+
| `context101 deploy` | deploy the AWS stack |
|
|
30
|
+
| `context101 list` | list Context101 CloudFormation stacks |
|
|
31
|
+
| `context101 destroy <name>` | tear down a listed stack |
|
|
32
|
+
| `context101 config` | show deploy-env keys (values redacted) |
|
|
33
|
+
| `context101 config set KEY=value` | write one key (chmod 600; value is not printed) |
|
|
34
|
+
| `context101 help` | list commands |
|
|
35
|
+
|
|
36
|
+
`list`, `help`, and `destroy --dry-run` work without a checkout.
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
context101 list
|
|
40
|
+
context101 help
|
|
41
|
+
context101 destroy Context101Stack --dry-run
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Name collision
|
|
45
|
+
|
|
46
|
+
The publishable package is **context101-cli**. The bin name is `context101`.
|
|
47
|
+
|
|
48
|
+
`npx context101` downloads Context7's MCP from npm. Unrelated.
|
|
49
|
+
|
|
50
|
+
## Repo
|
|
51
|
+
|
|
52
|
+
https://github.com/jginorio/context101
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "context101-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "Context101 self-host CLI. Use `npx context101-cli` or the `context101` bin.
|
|
5
|
+
"description": "Context101 self-host CLI — your context. every agent. Use `npx context101-cli` or the `context101` bin. Unscoped `npx context101` is Context7's MCP, not this tool.",
|
|
6
|
+
"license": "MIT",
|
|
6
7
|
"type": "module",
|
|
7
8
|
"bin": {
|
|
8
9
|
"context101": "./bin/context101.js"
|
|
@@ -11,6 +12,22 @@
|
|
|
11
12
|
"bin",
|
|
12
13
|
"src"
|
|
13
14
|
],
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/jginorio/context101.git"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/jginorio/context101",
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/jginorio/context101/issues"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"context101",
|
|
25
|
+
"cli",
|
|
26
|
+
"knowledge-base",
|
|
27
|
+
"bedrock",
|
|
28
|
+
"mcp",
|
|
29
|
+
"self-host"
|
|
30
|
+
],
|
|
14
31
|
"scripts": {
|
|
15
32
|
"test": "node --test test/*.test.js"
|
|
16
33
|
},
|
package/src/main.js
CHANGED
|
@@ -3,7 +3,7 @@ import { runConfig } from "./config.js";
|
|
|
3
3
|
import { runDeploy } from "./deploy.js";
|
|
4
4
|
import { runInit } from "./init.js";
|
|
5
5
|
import { runDestroy, runList } from "./stacks.js";
|
|
6
|
-
import { writers } from "./style.js";
|
|
6
|
+
import { banner, writers } from "./style.js";
|
|
7
7
|
|
|
8
8
|
export async function main(argv, ctx) {
|
|
9
9
|
const io = writers(ctx);
|
|
@@ -22,6 +22,7 @@ export async function main(argv, ctx) {
|
|
|
22
22
|
if (opts.help || opts.command === "help") {
|
|
23
23
|
const topic =
|
|
24
24
|
opts.helpTopic ?? (opts.command !== "help" ? opts.command : null);
|
|
25
|
+
banner(ctx);
|
|
25
26
|
io.write(helpText(topic));
|
|
26
27
|
return 0;
|
|
27
28
|
}
|
package/src/stacks.js
CHANGED
|
@@ -44,21 +44,31 @@ export function listDeployments({ exec, env, region = SMOOTH_REGION } = {}) {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
export function
|
|
47
|
+
export function statusTone(status, colors = {}) {
|
|
48
|
+
const s = String(status);
|
|
49
|
+
if (/FAIL|ROLLBACK/i.test(s)) return colors.red ?? "";
|
|
50
|
+
if (/IN_PROGRESS|PENDING|REVIEW/i.test(s)) return colors.violet ?? "";
|
|
51
|
+
if (/COMPLETE/i.test(s)) return colors.magenta ?? "";
|
|
52
|
+
return colors.violet ?? "";
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function formatDeployments(stacks, { region = SMOOTH_REGION, colors } = {}) {
|
|
56
|
+
const c = colors ?? { magenta: "", violet: "", dim: "", red: "", bold: "", reset: "" };
|
|
48
57
|
if (!stacks.length) {
|
|
49
58
|
return [`No Context101 deployments in ${region}.`, `Next: ${DEPLOY_CLI}`].join("\n");
|
|
50
59
|
}
|
|
51
60
|
const nameW = Math.max(4, ...stacks.map((s) => String(s.StackName).length));
|
|
52
61
|
const statusW = Math.max(6, ...stacks.map((s) => String(s.StackStatus).length));
|
|
53
62
|
const lines = [
|
|
54
|
-
|
|
63
|
+
`${c.dim}Context101 deployments in ${region}${c.reset}`,
|
|
55
64
|
"",
|
|
56
|
-
`${"NAME".padEnd(nameW)} ${"STATUS".padEnd(statusW)} UPDATED`,
|
|
65
|
+
`${c.dim}${"NAME".padEnd(nameW)} ${"STATUS".padEnd(statusW)} UPDATED${c.reset}`,
|
|
57
66
|
];
|
|
58
67
|
for (const stack of stacks) {
|
|
59
68
|
const updated = stack.LastUpdatedTime || stack.CreationTime || "";
|
|
69
|
+
const tone = statusTone(stack.StackStatus, c);
|
|
60
70
|
lines.push(
|
|
61
|
-
`${String(stack.StackName).padEnd(nameW)} ${String(stack.StackStatus).padEnd(statusW)} ${updated}`
|
|
71
|
+
`${String(stack.StackName).padEnd(nameW)} ${tone}${String(stack.StackStatus).padEnd(statusW)}${c.reset} ${c.dim}${updated}${c.reset}`
|
|
62
72
|
);
|
|
63
73
|
}
|
|
64
74
|
return lines.join("\n");
|
|
@@ -80,7 +90,7 @@ export async function runList(opts, ctx) {
|
|
|
80
90
|
io.err(listed.error);
|
|
81
91
|
return 1;
|
|
82
92
|
}
|
|
83
|
-
io.write(formatDeployments(listed.stacks, { region: SMOOTH_REGION }));
|
|
93
|
+
io.write(formatDeployments(listed.stacks, { region: SMOOTH_REGION, colors: io.c }));
|
|
84
94
|
io.write("");
|
|
85
95
|
return 0;
|
|
86
96
|
}
|
|
@@ -113,7 +123,7 @@ export async function runDestroy(opts, ctx) {
|
|
|
113
123
|
return 1;
|
|
114
124
|
}
|
|
115
125
|
|
|
116
|
-
io.write(formatDeployments(listed.stacks, { region: SMOOTH_REGION }));
|
|
126
|
+
io.write(formatDeployments(listed.stacks, { region: SMOOTH_REGION, colors: io.c }));
|
|
117
127
|
io.write("");
|
|
118
128
|
|
|
119
129
|
const known = listed.stacks.some((stack) => stack.StackName === stackName);
|
package/src/style.js
CHANGED
|
@@ -1,19 +1,40 @@
|
|
|
1
|
+
export const TAGLINE = "your context. every agent.";
|
|
2
|
+
|
|
3
|
+
const MAGENTA = [184, 85, 201];
|
|
4
|
+
const VIOLET = [139, 92, 246];
|
|
5
|
+
const DUSTY = [168, 158, 180];
|
|
6
|
+
const MAGENTA_256 = 170;
|
|
7
|
+
const VIOLET_256 = 99;
|
|
8
|
+
const DUSTY_256 = 139;
|
|
9
|
+
|
|
1
10
|
function enabled(stream) {
|
|
2
11
|
if (process.env.NO_COLOR) return false;
|
|
3
12
|
if (process.env.FORCE_COLOR === "0") return false;
|
|
4
13
|
return Boolean(stream && stream.isTTY);
|
|
5
14
|
}
|
|
6
15
|
|
|
16
|
+
function truecolor() {
|
|
17
|
+
const colorterm = String(process.env.COLORTERM || "").toLowerCase();
|
|
18
|
+
if (colorterm === "truecolor" || colorterm === "24bit") return true;
|
|
19
|
+
const term = String(process.env.TERM || "").toLowerCase();
|
|
20
|
+
return term.includes("truecolor") || term.includes("direct");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function fg(rgb, fallback256) {
|
|
24
|
+
if (truecolor()) return `\x1b[38;2;${rgb[0]};${rgb[1]};${rgb[2]}m`;
|
|
25
|
+
return `\x1b[38;5;${fallback256}m`;
|
|
26
|
+
}
|
|
27
|
+
|
|
7
28
|
export function palette(stream = process.stdout) {
|
|
8
29
|
if (!enabled(stream)) {
|
|
9
|
-
return {
|
|
30
|
+
return { magenta: "", violet: "", dim: "", red: "", bold: "", reset: "" };
|
|
10
31
|
}
|
|
11
32
|
return {
|
|
33
|
+
magenta: fg(MAGENTA, MAGENTA_256),
|
|
34
|
+
violet: fg(VIOLET, VIOLET_256),
|
|
35
|
+
dim: fg(DUSTY, DUSTY_256),
|
|
12
36
|
red: "\x1b[31m",
|
|
13
|
-
green: "\x1b[32m",
|
|
14
|
-
yellow: "\x1b[33m",
|
|
15
37
|
bold: "\x1b[1m",
|
|
16
|
-
dim: "\x1b[2m",
|
|
17
38
|
reset: "\x1b[0m",
|
|
18
39
|
};
|
|
19
40
|
}
|
|
@@ -28,10 +49,10 @@ export function writers(io) {
|
|
|
28
49
|
out.write(`${line}\n`);
|
|
29
50
|
},
|
|
30
51
|
ok(msg) {
|
|
31
|
-
out.write(`${c.
|
|
52
|
+
out.write(`${c.magenta}✓${c.reset} ${msg}\n`);
|
|
32
53
|
},
|
|
33
54
|
warn(msg) {
|
|
34
|
-
err.write(`${c.
|
|
55
|
+
err.write(`${c.violet}!${c.reset} ${msg}\n`);
|
|
35
56
|
},
|
|
36
57
|
err(msg) {
|
|
37
58
|
err.write(`${c.red}✗${c.reset} ${msg}\n`);
|
|
@@ -48,7 +69,7 @@ export function writers(io) {
|
|
|
48
69
|
export function banner(io) {
|
|
49
70
|
const { c, write } = writers(io);
|
|
50
71
|
write();
|
|
51
|
-
write(`${c.bold}Context101${c.reset}`);
|
|
52
|
-
write(`${c.dim}
|
|
72
|
+
write(`${c.bold}${c.magenta}Context101${c.reset}`);
|
|
73
|
+
write(`${c.dim}${TAGLINE}${c.reset}`);
|
|
53
74
|
write();
|
|
54
75
|
}
|