@coderook/cli 0.14.1 → 0.16.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.
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "coderook",
3
+ "displayName": "CodeRook",
4
+ "description": "Save, browse and restore whole-snapshot versions of a project on CodeRook, from Claude Code.",
5
+ "version": "0.16.0",
6
+ "author": { "name": "ACCA Gaming Productions", "url": "https://coderook.com" },
7
+ "homepage": "https://coderook.com/docs#assistants",
8
+ "license": "SEE LICENSE IN LICENSE.txt",
9
+ "keywords": ["coderook", "versioning", "snapshots", "backup"]
10
+ }
package/README.md CHANGED
@@ -122,36 +122,88 @@ it helps, raw where it does not, and a SHA-256 for every chunk and file.
122
122
  Extraction is verified and atomic — a damaged bundle fails rather than leaving
123
123
  a half-written tree.
124
124
 
125
- ## Claude Code and Codex
125
+ ## Claude Code
126
126
 
127
- CodeRook can be a tool your assistant uses while it works. Both speak the same
128
- protocol, so one server covers them.
127
+ ```
128
+ coderook skill
129
+ ```
130
+
131
+ That is the whole setup. It writes a short guide into Claude Code's skills
132
+ folder, and from then on you ask for what you want in ordinary words:
133
+
134
+ > save this to CodeRook
135
+
136
+ > what have I changed?
137
+
138
+ > what versions does this project have?
139
+
140
+ Claude works out which commands to run. You can also call it by name with
141
+ `/coderook`.
142
+
143
+ `coderook skill --project` writes it into `./.claude` instead of your home
144
+ folder, so it travels with the repository and everybody who clones it has it
145
+ too.
146
+
147
+ Sign in once per machine first — `coderook sign-in` — or set `CODEROOK_TOKEN`
148
+ in automation. The skill will not save anything without asking you first, and
149
+ never deletes.
150
+
151
+ ## Installing it as a plugin instead
152
+
153
+ If you would rather not install the command line first, CodeRook publishes a
154
+ plugin marketplace of its own:
155
+
156
+ ```
157
+ /plugin marketplace add https://coderook.com/marketplace.json
158
+ /plugin install coderook@coderook
159
+ ```
160
+
161
+ That fetches the same package from npm and brings the skill with it. The
162
+ marketplace is a plain file on coderook.com rather than a git repository, so
163
+ there is no repository to clone and no second account anywhere.
164
+
165
+ One thing to know: a plugin install puts the package in Claude Code's plugin
166
+ folder, not on your `PATH`. The skill copes with that on its own by falling
167
+ back to `npx -y @coderook/cli`, but `npm install --global @coderook/cli` is
168
+ faster if you plan to run commands yourself as well.
169
+
170
+ ## A structured connection instead
171
+
172
+ The skill teaches Claude the command line, which needs no configuration. If you
173
+ would rather it had structured tools, there is an MCP server as well. It works
174
+ with Codex too, which is the reason it exists.
129
175
 
130
176
  Claude Code:
131
177
 
132
178
  ```
133
- claude mcp add coderook -- coderook mcp
179
+ claude mcp add --scope user coderook -- npx -y @coderook/cli mcp
134
180
  ```
135
181
 
136
182
  Codex, in `~/.codex/config.toml`:
137
183
 
138
184
  ```toml
139
185
  [mcp_servers.coderook]
140
- command = "coderook"
141
- args = ["mcp"]
186
+ command = "npx"
187
+ args = ["-y", "@coderook/cli", "mcp"]
142
188
  ```
143
189
 
144
- It offers five things, all of which read: your projects, a project's versions,
145
- the files in a version, one file's contents at a version, and what has changed
146
- in a local folder.
190
+ To share it with everyone on a project, commit this beside the code:
147
191
 
148
- It cannot save a version, delete anything, or sign in or out. That is
149
- deliberate — an assistant that goes wrong can waste your time but not your
150
- work, and saving stays something a person types. A project whose owner has
151
- turned off machine reading is refused in words rather than as a status code.
192
+ ```json
193
+ // .mcp.json
194
+ {
195
+ "mcpServers": {
196
+ "coderook": {
197
+ "command": "npx",
198
+ "args": ["-y", "@coderook/cli", "mcp"]
199
+ }
200
+ }
201
+ }
202
+ ```
152
203
 
153
- The server is launched by the assistant and exits with it; there is no reason
154
- to run `coderook mcp` by hand.
204
+ It offers five things, all of which read: your projects, a project's versions,
205
+ the files in a version, one file's contents at a version, and what has changed
206
+ in a local folder. It cannot save, delete, or sign in or out.
155
207
 
156
208
  ## Checking things
157
209
 
@@ -26,6 +26,7 @@ const progress_js_1 = require("./progress.js");
26
26
  const project_commands_js_1 = require("./project_commands.js");
27
27
  const track_commands_js_1 = require("./track_commands.js");
28
28
  const mcp_js_1 = require("./mcp.js");
29
+ const skill_command_js_1 = require("./skill_command.js");
29
30
  const service_commands_js_1 = require("./service_commands.js");
30
31
  const worktree_js_1 = require("../../desktop-app/src/main/worktree.js");
31
32
  const upload_js_1 = require("../../desktop-app/src/main/upload.js");
@@ -1444,6 +1445,38 @@ const SPECS = [
1444
1445
  examples: ["coderook runner my-game --labels windows,signing"],
1445
1446
  run: commandRunner,
1446
1447
  },
1448
+ {
1449
+ /*
1450
+ The other way to hand this to an assistant is a plugin marketplace,
1451
+ and marketplaces live in git repositories — an odd thing to require
1452
+ of people using a version host that is deliberately not git. A skill
1453
+ is a file in a folder, and this already knows where the folder is.
1454
+ */
1455
+ name: "skill",
1456
+ group: "Other",
1457
+ summary: "teach Claude Code about CodeRook",
1458
+ usage: "skill [--project]",
1459
+ detail: "Writes a short guide into Claude Code's skills folder, so it knows what\n" +
1460
+ "CodeRook is and how to drive it. After that you ask for it in words:\n" +
1461
+ "'save this to CodeRook', 'what changed?' — or run it by name with\n" +
1462
+ "/coderook.\n" +
1463
+ "\n" +
1464
+ "Personal by default, so it is there in every project on this machine.\n" +
1465
+ "--project writes it into ./.claude instead, where it travels with the\n" +
1466
+ "repository for everybody who clones it.\n" +
1467
+ "\n" +
1468
+ "It teaches the command line rather than the MCP server, because that\n" +
1469
+ "needs no configuration at all. `coderook mcp` is still there when a\n" +
1470
+ "structured connection is wanted.\n",
1471
+ options: [
1472
+ {
1473
+ flags: "--project",
1474
+ description: "install into this project rather than for you",
1475
+ },
1476
+ ],
1477
+ examples: ["coderook skill", "coderook skill --project"],
1478
+ run: skill_command_js_1.commandSkill,
1479
+ },
1447
1480
  {
1448
1481
  /*
1449
1482
  The assistants speak one protocol between them, so this is one server
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ /**
3
+ * Teaching an assistant about CodeRook, in one command.
4
+ *
5
+ * The other route in is a plugin marketplace, and marketplaces live in git
6
+ * repositories — which is a strange thing to require of people using a version
7
+ * host that is deliberately not git, and stranger still when the recommended
8
+ * host is the one this product exists as an alternative to.
9
+ *
10
+ * A skill is a file in a folder. The command line is already installed and
11
+ * already knows where that folder is, so it writes it: no marketplace, no
12
+ * clone, no second account. `coderook skill` and the assistant knows what
13
+ * CodeRook is and how to drive it from then on, in every project.
14
+ *
15
+ * The skill teaches it the command line rather than the MCP server. Both work,
16
+ * but the command line needs no configuration at all — the assistant already
17
+ * has a shell, and a thing that works with nothing to set up is the thing most
18
+ * people should be offered first.
19
+ */
20
+ var __importDefault = (this && this.__importDefault) || function (mod) {
21
+ return (mod && mod.__esModule) ? mod : { "default": mod };
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.commandSkill = commandSkill;
25
+ const promises_1 = require("node:fs/promises");
26
+ const node_os_1 = __importDefault(require("node:os"));
27
+ const node_path_1 = __importDefault(require("node:path"));
28
+ const node_process_1 = __importDefault(require("node:process"));
29
+ const dim = (value) => `[2m${value}[0m`;
30
+ const bold = (value) => `[1m${value}[0m`;
31
+ const red = (value) => `[31m${value}[0m`;
32
+ const green = (value) => `[32m${value}[0m`;
33
+ const accent = (value) => `[33m${value}[0m`;
34
+ /**
35
+ * The skill as it ships, found relative to this file.
36
+ *
37
+ * Not read from the working directory, because the command is run from
38
+ * somebody's project and the file lives wherever npm put the package.
39
+ */
40
+ async function shipped() {
41
+ /*
42
+ `__dirname` rather than `import.meta.url`: this package compiles to
43
+ CommonJS, where the latter is not available and the build refuses it.
44
+ */
45
+ const here = __dirname;
46
+ /*
47
+ Compiled to dist/cli/src, so the package root is three levels up. Tried in
48
+ order rather than assumed, so running from source works as well as running
49
+ from an install.
50
+ */
51
+ const candidates = [
52
+ node_path_1.default.resolve(here, "../../../skills/coderook/SKILL.md"),
53
+ node_path_1.default.resolve(here, "../../skills/coderook/SKILL.md"),
54
+ node_path_1.default.resolve(here, "../skills/coderook/SKILL.md"),
55
+ ];
56
+ for (const candidate of candidates) {
57
+ try {
58
+ return await (0, promises_1.readFile)(candidate, "utf8");
59
+ }
60
+ catch {
61
+ /* try the next shape */
62
+ }
63
+ }
64
+ throw new Error("The skill file is missing from this installation.");
65
+ }
66
+ /**
67
+ * Where the assistant looks.
68
+ *
69
+ * Personal by default — somebody who installs this wants it in every project,
70
+ * not only the one they happened to be standing in. `--project` writes it
71
+ * beside the code instead, which is what to do when it should travel with the
72
+ * repository for everybody who clones it.
73
+ */
74
+ function destination(project) {
75
+ const root = project
76
+ ? node_path_1.default.join(node_process_1.default.cwd(), ".claude")
77
+ : node_path_1.default.join(node_os_1.default.homedir(), ".claude");
78
+ return node_path_1.default.join(root, "skills", "coderook", "SKILL.md");
79
+ }
80
+ async function commandSkill(parsed) {
81
+ const project = parsed.flags.has("project");
82
+ const target = destination(project);
83
+ let body;
84
+ try {
85
+ body = await shipped();
86
+ }
87
+ catch (error) {
88
+ console.error(red(error instanceof Error ? error.message : String(error)));
89
+ return 1;
90
+ }
91
+ /*
92
+ Overwritten without asking, because the file is ours and the only reason it
93
+ differs is that it is an older copy. Anything a person wrote themselves
94
+ belongs under a different name.
95
+ */
96
+ await (0, promises_1.mkdir)(node_path_1.default.dirname(target), { recursive: true });
97
+ await (0, promises_1.writeFile)(target, body, "utf8");
98
+ console.log(green("Installed the CodeRook skill."));
99
+ console.log(dim(" ") + target);
100
+ console.log("");
101
+ console.log(project
102
+ ? dim("Everyone who opens this project in Claude Code now has it.")
103
+ : dim("Claude Code has it in every project on this machine."));
104
+ console.log("");
105
+ console.log(dim("Ask for it in words — ") + accent("“save this to CodeRook”"));
106
+ console.log(dim("or run it by name — ") + accent("/coderook"));
107
+ console.log("");
108
+ console.log(dim("Signed in? ") +
109
+ bold("coderook whoami") +
110
+ dim(" · if not: ") +
111
+ bold("coderook sign-in"));
112
+ return 0;
113
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coderook/cli",
3
- "version": "0.14.1",
3
+ "version": "0.16.0",
4
4
  "description": "CodeRook from the command line, on any operating system",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "homepage": "https://coderook.com",
@@ -20,14 +20,16 @@
20
20
  "coderook": "dist/cli/src/cli.js"
21
21
  },
22
22
  "files": [
23
- "dist"
23
+ ".claude-plugin",
24
+ "dist",
25
+ "skills"
24
26
  ],
25
27
  "scripts": {
26
28
  "build": "tsc -p tsconfig.json",
27
29
  "check": "tsc -p tsconfig.json --noEmit",
28
30
  "test": "tsc -p tsconfig.json && node --test --experimental-strip-types test/*.test.ts",
29
31
  "start": "node dist/cli/src/cli.js",
30
- "prepublishOnly": "npm run build",
32
+ "prepublishOnly": "npm run sync:plugin && npm run build",
31
33
  "test:e2e": "node test/e2e.mjs",
32
34
  "test:matrix": "node test/state-matrix.mjs",
33
35
  "test:attempt": "node test/attempt-identity.mjs",
@@ -39,7 +41,8 @@
39
41
  "test:floor": "node test/version-floor.mjs",
40
42
  "test:faultsubmit": "node test/fault-submit.mjs",
41
43
  "test:race": "node test/race-attempts.mjs",
42
- "test:runner": "node test/runner-live.mjs"
44
+ "test:runner": "node test/runner-live.mjs",
45
+ "sync:plugin": "node scripts/sync-plugin-version.mjs"
43
46
  },
44
47
  "devDependencies": {
45
48
  "@types/node": "24.10.1",
@@ -0,0 +1,130 @@
1
+ ---
2
+ name: coderook
3
+ description: Save, browse and restore versions of a project on CodeRook — a version host where every version is a complete snapshot and there is no git to learn. Use when asked to save or submit work to CodeRook, check what has changed, look at a project's versions or files, fetch a project, start or switch a line of work, or resolve a save that landed at the same time as somebody else's.
4
+ allowed-tools: Bash Read
5
+ ---
6
+
7
+ # CodeRook
8
+
9
+ CodeRook stores whole snapshots of a folder. A version names every file the
10
+ project had at that moment, so restoring one never depends on the versions
11
+ around it, and there is no staging area, no branches to rebase and no history
12
+ to rewrite.
13
+
14
+ Everything here is the `coderook` command line. Run it with Bash.
15
+
16
+ ## Before anything else
17
+
18
+ `coderook whoami` says who this machine is signed in as. If it refuses, the
19
+ person needs to run `coderook sign-in` themselves — it takes a personal access
20
+ token, so do not attempt it on their behalf.
21
+
22
+ If the command is not found at all, this machine has the skill but not the
23
+ command line. Either install it once with
24
+ `npm install --global @coderook/cli`, or put `npx -y @coderook/cli` where
25
+ `coderook` appears below — the commands are identical, npx is just slower
26
+ to start.
27
+
28
+ ## Reading
29
+
30
+ ```bash
31
+ coderook status # what has changed in this folder since its last version
32
+ coderook projects # every project on the account
33
+ coderook versions [project] # what has been saved, newest first
34
+ coderook tracks [project] # the lines a project has, and any waiting on a decision
35
+ ```
36
+
37
+ `status` is the one to reach for when somebody asks what is uncommitted, what
38
+ changed, or whether anything needs saving. It reads the folder and changes
39
+ nothing.
40
+
41
+ ## Saving
42
+
43
+ ```bash
44
+ coderook submit -m "What changed, in a sentence"
45
+ ```
46
+
47
+ Send only what changed; the version still names every file. Write the message
48
+ yourself from the actual diff rather than asking for one — a message like
49
+ "update" helps nobody reading the history later.
50
+
51
+ **Ask before running this.** Saving is the one thing here that leaves a mark on
52
+ somebody's account, and a version saved by mistake is a version they have to
53
+ explain. Propose it, say what it would send, and let them agree.
54
+
55
+ `coderook submit -n` shows exactly what would be sent without sending it. Use
56
+ that freely; it is safe and it is the honest way to answer "what would this
57
+ upload?".
58
+
59
+ ## Fetching
60
+
61
+ ```bash
62
+ coderook get # bring this folder up to date
63
+ coderook clone <project> [dir] # fetch a project into a new folder
64
+ ```
65
+
66
+ `get` protects local edits by default. `coderook get --replace` discards them
67
+ to make an exact copy — only run it when the person has said so in those terms.
68
+
69
+ ## Lines of work
70
+
71
+ A project can have more than one line, so two people can save without one
72
+ landing on top of the other.
73
+
74
+ ```bash
75
+ coderook track # which line this folder saves to
76
+ coderook track spike --new # start a line and switch to it
77
+ coderook track main # switch back
78
+ coderook submit --track spike -m "…"
79
+ ```
80
+
81
+ Switching says where the next save goes and nothing else — no files move.
82
+ Run `coderook get` afterwards to bring that line's files in.
83
+
84
+ ## When two saves collide
85
+
86
+ If somebody saved while this folder was behind, the second save becomes a merge
87
+ waiting on a decision rather than overwriting anything.
88
+
89
+ ```bash
90
+ coderook merges # this folder's saves waiting on a decision
91
+ coderook merge <ref> # look at one, and decide
92
+ ```
93
+
94
+ Read the conflict out to the person and let them choose. Do not pick a side for
95
+ them: the whole reason it stopped is that the service could not tell which copy
96
+ was wanted.
97
+
98
+ ## What is worth leaving out
99
+
100
+ ```bash
101
+ coderook ignore --suggest # dependency directories, build output, virtual environments
102
+ coderook ignore --suggest --apply # add the confident ones to .gitignore
103
+ ```
104
+
105
+ Rules live in the project's own `.gitignore`, so CodeRook, git and the website
106
+ all read one file.
107
+
108
+ ## Bundles
109
+
110
+ ```bash
111
+ coderook bundle . project.cbx # the whole project, every version, as one file
112
+ coderook inspect project.cbx # what is inside, without unpacking
113
+ coderook unbundle project.cbx ./restored
114
+ ```
115
+
116
+ ## Things not to do
117
+
118
+ - Do not run `coderook delete` unless the person has asked for that project to
119
+ be deleted, by name, in this conversation.
120
+ - Do not run `coderook sign-out`. It costs them a token they have to fetch
121
+ again and gains nothing.
122
+ - Do not guess a project name. `coderook projects` lists them; a folder that is
123
+ already linked needs no name at all.
124
+
125
+ ## If something refuses
126
+
127
+ The commands explain themselves — pass the message on rather than rewording it.
128
+ A refusal that says a token was not accepted means signing in; one that says a
129
+ project does not allow machines means its owner turned that off deliberately,
130
+ and the answer is to say so, not to find another route in.