@opvs-ai/cli 0.1.3 → 0.2.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/README.md +209 -0
- package/dist/commands/auth.js +35 -23
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/boards.js +9 -6
- package/dist/commands/boards.js.map +1 -1
- package/dist/commands/comments.js +6 -4
- package/dist/commands/comments.js.map +1 -1
- package/dist/commands/config.js +99 -28
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/docs.js +14 -9
- package/dist/commands/docs.js.map +1 -1
- package/dist/commands/session.js +4 -5
- package/dist/commands/session.js.map +1 -1
- package/dist/commands/tasks.js +11 -7
- package/dist/commands/tasks.js.map +1 -1
- package/dist/commands/workspace.d.ts +5 -0
- package/dist/commands/workspace.js +65 -0
- package/dist/commands/workspace.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/api.d.ts +3 -3
- package/dist/lib/api.js +6 -6
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/config.d.ts +52 -3
- package/dist/lib/config.js +208 -15
- package/dist/lib/config.js.map +1 -1
- package/dist/types.d.ts +22 -2
- package/dist/types.js +7 -2
- package/dist/types.js.map +1 -1
- package/package.json +3 -2
package/README.md
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# @opvs-ai/cli
|
|
2
|
+
|
|
3
|
+
Terminal access to [AgentBoard](https://opvs.ai) + AgentDocs for AI coding agents.
|
|
4
|
+
|
|
5
|
+
Gives Claude Code, Cursor, Windsurf, and other terminal AI agents native shell access to task boards and documentation via simple CLI commands.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @opvs-ai/cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or run without installing:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx @opvs-ai/cli --help
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# 1. Authenticate (sends approval email to workspace admin)
|
|
23
|
+
opvs auth request -w my-workspace -e admin@example.com
|
|
24
|
+
|
|
25
|
+
# 2. Check your boards
|
|
26
|
+
opvs boards list
|
|
27
|
+
|
|
28
|
+
# 3. See your assigned tasks
|
|
29
|
+
opvs tasks list --self
|
|
30
|
+
|
|
31
|
+
# 4. Complete a task with results
|
|
32
|
+
opvs tasks update <task-id> --status review --result-file ./output.md
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Auth Flow
|
|
36
|
+
|
|
37
|
+
The CLI uses AI-native authentication. The agent requests its own token, and a human approves via email:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
Agent runs: opvs auth request -w <workspace> -e <admin-email>
|
|
41
|
+
--> Approval email sent to admin
|
|
42
|
+
--> CLI polls for approval every 3s
|
|
43
|
+
|
|
44
|
+
Admin clicks: [Approve] button in email
|
|
45
|
+
--> Token generated and delivered to CLI
|
|
46
|
+
--> Saved to ~/.opvs/config.json
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
No passwords, no copy-pasting tokens. The human stays in control.
|
|
50
|
+
|
|
51
|
+
## Multi-Workspace Support
|
|
52
|
+
|
|
53
|
+
The CLI supports multiple workspaces (brands) with kubectl-style context switching. Each workspace has its own token, brand, and API URL.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Authenticate to multiple workspaces
|
|
57
|
+
opvs auth request -w my-company -e admin@mycompany.com
|
|
58
|
+
opvs auth request -w other-brand -e admin@other.com
|
|
59
|
+
|
|
60
|
+
# List all workspaces (* = current)
|
|
61
|
+
opvs workspace list
|
|
62
|
+
|
|
63
|
+
# Switch workspace
|
|
64
|
+
opvs workspace use other-brand
|
|
65
|
+
|
|
66
|
+
# Run a command against a specific workspace (without switching)
|
|
67
|
+
opvs -w my-company boards list
|
|
68
|
+
|
|
69
|
+
# Show current workspace details
|
|
70
|
+
opvs workspace current
|
|
71
|
+
|
|
72
|
+
# Remove a workspace
|
|
73
|
+
opvs workspace remove old-brand
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Config File
|
|
77
|
+
|
|
78
|
+
All workspaces are stored in `~/.opvs/config.json`:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"version": 2,
|
|
83
|
+
"current_workspace": "my-company",
|
|
84
|
+
"format": "yaml",
|
|
85
|
+
"workspaces": {
|
|
86
|
+
"my-company": {
|
|
87
|
+
"api_url": "https://app.opvs.ai",
|
|
88
|
+
"token": "pat_...",
|
|
89
|
+
"brand_id": 1,
|
|
90
|
+
"brand_name": "My Company"
|
|
91
|
+
},
|
|
92
|
+
"other-brand": {
|
|
93
|
+
"api_url": "https://app.opvs.ai",
|
|
94
|
+
"token": "pat_...",
|
|
95
|
+
"brand_id": 11,
|
|
96
|
+
"brand_name": "Other Brand"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Environment Variables
|
|
103
|
+
|
|
104
|
+
Override workspace selection and settings without modifying config:
|
|
105
|
+
|
|
106
|
+
| Variable | Description |
|
|
107
|
+
|----------|-------------|
|
|
108
|
+
| `OPVS_WORKSPACE` | Workspace slug to use |
|
|
109
|
+
| `OPVS_API_URL` | Override API base URL |
|
|
110
|
+
| `OPVS_TOKEN` | Override PAT token (useful in CI/CD) |
|
|
111
|
+
| `OPVS_FORMAT` | Override output format |
|
|
112
|
+
|
|
113
|
+
## Commands
|
|
114
|
+
|
|
115
|
+
### Boards
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
opvs boards list # List all boards
|
|
119
|
+
opvs boards get <id> # Board details + columns
|
|
120
|
+
opvs boards create -n "Sprint 1" # Create a board
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Tasks
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
opvs tasks list --board <id> # List tasks on a board
|
|
127
|
+
opvs tasks list --self # My assigned tasks
|
|
128
|
+
opvs tasks get <id> # Task details
|
|
129
|
+
opvs tasks create --board <id> -t "Title" # Create task
|
|
130
|
+
opvs tasks update <id> --status review # Update status
|
|
131
|
+
opvs tasks update <id> --result-file out.md # Attach result from file
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Comments
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
opvs comments list <task-id> # List task comments
|
|
138
|
+
opvs comments add <task-id> "message" # Add inline comment
|
|
139
|
+
opvs comments add <task-id> -f output.md # Comment from file
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Docs
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
opvs docs list # List doc projects
|
|
146
|
+
opvs docs get <project> <slug> # Read a page
|
|
147
|
+
opvs docs create <project> -t "Title" -s "slug" -f content.md
|
|
148
|
+
opvs docs update <project> <slug> -f content.md
|
|
149
|
+
opvs docs search "query" # Search docs
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Session
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
opvs session get --self # Your context + assigned tasks
|
|
156
|
+
opvs session get --board <id> # Board overview
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Config
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
opvs config set api_url https://app.opvs.ai
|
|
163
|
+
opvs config set format yaml # yaml | json | md
|
|
164
|
+
opvs config get # Show current workspace config
|
|
165
|
+
opvs config get --all # Show all workspaces
|
|
166
|
+
opvs config path # Config file location
|
|
167
|
+
opvs init # Print CLAUDE.md snippet
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Auth
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
opvs auth request -w <slug> -e <email> # Request token
|
|
174
|
+
opvs auth status # Current auth info
|
|
175
|
+
opvs auth revoke # Revoke token
|
|
176
|
+
opvs auth list # List agent tokens (admin)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Workspace
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
opvs workspace list # List all workspaces
|
|
183
|
+
opvs workspace use <slug> # Switch current workspace
|
|
184
|
+
opvs workspace current # Show current workspace details
|
|
185
|
+
opvs workspace remove <slug> # Remove a saved workspace
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## YAML Output
|
|
189
|
+
|
|
190
|
+
All read commands return YAML by default for token-efficient AI agent consumption (40-76% fewer tokens than JSON). Set format with:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
opvs config set format yaml # default
|
|
194
|
+
opvs config set format json
|
|
195
|
+
opvs config set format md
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Claude Code Integration
|
|
199
|
+
|
|
200
|
+
Run `opvs init` to generate a CLAUDE.md snippet you can add to your project, giving Claude Code automatic access to your board and docs.
|
|
201
|
+
|
|
202
|
+
## Requirements
|
|
203
|
+
|
|
204
|
+
- Node.js 18+
|
|
205
|
+
- An OPVS workspace ([opvs.ai](https://opvs.ai))
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
Proprietary - OPVS.ai
|
package/dist/commands/auth.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* opvs auth — AI-native token provisioning + management
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import { getEffectiveConfig, saveWorkspace, setCurrentWorkspace, loadRawConfig, } from "../lib/config.js";
|
|
5
5
|
import { apiUnauthPost, createClient } from "../lib/api.js";
|
|
6
6
|
import { buildFingerprint } from "../lib/fingerprint.js";
|
|
7
7
|
import { pollForApproval } from "../lib/auth-poll.js";
|
|
8
8
|
import { printJson } from "../lib/format.js";
|
|
9
|
+
import { DEFAULT_WORKSPACE } from "../types.js";
|
|
9
10
|
export function registerAuthCommands(program) {
|
|
10
11
|
const auth = program.command("auth").description("Token authentication");
|
|
11
12
|
auth
|
|
@@ -18,8 +19,10 @@ export function registerAuthCommands(program) {
|
|
|
18
19
|
.option("-t, --ttl <hours>", "Token TTL in hours", "72")
|
|
19
20
|
.option("--api-url <url>", "API base URL (overrides config)")
|
|
20
21
|
.action(async (opts) => {
|
|
21
|
-
|
|
22
|
-
const
|
|
22
|
+
// Resolve API URL: explicit flag > existing workspace > default
|
|
23
|
+
const config = loadRawConfig();
|
|
24
|
+
const existing = config.workspaces[opts.workspace];
|
|
25
|
+
const baseUrl = opts.apiUrl || existing?.api_url || DEFAULT_WORKSPACE.api_url;
|
|
23
26
|
const fingerprint = buildFingerprint();
|
|
24
27
|
const scopes = opts.scopes.split(",").map((s) => s.trim());
|
|
25
28
|
console.log(`Requesting access to workspace "${opts.workspace}"...`);
|
|
@@ -40,14 +43,15 @@ export function registerAuthCommands(program) {
|
|
|
40
43
|
// Start polling
|
|
41
44
|
const result = await pollForApproval(baseUrl, request_id, poll_token);
|
|
42
45
|
if (result.status === "active" && result.token) {
|
|
43
|
-
// Save token
|
|
44
|
-
|
|
46
|
+
// Save token to workspace-scoped config
|
|
47
|
+
saveWorkspace(opts.workspace, {
|
|
45
48
|
api_url: baseUrl,
|
|
46
49
|
token: result.token,
|
|
47
50
|
brand_id: result.brand_id ?? null,
|
|
48
51
|
brand_name: result.brand_name ?? "",
|
|
49
52
|
});
|
|
50
|
-
|
|
53
|
+
setCurrentWorkspace(opts.workspace);
|
|
54
|
+
console.log(`\nAuthenticated! Token saved to workspace "${opts.workspace}".`);
|
|
51
55
|
console.log(`Brand: ${result.brand_name} (ID: ${result.brand_id})`);
|
|
52
56
|
console.log(`Scopes: ${result.scopes?.join(", ")}`);
|
|
53
57
|
}
|
|
@@ -74,13 +78,14 @@ export function registerAuthCommands(program) {
|
|
|
74
78
|
.command("status")
|
|
75
79
|
.description("Show current authentication status")
|
|
76
80
|
.action(async () => {
|
|
77
|
-
const
|
|
78
|
-
if (!cfg.token) {
|
|
79
|
-
console.log("Not authenticated. Run `opvs auth request` to get a token.");
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
81
|
+
const wsSlug = program.opts().workspace;
|
|
82
82
|
try {
|
|
83
|
-
const
|
|
83
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
84
|
+
if (!cfg.token) {
|
|
85
|
+
console.log("Not authenticated. Run `opvs auth request` to get a token.");
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const client = createClient(wsSlug);
|
|
84
89
|
const res = await client.get("/api/v1/auth/me");
|
|
85
90
|
const data = await res.json();
|
|
86
91
|
printJson(data);
|
|
@@ -98,15 +103,16 @@ export function registerAuthCommands(program) {
|
|
|
98
103
|
});
|
|
99
104
|
auth
|
|
100
105
|
.command("revoke")
|
|
101
|
-
.description("Revoke the current
|
|
106
|
+
.description("Revoke the token for the current workspace")
|
|
102
107
|
.action(async () => {
|
|
103
|
-
const
|
|
104
|
-
if (!cfg.token) {
|
|
105
|
-
console.log("Not authenticated — nothing to revoke.");
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
+
const wsSlug = program.opts().workspace;
|
|
108
109
|
try {
|
|
109
|
-
const
|
|
110
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
111
|
+
if (!cfg.token) {
|
|
112
|
+
console.log("Not authenticated — nothing to revoke.");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const client = createClient(wsSlug);
|
|
110
116
|
// Find the token ID by matching prefix from the tokens list
|
|
111
117
|
const prefix = cfg.token.slice(0, 16);
|
|
112
118
|
const listRes = await client.get("/api/v1/tokens");
|
|
@@ -119,13 +125,18 @@ export function registerAuthCommands(program) {
|
|
|
119
125
|
else {
|
|
120
126
|
console.log("Token not found on server (may already be revoked).");
|
|
121
127
|
}
|
|
122
|
-
|
|
123
|
-
|
|
128
|
+
// Clear token in workspace config
|
|
129
|
+
saveWorkspace(cfg.workspace_slug, { token: "", brand_id: null, brand_name: "" });
|
|
130
|
+
console.log(`Local config cleared for workspace "${cfg.workspace_slug}".`);
|
|
124
131
|
}
|
|
125
132
|
catch (err) {
|
|
126
133
|
const e = err;
|
|
127
134
|
// Clear local config even if server revoke fails
|
|
128
|
-
|
|
135
|
+
try {
|
|
136
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
137
|
+
saveWorkspace(cfg.workspace_slug, { token: "", brand_id: null, brand_name: "" });
|
|
138
|
+
}
|
|
139
|
+
catch { /* ignore */ }
|
|
129
140
|
console.error(`Server revoke failed (${e.detail}), but local config cleared.`);
|
|
130
141
|
}
|
|
131
142
|
});
|
|
@@ -133,8 +144,9 @@ export function registerAuthCommands(program) {
|
|
|
133
144
|
.command("list")
|
|
134
145
|
.description("List all agent tokens for the workspace (admin)")
|
|
135
146
|
.action(async () => {
|
|
147
|
+
const wsSlug = program.opts().workspace;
|
|
136
148
|
try {
|
|
137
|
-
const client = createClient();
|
|
149
|
+
const client = createClient(wsSlug);
|
|
138
150
|
const res = await client.get("/api/v1/auth/pat/agents");
|
|
139
151
|
const data = await res.json();
|
|
140
152
|
printJson(data);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/boards.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* opvs boards — board CRUD
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import { getEffectiveConfig } from "../lib/config.js";
|
|
5
5
|
import { createClient } from "../lib/api.js";
|
|
6
6
|
import { buildUrl, printResponse, printJson } from "../lib/format.js";
|
|
7
7
|
export function registerBoardCommands(program) {
|
|
@@ -11,9 +11,10 @@ export function registerBoardCommands(program) {
|
|
|
11
11
|
.description("List boards")
|
|
12
12
|
.option("--status <status>", "Filter by status")
|
|
13
13
|
.action(async (opts) => {
|
|
14
|
-
const
|
|
14
|
+
const wsSlug = program.opts().workspace;
|
|
15
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
15
16
|
try {
|
|
16
|
-
const client = createClient();
|
|
17
|
+
const client = createClient(wsSlug);
|
|
17
18
|
const params = {};
|
|
18
19
|
if (opts.status)
|
|
19
20
|
params.status = opts.status;
|
|
@@ -31,9 +32,10 @@ export function registerBoardCommands(program) {
|
|
|
31
32
|
.command("get <id>")
|
|
32
33
|
.description("Get board details")
|
|
33
34
|
.action(async (id) => {
|
|
34
|
-
const
|
|
35
|
+
const wsSlug = program.opts().workspace;
|
|
36
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
35
37
|
try {
|
|
36
|
-
const client = createClient();
|
|
38
|
+
const client = createClient(wsSlug);
|
|
37
39
|
const url = buildUrl(`/api/v1/board/boards/${id}`, undefined, cfg.format);
|
|
38
40
|
const res = await client.get(url);
|
|
39
41
|
await printResponse(res);
|
|
@@ -50,8 +52,9 @@ export function registerBoardCommands(program) {
|
|
|
50
52
|
.requiredOption("-n, --name <name>", "Board name")
|
|
51
53
|
.option("-d, --description <desc>", "Board description")
|
|
52
54
|
.action(async (opts) => {
|
|
55
|
+
const wsSlug = program.opts().workspace;
|
|
53
56
|
try {
|
|
54
|
-
const client = createClient();
|
|
57
|
+
const client = createClient(wsSlug);
|
|
55
58
|
const body = { name: opts.name };
|
|
56
59
|
if (opts.description)
|
|
57
60
|
body.description = opts.description;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boards.js","sourceRoot":"","sources":["../../src/commands/boards.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"boards.js","sourceRoot":"","sources":["../../src/commands/boards.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* opvs comments — task comments (activity feed)
|
|
3
3
|
*/
|
|
4
4
|
import { readFileSync } from "node:fs";
|
|
5
|
-
import {
|
|
5
|
+
import { getEffectiveConfig } from "../lib/config.js";
|
|
6
6
|
import { createClient } from "../lib/api.js";
|
|
7
7
|
import { buildUrl, printResponse, printJson } from "../lib/format.js";
|
|
8
8
|
export function registerCommentCommands(program) {
|
|
@@ -12,9 +12,10 @@ export function registerCommentCommands(program) {
|
|
|
12
12
|
.description("List comments on a task")
|
|
13
13
|
.option("--limit <n>", "Max results", "25")
|
|
14
14
|
.action(async (taskId, opts) => {
|
|
15
|
-
const
|
|
15
|
+
const wsSlug = program.opts().workspace;
|
|
16
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
16
17
|
try {
|
|
17
|
-
const client = createClient();
|
|
18
|
+
const client = createClient(wsSlug);
|
|
18
19
|
const params = {};
|
|
19
20
|
if (opts.limit)
|
|
20
21
|
params.limit = opts.limit;
|
|
@@ -33,8 +34,9 @@ export function registerCommentCommands(program) {
|
|
|
33
34
|
.description("Add a comment to a task")
|
|
34
35
|
.option("-f, --file <path>", "Read comment body from file")
|
|
35
36
|
.action(async (taskId, message, opts) => {
|
|
37
|
+
const wsSlug = program.opts().workspace;
|
|
36
38
|
try {
|
|
37
|
-
const client = createClient();
|
|
39
|
+
const client = createClient(wsSlug);
|
|
38
40
|
let body;
|
|
39
41
|
if (opts.file) {
|
|
40
42
|
body = readFileSync(opts.file, "utf-8");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comments.js","sourceRoot":"","sources":["../../src/commands/comments.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"comments.js","sourceRoot":"","sources":["../../src/commands/comments.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/config.js
CHANGED
|
@@ -1,45 +1,99 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* opvs config — manage CLI configuration + opvs init
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import { getEffectiveConfig, saveWorkspace, saveGlobal, resetConfig, getConfigPath, loadRawConfig, } from "../lib/config.js";
|
|
5
|
+
const GLOBAL_KEYS = ["format"];
|
|
6
|
+
const WORKSPACE_KEYS = ["api_url", "token", "brand_id", "brand_name"];
|
|
7
|
+
const ALL_KEYS = [...GLOBAL_KEYS, ...WORKSPACE_KEYS];
|
|
5
8
|
export function registerConfigCommands(program) {
|
|
6
9
|
const config = program.command("config").description("Manage CLI configuration");
|
|
7
10
|
config
|
|
8
11
|
.command("set <key> <value>")
|
|
9
12
|
.description("Set a config value (api_url, token, brand_id, brand_name, format)")
|
|
10
13
|
.action((key, value) => {
|
|
11
|
-
|
|
12
|
-
if (!valid.includes(key)) {
|
|
14
|
+
if (!ALL_KEYS.includes(key)) {
|
|
13
15
|
console.error(`Unknown config key: ${key}`);
|
|
14
|
-
console.error(`Valid keys: ${
|
|
16
|
+
console.error(`Valid keys: ${ALL_KEYS.join(", ")}`);
|
|
15
17
|
process.exit(1);
|
|
16
18
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
if (GLOBAL_KEYS.includes(key)) {
|
|
20
|
+
// Global setting
|
|
21
|
+
if (key === "format") {
|
|
22
|
+
const valid = ["yaml", "json", "md"];
|
|
23
|
+
if (!valid.includes(value)) {
|
|
24
|
+
console.error(`Invalid format. Choose: ${valid.join(", ")}`);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
saveGlobal({ format: value });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
// Workspace-scoped setting
|
|
32
|
+
const wsSlug = program.opts().workspace;
|
|
33
|
+
let cfg;
|
|
34
|
+
try {
|
|
35
|
+
cfg = getEffectiveConfig(wsSlug);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
console.error("No workspace selected. Use -w <slug> or run `opvs workspace use <slug>` first.");
|
|
39
|
+
process.exit(1);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const parsed = key === "brand_id" ? Number(value) : value;
|
|
43
|
+
saveWorkspace(cfg.workspace_slug, { [key]: parsed });
|
|
44
|
+
}
|
|
19
45
|
console.log(`${key} = ${value}`);
|
|
20
46
|
});
|
|
21
47
|
config
|
|
22
48
|
.command("get [key]")
|
|
23
49
|
.description("Show current config (or a specific key)")
|
|
24
|
-
.
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
50
|
+
.option("--all", "Show full config with all workspaces")
|
|
51
|
+
.action((key, opts) => {
|
|
52
|
+
if (opts.all) {
|
|
53
|
+
const raw = loadRawConfig();
|
|
54
|
+
// Mask tokens in all workspaces
|
|
55
|
+
const display = {
|
|
56
|
+
...raw,
|
|
57
|
+
workspaces: Object.fromEntries(Object.entries(raw.workspaces).map(([slug, ws]) => [
|
|
58
|
+
slug,
|
|
59
|
+
{ ...ws, token: ws.token ? `${ws.token.slice(0, 12)}...` : "(not set)" },
|
|
60
|
+
])),
|
|
61
|
+
};
|
|
62
|
+
console.log(JSON.stringify(display, null, 2));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const wsSlug = program.opts().workspace;
|
|
67
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
68
|
+
if (key) {
|
|
69
|
+
const val = cfg[key];
|
|
70
|
+
if (val === undefined) {
|
|
71
|
+
console.error(`Unknown config key: ${key}`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
console.log(val);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
const display = {
|
|
78
|
+
workspace: cfg.workspace_slug,
|
|
79
|
+
api_url: cfg.api_url,
|
|
80
|
+
brand_name: cfg.brand_name || "(not set)",
|
|
81
|
+
brand_id: cfg.brand_id,
|
|
82
|
+
token: cfg.token ? `${cfg.token.slice(0, 12)}...` : "(not set)",
|
|
83
|
+
format: cfg.format,
|
|
84
|
+
};
|
|
85
|
+
console.log(JSON.stringify(display, null, 2));
|
|
31
86
|
}
|
|
32
|
-
console.log(val);
|
|
33
87
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
88
|
+
catch (err) {
|
|
89
|
+
const e = err;
|
|
90
|
+
console.error(e.message);
|
|
91
|
+
process.exit(1);
|
|
38
92
|
}
|
|
39
93
|
});
|
|
40
94
|
config
|
|
41
95
|
.command("reset")
|
|
42
|
-
.description("Reset config to defaults")
|
|
96
|
+
.description("Reset config to defaults (removes all workspaces)")
|
|
43
97
|
.action(() => {
|
|
44
98
|
resetConfig();
|
|
45
99
|
console.log("Config reset to defaults.");
|
|
@@ -55,29 +109,46 @@ export function registerConfigCommands(program) {
|
|
|
55
109
|
.command("init")
|
|
56
110
|
.description("Print a CLAUDE.md snippet for AI agent integration")
|
|
57
111
|
.action(() => {
|
|
58
|
-
|
|
112
|
+
let wsInfo = "";
|
|
113
|
+
try {
|
|
114
|
+
const wsSlug = program.opts().workspace;
|
|
115
|
+
const cfg = getEffectiveConfig(wsSlug);
|
|
116
|
+
wsInfo = `
|
|
117
|
+
## Config
|
|
118
|
+
- Workspace: ${cfg.workspace_slug}
|
|
119
|
+
- API: ${cfg.api_url}
|
|
120
|
+
- Brand: ${cfg.brand_name || "(not set)"}
|
|
121
|
+
- Format: ${cfg.format}
|
|
122
|
+
`;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
wsInfo = `
|
|
126
|
+
## Config
|
|
127
|
+
- Run \`opvs auth request -w <slug> -e <admin-email>\` to authenticate first.
|
|
128
|
+
`;
|
|
129
|
+
}
|
|
59
130
|
const snippet = `# OPVS AgentBoard + Docs
|
|
60
131
|
|
|
61
132
|
## Setup
|
|
62
133
|
Run \`opvs auth request --workspace <slug> --email <your-email>\` if not authenticated.
|
|
63
134
|
|
|
135
|
+
## Workspace
|
|
136
|
+
- \`opvs workspace list\` — List configured workspaces
|
|
137
|
+
- \`opvs workspace use <slug>\` — Switch workspace
|
|
138
|
+
- \`opvs -w <slug> <command>\` — Run a command against a specific workspace
|
|
139
|
+
|
|
64
140
|
## Board Commands
|
|
65
141
|
- \`opvs session get --self\` — Board context + assigned tasks
|
|
66
142
|
- \`opvs tasks list --self --status pending\` — Pending tasks
|
|
67
|
-
- \`opvs
|
|
68
|
-
- \`opvs
|
|
143
|
+
- \`opvs tasks update <id> --status review --result-file ./output.md\` — Complete a task
|
|
144
|
+
- \`opvs comments add <id> "message"\` — Add a comment
|
|
69
145
|
|
|
70
146
|
## Docs Commands
|
|
71
147
|
- \`opvs docs list\` — List doc projects
|
|
72
148
|
- \`opvs docs get <project> <slug>\` — Read a page
|
|
73
149
|
- \`opvs docs update <project> <slug> --file ./output.md\` — Update a page
|
|
74
150
|
- \`opvs docs search "query"\` — Search docs
|
|
75
|
-
|
|
76
|
-
## Config
|
|
77
|
-
- API: ${cfg.api_url}
|
|
78
|
-
- Brand: ${cfg.brand_name || "(not set)"}
|
|
79
|
-
- Format: ${cfg.format}
|
|
80
|
-
`;
|
|
151
|
+
${wsInfo}`;
|
|
81
152
|
console.log(snippet);
|
|
82
153
|
});
|
|
83
154
|
}
|