nubase_cli 0.1.8 → 0.1.9
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 +12 -0
- package/dist/src/index.js +1 -1
- package/dist/src/install-skills.d.ts +6 -0
- package/dist/src/install-skills.js +47 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -126,6 +126,18 @@ The `npx` spec is pinned to the installed CLI version for reproducibility. Pass
|
|
|
126
126
|
|
|
127
127
|
Use `--mcp both` to also write project `.codex/config.toml` for Codex. Use `--no-mcp` to skip MCP config.
|
|
128
128
|
|
|
129
|
+
### Permissions
|
|
130
|
+
|
|
131
|
+
The MCP config's `env` block gates what the agent may do. Reads are always allowed; these flags gate write/execute tools:
|
|
132
|
+
|
|
133
|
+
| Flag | Default | Unlocks |
|
|
134
|
+
| --- | --- | --- |
|
|
135
|
+
| `NUBASE_ALLOW_SQL_EXECUTE` | **on** | `sql_execute` (run SQL) |
|
|
136
|
+
| `NUBASE_ALLOW_ADMIN_WRITE` | **on** | create/delete buckets & users, issue/revoke gateway keys |
|
|
137
|
+
| `NUBASE_ALLOW_DANGEROUS_SQL` | **off** | SQL classified DANGEROUS (DROP/TRUNCATE/...) |
|
|
138
|
+
|
|
139
|
+
`install-skills` writes SQL-execute and admin-write into the config by default; dangerous SQL stays off. Opt out per install with `--no-sql-execute` / `--no-admin-write`, or opt into dangerous SQL with `--allow-dangerous-sql`. You can also edit the flags directly in `.mcp.json` (or `.codex/config.toml`) afterwards.
|
|
140
|
+
|
|
129
141
|
Installed structure:
|
|
130
142
|
|
|
131
143
|
- `nubase/SKILL.md`
|
package/dist/src/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { installSkills, parseInstallArgs } from './install-skills.js';
|
|
|
6
6
|
import { McpStdioServer } from './mcp-stdio.js';
|
|
7
7
|
import { NubaseClient } from './nubase-client.js';
|
|
8
8
|
import { callTool, TOOLS } from './tools.js';
|
|
9
|
-
const CLI_VERSION = '0.1.
|
|
9
|
+
const CLI_VERSION = '0.1.9';
|
|
10
10
|
if (process.argv[2] === 'install-skills') {
|
|
11
11
|
const options = parseInstallArgs(process.argv.slice(3));
|
|
12
12
|
const installed = await installSkills(options);
|
|
@@ -11,6 +11,9 @@ export interface InstallSkillsOptions {
|
|
|
11
11
|
skillsScope?: SkillInstallScope;
|
|
12
12
|
mcp?: McpInstallTarget;
|
|
13
13
|
mcpDelivery?: McpDelivery;
|
|
14
|
+
allowSqlExecute?: boolean;
|
|
15
|
+
allowAdminWrite?: boolean;
|
|
16
|
+
allowDangerousSql?: boolean;
|
|
14
17
|
configPath?: string;
|
|
15
18
|
homeDir?: string;
|
|
16
19
|
}
|
|
@@ -24,5 +27,8 @@ export declare function parseInstallArgs(argv: string[]): {
|
|
|
24
27
|
skillsScope: SkillInstallScope;
|
|
25
28
|
mcp: McpInstallTarget;
|
|
26
29
|
mcpDelivery: McpDelivery;
|
|
30
|
+
allowSqlExecute: boolean;
|
|
31
|
+
allowAdminWrite: boolean;
|
|
32
|
+
allowDangerousSql: boolean;
|
|
27
33
|
configPath: string;
|
|
28
34
|
};
|
|
@@ -30,11 +30,12 @@ export async function installSkills(options) {
|
|
|
30
30
|
mcpCommand = await npxMcpCommand();
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
const permissionEnv = buildPermissionEnv(options);
|
|
33
34
|
if (mcpTargets.includes('claude')) {
|
|
34
|
-
installed.push(await installClaudeMcpConfig(options.projectDir, configPath, mcpCommand));
|
|
35
|
+
installed.push(await installClaudeMcpConfig(options.projectDir, configPath, mcpCommand, permissionEnv));
|
|
35
36
|
}
|
|
36
37
|
if (mcpTargets.includes('codex')) {
|
|
37
|
-
installed.push(await installCodexMcpConfig(options.projectDir, configPath, mcpCommand));
|
|
38
|
+
installed.push(await installCodexMcpConfig(options.projectDir, configPath, mcpCommand, permissionEnv));
|
|
38
39
|
}
|
|
39
40
|
installed.push(await ensureProjectGitignore(options.projectDir));
|
|
40
41
|
return installed;
|
|
@@ -47,6 +48,9 @@ export function parseInstallArgs(argv) {
|
|
|
47
48
|
let skillsScope = 'user';
|
|
48
49
|
let mcp = 'claude';
|
|
49
50
|
let mcpDelivery = 'npx';
|
|
51
|
+
let allowSqlExecute = true;
|
|
52
|
+
let allowAdminWrite = true;
|
|
53
|
+
let allowDangerousSql = false;
|
|
50
54
|
let configPath;
|
|
51
55
|
const authArgs = ['--prompt-only'];
|
|
52
56
|
for (let i = 0; i < argv.length; i += 1) {
|
|
@@ -97,6 +101,15 @@ export function parseInstallArgs(argv) {
|
|
|
97
101
|
}
|
|
98
102
|
mcpDelivery = value;
|
|
99
103
|
}
|
|
104
|
+
else if (arg === '--no-sql-execute') {
|
|
105
|
+
allowSqlExecute = false;
|
|
106
|
+
}
|
|
107
|
+
else if (arg === '--no-admin-write') {
|
|
108
|
+
allowAdminWrite = false;
|
|
109
|
+
}
|
|
110
|
+
else if (arg === '--allow-dangerous-sql') {
|
|
111
|
+
allowDangerousSql = true;
|
|
112
|
+
}
|
|
100
113
|
else if (arg === '--config') {
|
|
101
114
|
const value = argv[++i];
|
|
102
115
|
if (!value)
|
|
@@ -115,7 +128,20 @@ export function parseInstallArgs(argv) {
|
|
|
115
128
|
}
|
|
116
129
|
configPath = configPath ?? projectConfigPath(projectDir);
|
|
117
130
|
authArgs.push('--config', configPath);
|
|
118
|
-
return {
|
|
131
|
+
return {
|
|
132
|
+
target,
|
|
133
|
+
projectDir,
|
|
134
|
+
authorize,
|
|
135
|
+
authArgs,
|
|
136
|
+
skills,
|
|
137
|
+
skillsScope,
|
|
138
|
+
mcp,
|
|
139
|
+
mcpDelivery,
|
|
140
|
+
allowSqlExecute,
|
|
141
|
+
allowAdminWrite,
|
|
142
|
+
allowDangerousSql,
|
|
143
|
+
configPath,
|
|
144
|
+
};
|
|
119
145
|
}
|
|
120
146
|
function bundledSkillDir() {
|
|
121
147
|
return path.join(bundledPackageRoot(), 'skills', 'nubase');
|
|
@@ -169,7 +195,18 @@ async function installProjectMcpBridge(projectDir) {
|
|
|
169
195
|
entrypoint,
|
|
170
196
|
};
|
|
171
197
|
}
|
|
172
|
-
|
|
198
|
+
// Defaults: SQL execute + admin write ON, dangerous SQL OFF. Reads never need a flag.
|
|
199
|
+
function buildPermissionEnv(options) {
|
|
200
|
+
const env = {};
|
|
201
|
+
if (options.allowSqlExecute ?? true)
|
|
202
|
+
env.NUBASE_ALLOW_SQL_EXECUTE = 'true';
|
|
203
|
+
if (options.allowAdminWrite ?? true)
|
|
204
|
+
env.NUBASE_ALLOW_ADMIN_WRITE = 'true';
|
|
205
|
+
if (options.allowDangerousSql ?? false)
|
|
206
|
+
env.NUBASE_ALLOW_DANGEROUS_SQL = 'true';
|
|
207
|
+
return env;
|
|
208
|
+
}
|
|
209
|
+
async function installClaudeMcpConfig(projectDir, nubaseConfigPath, mcpCommand, permissionEnv) {
|
|
173
210
|
const mcpConfigPath = path.join(projectDir, '.mcp.json');
|
|
174
211
|
const config = await readProjectMcpConfig(mcpConfigPath);
|
|
175
212
|
config.mcpServers = {
|
|
@@ -181,17 +218,18 @@ async function installClaudeMcpConfig(projectDir, nubaseConfigPath, mcpCommand)
|
|
|
181
218
|
env: {
|
|
182
219
|
NUBASE_AGENT_ID: 'claude-code',
|
|
183
220
|
NUBASE_CONFIG: nubaseConfigPath,
|
|
221
|
+
...permissionEnv,
|
|
184
222
|
},
|
|
185
223
|
},
|
|
186
224
|
};
|
|
187
225
|
await writeFile(mcpConfigPath, `${JSON.stringify(config, null, 2)}\n`, 'utf8');
|
|
188
226
|
return mcpConfigPath;
|
|
189
227
|
}
|
|
190
|
-
async function installCodexMcpConfig(projectDir, nubaseConfigPath, mcpCommand) {
|
|
228
|
+
async function installCodexMcpConfig(projectDir, nubaseConfigPath, mcpCommand, permissionEnv) {
|
|
191
229
|
const configPath = path.join(projectDir, '.codex', 'config.toml');
|
|
192
230
|
await mkdir(path.dirname(configPath), { recursive: true });
|
|
193
231
|
const existing = await readTextIfExists(configPath);
|
|
194
|
-
const block = codexMcpBlock(nubaseConfigPath, mcpCommand);
|
|
232
|
+
const block = codexMcpBlock(nubaseConfigPath, mcpCommand, permissionEnv);
|
|
195
233
|
const next = upsertCodexMcpBlock(existing, block);
|
|
196
234
|
await writeFile(configPath, next, 'utf8');
|
|
197
235
|
return configPath;
|
|
@@ -216,9 +254,10 @@ async function readTextIfExists(filePath) {
|
|
|
216
254
|
throw err;
|
|
217
255
|
}
|
|
218
256
|
}
|
|
219
|
-
function codexMcpBlock(configPath, mcpCommand) {
|
|
257
|
+
function codexMcpBlock(configPath, mcpCommand, permissionEnv) {
|
|
220
258
|
const command = mcpCommand?.command ?? 'npx';
|
|
221
259
|
const args = mcpCommand?.args ?? ['-y', 'nubase_cli@latest'];
|
|
260
|
+
const permissionLines = Object.entries(permissionEnv).map(([key, value]) => `${key} = "${escapeTomlString(value)}"`);
|
|
222
261
|
return [
|
|
223
262
|
'[mcp_servers.nubase]',
|
|
224
263
|
'type = "stdio"',
|
|
@@ -229,6 +268,7 @@ function codexMcpBlock(configPath, mcpCommand) {
|
|
|
229
268
|
'[mcp_servers.nubase.env]',
|
|
230
269
|
'NUBASE_AGENT_ID = "codex"',
|
|
231
270
|
`NUBASE_CONFIG = "${escapeTomlString(configPath)}"`,
|
|
271
|
+
...permissionLines,
|
|
232
272
|
'',
|
|
233
273
|
].join('\n');
|
|
234
274
|
}
|