set-prompt 0.8.2 → 0.8.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/CHANGELOG.md +14 -1
- package/README.md +5 -5
- package/dist/index.js +25 -19
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## [0.8.3] - 2026-05-02
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- **Hermes plugin renamed `set-prompt` → `sppt`** for ergonomics. Plugin skills are loaded via `skill_view("sppt:<name>")` instead of the longer `skill_view("set-prompt:<name>")`. Internally aligned with the rest of set-prompt where every other agent already uses `PLUGIN_NAME = "sppt"` as the plugin identifier (Claude Code, Codex, etc.) — Hermes was the lone outlier still using `MARKET_NAME = "set-prompt"`.
|
|
11
|
+
- Plugin directory: `~/.hermes/plugins/set-prompt/` → `~/.hermes/plugins/sppt/`
|
|
12
|
+
- `plugin.yaml` `name`: `set-prompt` → `sppt`
|
|
13
|
+
- `~/.hermes/config.yaml` `plugins.enabled` entry: `- set-prompt` → `- sppt`
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- **Post-link guidance** — `set-prompt link hermes` now prints a hint explaining that plugin skills don't appear in `/skills list` (Hermes policy) and shows the explicit qualified-load form: `skill_view("sppt:<skill-name>")`. This addresses the common confusion of "the link succeeded but my skills aren't showing up" — they're registered, just opt-in via qualified namespace as documented by Hermes.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
7
20
|
## [0.8.2] - 2026-05-02
|
|
8
21
|
|
|
9
22
|
### Fixed
|
|
@@ -16,7 +29,7 @@ All notable changes to this project will be documented in this file.
|
|
|
16
29
|
- **`register_command` now uses keyword arguments** (`handler=`, `description=`) to match the official Hermes plugin examples (e.g. `disk-cleanup`) and stay robust if Hermes reorders positional parameters.
|
|
17
30
|
|
|
18
31
|
### Notes
|
|
19
|
-
- After upgrading, re-run `set-prompt link hermes` to regenerate `__init__.py`, then restart Hermes. The plugin should now load with `✓
|
|
32
|
+
- After upgrading, re-run `set-prompt link hermes` to regenerate `__init__.py`, then restart Hermes. The plugin should now load with `✓ sppt v1.0` (renamed from `set-prompt` in 0.8.3) and skills become loadable via `skill_view("sppt:<name>")` (plugin skills are opt-in explicit loads — they do not appear in Hermes's auto-listed `available_skills` index).
|
|
20
33
|
- Hook callbacks remain `def runner(*args, **kwargs)` — Hermes documents that all hook callbacks should accept `**kwargs` for forward compatibility, and the bridge's role is purely to forward the payload to the user-defined hook command via stdin JSON.
|
|
21
34
|
|
|
22
35
|
---
|
package/README.md
CHANGED
|
@@ -109,7 +109,7 @@ The interactive mode shows all agents with their current state. **Check to link,
|
|
|
109
109
|
| Cursor | dir symlinks into `~/.cursor/` | `skills/`, `agents/`, `commands/`, `hooks/`, `mcp.json` (hardlink) |
|
|
110
110
|
| OpenCode | dir symlinks into `~/.config/opencode/` | `skills/`, `commands/`, `agents/` |
|
|
111
111
|
| Gemini CLI | dir symlinks into `~/.gemini/` | `skills/`, `commands/`, `agents/` |
|
|
112
|
-
| Hermes | Python plugin adapter at `~/.hermes/plugins/
|
|
112
|
+
| Hermes | Python plugin adapter at `~/.hermes/plugins/sppt/` | `skills/`, `commands/`, `hooks/hooks.json` (read directly from repo at startup) |
|
|
113
113
|
|
|
114
114
|
> **Note on Claude Code**: Operates as a plugin. Restart Claude Code after linking for the plugin to be recognized.
|
|
115
115
|
|
|
@@ -123,7 +123,7 @@ The interactive mode shows all agents with their current state. **Check to link,
|
|
|
123
123
|
|
|
124
124
|
> **Note on Gemini CLI**: Skills follow the standard `skills/<name>/SKILL.md` pattern. Commands use `.toml` format (not `.md`) and agents use `.md` with YAML frontmatter. Files in your repo's `commands/` must be TOML for Gemini CLI to recognize them. **Agents have strict frontmatter validation** — unknown keys (e.g. `allowed-tools`, `color`, `mode` from other platforms) cause Gemini CLI to reject the agent. See `SET_PROMPT_GUIDE.md` for the allowed keys.
|
|
125
125
|
|
|
126
|
-
> **Note on Hermes**: Hermes plugins must register skills/commands/hooks programmatically — directory drop-ins are not auto-discovered. set-prompt generates a small Python adapter (`~/.hermes/plugins/
|
|
126
|
+
> **Note on Hermes**: Hermes plugins must register skills/commands/hooks programmatically — directory drop-ins are not auto-discovered. set-prompt generates a small Python adapter (`~/.hermes/plugins/sppt/__init__.py`) with the repo's absolute path baked in, so no symlinks are needed. **Restart Hermes after `link` (or after adding/removing a skill in your repo)** — `register()` runs only once at Hermes startup. Activation requires `sppt` listed under `plugins.enabled` in `~/.hermes/config.yaml` — set-prompt writes this entry automatically (creating the file when absent, or appending to the existing list while preserving other entries and comments via AST-based YAML editing with backup/rollback). **Plugin skills don't appear in `/skills list`** (Hermes policy — plugin skills are opt-in explicit loads, not part of the auto-listed `available_skills` index). Load them with the qualified namespace: `skill_view("sppt:<name>")` — e.g. `skill_view("sppt:dev-base")`. Hooks are observation-only on the Hermes side: the same `hooks/hooks.json` is reused, but Hermes events (`pre_tool_call`, `on_session_start`, etc.) are picked up while Claude/Cursor keys are ignored. Hook scripts can reference `${SET_PROMPT_REPO}`.
|
|
127
127
|
|
|
128
128
|
---
|
|
129
129
|
|
|
@@ -237,8 +237,8 @@ set-prompt uninstall
|
|
|
237
237
|
└── antigravity/ (Antigravity's own subtree, unrelated)
|
|
238
238
|
|
|
239
239
|
~/.hermes/ # Hermes (Python plugin adapter, no symlinks)
|
|
240
|
-
├── config.yaml # plugins.enabled: [
|
|
241
|
-
└── plugins/
|
|
240
|
+
├── config.yaml # plugins.enabled: [sppt] (created if absent)
|
|
241
|
+
└── plugins/sppt/
|
|
242
242
|
├── plugin.yaml # Hermes manifest
|
|
243
243
|
└── __init__.py # REPO_DIR baked in; reads <repo>/{skills,commands,hooks/hooks.json} at startup
|
|
244
244
|
```
|
|
@@ -255,7 +255,7 @@ set-prompt uninstall
|
|
|
255
255
|
- **Cursor** — replaces directories and `mcp.json` in `~/.cursor/`
|
|
256
256
|
- **OpenCode** — replaces directories in `~/.config/opencode/`
|
|
257
257
|
- **Gemini CLI** — replaces directories in `~/.gemini/` (`antigravity/` subtree untouched)
|
|
258
|
-
- **Hermes** — generates `~/.hermes/plugins/
|
|
258
|
+
- **Hermes** — generates `~/.hermes/plugins/sppt/{plugin.yaml, __init__.py}` and adds `sppt` to `~/.hermes/config.yaml` under `plugins.enabled` (creates the file when absent; appends to the existing list while preserving other entries and comments)
|
|
259
259
|
|
|
260
260
|
Before making any changes, `set-prompt` creates a backup and rolls back automatically on failure. However, you should be aware that:
|
|
261
261
|
|
package/dist/index.js
CHANGED
|
@@ -39,7 +39,7 @@ var OPENCODE_BACKUP_DIR = path.join(OPENCODE_DIR, "SET_PROMPT_BACKUP");
|
|
|
39
39
|
var GEMINICLI_DIR = path.join(os.homedir(), ".gemini");
|
|
40
40
|
var GEMINICLI_BACKUP_DIR = path.join(GEMINICLI_DIR, "SET_PROMPT_BACKUP");
|
|
41
41
|
var HERMES_DIR = path.join(os.homedir(), ".hermes");
|
|
42
|
-
var HERMES_PLUGIN_DIR = path.join(HERMES_DIR, "plugins",
|
|
42
|
+
var HERMES_PLUGIN_DIR = path.join(HERMES_DIR, "plugins", PLUGIN_NAME);
|
|
43
43
|
var HERMES_CONFIG_PATH = path.join(HERMES_DIR, "config.yaml");
|
|
44
44
|
var PROMPT_DIR_NAMES = ["skills", "commands", "hooks", "agents", "rules"];
|
|
45
45
|
var AGENT_PROMPT_DIRS = {
|
|
@@ -549,7 +549,7 @@ required_environment_variables:
|
|
|
549
549
|
|
|
550
550
|
> **Gemini CLI note**: Only \`name\` and \`description\` are recognized. \`name\` must be lowercase with hyphens and match the directory name.
|
|
551
551
|
|
|
552
|
-
> **Hermes note (set-prompt integration)**: Hermes does not auto-discover files in standard directories \u2014 plugins must register skills programmatically. set-prompt generates \`~/.hermes/plugins/
|
|
552
|
+
> **Hermes note (set-prompt integration)**: Hermes does not auto-discover files in standard directories \u2014 plugins must register skills programmatically. set-prompt generates \`~/.hermes/plugins/sppt/{plugin.yaml, __init__.py}\` on \`set-prompt link hermes\`. The \`__init__.py\` reads \`<repo>/skills/<skill-name>/SKILL.md\` directly (REPO_DIR is baked in at link time) and calls \`ctx.register_skill(name, Path(SKILL.md))\` at Hermes startup. The skill directory layout is the same as other platforms \u2014 no nested category folder. **Plugin skills don't appear in \`/skills list\`** (Hermes policy \u2014 plugin skills are opt-in explicit loads). Load with the qualified namespace: \`skill_view("sppt:<skill-name>")\` \u2014 e.g. \`skill_view("sppt:dev-base")\`.
|
|
553
553
|
|
|
554
554
|
| Field | Required | Platform | Description |
|
|
555
555
|
|-------|----------|----------|-------------|
|
|
@@ -2491,7 +2491,7 @@ import fs13 from "fs";
|
|
|
2491
2491
|
import chalk14 from "chalk";
|
|
2492
2492
|
import { confirm as confirm11 } from "@inquirer/prompts";
|
|
2493
2493
|
import YAML from "yaml";
|
|
2494
|
-
var PLUGIN_YAML = `name: ${
|
|
2494
|
+
var PLUGIN_YAML = `name: ${PLUGIN_NAME}
|
|
2495
2495
|
version: "1.0"
|
|
2496
2496
|
description: Managed by set-prompt
|
|
2497
2497
|
`;
|
|
@@ -2645,7 +2645,7 @@ def register(ctx):
|
|
|
2645
2645
|
var FRESH_CONFIG_YAML = `# Generated by set-prompt
|
|
2646
2646
|
plugins:
|
|
2647
2647
|
enabled:
|
|
2648
|
-
- ${
|
|
2648
|
+
- ${PLUGIN_NAME}
|
|
2649
2649
|
`;
|
|
2650
2650
|
var writePluginManifest = (repoPath) => {
|
|
2651
2651
|
fs13.writeFileSync(path12.join(HERMES_PLUGIN_DIR, "plugin.yaml"), PLUGIN_YAML, "utf-8");
|
|
@@ -2707,7 +2707,7 @@ var ensureHermesConfigEnabled = () => {
|
|
|
2707
2707
|
}
|
|
2708
2708
|
let plugins = doc.get("plugins");
|
|
2709
2709
|
if (plugins == null) {
|
|
2710
|
-
doc.set("plugins", doc.createNode({ enabled: [
|
|
2710
|
+
doc.set("plugins", doc.createNode({ enabled: [PLUGIN_NAME] }));
|
|
2711
2711
|
writeWithBackup(HERMES_CONFIG_PATH, String(doc));
|
|
2712
2712
|
console.log(chalk14.green(" \u2713 ") + chalk14.dim(`added plugins.enabled to ${HERMES_CONFIG_PATH}`));
|
|
2713
2713
|
return;
|
|
@@ -2719,7 +2719,7 @@ var ensureHermesConfigEnabled = () => {
|
|
|
2719
2719
|
}
|
|
2720
2720
|
let enabled = plugins.get("enabled");
|
|
2721
2721
|
if (enabled == null) {
|
|
2722
|
-
plugins.set("enabled", doc.createNode([
|
|
2722
|
+
plugins.set("enabled", doc.createNode([PLUGIN_NAME]));
|
|
2723
2723
|
writeWithBackup(HERMES_CONFIG_PATH, String(doc));
|
|
2724
2724
|
console.log(chalk14.green(" \u2713 ") + chalk14.dim(`added plugins.enabled to ${HERMES_CONFIG_PATH}`));
|
|
2725
2725
|
return;
|
|
@@ -2731,15 +2731,15 @@ var ensureHermesConfigEnabled = () => {
|
|
|
2731
2731
|
}
|
|
2732
2732
|
const alreadyListed = enabled.items.some((item) => {
|
|
2733
2733
|
const v = YAML.isScalar(item) ? item.value : item;
|
|
2734
|
-
return v ===
|
|
2734
|
+
return v === PLUGIN_NAME;
|
|
2735
2735
|
});
|
|
2736
2736
|
if (alreadyListed) {
|
|
2737
|
-
console.log(chalk14.dim(` \u2713 ${
|
|
2737
|
+
console.log(chalk14.dim(` \u2713 ${PLUGIN_NAME} already listed in ${HERMES_CONFIG_PATH}`));
|
|
2738
2738
|
return;
|
|
2739
2739
|
}
|
|
2740
|
-
enabled.add(
|
|
2740
|
+
enabled.add(PLUGIN_NAME);
|
|
2741
2741
|
writeWithBackup(HERMES_CONFIG_PATH, String(doc));
|
|
2742
|
-
console.log(chalk14.green(" \u2713 ") + chalk14.dim(`enabled "${
|
|
2742
|
+
console.log(chalk14.green(" \u2713 ") + chalk14.dim(`enabled "${PLUGIN_NAME}" in ${HERMES_CONFIG_PATH}`));
|
|
2743
2743
|
};
|
|
2744
2744
|
var linkHermes = async () => {
|
|
2745
2745
|
const repoPath = resolveRepoPath();
|
|
@@ -2759,6 +2759,8 @@ Setting up Hermes plugin...`));
|
|
|
2759
2759
|
configManager.save();
|
|
2760
2760
|
console.log(chalk14.dim(`
|
|
2761
2761
|
\u2139 Hermes loads plugins at startup \u2014 restart Hermes to pick up new skills/commands.`));
|
|
2762
|
+
console.log(chalk14.dim(` \u2139 Plugin skills don't appear in /skills list (Hermes policy).`));
|
|
2763
|
+
console.log(chalk14.dim(` Load explicitly: `) + chalk14.cyan(`skill_view("${PLUGIN_NAME}:<skill-name>")`) + chalk14.dim(` \u2014 e.g. `) + chalk14.cyan(`skill_view("${PLUGIN_NAME}:dev-base")`));
|
|
2762
2764
|
} catch (ex) {
|
|
2763
2765
|
console.error(chalk14.red(`\u274C Failed to set up Hermes plugin: ${ex.message}`));
|
|
2764
2766
|
}
|
|
@@ -2787,42 +2789,46 @@ Removing Hermes plugin...`));
|
|
|
2787
2789
|
fs13.unlinkSync(HERMES_CONFIG_PATH);
|
|
2788
2790
|
console.log(chalk14.red(" removed") + chalk14.dim(`: ${HERMES_CONFIG_PATH}`));
|
|
2789
2791
|
} else {
|
|
2790
|
-
|
|
2792
|
+
removeEntryFromConfig(PLUGIN_NAME);
|
|
2791
2793
|
}
|
|
2792
2794
|
}
|
|
2793
2795
|
configManager.hermes = null;
|
|
2794
2796
|
configManager.save();
|
|
2795
2797
|
};
|
|
2796
|
-
var
|
|
2798
|
+
var removeEntryFromConfig = (entryName) => {
|
|
2799
|
+
if (fs13.existsSync(HERMES_CONFIG_PATH) === false) {
|
|
2800
|
+
return false;
|
|
2801
|
+
}
|
|
2797
2802
|
const content = fs13.readFileSync(HERMES_CONFIG_PATH, "utf-8");
|
|
2798
2803
|
let doc;
|
|
2799
2804
|
try {
|
|
2800
2805
|
doc = YAML.parseDocument(content);
|
|
2801
2806
|
} catch (ex) {
|
|
2802
2807
|
console.warn(chalk14.yellow(` \u26A0 Failed to parse Hermes config (${ex.message}) \u2014 leaving file untouched.`));
|
|
2803
|
-
return;
|
|
2808
|
+
return false;
|
|
2804
2809
|
}
|
|
2805
2810
|
if (doc.errors.length > 0) {
|
|
2806
|
-
return;
|
|
2811
|
+
return false;
|
|
2807
2812
|
}
|
|
2808
2813
|
const plugins = doc.get("plugins");
|
|
2809
2814
|
if (!YAML.isMap(plugins)) {
|
|
2810
|
-
return;
|
|
2815
|
+
return false;
|
|
2811
2816
|
}
|
|
2812
2817
|
const enabled = plugins.get("enabled");
|
|
2813
2818
|
if (!YAML.isSeq(enabled)) {
|
|
2814
|
-
return;
|
|
2819
|
+
return false;
|
|
2815
2820
|
}
|
|
2816
2821
|
const idx = enabled.items.findIndex((item) => {
|
|
2817
2822
|
const v = YAML.isScalar(item) ? item.value : item;
|
|
2818
|
-
return v ===
|
|
2823
|
+
return v === entryName;
|
|
2819
2824
|
});
|
|
2820
2825
|
if (idx === -1) {
|
|
2821
|
-
return;
|
|
2826
|
+
return false;
|
|
2822
2827
|
}
|
|
2823
2828
|
enabled.delete(idx);
|
|
2824
2829
|
writeWithBackup(HERMES_CONFIG_PATH, String(doc));
|
|
2825
|
-
console.log(chalk14.red(" removed") + chalk14.dim(` "${
|
|
2830
|
+
console.log(chalk14.red(" removed") + chalk14.dim(` "${entryName}" from: ${HERMES_CONFIG_PATH}`));
|
|
2831
|
+
return true;
|
|
2826
2832
|
};
|
|
2827
2833
|
|
|
2828
2834
|
// src/commands/link-command.ts
|