@ols-cli/lightspeed 0.1.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/CHANGELOG.md ADDED
@@ -0,0 +1,29 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 (2026-04-10)
4
+
5
+ ### Initial Release
6
+
7
+ - Forked from [pi-mono](https://github.com/badlogic/pi-mono) (MIT, by Mario Zechner)
8
+ - Rebranded as `ols` (OpenShift Lightspeed CLI)
9
+ - **OLS Client** (`packages/ols-client/`): Full REST API client for OpenShift Lightspeed Service
10
+ - Query, streaming query, conversations, feedback, health check
11
+ - Kubeconfig token extraction for K8S auth
12
+ - Config from `~/.ols/config.json` or `OLS_SERVICE_URL` env var
13
+ - **OLS Tools** (`packages/ols-cli/src/core/tools/ols/`):
14
+ - `ols_query` — Natural language queries with RAG
15
+ - `ols_stream` — Streaming responses
16
+ - `ols_health` — Service health check
17
+ - `ols_conversations` — List past conversations
18
+ - `ols_feedback` — Submit feedback
19
+ - **OpenShift Tools** (`packages/ols-cli/src/core/tools/openshift-tools.ts`):
20
+ - `oc_get` — Get resources
21
+ - `oc_describe` — Describe resources
22
+ - `oc_logs` — Fetch pod logs
23
+ - `oc_exec` — Execute commands in pods
24
+ - `cluster_status` — Cluster health overview
25
+ - **Skills**: troubleshoot-pod, deploy-app, security-audit, cluster-health
26
+ - **oc plugin**: `oc lightspeed` support via `oc-lightspeed` wrapper
27
+ - **Claude Code plugin**: `.claude-plugin/plugin.json`
28
+ - **OpenClaw skill**: `SKILL.md` (AgentSkills format)
29
+ - **Install script**: `install.sh` for quick setup
package/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # Lightspeed CLI
2
+
3
+ AI-powered OpenShift assistant from your terminal. Built on [pi-mono](https://github.com/badlogic/pi-mono).
4
+
5
+ Connects to [OpenShift Lightspeed Service (OLS)](https://github.com/openshift/lightspeed-service) and gives you an interactive AI chat in your terminal — powered by your cluster's OLS instance.
6
+
7
+ ## Features
8
+
9
+ - 🤖 Interactive AI assistant for OpenShift (TUI)
10
+ - 🔄 Streaming responses via SSE
11
+ - 💬 Session management with branching
12
+ - 🔐 K8S auth from kubeconfig (oc login)
13
+ - 🛠️ OpenShift-aware tools (oc-get, oc-describe, oc-logs)
14
+ - 📊 Cluster status at a glance
15
+ - 🔌 `oc` plugin compatible (`oc lightspeed`)
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ npm install -g @ols-cli/lightspeed
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```bash
26
+ # Configure OLS endpoint
27
+ ols config set serviceUrl https://lightspeed-service.openshift-operators.svc:8443
28
+
29
+ # Interactive mode
30
+ ols
31
+
32
+ # One-shot query
33
+ ols "how do I scale my deployment?"
34
+
35
+ # Health check
36
+ ols health
37
+
38
+ # List conversations
39
+ ols conversations
40
+ ```
41
+
42
+ ## Usage
43
+
44
+ ```bash
45
+ # Interactive mode
46
+ ols
47
+
48
+ # One-shot query
49
+ ols "how do I scale my deployment?"
50
+
51
+ # Streaming mode
52
+ ols --stream "check my pod health"
53
+
54
+ # As oc plugin
55
+ oc lightspeed "what's wrong with my cluster?"
56
+ ```
57
+
58
+ ## Configuration
59
+
60
+ ```bash
61
+ # Configure OLS endpoint
62
+ ols config set serviceUrl https://lightspeed-service.openshift-operators.svc:8443
63
+
64
+ # Or via environment
65
+ export OLS_SERVICE_URL=https://lightspeed-service.example.com:8443
66
+
67
+ # Auth comes from kubeconfig — just oc login
68
+ oc login https://api.my-cluster:6443
69
+ ```
70
+
71
+ ## Tools
72
+
73
+ | Tool | Description |
74
+ |------|-------------|
75
+ | `ols_query` | Query OLS for OpenShift knowledge (RAG-powered) |
76
+ | `ols_stream` | Streaming query to OLS |
77
+ | `ols_health` | Check OLS service health |
78
+ | `ols_conversations` | List past conversations |
79
+ | `ols_feedback` | Submit response feedback |
80
+ | `oc_get` | Get OpenShift resources |
81
+ | `oc_describe` | Describe resources in detail |
82
+ | `oc_logs` | Fetch pod logs |
83
+ | `oc_exec` | Execute commands in pods |
84
+ | `cluster_status` | Quick cluster health overview |
85
+
86
+ ## Skills
87
+
88
+ | Skill | When to Use |
89
+ |-------|-------------|
90
+ | `troubleshoot-pod` | Pod is CrashLooping, failing, or not ready |
91
+ | `deploy-app` | Deploying a new application |
92
+ | `security-audit` | Security posture review |
93
+ | `cluster-health` | Overall cluster health check |
94
+
95
+ ## Architecture
96
+
97
+ ```
98
+ lightspeed-cli/
99
+ ├── packages/
100
+ │ ├── ai/ — Unified LLM API (from pi-mono)
101
+ │ ├── agent/ — Agent runtime with tool calling (from pi-mono)
102
+ │ ├── tui/ — Terminal UI library (from pi-mono)
103
+ │ ├── ols-client/ — OLS REST API client (new)
104
+ │ └── ols-cli/ — CLI entry point + TUI (from pi-mono coding-agent)
105
+ │ └── src/core/tools/ols/ — OLS + OpenShift tools
106
+ ├── skills/ — OpenShift-specific agent skills
107
+ ├── scripts/oc-lightspeed — oc plugin wrapper
108
+ ├── .claude-plugin/ — Claude Code compatible
109
+ ├── SKILL.md — OpenClaw / AgentSkills compatible
110
+ └── README.md
111
+ ```
112
+
113
+ ## Requirements
114
+
115
+ - Node.js >= 20.6.0
116
+ - OpenShift cluster with Lightspeed Service deployed
117
+ - `oc` CLI (for auth via kubeconfig)
118
+
119
+ ## License
120
+
121
+ Apache-2.0 (original pi-mono code is MIT)
package/bin/ols.js ADDED
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ols — OpenShift Lightspeed CLI
4
+ *
5
+ * Usage:
6
+ * ols Interactive mode
7
+ * ols "how do I scale?" One-shot query
8
+ * ols health Check OLS health
9
+ * ols conversations List conversations
10
+ * ols config set <key> <val> Set config
11
+ * ols config show Show config
12
+ */
13
+ import { OLSClient, loadOLSConfig, saveOLSConfig } from "@ols-cli/client";
14
+
15
+ // ─── Colors (zero deps) ───
16
+ const cyan = "\x1b[36m";
17
+ const green = "\x1b[32m";
18
+ const red = "\x1b[31m";
19
+ const yellow = "\x1b[33m";
20
+ const bold = "\x1b[1m";
21
+ const reset = "\x1b[0m";
22
+ const dim = "\x1b[2m";
23
+
24
+ // ─── Config ───
25
+ function configCmd(args: string[]): void {
26
+ const cmd = args[0];
27
+ if (!cmd || cmd === "show") {
28
+ const cfg = loadOLSConfig();
29
+ console.log(JSON.stringify(cfg, null, 2));
30
+ return;
31
+ }
32
+ if (cmd === "set" && args[1] && args[2] !== undefined) {
33
+ const cfg = loadOLSConfig();
34
+ const val = args[2] === "true" ? true : args[2] === "false" ? false : args[2];
35
+ (cfg as any)[args[1]] = val;
36
+ saveOLSConfig(cfg);
37
+ console.log(`${green}✓${reset} Set ${args[1]} = ${args[2]}`);
38
+ return;
39
+ }
40
+ if (cmd === "init") {
41
+ console.log(`${cyan}OpenShift Lightspeed CLI Configuration${reset}\n`);
42
+ console.log(" ols config set serviceUrl https://lightspeed-service.example.com:8443");
43
+ console.log(" ols config set namespace openshift-operators\n");
44
+ console.log("Auth comes from kubeconfig — just run: oc login");
45
+ return;
46
+ }
47
+ console.log("Usage: ols config [show|set|init]");
48
+ }
49
+
50
+ // ─── Health ───
51
+ async function healthCmd(): Promise<void> {
52
+ try {
53
+ const client = new OLSClient(loadOLSConfig());
54
+ const h = await client.health();
55
+ console.log(`${green}✓${reset} OLS Status: ${h.status}`);
56
+ if (h.services) {
57
+ for (const [name, status] of Object.entries(h.services)) {
58
+ const icon = status === "ok" || status === "ready" ? green : yellow;
59
+ console.log(` ${icon}●${reset} ${name}: ${status}`);
60
+ }
61
+ }
62
+ } catch (e: any) {
63
+ console.error(`${red}✗${reset} ${e.message}`);
64
+ process.exit(1);
65
+ }
66
+ }
67
+
68
+ // ─── Conversations ───
69
+ async function conversationsCmd(): Promise<void> {
70
+ try {
71
+ const client = new OLSClient(loadOLSConfig());
72
+ const convos = await client.listConversations();
73
+ if (convos.length === 0) {
74
+ console.log(`${dim}No conversations found.${reset}`);
75
+ return;
76
+ }
77
+ console.log(`${bold}Recent Conversations${reset}\n`);
78
+ for (const c of convos.slice(0, 20)) {
79
+ const date = new Date(c.created_at).toLocaleDateString();
80
+ console.log(` ${cyan}${c.id}${reset} ${dim}${date}${reset} ${c.first_query || "(no query)"} [${c.message_count} msgs]`);
81
+ }
82
+ } catch (e: any) {
83
+ console.error(`${red}✗${reset} ${e.message}`);
84
+ process.exit(1);
85
+ }
86
+ }
87
+
88
+ // ─── One-shot query ───
89
+ async function queryCmd(question: string): Promise<void> {
90
+ try {
91
+ const client = new OLSClient(loadOLSConfig());
92
+ const resp = await client.query({ query: question });
93
+ console.log(`\n${resp.response}\n`);
94
+ if (resp.referenced_documents?.length) {
95
+ console.log(`${dim}References:${reset}`);
96
+ for (const doc of resp.referenced_documents) {
97
+ console.log(` ${cyan}→${reset} ${doc.title} ${dim}(${doc.url})${reset}`);
98
+ }
99
+ console.log();
100
+ }
101
+ if (resp.conversation_id) {
102
+ console.log(`${dim}Conversation: ${resp.conversation_id}${reset}`);
103
+ }
104
+ } catch (e: any) {
105
+ console.error(`${red}✗${reset} ${e.message}`);
106
+ process.exit(1);
107
+ }
108
+ }
109
+
110
+ // ─── Interactive REPL ───
111
+ async function interactiveMode(): Promise<void> {
112
+ const readline = await import("readline");
113
+
114
+ console.log(`\n${bold}${cyan}OpenShift Lightspeed CLI${reset} v0.1.0`);
115
+ console.log(`${dim}Type your question, or 'quit' to exit.${reset}\n`);
116
+
117
+ let conversationId: string | undefined;
118
+
119
+ const rl = readline.createInterface({
120
+ input: process.stdin,
121
+ output: process.stdout,
122
+ prompt: `${green}ols>${reset} `,
123
+ });
124
+
125
+ rl.prompt();
126
+
127
+ rl.on("line", async (line) => {
128
+ const input = line.trim();
129
+ if (!input) { rl.prompt(); return; }
130
+ if (input === "quit" || input === "exit" || input === "q") {
131
+ console.log(`${dim}Bye!${reset}`);
132
+ process.exit(0);
133
+ }
134
+ if (input === "health") { await healthCmd(); rl.prompt(); return; }
135
+ if (input === "conversations") { await conversationsCmd(); rl.prompt(); return; }
136
+
137
+ try {
138
+ const client = new OLSClient(loadOLSConfig());
139
+ const resp = await client.query({ query: input, conversation_id: conversationId });
140
+ conversationId = resp.conversation_id;
141
+ console.log(`\n${resp.response}\n`);
142
+ if (resp.referenced_documents?.length) {
143
+ console.log(`${dim}References:${reset}`);
144
+ for (const doc of resp.referenced_documents) {
145
+ console.log(` ${cyan}→${reset} ${doc.title}`);
146
+ }
147
+ console.log();
148
+ }
149
+ } catch (e: any) {
150
+ console.error(`${red}✗${reset} ${e.message}`);
151
+ }
152
+ rl.prompt();
153
+ });
154
+ }
155
+
156
+ // ─── Main ───
157
+ async function main(): Promise<void> {
158
+ const args = process.argv.slice(2);
159
+
160
+ if (args.length === 0) {
161
+ return interactiveMode();
162
+ }
163
+
164
+ const cmd = args[0];
165
+
166
+ if (cmd === "config") return configCmd(args.slice(1));
167
+ if (cmd === "health") return await healthCmd();
168
+ if (cmd === "conversations" || cmd === "convos") return await conversationsCmd();
169
+ if (cmd === "--help" || cmd === "-h" || cmd === "help") {
170
+ console.log(`${bold}Usage:${reset}
171
+ ols Interactive mode
172
+ ols "your question" One-shot query
173
+ ols health Check OLS service health
174
+ ols conversations List past conversations
175
+ ols config show Show configuration
176
+ ols config set <key> <val> Set config value
177
+ ols config init Setup help
178
+ ols help This help
179
+ `);
180
+ return;
181
+ }
182
+
183
+ // Treat as query
184
+ return await queryCmd(args.join(" "));
185
+ }
186
+
187
+ main().catch((e) => {
188
+ console.error(`${red}Fatal:${reset} ${e.message}`);
189
+ process.exit(1);
190
+ });
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@ols-cli/lightspeed",
3
+ "version": "0.1.0",
4
+ "description": "OpenShift Lightspeed CLI — AI-powered assistant for OpenShift from your terminal",
5
+ "type": "module",
6
+ "bin": {
7
+ "ols": "./bin/ols.js"
8
+ },
9
+ "main": "./src/index.js",
10
+ "files": [
11
+ "bin",
12
+ "src",
13
+ "skills",
14
+ "README.md",
15
+ "CHANGELOG.md"
16
+ ],
17
+ "scripts": {
18
+ "test": "echo \"no tests yet\""
19
+ },
20
+ "keywords": [
21
+ "openshift", "lightspeed", "ols", "kubernetes", "cli",
22
+ "ai-agent", "assistant", "terminal", "devops"
23
+ ],
24
+ "author": "Chin (kcns008)",
25
+ "license": "Apache-2.0",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/kcns008/lightspeed-cli.git"
29
+ },
30
+ "homepage": "https://github.com/kcns008/lightspeed-cli#readme",
31
+ "bugs": {
32
+ "url": "https://github.com/kcns008/lightspeed-cli/issues"
33
+ },
34
+ "engines": {
35
+ "node": ">=20.6.0"
36
+ },
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "dependencies": {
41
+ "@ols-cli/client": "^0.1.0"
42
+ }
43
+ }
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: cluster-health
3
+ description: >
4
+ Check the overall health of an OpenShift cluster. Use when the user asks about
5
+ cluster status, node health, capacity, or wants a quick health overview.
6
+ metadata:
7
+ author: kcns008
8
+ version: "0.1.0"
9
+ ---
10
+
11
+ # Cluster Health Check
12
+
13
+ ## Steps
14
+
15
+ 1. **Node status**
16
+ ```
17
+ cluster_status: (no args for full cluster)
18
+ ```
19
+
20
+ 2. **Check for warnings**
21
+ ```bash
22
+ oc get events -A --field-selector type=Warning --sort-by='.lastTimestamp'
23
+ ```
24
+
25
+ 3. **Check cluster operators** (OpenShift only)
26
+ ```bash
27
+ oc get clusteroperators
28
+ oc get co -o jsonpath='{range .items[?(@.status.conditions[?(@.type=="Available")].status!="True")]}{.metadata.name}{"\n"}{end}'
29
+ ```
30
+
31
+ 4. **Check alerts** (if monitoring stack available)
32
+ ```bash
33
+ oc get alerts -n openshift-monitoring
34
+ ```
35
+
36
+ 5. **Resource capacity**
37
+ ```bash
38
+ oc top nodes
39
+ oc get pods -A --field-selector=status.phase!=Running,status.phase!=Succeeded
40
+ ```
41
+
42
+ 6. **Summarize health**
43
+ - 🟢 Healthy — all nodes ready, no critical alerts
44
+ - 🟡 Warning — degraded operators or resource pressure
45
+ - 🔴 Critical — nodes down, pods failing, alerts firing
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: deploy-app
3
+ description: >
4
+ Guide deploying an application to OpenShift. Use when the user wants to deploy
5
+ a new app, create a deployment, set up services and routes. Covers S2I, Docker,
6
+ Helm, and raw YAML approaches.
7
+ metadata:
8
+ author: kcns008
9
+ version: "0.1.0"
10
+ ---
11
+
12
+ # Deploy Application
13
+
14
+ ## Steps
15
+
16
+ 1. **Ask about the app**
17
+ - What's the source? (Git repo, container image, local code)
18
+ - What's the runtime? (Java, Node.js, Python, Go, etc.)
19
+ - Which namespace/project?
20
+
21
+ 2. **Choose deployment method**
22
+
23
+ | Method | Best For |
24
+ |--------|----------|
25
+ | `oc new-app` | Quick deploy from source or image |
26
+ | `oc new-build` + deploy | Custom build pipeline |
27
+ | Helm chart | Complex apps with config |
28
+ | Raw YAML/Kustomize | Full control |
29
+
30
+ 3. **Deploy**
31
+ ```bash
32
+ # From Git (S2I)
33
+ oc new-app https://github.com/user/repo.git --name=myapp -n myns
34
+
35
+ # From image
36
+ oc new-app myimage:tag --name=myapp -n myns
37
+
38
+ # Expose
39
+ oc expose svc/myapp
40
+ ```
41
+
42
+ 4. **Verify**
43
+ ```
44
+ oc_get: resource=pods -n <namespace>
45
+ oc_get: resource=svc -n <namespace>
46
+ oc_get: resource=route -n <namespace>
47
+ ```
48
+
49
+ 5. **Set up health checks** (if not auto-detected)
50
+ ```bash
51
+ oc set probe dc/myapp --readiness --get-url=http://:8080/health
52
+ oc set probe dc/myapp --liveness --get-url=http://:8080/health
53
+ ```
54
+
55
+ 6. **Configure resources**
56
+ ```bash
57
+ oc set resources dc/myapp --requests=cpu=100m,memory=256Mi --limits=cpu=500m,memory=512Mi
58
+ ```
@@ -0,0 +1,48 @@
1
+ ---
2
+ name: security-audit
3
+ description: >
4
+ Run a security audit on an OpenShift namespace or cluster. Use when the user
5
+ asks about security posture, RBAC, SCCs, network policies, or compliance.
6
+ metadata:
7
+ author: kcns008
8
+ version: "0.1.0"
9
+ ---
10
+
11
+ # Security Audit
12
+
13
+ ## Steps
14
+
15
+ 1. **Check RBAC**
16
+ ```bash
17
+ oc get clusterrolebindings -o wide
18
+ oc get rolebindings -n <namespace>
19
+ oc auth can-i --list --as=system:serviceaccount:<ns>:<sa>
20
+ ```
21
+
22
+ 2. **Check Security Context Constraints**
23
+ ```bash
24
+ oc get scc
25
+ oc describe scc restricted
26
+ ```
27
+
28
+ 3. **Check pod security**
29
+ ```bash
30
+ oc get pods -n <namespace> -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.securityContext}{"\n"}{end}'
31
+ ```
32
+
33
+ 4. **Check network policies**
34
+ ```bash
35
+ oc get networkpolicies -n <namespace>
36
+ ```
37
+
38
+ 5. **Check image vulnerabilities** (if Security Operator installed)
39
+ ```bash
40
+ oc get vulnerabilities -n <namespace>
41
+ oc get imagevulnerabilities -n <namespace>
42
+ ```
43
+
44
+ 6. **Summarize findings**
45
+ - Overly permissive RBAC
46
+ - Pods running as root
47
+ - Missing network policies
48
+ - Known vulnerabilities
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: troubleshoot-pod
3
+ description: >
4
+ Troubleshoot a problematic pod in OpenShift. Use when a pod is CrashLooping,
5
+ not ready, failing health checks, or showing errors. Walks through events,
6
+ logs, describe, and common failure patterns.
7
+ metadata:
8
+ author: kcns008
9
+ version: "0.1.0"
10
+ ---
11
+
12
+ # Troubleshoot Pod
13
+
14
+ ## Steps
15
+
16
+ 1. **Get pod status**
17
+ ```
18
+ oc_get: resource=pods -n <namespace>
19
+ ```
20
+ Identify the problematic pod. Note its status (CrashLoopBackOff, ImagePullBackOff, Pending, etc.)
21
+
22
+ 2. **Describe the pod**
23
+ ```
24
+ oc_describe: resource=pod/<pod-name> -n <namespace>
25
+ ```
26
+ Look for: Events (bottom), State, Last State, Reason, Message
27
+
28
+ 3. **Check events**
29
+ ```
30
+ bash: oc get events -n <namespace> --sort-by='.lastTimestamp' --field-selector involvedObject.name=<pod-name>
31
+ ```
32
+
33
+ 4. **Fetch logs**
34
+ ```
35
+ oc_logs: pod=<pod-name> -n <namespace> --tail=100
36
+ ```
37
+ If crashed previously, add `--previous` flag
38
+
39
+ 5. **Diagnose based on patterns**
40
+
41
+ | Status | Common Cause | Fix |
42
+ |--------|-------------|-----|
43
+ | CrashLoopBackOff | App crash on startup | Check logs for exception/exit code |
44
+ | ImagePullBackOff | Wrong image/tag or no pull secret | Verify image name, check secrets |
45
+ | Pending | No resources (CPU/memory) or PVC issues | Check node capacity, PVC status |
46
+ | OOMKilled | Memory limit too low | Increase memory limit |
47
+ | Error | Config/secrets missing | Check env vars, mounted configmaps |
48
+ | Completed | Job/one-shot finished | Normal for Jobs |
49
+
50
+ 6. **Summarize findings and suggest fix**