hermes-cursor-acp 0.0.0-stage → 0.1.1

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.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +74 -2
  3. package/bin/cli.js +118 -0
  4. package/package.json +32 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Neeraj Kumar Singh Beshane
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,75 @@
1
- # Temporary Holding Version
1
+ # hermes-cursor-acp
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Use your Cursor subscription models (Claude, GPT, Grok, Gemini, Composer) as the model behind [Hermes Agent](https://github.com/NousResearch/hermes-agent).
4
+
5
+ Cursor doesn't expose a chat-completions API, but the Cursor CLI ships an ACP server (`agent acp`). This plugin drives it through Hermes' ACP shim. Hermes keeps its own tools, memory, and skills. Cursor only supplies the model.
6
+
7
+ ## How it works
8
+
9
+ - Hermes tool schemas go to the model as text. The model replies with `<tool_call>` blocks, and Hermes runs those calls itself.
10
+ - The plugin parses tool calls with its own extractor. Hermes' built-in bridge silently drops two common shapes: the flat `{"name", "arguments"}` form, and a real block that follows a mention of `<tool_call>` in prose.
11
+ - The plugin rewrites `.cursor/cli.json` in an empty private workspace (`$HERMES_HOME/cache/cursor-acp-workspace`) every time a client starts, with a deny-all list (`Read`, `Write`, `Shell`, `WebFetch`, `Mcp`). This deny list is the security fence. Cursor's native tools run inside the CLI rather than over ACP, and without the list its Read tool can open any absolute path on disk.
12
+ - Models can be chosen by bare name (`claude-opus-5-5`) or by full advertised id (`claude-opus-5-5[context=300k,effort=high,fast=false]`). An unknown name raises an error instead of silently using Cursor's default.
13
+ - Responses report `usage=None`. Cursor sends no token counts, and a zero reading would stall Hermes' proactive context compression.
14
+
15
+ ## Install
16
+
17
+ ### Option 1: One-command install (recommended)
18
+
19
+ ```bash
20
+ npx hermes-cursor-acp
21
+ ```
22
+
23
+ This installs and enables the plugin in Hermes, verifies your Cursor CLI (`agent`) installation, and checks that your subscription models are accessible.
24
+
25
+ ### Option 2: Manual install
26
+
27
+ ```bash
28
+ curl https://cursor.com/install -fsS | bash # Cursor CLI
29
+ agent login # sign in with your Cursor account
30
+ agent models # confirm what your plan offers
31
+
32
+ git clone git@github.com:neerazz/hermes-cursor-acp.git ~/.hermes/plugins/cursor-acp
33
+ hermes plugins enable cursor-acp
34
+ ```
35
+
36
+ ## Use
37
+
38
+ ```bash
39
+ hermes --provider cursor -m claude-opus-5-5
40
+ ```
41
+
42
+ Or run `/model` inside Hermes and pick **Cursor Subscription (ACP)**.
43
+
44
+ ## Settings (env)
45
+
46
+ | Variable | Default | Purpose |
47
+ |---|---|---|
48
+ | `HERMES_CURSOR_ACP_COMMAND` | `agent` | Path to the Cursor CLI |
49
+ | `HERMES_CURSOR_ACP_ARGS` | `acp` | Argv tail |
50
+ | `HERMES_CURSOR_ACP_MODE` | `agent` | Cursor session mode. `ask` made gpt-5.6-sol refuse the bridge 2 times in 5. |
51
+ | `HERMES_CURSOR_ACP_CWD` | `$HERMES_HOME/cache/cursor-acp-workspace` | Private workspace |
52
+
53
+ ## Tests
54
+
55
+ ```bash
56
+ H=~/.hermes/hermes-agent
57
+ PYTHONPATH=$H uv run --no-project --python $H/venv/bin/python --with pytest python -m pytest tests -q -o addopts=
58
+ CURSOR_LIVE=1 ... # adds live tests against the real CLI (needs `agent login`)
59
+ ```
60
+
61
+ Live results on 2026-10-06 (Hermes v0.21.5, Cursor CLI 2026.10.01):
62
+
63
+ - Hermes tool-call bridging over 6 trials per model: claude-sonnet-5-5 6/6, claude-opus-5-5 6/6, composer-2.5 6/6, grok-4.7 6/6, gpt-5.6-sol 5/6. The one gpt miss answered from context without calling the tool.
64
+ - Fence probes sent as raw prompts, so the model was told to escape: Cursor's native Read, Grep, Shell, Write, and WebFetch were all blocked. The canary file content and a live GitHub SHA never came back.
65
+ - End-to-end multi-step runs through `hermes chat` (read_file, then terminal) executed both tools for real with composer-2.5 and gpt-5.6-sol.
66
+
67
+ ## Known limits
68
+
69
+ - Every turn starts a new ACP session. That adds 7–16s of latency and about 17k tokens of Cursor's harness prompt.
70
+ - Hermes records no token or cost data for these calls, so `/usage` and `/insights` undercount.
71
+ - When several sessions start at once, Cursor occasionally answers `set_model` with `Internal error`. The plugin retries up to 3 times.
72
+
73
+ ## License
74
+
75
+ MIT
package/bin/cli.js ADDED
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env node
2
+ // npx hermes-cursor-acp [install|status|uninstall]
3
+ // Thin wrapper over the official CLIs: `hermes plugins install` and Cursor's `agent`.
4
+ // No credentials or tokens pass through this script.
5
+ "use strict";
6
+
7
+ const { spawnSync } = require("node:child_process");
8
+ const fs = require("node:fs");
9
+ const os = require("node:os");
10
+ const path = require("node:path");
11
+
12
+ const REPO = "https://github.com/neerazz/hermes-cursor-acp";
13
+ const PLUGIN = "cursor-acp";
14
+ const CURSOR_INSTALLER = "https://cursor.com/install";
15
+ const HERMES_DOCS = "https://hermes-agent.nousresearch.com/docs";
16
+
17
+ const [, , cmd = "install", ...rest] = process.argv;
18
+ const flags = new Set(rest);
19
+ const yes = flags.has("--yes") || flags.has("-y");
20
+
21
+ function which(bin) {
22
+ const r = spawnSync(process.platform === "win32" ? "where" : "which", [bin], { encoding: "utf8" });
23
+ return r.status === 0 ? r.stdout.split(/\r?\n/)[0].trim() : null;
24
+ }
25
+
26
+ function run(bin, args, opts = {}) {
27
+ console.log(`$ ${bin} ${args.join(" ")}`);
28
+ const r = spawnSync(bin, args, { stdio: "inherit", shell: process.platform === "win32", ...opts });
29
+ if (r.error) throw r.error;
30
+ return r.status ?? 1;
31
+ }
32
+
33
+ function die(msg, code = 1) {
34
+ console.error(`\n✗ ${msg}`);
35
+ process.exit(code);
36
+ }
37
+
38
+ function requireHermes() {
39
+ if (!which("hermes")) {
40
+ die(`Hermes Agent not found on PATH. Install it first: ${HERMES_DOCS}`);
41
+ }
42
+ }
43
+
44
+ async function ensureCursorCli() {
45
+ if (which("agent")) return;
46
+ if (!yes) {
47
+ die(`Cursor CLI (agent) not found.\n Install it with:\n curl ${CURSOR_INSTALLER} -fsS | bash\n or re-run with --yes to install it now.`);
48
+ }
49
+ console.log(`Installing Cursor CLI from ${CURSOR_INSTALLER}...`);
50
+ const code = run("bash", ["-c", `curl ${CURSOR_INSTALLER} -fsS | bash`]);
51
+ if (code !== 0 || !which("agent")) {
52
+ die("Cursor CLI installation failed or `agent` is not on PATH. Open a new terminal and re-run.");
53
+ }
54
+ }
55
+
56
+ async function install() {
57
+ requireHermes();
58
+ await ensureCursorCli();
59
+ const ref = rest.find((a) => /^[0-9a-f]{40}$/.test(a));
60
+ const args = ["plugins", "install", REPO, "--enable"];
61
+ if (ref) args.push("--ref", ref);
62
+ if (flags.has("--force")) args.push("--force");
63
+
64
+ console.log(`Installing ${PLUGIN} into Hermes...`);
65
+ if (run("hermes", args) !== 0) die("`hermes plugins install` failed (see output above).");
66
+
67
+ console.log("\nVerifying Cursor CLI connection...");
68
+ const modelsCheck = spawnSync("agent", ["models"], { encoding: "utf8" });
69
+ if (modelsCheck.status !== 0) {
70
+ console.log("\nNotice: Cursor CLI is installed but may not be signed in.");
71
+ console.log("Run `agent login` in your terminal to authenticate your Cursor subscription.");
72
+ } else {
73
+ console.log("✓ Cursor CLI is authenticated and active.");
74
+ }
75
+
76
+ console.log(`\n✓ Done! Start Hermes with your Cursor subscription:\n`);
77
+ console.log(` hermes --provider cursor -m claude-opus-5-5`);
78
+ console.log(` hermes --provider cursor -m composer-2.5\n`);
79
+ console.log(`Or select 'Cursor Subscription (ACP)' from /model inside Hermes.`);
80
+ }
81
+
82
+ function status() {
83
+ requireHermes();
84
+ console.log("Hermes: " + (which("hermes") || "not found"));
85
+ console.log("Cursor CLI (`agent`): " + (which("agent") || "not found"));
86
+ if (which("agent")) {
87
+ console.log("\nChecking Cursor models:");
88
+ run("agent", ["models"]);
89
+ }
90
+ console.log("\nHermes plugin status:");
91
+ process.exit(run("hermes", ["plugins", "list"]));
92
+ }
93
+
94
+ function uninstall() {
95
+ requireHermes();
96
+ process.exit(run("hermes", ["plugins", "remove", PLUGIN]));
97
+ }
98
+
99
+ function help() {
100
+ console.log(`hermes-cursor-acp — Cursor Subscription models for Hermes Agent
101
+
102
+ Usage: npx hermes-cursor-acp [command] [flags]
103
+
104
+ Commands:
105
+ install Install + enable the Hermes plugin, verify Cursor CLI (default)
106
+ status Show CLI and plugin status
107
+ uninstall Remove the plugin from Hermes
108
+
109
+ Flags:
110
+ --yes, -y Install the Cursor CLI automatically if missing
111
+ --force Reinstall over an existing copy
112
+ <40-hex sha> Pin the plugin to an exact commit
113
+
114
+ Platform: ${os.platform()} ${os.arch()}`);
115
+ }
116
+
117
+ const commands = { install, status, uninstall, help, "--help": help, "-h": help };
118
+ Promise.resolve((commands[cmd] || (() => { help(); process.exit(2); }))()).catch((err) => die(err.message || String(err)));
package/package.json CHANGED
@@ -1,6 +1,34 @@
1
1
  {
2
2
  "name": "hermes-cursor-acp",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.1",
4
+ "description": "One-command Cursor subscription models for Hermes Agent: installs the cursor-acp provider plugin and verifies the Cursor CLI ACP server.",
5
+ "bin": {
6
+ "hermes-cursor-acp": "bin/cli.js"
7
+ },
8
+ "files": [
9
+ "bin/cli.js",
10
+ "README.md",
11
+ "LICENSE"
12
+ ],
13
+ "engines": {
14
+ "node": ">=18"
15
+ },
16
+ "keywords": [
17
+ "hermes",
18
+ "hermes-agent",
19
+ "hermes-plugin",
20
+ "cursor",
21
+ "acp",
22
+ "claude",
23
+ "composer",
24
+ "gpt"
25
+ ],
26
+ "author": "Neeraj Kumar Singh Beshane (https://github.com/neerazz)",
27
+ "license": "MIT",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "git+https://github.com/neerazz/hermes-cursor-acp.git"
31
+ },
32
+ "homepage": "https://github.com/neerazz/hermes-cursor-acp#readme",
33
+ "bugs": "https://github.com/neerazz/hermes-cursor-acp/issues"
34
+ }