fix(cli): clarify skill scope and stabilize Node 22 tests

Require the bootstrap agent to ask whether the skill should be installed locally or globally, and suppress only SQLite’s ExperimentalWarning in CLI test processes.
This commit is contained in:
tommy0103
2026-07-16 20:51:58 +08:00
parent 0d3797b55d
commit cc01df9fec
7 changed files with 68 additions and 8 deletions
+3 -2
View File
@@ -65,8 +65,9 @@ curl -fsSL https://raw.githubusercontent.com/tommy0103/obelisk/main/SKILL.md
``` ```
The agent will ask before changing your machine, install and verify the CLI, The agent will ask before changing your machine, install and verify the CLI,
then install the formal `/obelisk` skill. The bootstrap guide is only for then ask whether the formal `/obelisk` skill should be installed for the current
one-time setup; it is not the query skill itself. project or globally. The bootstrap guide is only for one-time setup; it is not
the query skill itself.
#### Install manually #### Install manually
+25 -4
View File
@@ -46,15 +46,36 @@ Verify the result:
obelisk --version obelisk --version
``` ```
## 3. Install the official skill ## 3. Choose the skill installation scope
The standard skills installer defaults to the current project. Before running
it, tell the user about that default and ask whether `/obelisk` should be
installed:
- **For the current project only** — available only in the project where the
installer runs.
- **Globally** — available across the user's projects.
Do not silently choose the current-project default. If the user already stated
the scope explicitly, use that choice without asking again.
Run the command that matches the user's answer:
Current project:
```bash ```bash
obelisk install obelisk install
``` ```
Pass through any target or scope options the user requested. The command uses Global:
the standard skills installer, so follow its prompts instead of copying skill
files by hand. ```bash
obelisk install --global
```
Pass through any additional target options the user requested. The command
uses the standard skills installer, so follow its prompts instead of copying
skill files by hand.
After installation, tell the user to reload their agent if the new `/obelisk` After installation, tell the user to reload their agent if the new `/obelisk`
skill is not discovered immediately. This bootstrap document is not the query skill is not discovered immediately. This bootstrap document is not the query
+2 -1
View File
@@ -12,7 +12,8 @@ Install Obelisk by fetching and following this guide:
curl -fsSL https://raw.githubusercontent.com/tommy0103/obelisk/main/SKILL.md curl -fsSL https://raw.githubusercontent.com/tommy0103/obelisk/main/SKILL.md
``` ```
The agent installs and verifies the CLI first, then installs this skill. The agent installs and verifies the CLI first, then asks whether this skill
should be installed for the current project or globally.
## Install manually ## Install manually
+11
View File
@@ -0,0 +1,11 @@
{
"version": 1,
"skills": {
"obelisk": {
"source": "tommy0103/obelisk-skill",
"sourceType": "github",
"skillPath": "skills/obelisk/SKILL.md",
"computedHash": "3f8e5bd50cd3bdfe6658243a3379bf4c44379a60bed3c1c946195529db1b8dfd"
}
}
}
+4
View File
@@ -21,6 +21,10 @@ test('root SKILL.md bootstraps the CLI before installing the official skill', ()
assert.match(source, /install\.sh/); assert.match(source, /install\.sh/);
assert.match(source, /obelisk --version/); assert.match(source, /obelisk --version/);
assert.match(source, /obelisk install/); assert.match(source, /obelisk install/);
assert.match(source, /defaults to the current project/i);
assert.match(source, /ask whether .*should be\s+installed/is);
assert.match(source, /obelisk install --global/);
assert.match(source, /Do not silently choose the current-project default/);
assert.doesNotMatch(source, /obelisk --query/); assert.doesNotMatch(source, /obelisk --query/);
}); });
+18
View File
@@ -30,6 +30,24 @@ test('obelisk --version reports the installed CLI package version', () => {
assert.equal(result.stderr, ''); assert.equal(result.stderr, '');
}); });
test('CLI test process suppresses only Node ExperimentalWarning output', () => {
const home = mkdtempSync(join(tmpdir(), 'obelisk-cli-warning-'));
const preload = join(home, 'warnings.cjs');
writeFileSync(preload, `
process.emitWarning('simulated SQLite warning', 'ExperimentalWarning');
process.emitWarning('ordinary warning stays visible', 'ObeliskTestWarning');
`);
const result = runCli(['--version'], {
home,
env: { NODE_OPTIONS: `--require=${preload}` },
});
assert.equal(result.status, 0, result.stderr || result.stdout);
assert.doesNotMatch(result.stderr, /simulated SQLite warning/);
assert.match(result.stderr, /ordinary warning stays visible/);
});
test('obelisk install delegates official skill installation to the skills CLI', () => { test('obelisk install delegates official skill installation to the skills CLI', () => {
const home = mkdtempSync(join(tmpdir(), 'obelisk-cli-install-')); const home = mkdtempSync(join(tmpdir(), 'obelisk-cli-install-'));
const fakeBin = join(home, 'bin'); const fakeBin = join(home, 'bin');
+5 -1
View File
@@ -6,7 +6,11 @@ export const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
export const cliEntry = join(repoRoot, 'packages', 'cli', 'dist', 'cli', 'src', 'obelisk.js'); export const cliEntry = join(repoRoot, 'packages', 'cli', 'dist', 'cli', 'src', 'obelisk.js');
export function runCli(args, { home, env = {}, cwd = repoRoot } = {}) { export function runCli(args, { home, env = {}, cwd = repoRoot } = {}) {
return spawnSync(process.execPath, [cliEntry, ...args], { return spawnSync(process.execPath, [
'--disable-warning=ExperimentalWarning',
cliEntry,
...args,
], {
cwd, cwd,
env: { env: {
...process.env, ...process.env,