cherry-works 0.1.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tam Nguyen
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 ADDED
@@ -0,0 +1,253 @@
1
+ # Cherry Works
2
+
3
+ A charter engine for coding agents. You write your team's standards as small
4
+ markdown files, and `cw` checks them, tests them and compiles them into the
5
+ files your coding agent actually reads.
6
+
7
+ ```text
8
+ .cw/charter/guide/no-any.md ──cw build──▶ CLAUDE.md
9
+ .cw/charter/sensor/lint.md .claude/rules/…
10
+ .cw/charter/posture/secrets.md .claude/settings.json (hooks, permissions)
11
+ … .claude/skills/…, .claude/commands/…
12
+ ```
13
+
14
+ ## Why
15
+
16
+ A coding agent follows whatever instructions it can see. Those instructions
17
+ usually end up as one long prompt file that nobody reviews and that falls out of
18
+ date. Cherry Works handles them the way you handle code:
19
+
20
+ - **Small, typed files.** Each rule is a separate primitive of one kind, such as
21
+ a guide, a sensor or a posture. Each kind says which fields it requires and
22
+ when it comes up.
23
+ - **One build.** `cw build` regenerates every file the agent reads from the
24
+ charter in one pass. Nothing is edited by hand, and a rule you delete
25
+ disappears from the output.
26
+ - **Checked and tested.** `cw doctor` names each broken file and says how to fix
27
+ it. `cw test` runs cases that pin down which rule must come up for which file
28
+ or event. It runs no command and needs no agent, so the result is the same on
29
+ every machine.
30
+ - **Shared without copying.** You can install another team's charter as a vendor
31
+ source. It is pinned to a version and committed with your code, and it never
32
+ silently overrides your own rules.
33
+
34
+ ## Requirements
35
+
36
+ - Node.js 22 or later
37
+ - git
38
+ - A supported agent. Today that is [Claude Code](https://claude.com/claude-code).
39
+ `cw` always writes a neutral output under `.cw/out/` as well.
40
+
41
+ ## Install
42
+
43
+ ```bash
44
+ npm install -g cherry-works
45
+ cw --help
46
+ ```
47
+
48
+ To run it once without installing anything, use `npx cherry-works <command>`.
49
+ To pin one version to a repository, so that its scripts and its CI run that
50
+ version whatever is installed globally, add it as a development dependency:
51
+
52
+ ```bash
53
+ npm install -D cherry-works
54
+ npx cw --version
55
+ ```
56
+
57
+ `cw --version` prints the version you are running. Upgrade with
58
+ `npm install -g cherry-works@latest`.
59
+
60
+ ## Install from source
61
+
62
+ To run `cw` from a checkout of this repository, you also need pnpm 10 or later.
63
+ Build it and link it globally:
64
+
65
+ ```bash
66
+ git clone https://github.com/tamnguyenvt/cherry-works.git
67
+ cd cherry-works
68
+ pnpm install
69
+ pnpm build
70
+ pnpm link --global
71
+ cw --help
72
+ ```
73
+
74
+ The link points at your checkout. After you change the sources, run
75
+ `pnpm build` again. To remove the link, run `pnpm uninstall --global cherry-works`.
76
+
77
+ ## Quick start
78
+
79
+ Inside the git repository you want to govern:
80
+
81
+ ```bash
82
+ cw init # asks which agent to compile for, then scaffolds .cw/charter/
83
+ cw kinds guide # what a guide requires
84
+ cw add guide no-any --header description="No any in TypeScript." --header globs="src/**/*.ts"
85
+ cw edit guide:no-any # write the body in $VISUAL or $EDITOR
86
+ cw build # compile the charter for your agent
87
+ cw doctor # check that everything holds
88
+ ```
89
+
90
+ Commit `.cw/` together with what `cw build` wrote. Your agent now reads the rule
91
+ in every session in this repository.
92
+
93
+ ## The charter
94
+
95
+ A primitive is a markdown file with YAML front matter. The folder it sits in
96
+ names its kind:
97
+
98
+ ```markdown
99
+ ---
100
+ kind: guide
101
+ id: no-single-word-naming
102
+ description: How to name a function or a variable.
103
+ globs: ["src/**/*.ts"]
104
+ ---
105
+
106
+ Never name a function or variable with a single vague word such as `it`, `data`
107
+ or `merged`. Name it after what it holds or does.
108
+ ```
109
+
110
+ Each kind comes up at a different time:
111
+
112
+ | Kind | Comes up when |
113
+ |---|---|
114
+ | `guide` | a touched file matches one of its `globs`, or on every turn when it has no globs |
115
+ | `sensor` | the `signal` it names is raised, and the harness runs its `run` command |
116
+ | `command` | it is asked for by name, or a request matches its description |
117
+ | `skill` | one of its `triggers` matches the request |
118
+ | `playbook` | one of its `triggers` matches; its body is a sequence of commands |
119
+ | `agent` | it is spawned by identity, with only the `tools` it lists |
120
+ | `posture` | always, wherever the host can be told what to `allow` and `deny` |
121
+ | `corpus` | a primitive's `rationale` cites it, to give the reasoning behind a rule |
122
+ | `mixin` | never on its own; its body is lent to the primitives that pull it in |
123
+
124
+ `cw kinds <kind>` gives the exact fields each kind takes. An identity is
125
+ `kind:id`, and it names exactly one primitive across the whole charter. If two
126
+ files claim the same identity, the build is refused and both files are named.
127
+
128
+ ## Commands
129
+
130
+ | Command | What it does |
131
+ |---|---|
132
+ | `cw init [--agent]` | Set the repository up under a charter |
133
+ | `cw build [--preview]` | Compile the charter, or show what a build would write |
134
+ | `cw list [--kind] [--min]` | List what the charter holds |
135
+ | `cw kinds [kind]` | List the kinds, or the fields one of them requires |
136
+ | `cw add <kind> <id> [--header k=v …]` | Write a new primitive |
137
+ | `cw edit <identity>` | Open a primitive's file in your editor |
138
+ | `cw remove <identity> [--yes]` | Delete a primitive this repository authored |
139
+ | `cw explain <identity>` | Show which file declares an identity, what it pulls in and which tests name it |
140
+ | `cw doctor` | Check the agents, the charter, the vendor sources and the compiled output |
141
+ | `cw test` | Run every case in `.cw/test/` against the charter |
142
+ | `cw suite add \| edit \| remove` | Manage test files |
143
+ | `cw vendor add <source> [--ref] \| remove \| list` | Install, update, remove or list vendor sources |
144
+ | `cw portal [--port]` | Open the charter in a browser on this machine |
145
+
146
+ `cw doctor` exits with a failure status when the charter has an error, when a
147
+ vendored file was edited in this repository, or when the compiled output no
148
+ longer matches the charter. That makes it a gate you can run in CI.
149
+
150
+ ## The portal
151
+
152
+ If you would rather not remember commands and field names, run the portal from
153
+ inside a governed repository:
154
+
155
+ ```bash
156
+ cw portal # serves on port 9927, or the next free port
157
+ cw portal --port 8080
158
+ ```
159
+
160
+ It prints an address such as `http://127.0.0.1:9927/?t=…`. Open that address in
161
+ your browser. The page has three tabs:
162
+
163
+ ![The Repo Charter tab: kind chips, and the guides of a repository with their globs, rationale and mixins](docs/images/portal-charter.png)
164
+
165
+ - **Repo Charter** lists every primitive of this repository by kind, with the
166
+ engine's own line on when that kind comes up. From here you can create a
167
+ primitive, then open it to edit its fields and its markdown body, or delete
168
+ it. The form is built from what the kind requires, so it asks only for the
169
+ fields that kind takes. The **?** on a row explains the primitive: when it
170
+ comes up, what it pulls in, what cites it and which tests name it.
171
+
172
+ | Editing a primitive | Explaining it |
173
+ |---|---|
174
+ | ![The form for guide:no-any, with its globs, rationale, mixins and markdown body](docs/images/portal-edit.png) | ![The explanation of guide:no-any: when it comes up, what it pulls in and the test that names it](docs/images/portal-explain.png) |
175
+ - **Vendor** lists the vendor sources you installed and their primitives, which
176
+ are read-only. You can add a source by its git address and a version, or
177
+ remove one.
178
+ - **Test** lists the test files in `.cw/test/`. You can create, edit and delete
179
+ them, and run every case to see which pass and why a failing one failed.
180
+
181
+ ![The Test tab after a run: 4 of 5 cases pass, and the failing case says why](docs/images/portal-tests.png)
182
+
183
+ The header has a search that finds any primitive in any layer, and two buttons:
184
+ **Build**, which shows what a build would write before it writes anything, and
185
+ **Doctor**, which runs the health check and offers a build when the output is
186
+ behind.
187
+
188
+ The portal drives the same engine as the command line and adds no behaviour of
189
+ its own. What it shows is what the engine answered, and everything it does has
190
+ a command-line equivalent. When the engine refuses a change, the portal shows
191
+ the refusal in the engine's words and writes nothing. It listens only on
192
+ `127.0.0.1`, and every request needs the token in the printed address. Stop it
193
+ with Ctrl+C.
194
+
195
+ ## Testing a charter
196
+
197
+ A test file in `.cw/test/` describes situations and what must come up in each
198
+ one:
199
+
200
+ ```json
201
+ {
202
+ "description": "The TypeScript guide comes up on source files.",
203
+ "cases": [
204
+ { "do": { "touchFile": "src/one.ts" }, "expect": { "activate": "guide:no-any" } },
205
+ { "when": "Stop", "expect": { "run": "sensor:lint" } },
206
+ { "do": { "touchFile": ".env" }, "expect": { "allow": false } }
207
+ ]
208
+ }
209
+ ```
210
+
211
+ `cw test` resolves each case against the charter and reports the ones that no
212
+ longer hold.
213
+
214
+ ## Vendor sources
215
+
216
+ ```bash
217
+ cw vendor add git@github.com:your-org/charter-baseline.git --ref v1.2.0
218
+ ```
219
+
220
+ A vendor source is a git repository with primitives laid out in folders by kind.
221
+ It is installed under `.cw/vendor/<name>/`, pinned to the ref you chose and
222
+ committed. Vendored primitives are read-only. To differ from one, write your own
223
+ primitive under a new identity.
224
+
225
+ ## Your agent can write rules too
226
+
227
+ Every governed repository gets a built-in skill, `skill:cw-author`. It teaches
228
+ the agent to ask `cw kinds` what a kind requires and to write primitives with
229
+ `cw add`, instead of copying fields from memory.
230
+
231
+ ## Development
232
+
233
+ ```bash
234
+ pnpm install
235
+ pnpm exec playwright install chromium # once per machine, for the portal's browser tests
236
+ pnpm test # dependency rules, build, then every test
237
+ pnpm typecheck
238
+ pnpm cw <command> # run the CLI from source, without building
239
+ ```
240
+
241
+ A release is `pnpm release <version>`, run from a clean `develop` level with
242
+ `origin/develop`. It runs the tests, installs the exact package it would publish
243
+ into a fresh repository and builds it there, and only then commits, tags
244
+ `v<version>`, publishes and pushes. `pnpm release <version> --dry-run` runs
245
+ every check and changes nothing. A plain `npm publish` is refused.
246
+
247
+ The engine follows a hexagonal layout. `src/hexagon/` holds the domain, the
248
+ application use cases and their ports. `src/driver/` holds the CLI and the
249
+ portal that drive it. `src/zdriven/` holds the adapters for files, git and YAML.
250
+ The design is written in [specs/spec.md](specs/spec.md) and
251
+ [specs/plan.md](specs/plan.md).
252
+
253
+ This repository is governed by its own charter under [.cw/charter/](.cw/charter/).
package/dist/cw.js ADDED
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+
3
+ // package.json
4
+ var package_default = {
5
+ name: "cherry-works",
6
+ version: "0.1.0",
7
+ description: "The charter engine: resolves a charter and compiles it into what a coding agent reads.",
8
+ keywords: [
9
+ "claude-code",
10
+ "coding-agent",
11
+ "charter",
12
+ "ai-agents",
13
+ "cli",
14
+ "guardrails"
15
+ ],
16
+ homepage: "https://github.com/tamnguyenvt/cherry-works#readme",
17
+ bugs: {
18
+ url: "https://github.com/tamnguyenvt/cherry-works/issues"
19
+ },
20
+ repository: {
21
+ type: "git",
22
+ url: "git+https://github.com/tamnguyenvt/cherry-works.git"
23
+ },
24
+ license: "MIT",
25
+ author: "Tam Nguyen",
26
+ type: "module",
27
+ engines: {
28
+ node: ">=22",
29
+ pnpm: ">=10"
30
+ },
31
+ packageManager: "pnpm@10.2.1",
32
+ bin: {
33
+ cw: "./dist/cw.js"
34
+ },
35
+ files: [
36
+ "dist"
37
+ ],
38
+ imports: {
39
+ "#hexagon/*": "./src/hexagon/*",
40
+ "#portal/*": "./dist/portal/*"
41
+ },
42
+ scripts: {
43
+ build: "tsup && tailwindcss -i src/driver/portal/page/styles.css -o dist/portal/styles.css --minify",
44
+ typecheck: "tsc --noEmit && tsc --noEmit -p src/driver/portal/page",
45
+ test: 'pnpm run lint:deps && pnpm run build && node --import tsx --test "test/**/*.test.ts"',
46
+ cw: "node --import tsx main.ts",
47
+ "lint:deps": "depcruise src main.ts",
48
+ "specs:link": "node --import tsx scripts/link-specs.ts",
49
+ "specs:check": "node --import tsx scripts/link-specs.ts --check",
50
+ release: "node --import tsx scripts/release.ts",
51
+ prepublishOnly: `node -e "console.error('Publish with \\"pnpm release <version>\\", which checks the package first.'); process.exit(1)"`
52
+ },
53
+ devDependencies: {
54
+ "@codemirror/commands": "^6.11.1",
55
+ "@codemirror/lang-markdown": "^6.5.2",
56
+ "@codemirror/language": "^6.12.4",
57
+ "@codemirror/state": "^6.7.4",
58
+ "@codemirror/view": "^6.43.11",
59
+ "@tailwindcss/cli": "^4.3.3",
60
+ "@tanstack/react-query": "^5.103.2",
61
+ "@types/node": "^22.10.2",
62
+ "@types/picomatch": "^4.0.3",
63
+ "@types/prompts": "^2.4.9",
64
+ "@types/react": "^19.3.0",
65
+ "@types/react-dom": "^19.3.0",
66
+ "@types/yargs": "^17.0.35",
67
+ "class-variance-authority": "^0.7.1",
68
+ clsx: "^2.1.1",
69
+ cmdk: "^1.1.1",
70
+ "dependency-cruiser": "^18.2.0",
71
+ "lucide-react": "^1.47.0",
72
+ marked: "^18.0.13",
73
+ playwright: "^1.63.0",
74
+ "radix-ui": "^1.6.7",
75
+ react: "^19.3.0",
76
+ "react-dom": "^19.3.0",
77
+ sonner: "^2.0.8",
78
+ "tailwind-merge": "^3.7.0",
79
+ tailwindcss: "^4.3.3",
80
+ tsup: "^8.3.5",
81
+ tsx: "^4.19.2",
82
+ "tw-animate-css": "^1.4.0",
83
+ typescript: "^5.7.2"
84
+ },
85
+ pnpm: {
86
+ onlyBuiltDependencies: [
87
+ "esbuild"
88
+ ]
89
+ },
90
+ dependencies: {
91
+ "@hono/node-server": "^2.1.1",
92
+ "@hono/zod-openapi": "^1.6.3",
93
+ hono: "^4.13.7",
94
+ picomatch: "^4.0.7",
95
+ prompts: "^2.4.2",
96
+ yaml: "^2.9.0",
97
+ yargs: "^18.1.0",
98
+ zod: "^4.6.1"
99
+ }
100
+ };
101
+
102
+ // bin.ts
103
+ var _a;
104
+ var neededMajor = Number((_a = /\d+/.exec(package_default.engines.node)) == null ? void 0 : _a[0]);
105
+ var runningMajor = Number(process.versions.node.split(".")[0]);
106
+ if (runningMajor < neededMajor) {
107
+ process.stderr.write(
108
+ `cw needs Node.js ${neededMajor} or later, and this is Node.js ${process.versions.node}.
109
+ Install Node.js ${neededMajor} or later, then run cw again.
110
+ `
111
+ );
112
+ process.exitCode = 1;
113
+ } else {
114
+ const commandEntry = "./main.js";
115
+ void import(commandEntry);
116
+ }