@meowshed/meow-code 0.2.1 → 0.6.2

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/README.md CHANGED
@@ -1,13 +1,15 @@
1
1
  ---
2
- reader: someone installing or running meow-code on Pi
2
+ reader: someone installing or running the meowpaw practice layer on Pi
3
3
  answers: what meow-code provides, what it adds to a session and how to install it
4
4
  kind: reference
5
- describes: [@meowshed/meow-code@0.2.1]
5
+ describes: [@meowshed/meow-code@0.6.2]
6
6
  ---
7
7
 
8
8
  # @meowshed/meow-code
9
9
 
10
- Holds how Claude Code changes code, writes a check and debugs a defect: the smallest correct change, the most precise edit, checks seen failing, and a defect reproduced before any cause is offered. It keeps up to 600 characters in context on every turn. Distributed as a Pi package.
10
+ The meowpaw practice layer: how code is changed, checked and debugged; how
11
+ skills, agents and prompts are authored; and how licence headers are applied
12
+ and checked. Distributed as a Pi package.
11
13
 
12
14
  ## Install it
13
15
 
@@ -26,3 +28,37 @@ pi install npm:@meowshed/meow-core # carries the binary the launchers run
26
28
 
27
29
  Installing from this repository's checkout is the development install: it
28
30
  loads the package in place and runs no lifecycle script.
31
+
32
+ ```bash
33
+ pi install packages/meow-code # development install, from the checkout
34
+ ```
35
+
36
+ ## What it does
37
+
38
+ ### Changing code
39
+
40
+ The `change` skill holds how Claude Code makes the smallest correct change,
41
+ writes a check seen failing and keeps each edit to one purpose.
42
+
43
+ ### Debugging
44
+
45
+ The `debug` skill holds how Claude Code reproduces a defect before offering a
46
+ cause, tests one hypothesis at a time and fixes the most probable accident
47
+ first.
48
+
49
+ ### Authoring
50
+
51
+ The `write` skill holds how Claude Code writes skills, agents, output styles,
52
+ commands and hooks, checks them and reports each unit's context cost.
53
+
54
+ ### Licensing
55
+
56
+ The `header` skill holds how Claude Code adds the licence header a repository
57
+ declares, never rewrites an existing one, and checks that every tracked file
58
+ is covered.
59
+
60
+ ## Binaries
61
+
62
+ The package carries shell wrappers for `meow-author` and `meow-licence`. Each
63
+ wrapper resolves the platform-specific `meow` binary at runtime and runs it
64
+ with the unit's subcommand.
@@ -0,0 +1,49 @@
1
+ #!/bin/sh
2
+ # SPDX-FileCopyrightText: 2026 Andrew Vasilyev <me@retran.me>
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ # Runs this unit's binary of the native tool for this machine (SPC-1080).
6
+ # Where there is none, it reports the material as unchecked, because material
7
+ # nobody checked must never read as material that passed.
8
+
9
+ case $0 in
10
+ */*) here=${0%/*} ;;
11
+ *) here=$(command -v "$0") && here=${here%/*} ;;
12
+ esac
13
+ system='' cpu='' exe=''
14
+ case $(uname -s 2>/dev/null) in
15
+ Darwin) system=apple-darwin ;;
16
+ Linux) system=unknown-linux-musl ;;
17
+ MINGW* | MSYS* | CYGWIN*) system=pc-windows-msvc exe=.exe ;;
18
+ esac
19
+ case $(uname -m 2>/dev/null) in
20
+ arm64 | aarch64) cpu=aarch64 ;;
21
+ x86_64 | amd64) cpu=x86_64 ;;
22
+ esac
23
+ binary="$here/$cpu-$system/meow$exe"
24
+ if [ -n "$system" ] && [ -n "$cpu" ] && [ -f "$binary" ]; then
25
+ [ -x "$binary" ] || chmod +x "$binary" 2>/dev/null
26
+ exec "$binary" author "$@"
27
+ fi
28
+
29
+ # The core package carries the meow binary (ADR-2810); where it
30
+ # sits on PATH, this wrapper runs its subcommand through it.
31
+ if command -v meow >/dev/null 2>&1; then
32
+ exec meow author "$@"
33
+ fi
34
+
35
+ reason="no meow binary was found for this machine, $(uname -s 2>/dev/null) on $(uname -m 2>/dev/null); reinstall the unit, which ships one for macOS, Linux and Windows on arm64 and x86_64"
36
+ case "$1" in
37
+ check)
38
+ echo "meow-author check: unchecked: $reason"
39
+ exit 3
40
+ ;;
41
+ cost)
42
+ echo "meow-author cost: unchecked: $reason"
43
+ exit 3
44
+ ;;
45
+ *)
46
+ echo "usage: meow-author check [path...] | meow-author cost" >&2
47
+ exit 2
48
+ ;;
49
+ esac
@@ -0,0 +1,45 @@
1
+ #!/bin/sh
2
+ # SPDX-FileCopyrightText: 2026 Andrew Vasilyev <me@retran.me>
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ # Runs this unit's binary of the native tool for this machine (SPC-1080).
6
+ # Where there is none, it reports the message as unchecked, because a message
7
+ # nobody checked must never read as one that passed.
8
+
9
+ case $0 in
10
+ */*) here=${0%/*} ;;
11
+ *) here=$(command -v "$0") && here=${here%/*} ;;
12
+ esac
13
+ system='' cpu='' exe=''
14
+ case $(uname -s 2>/dev/null) in
15
+ Darwin) system=apple-darwin ;;
16
+ Linux) system=unknown-linux-musl ;;
17
+ MINGW* | MSYS* | CYGWIN*) system=pc-windows-msvc exe=.exe ;;
18
+ esac
19
+ case $(uname -m 2>/dev/null) in
20
+ arm64 | aarch64) cpu=aarch64 ;;
21
+ x86_64 | amd64) cpu=x86_64 ;;
22
+ esac
23
+ binary="$here/$cpu-$system/meow$exe"
24
+ if [ -n "$system" ] && [ -n "$cpu" ] && [ -f "$binary" ]; then
25
+ [ -x "$binary" ] || chmod +x "$binary" 2>/dev/null
26
+ exec "$binary" licence "$@"
27
+ fi
28
+
29
+ # The core package carries the meow binary (ADR-2810); where it
30
+ # sits on PATH, this wrapper runs its subcommand through it.
31
+ if command -v meow >/dev/null 2>&1; then
32
+ exec meow licence "$@"
33
+ fi
34
+
35
+ reason="no meow binary was found for this machine, $(uname -s 2>/dev/null) on $(uname -m 2>/dev/null); reinstall the unit, which ships one for macOS, Linux and Windows on arm64 and x86_64"
36
+ case "$1" in
37
+ check)
38
+ echo "meow-licence check: unchecked: $reason"
39
+ exit 3
40
+ ;;
41
+ *)
42
+ echo "usage: meow-licence check" >&2
43
+ exit 2
44
+ ;;
45
+ esac
package/budget.toml CHANGED
@@ -1,7 +1,7 @@
1
1
  # SPDX-FileCopyrightText: 2026 Andrew Vasilyev <me@retran.me>
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
 
4
- # What the unit keeps in context on every turn: the descriptions of its two
5
- # skills, which route them. Measured at 502 by the budget check on
6
- # 2026-09-27; the budget adds about one sentence.
7
- permanent_characters = 600
4
+ # What this unit may load on every turn, in characters (REQ-4120): the
5
+ # change skill, the debug skill, the write skill and the header skill.
6
+ # Measured at 1380 by the budget check on 2026-10-04.
7
+ permanent_characters = 1380
@@ -0,0 +1,22 @@
1
+ // SPDX-FileCopyrightText: 2026 Andrew Vasilyev <me@retran.me>
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ /**
5
+ * meowpaw practice extension for Pi.
6
+ *
7
+ * Puts the package's bin wrappers on PATH so the skills can call
8
+ * meow-author and meow-licence by name, the way Claude Code does natively
9
+ * for a plugin's bin/. The practice layer's behaviour is carried by its
10
+ * skills; the kernel carries the reply shape.
11
+ */
12
+
13
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
14
+ import { join, dirname } from "node:path";
15
+ import { fileURLToPath } from "node:url";
16
+
17
+ const __dirname = dirname(fileURLToPath(import.meta.url));
18
+ const binDir = join(__dirname, "..", "bin");
19
+
20
+ export default function (_pi: ExtensionAPI) {
21
+ process.env.PATH = `${binDir}:${process.env.PATH ?? ""}`;
22
+ }
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "@meowshed/meow-code",
3
- "version": "0.2.1",
4
- "description": "Holds how Claude Code changes code, writes a check and debugs a defect: the smallest correct change, the most precise edit, checks seen failing, and a defect reproduced before any cause is offered. It keeps up to 600 characters in context on every turn. Distributed as a Pi package.",
3
+ "version": "0.6.2",
4
+ "description": "The meowpaw practice layer: how code is changed, checked and debugged; how skills and agents are authored; and how licence headers are applied and checked. Distributed as a Pi package.",
5
5
  "keywords": [
6
6
  "pi-package",
7
- "meowpaw"
7
+ "meowpaw",
8
+ "practice",
9
+ "authoring",
10
+ "editing",
11
+ "licencing"
8
12
  ],
9
13
  "license": "Apache-2.0",
10
14
  "author": {
@@ -15,6 +19,14 @@
15
19
  "type": "git",
16
20
  "url": "https://github.com/meowshed/meowpaw"
17
21
  },
22
+ "pi": {
23
+ "extensions": [
24
+ "extensions/practice.ts"
25
+ ],
26
+ "skills": [
27
+ "skills"
28
+ ]
29
+ },
18
30
  "peerDependencies": {
19
31
  "@earendil-works/pi-coding-agent": "*",
20
32
  "@earendil-works/pi-ai": "*",
@@ -22,9 +34,7 @@
22
34
  "@earendil-works/pi-tui": "*",
23
35
  "typebox": "*"
24
36
  },
25
- "pi": {
26
- "skills": [
27
- "skills"
28
- ]
37
+ "publishConfig": {
38
+ "access": "public"
29
39
  }
30
40
  }
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: header
3
+ description: The licence header this repository declares for its files. It MUST be loaded before any new file is created in a repository with a REUSE.toml, a [licence] table in .meowpaw/profile.toml or licence headers in its files. It MUST NOT be used to change a header a file already carries.
4
+ ---
5
+
6
+ <role>
7
+ You add the licence header a repository declares to each file you create, and
8
+ you never touch a header a file already carries. The licence is the project's
9
+ decision, so you copy what it declared and never choose one yourself.
10
+ </role>
11
+
12
+ <steps name="head a new file">
13
+ 1. Before you create a file, read the declaration: `REUSE.toml` at the
14
+ repository's root, the `header` list under `[licence]` in
15
+ `.meowpaw/profile.toml`, and the header the repository's files already
16
+ carry.
17
+ 2. If an annotation in `REUSE.toml` covers the new file's path, add nothing,
18
+ because the bulk declaration already covers it.
19
+ 3. Otherwise take the header's lines from `[licence]`, or where the profile
20
+ declares none, from the header the repository's files carry, and put them
21
+ at the top of the new file in the comment form its format permits. For a
22
+ file that can't carry a comment, write them to `<file>.license` beside it.
23
+ 4. If the repository declares nothing in any of the three places, write no
24
+ header and say that its licensing is undeclared.
25
+ 5. After creating files, run `meow-licence check`
26
+ and report what it printed.
27
+ </steps>
28
+
29
+ <rules name="headers">
30
+ - L1. Add the declared header to every file you create that no annotation
31
+ covers, code and documents alike, because a file copied out of the
32
+ repository carries only the licensing written in it.
33
+ - L2. Write the header lines exactly as the repository declares them, never a
34
+ default of your own, because the header's form is the repository's choice.
35
+ - L3. Put the lines in the comment form the file's own format permits, or in a
36
+ `.license` file beside a file that can't carry a comment, because a header
37
+ that breaks the file's syntax breaks the file.
38
+ - L4. Where `[licence]` declares no lines, copy the header the repository's
39
+ own files carry, because that is the form the project already chose.
40
+ - L5. Never rewrite, reflow, reorder or move a header a file already carries,
41
+ because reformatting a legal notice is modifying it.
42
+ - L6. Where the repository declares no licensing, write no header and report
43
+ it as undeclared, and never choose a licence for the project, because the
44
+ licence is the project's decision.
45
+ </rules>
@@ -0,0 +1,185 @@
1
+ ---
2
+ name: write
3
+ description: How a skill, agent definition, output style, command or hook prompt for Claude Code is written in this repository. It MUST be loaded before any of them is created, edited or reviewed, including a one-line change to a skill's description. It MUST NOT be skipped, however small the change looks.
4
+ ---
5
+
6
+ <role>
7
+ You write material Claude Code loads: skills, agent definitions, output
8
+ styles, commands and the prompts inside hooks. The model that reads it follows
9
+ what it says literally, so a rule in material loaded on demand states its
10
+ reason, a rule in always-loaded material does so only where C5 says, and every
11
+ procedure states where it stops.
12
+ </role>
13
+
14
+ <steps name="write material">
15
+ 1. Decide what the material is: knowledge the model loads, an action a person
16
+ invokes, or a long read that ends in a short answer.
17
+ 2. Write its front matter: what it is for and when to load it, and the
18
+ invocation, paths and context its kind needs. For an agent, write
19
+ `maxTurns`, `tools`, `model`, `effort`, `omitClaudeMd` and `skills`, as D3
20
+ to D8 set out.
21
+ 3. Write the body in the five tags, `<role>`, `<rules>`, `<steps>`,
22
+ `<example>` and `<input>`, using `<steps>`, `<example>` and `<input>` only
23
+ where the content mixes kinds (B2), with every obligation a numbered list
24
+ item under `<rules>` and every file the material relies on named in the
25
+ body of its own file.
26
+ 4. Where the material adds to what loads on every turn, run
27
+ `meow-author cost`. Before cutting or keeping
28
+ material, run `/skill-doctor` and read how often the material was used.
29
+ 5. Run `meow-author check` on the directory you
30
+ wrote in, fix each line it names, and stop when it passes.
31
+ </steps>
32
+
33
+ <rules name="what material declares">
34
+ - A1. Give every skill and agent a description of what it is for and when to
35
+ load it, because the model chooses what to load from that line alone.
36
+ - A2. Write a command as a skill only a person invokes, with
37
+ `disable-model-invocation: true`, and ship no `commands/` directory,
38
+ because two kinds of loadable material give the next author two places to
39
+ look.
40
+ - A3. Let only a person invoke material with side effects, and only the model
41
+ load material that is knowledge, because the model must not act unasked and
42
+ a person gains nothing by invoking a rule.
43
+ - A4. Declare `paths` for material that applies to one language or one
44
+ directory, because loading it everywhere costs every other session.
45
+ - A5. Run material whose work is a long read ending in a short answer in a
46
+ forked context, so the reading stays out of the context that continues.
47
+ - A6. Keep anything the material injects at invocation cheap and certain.
48
+ Cheap means it finishes inside the platform's two-minute timeout. Certain
49
+ means it exits zero wherever the skill runs, because the platform aborts the
50
+ invocation on a non-zero exit. Run no verification verb (format, lint,
51
+ check, test or build) in the injection, because a verb belongs in the body as
52
+ an instruction. A verb can exit non-zero, and a test run can exceed the
53
+ timeout. Never let the material depend on the injection, because a setting
54
+ can turn injection off, and a failing injection aborts every invocation.
55
+ - A7. Rely on the platform's namespacing of a plugin's skills for every
56
+ command, and claim no bare name, because a bare name lasts only until
57
+ something else claims it.
58
+ - A8. Propose the permissions the material needs in its own file, and leave
59
+ the repository to declare them, because permissions are the repository's
60
+ decision.
61
+ </rules>
62
+
63
+ <rules name="how the body is written">
64
+ - B1. Use only the five tags, none inside another and each closed, with no
65
+ Markdown heading, because a heading or a new tag is structure the next
66
+ author reinvents differently.
67
+ - B2. Use tags where the material mixes kinds of content, and not as
68
+ decoration around a single instruction, because a tag tells the model which
69
+ kind of content it is reading.
70
+ - B3. Put every obligation in a numbered item under `<rules>`, led by an
71
+ identifier, because an obligation elsewhere can't be extracted, checked or
72
+ cited.
73
+ - B4. End every procedure at a named stopping point, because a model with no
74
+ stopping point keeps going.
75
+ - B5. Show the failing case beside the corrected one wherever the material
76
+ teaches a judgement, because a judgement shown only right is learnt as a
77
+ rule of thumb.
78
+ - B6. Name every supporting file in the body of the material's own file with
79
+ when to read it, and reach it through this skill's own directory, because
80
+ a file nothing names is never loaded and a
81
+ fixed path breaks wherever the material is installed.
82
+ - B7. Say whether a script is run or read, and never summarise in prose a
83
+ script that is run, because a summary drifts from the script it describes.
84
+ - B8. Write instructions in the words of the work they govern, because the
85
+ model retrieves an instruction by the words a request uses.
86
+ - B9. Keep the form uniform with every other piece of material, meaning its
87
+ tags, front matter and rule identifiers, so one check audits all of it.
88
+ </rules>
89
+
90
+ <rules name="when material loads">
91
+ - C1. Load material needed only once a capability is chosen at that point, and
92
+ not before, because material loaded early costs every turn that never
93
+ chooses it.
94
+ - C2. Load material for an unusual case only in that case, and never carry it
95
+ in material that is always loaded, because the common case pays for it
96
+ otherwise.
97
+ - C3. Express one capability as one skill, not several overlapping ones,
98
+ because invoking an overlapping set loads every body in it.
99
+ - C4. Keep each skill to one discipline, and split one that spans two,
100
+ because a skill spanning two is loaded whole for either.
101
+ - C5. Give a rule its reason beside it where the rule is counter-intuitive or
102
+ the model's default is wrong. Otherwise keep the reason in material loaded
103
+ on demand, because an always-loaded reason is paid on every turn.
104
+ - C6. Before shipping a change that moves explanation out of always-loaded
105
+ material, measure the behaviour the material produces once with the
106
+ explanation and once without, because a shorter prompt that changes
107
+ behaviour is a regression and no saving.
108
+ - C7. Carry instruction that applies only to certain files in a path-scoped
109
+ rule, not in always-loaded material, because a path-scoped rule loads only
110
+ when those files are touched.
111
+ - C8. Count no saving from splitting always-loaded material into imported
112
+ files, because the platform expands imports at launch.
113
+ - C9. Load nothing because it might be relevant, because material that is
114
+ nearly relevant distracts the model and costs its context.
115
+ - C10. Put no obligation in a file the model reads at its own discretion,
116
+ because an obligation it can skip is one it will skip.
117
+ - C11. Put mutually exclusive branches of an instruction in separate files,
118
+ because a file holding both loads both whenever either is needed.
119
+ </rules>
120
+
121
+ <rules name="agents and delegation">
122
+ - D1. Ship knowledge, such as a lens (the questions a reviewer asks) or a
123
+ language's idioms, as a skill loaded into the working context and never as
124
+ an agent, because knowledge needs no isolation and an agent costs a fresh
125
+ context and a summary on every dispatch.
126
+ - D2. Never describe a delegated agent as a boundary that contains what it
127
+ does, because it runs in the parent's process and under the parent's
128
+ sandbox configuration.
129
+ - D3. Declare `maxTurns` as a positive integer, because it is the ceiling the
130
+ runner enforces, and an agent without one runs until the work or the
131
+ session ends.
132
+ - D4. Write `tools` as a list, `tools: []` included, because a missing list and
133
+ `*` both grant every tool, the delegation tool among them. In an agent a
134
+ plugin ships, list no `*`, `Agent` or `Task`, alone or restricted such as
135
+ `Agent(worker)`, because each reaches the delegation tool. The platform still
136
+ takes `Task` as the earlier name of `Agent`, which is why `Task` is among the
137
+ tools to avoid.
138
+ - D5. Name `model` as `sonnet`, `opus`, `haiku`, `fable` or a full identifier
139
+ containing `claude-`, never `inherit`, because `inherit` leaves the model,
140
+ and so the cost, to whichever session dispatches the agent.
141
+ - D6. Name `effort` as `low`, `medium`, `high`, `xhigh` or `max`, because a
142
+ missing one runs at the session's level, a cost nobody chose, and those
143
+ five are the levels the platform documents.
144
+ - D7. Set `omitClaudeMd` to `false` where the agent judges against the
145
+ repository's rules. Set it to `true` where the agent judges against a
146
+ standard it preloads. Write the key either way, because the platform honours
147
+ only `true`: a missing key loads the project's instructions exactly as
148
+ `false` does, and only a written value shows the author decided.
149
+ - D8. List in `skills` the skills the agent preloads, and write `skills: []`
150
+ where it needs none, because the list decides what the agent loads at
151
+ startup and grants nothing. An empty list states that nothing is needed.
152
+ - D9. Where you dispatch an agent, treat output marked partial (the agent
153
+ reached its ceiling) as unfinished work, because a partial list of findings
154
+ reads as a complete one. Until a run has shown that marking, treat the output
155
+ of any run that reached its ceiling the same way, because without the marking
156
+ nothing else says the list is partial.
157
+ - D10. In an agent a plugin ships, name the four outcomes `DONE`,
158
+ `DONE_WITH_CONCERNS`, `NEEDS_CONTEXT` and `BLOCKED`, and say when the agent
159
+ reports each. Have it write `outcome:`, a space and the word on a line of its
160
+ own, with one sentence naming the cause where the outcome isn't `DONE`. The
161
+ skill that dispatched it acts on the word without reading the rest, so the
162
+ check fails an agent that leaves one out. Have it carry the denial rule too:
163
+ where a tool call is denied, it issues no second call in another form, uses
164
+ no other tool to reach the same result, asks nobody for the permission and
165
+ ends as `BLOCKED`, naming the tool and what it was called on. The denial rule
166
+ exists because a question asked where nobody answers waits for nothing, and
167
+ a way round the denial reaches what the permission withheld.
168
+ </rules>
169
+
170
+ <example>
171
+ This example shows C5 applied to a rule in always-loaded material. The lines
172
+ below are examples, not rules. In the failing case the reason repeats what the
173
+ model's default already honours, and every turn pays for it:
174
+
175
+ `- R1. Write every file as UTF-8, because UTF-8 is the usual encoding.`
176
+
177
+ The corrected case drops the reason, because the default is right and nothing
178
+ counter-intuitive needs defending. A reason that is needed moves to material
179
+ loaded on demand:
180
+
181
+ `- R1. Write every file as UTF-8.`
182
+
183
+ A rule whose default is wrong keeps its reason beside it, as D5 does for
184
+ `inherit`.
185
+ </example>