@schneiderjoseph/devia 0.1.0 → 0.3.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/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0 — 2026-09-09
4
+
5
+ The standard is unchanged: `VERSION` stays at 0.1.0, no adopter needs `devia sync`.
6
+
7
+ ### devia is for every agent
8
+
9
+ 0.2.0 shipped `--global` serving Claude Code alone and reported the other agents as SKIP. Two of
10
+ those reasons were wrong: they came from an absence never verified. `~/.cursor/rules/` holds
11
+ user-level `.mdc` rules, and `~/.codex/skills/` uses the same `SKILL.md` convention as Claude
12
+ Code. The decision is recorded as G6: no agent is privileged.
13
+
14
+ `devia skills install --global` now writes, each in the format the agent actually reads:
15
+
16
+ | Agent | Path | File |
17
+ |---|---|---|
18
+ | Claude Code | `~/.claude/skills/devia/SKILL.md` | skill pack |
19
+ | Codex | `~/.codex/skills/devia/SKILL.md` | skill pack |
20
+ | Cursor | `~/.cursor/rules/devia.mdc` | rules adapter |
21
+ | Gemini | `~/.gemini/GEMINI.md` | universal contract, only when absent or empty |
22
+ | Copilot, Windsurf | — | `SKIP`: user-level configuration is editor settings, not a file devia can place (`12_DEBT.md` D8) |
23
+
24
+ `CLAUDE_CONFIG_DIR` and `CODEX_HOME` are honoured when set. A directory the agent owns is
25
+ written to freely; a file the **user** owns is written only when absent or empty, and otherwise
26
+ skipped with the reason rather than replaced. `--force` overrides both and names every path.
27
+
28
+ ## 0.2.0 — 2026-09-09
29
+
30
+ The standard is unchanged: `VERSION` stays at 0.1.0 and no adopter needs `devia sync`. This
31
+ release is the CLI only.
32
+
33
+ ### The skill, once for every project
34
+
35
+ - `devia skills install --global` installs the skill pack in the agent's own configuration
36
+ directory instead of one repository, so the contract applies everywhere. Claude Code is
37
+ supported (`~/.claude/skills/devia/SKILL.md`, or `CLAUDE_CONFIG_DIR` when set); Cursor,
38
+ Copilot and Windsurf report `SKIP` with the reason, because devia will not guess a path
39
+ inside someone's home directory
40
+ - It is the only command that writes outside `--root`: off by default, every path printed, an
41
+ edited file kept without `--force` (`04_PERMISSIONS.md`, `10_NEVER_ALWAYS.md`)
42
+
43
+ ### Bootstrap, fixed
44
+
45
+ - The skill and every agent adapter told an agent to run `npx devia init`. Since the package is
46
+ scoped, that resolves to nothing in a repository that has not installed devia: `404 devia@*`.
47
+ They now say `npm i -D @schneiderjoseph/devia && npx devia init`, which is what a cold start
48
+ actually needs. Found while installing the skill system-wide, where the cold start is the
49
+ normal case rather than the exception
50
+
3
51
  ## 0.1.0 — 2026-09-03
4
52
 
5
53
  First release. Devia consolidates three bodies of work into one maintained standard plus a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schneiderjoseph/devia",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "One standard, one memory: engineering and design rules plus living project memory for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -21,9 +21,12 @@ ls .devia
21
21
  **No `.devia/`** → initialise before writing any code:
22
22
 
23
23
  ```bash
24
+ npm i -D @schneiderjoseph/devia # the package is scoped, the command is not
24
25
  npx devia init
25
26
  ```
26
27
 
28
+ Install first: `npx devia` only resolves once the package is a dependency of the project.
29
+
27
30
  Then fill `.devia/00_OVERVIEW.md` from what the repository actually contains — stack, modules,
28
31
  where the truth lives. Read the code to fill it; do not invent it. This is not paperwork: it is
29
32
  the difference between a task and a guess (`AGT-002`).
@@ -1,4 +1,6 @@
1
+ import os from "node:os";
1
2
  import path from "node:path";
3
+ import process from "node:process";
2
4
  import { packageRoot, exists, read, writeFile } from "../lib/fs.mjs";
3
5
  import { color, heading, status, line } from "../lib/ui.mjs";
4
6
 
@@ -36,6 +38,89 @@ export function installAdapters(root, { force = false, agents = Object.keys(ADAP
36
38
  return { written, kept };
37
39
  }
38
40
 
41
+ const SKILL_PACK = path.join("skills", "devia", "SKILL.md");
42
+ const adapter = (file) => path.join("templates", "agents", file);
43
+
44
+ /**
45
+ * Where each agent keeps a contract that applies to every project, not one.
46
+ *
47
+ * devia is for every agent, so an agent is listed here as soon as its user-level location is
48
+ * known — and reported as SKIP with the reason when it is not. Each entry carries the file the
49
+ * agent actually reads: a skill pack where the agent loads skills, its own rules format
50
+ * otherwise. Guessing a path inside someone's home directory is the confident wrong answer this
51
+ * tool exists to prevent, so absence of evidence is reported, never rounded up.
52
+ */
53
+ function globalTargets() {
54
+ const home = os.homedir();
55
+ const configDir = (envVar, fallback) =>
56
+ process.env[envVar] ? path.resolve(process.env[envVar]) : path.join(home, fallback);
57
+
58
+ return {
59
+ claude: {
60
+ target: path.join(configDir("CLAUDE_CONFIG_DIR", ".claude"), "skills", "devia", "SKILL.md"),
61
+ source: SKILL_PACK,
62
+ },
63
+ codex: {
64
+ target: path.join(configDir("CODEX_HOME", ".codex"), "skills", "devia", "SKILL.md"),
65
+ source: SKILL_PACK,
66
+ },
67
+ cursor: {
68
+ target: path.join(home, ".cursor", "rules", "devia.mdc"),
69
+ source: adapter("cursor.mdc"),
70
+ },
71
+ gemini: {
72
+ // One file the user owns, not a directory devia can add to: written only when it is
73
+ // absent or empty, so a global instruction file is never silently replaced.
74
+ target: path.join(home, ".gemini", "GEMINI.md"),
75
+ source: adapter("AGENTS.md"),
76
+ onlyWhenEmpty: true,
77
+ },
78
+ copilot: {
79
+ reason: "user-level instructions live in the editor's settings, not a file devia can place",
80
+ },
81
+ windsurf: {
82
+ reason: "no user-level rules file — .windsurfrules is per repository",
83
+ },
84
+ };
85
+ }
86
+
87
+ /**
88
+ * Install the contract once for every project. This is the only path that writes outside
89
+ * `--root`: it happens behind `--global`, and it prints every path it touches
90
+ * (`04_PERMISSIONS.md`).
91
+ */
92
+ export function installGlobalSkill({ force = false } = {}) {
93
+ const written = [];
94
+ const kept = [];
95
+ const skipped = [];
96
+
97
+ for (const [key, entry] of Object.entries(globalTargets())) {
98
+ if (!entry.target) {
99
+ skipped.push([key, entry.reason]);
100
+ continue;
101
+ }
102
+ const content = read(path.join(packageRoot, entry.source));
103
+ if (content === null) {
104
+ skipped.push([key, `${entry.source} missing from the installed package`]);
105
+ continue;
106
+ }
107
+ if (exists(entry.target) && !force) {
108
+ const current = read(entry.target) || "";
109
+ if (entry.onlyWhenEmpty && current.trim()) {
110
+ skipped.push([key, `${path.basename(entry.target)} already has content — add the contract yourself`]);
111
+ continue;
112
+ }
113
+ if (current.trim()) {
114
+ kept.push([key, entry.target]);
115
+ continue;
116
+ }
117
+ }
118
+ writeFile(entry.target, content);
119
+ written.push([key, entry.target]);
120
+ }
121
+ return { written, kept, skipped };
122
+ }
123
+
39
124
  export function installSkill(root, { force = false, agents = Object.keys(SKILL_TARGETS) } = {}) {
40
125
  const skill = read(path.join(packageRoot, "skills", "devia", "SKILL.md"));
41
126
  const written = [];
@@ -64,12 +149,29 @@ ${color.bold("devia skills")} — the same contract for every coding agent
64
149
 
65
150
  devia skills list
66
151
  devia skills install [--agent all|${Object.keys(ADAPTERS).join("|")}] [--force] [--skill]
152
+ devia skills install --global [--force]
67
153
 
68
154
  --skill also install skills/devia/SKILL.md for Cursor and Claude Code
155
+ --global install the skill for every project, in the agent's own configuration
156
+ directory. The only command that writes outside --root; it prints
157
+ every path it touches
69
158
  `.trim());
70
159
  return flags.help ? 0 : 2;
71
160
  }
72
161
 
162
+ if (flags.global) {
163
+ const res = installGlobalSkill({ force: Boolean(flags.force) });
164
+ heading("devia skills install --global");
165
+ for (const [key, target] of res.written) status("PASS", key, target);
166
+ for (const [key, target] of res.kept) status("SKIP", `${key} — already there`, target);
167
+ for (const [key, reason] of res.skipped) status("SKIP", key, reason);
168
+ line("");
169
+ line(color.dim(" The skill is now available in every project. It still expects each"));
170
+ line(color.dim(" repository to carry its own .devia/ — the skill says how to create one."));
171
+ line("");
172
+ return 0;
173
+ }
174
+
73
175
  if (action === "list") {
74
176
  heading("Adapters");
75
177
  for (const [key, [, target]] of Object.entries(ADAPTERS)) {
@@ -10,7 +10,8 @@ This repository uses **devia**: a standard plus a living project memory in `.dev
10
10
  4. Read the memory file for the surface you are touching — see
11
11
  [`.devia/14_INDEX.md`](.devia/14_INDEX.md)
12
12
 
13
- If `.devia/` is missing, run `npx devia init` and fill `00_OVERVIEW.md` before writing code.
13
+ If `.devia/` is missing, run `npm i -D @schneiderjoseph/devia && npx devia init`, then fill
14
+ `00_OVERVIEW.md` before writing code.
14
15
 
15
16
  ## While working
16
17
 
@@ -10,7 +10,8 @@ work, updated with every change.
10
10
  3. `.devia/00_OVERVIEW.md` — what this project is
11
11
  4. The memory file for the surface you are touching (`.devia/14_INDEX.md`)
12
12
 
13
- No `.devia/`? Run `npx devia init` and fill `00_OVERVIEW.md` before writing code.
13
+ No `.devia/`? Run `npm i -D @schneiderjoseph/devia && npx devia init`, then fill
14
+ `00_OVERVIEW.md` before writing code.
14
15
 
15
16
  ## Rules that override default behaviour
16
17
 
@@ -7,7 +7,7 @@ This repository runs on devia. `.devia/` is the project memory and it is not opt
7
7
 
8
8
  1. Before the first edit, read `.devia/AGENTS.md`, `.devia/10_NEVER_ALWAYS.md`,
9
9
  `.devia/00_OVERVIEW.md`, and the memory file for the surface you are touching
10
- (`.devia/14_INDEX.md`). If `.devia/` does not exist, run `npx devia init` first (AGT-001,
10
+ (`.devia/14_INDEX.md`). If `.devia/` does not exist, run `npm i -D @schneiderjoseph/devia && npx devia init` first (AGT-001,
11
11
  AGT-002).
12
12
  2. Never invent an endpoint, field, config key or business rule. Unknown goes to
13
13
  `.devia/11_GAPS.md` or to the human — never into the code as a quiet default (AGT-004,
@@ -4,7 +4,7 @@ This repository runs on devia. `.devia/` is the project memory.
4
4
 
5
5
  1. Read `.devia/AGENTS.md`, `.devia/10_NEVER_ALWAYS.md`, `.devia/00_OVERVIEW.md` and the memory
6
6
  file for the surface you are touching before editing anything. No `.devia/`? Run
7
- `npx devia init` first.
7
+ `npm i -D @schneiderjoseph/devia && npx devia init` first.
8
8
  2. Never invent an endpoint, field, config key or business rule — record the unknown in
9
9
  `.devia/11_GAPS.md` or ask.
10
10
  3. Decided but not built goes to `.devia/12_DEBT.md`; never delete a line you did not discharge.