@ethlete/agent-rules 0.1.0-next.0 → 0.1.0-next.10

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 (134) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/README.md +363 -16
  3. package/content/git-hooks/post-checkout.sh +10 -0
  4. package/content/git-hooks/pre-push.sh +5 -0
  5. package/content/hooks/context-warning.py +430 -0
  6. package/content/output-styles/ste-clarity.md +131 -0
  7. package/content/rules/comments.md +50 -20
  8. package/content/skills/angular-patterns/SKILL.md +1 -1
  9. package/content/skills/api-source/SKILL.md +118 -0
  10. package/content/skills/figma-export/SKILL.md +193 -0
  11. package/content/skills/figma-export/dump-figma-layers.py +83 -0
  12. package/content/skills/figma-export/dump-figma-svg.py +235 -0
  13. package/content/skills/figma-export/measure-template.mjs +87 -0
  14. package/content/skills/git-commit/SKILL.md +6 -7
  15. package/content/skills/git-flow/SKILL.md +87 -0
  16. package/content/skills/handoff/SKILL.md +4 -0
  17. package/content/skills/query/SKILL.md +23 -13
  18. package/content/skills/rxjs-signals/SKILL.md +1 -1
  19. package/content/skills/sdk-docs/SKILL.md +10 -2
  20. package/content/skills/sdk-local-build/SKILL.md +115 -0
  21. package/content/skills/sdk-source/SKILL.md +133 -0
  22. package/content/skills/styleguide/STYLEGUIDE.md +2 -2
  23. package/content/skills/theming/SKILL.md +1 -1
  24. package/content/skills/timetrack/SKILL.md +66 -0
  25. package/package.json +12 -1
  26. package/src/index.js +35 -14
  27. package/src/index.js.map +1 -1
  28. package/src/lib/commitlint.d.ts +10 -0
  29. package/src/lib/commitlint.js +51 -0
  30. package/src/lib/commitlint.js.map +1 -0
  31. package/src/lib/config.d.ts +64 -2
  32. package/src/lib/config.js +54 -9
  33. package/src/lib/config.js.map +1 -1
  34. package/src/lib/git-flow/build.d.ts +35 -0
  35. package/src/lib/git-flow/build.js +24 -0
  36. package/src/lib/git-flow/build.js.map +1 -0
  37. package/src/lib/git-flow/config.d.ts +59 -0
  38. package/src/lib/git-flow/config.js +50 -0
  39. package/src/lib/git-flow/config.js.map +1 -0
  40. package/src/lib/git-flow/index.d.ts +6 -0
  41. package/src/lib/git-flow/index.js +10 -0
  42. package/src/lib/git-flow/index.js.map +1 -0
  43. package/src/lib/git-flow/parse.d.ts +49 -0
  44. package/src/lib/git-flow/parse.js +274 -0
  45. package/src/lib/git-flow/parse.js.map +1 -0
  46. package/src/lib/git-flow/rename.d.ts +24 -0
  47. package/src/lib/git-flow/rename.js +70 -0
  48. package/src/lib/git-flow/rename.js.map +1 -0
  49. package/src/lib/git-flow/start.d.ts +49 -0
  50. package/src/lib/git-flow/start.js +57 -0
  51. package/src/lib/git-flow/start.js.map +1 -0
  52. package/src/lib/git-flow/validate.d.ts +34 -0
  53. package/src/lib/git-flow/validate.js +72 -0
  54. package/src/lib/git-flow/validate.js.map +1 -0
  55. package/src/lib/git-flow-command.d.ts +4 -0
  56. package/src/lib/git-flow-command.js +157 -0
  57. package/src/lib/git-flow-command.js.map +1 -0
  58. package/src/lib/git-flow-repair.d.ts +17 -0
  59. package/src/lib/git-flow-repair.js +146 -0
  60. package/src/lib/git-flow-repair.js.map +1 -0
  61. package/src/lib/git-flow-start.d.ts +20 -0
  62. package/src/lib/git-flow-start.js +132 -0
  63. package/src/lib/git-flow-start.js.map +1 -0
  64. package/src/lib/git.d.ts +27 -0
  65. package/src/lib/git.js +49 -0
  66. package/src/lib/git.js.map +1 -0
  67. package/src/lib/gitlab.d.ts +35 -0
  68. package/src/lib/gitlab.js +98 -0
  69. package/src/lib/gitlab.js.map +1 -0
  70. package/src/lib/index.d.ts +2 -0
  71. package/src/lib/index.js +2 -0
  72. package/src/lib/index.js.map +1 -1
  73. package/src/lib/migrate.d.ts +6 -0
  74. package/src/lib/migrate.js +155 -0
  75. package/src/lib/migrate.js.map +1 -0
  76. package/src/lib/output-style-command.d.ts +3 -0
  77. package/src/lib/output-style-command.js +69 -0
  78. package/src/lib/output-style-command.js.map +1 -0
  79. package/src/lib/output-style.d.ts +38 -0
  80. package/src/lib/output-style.js +126 -0
  81. package/src/lib/output-style.js.map +1 -0
  82. package/src/lib/owned-paths.js +22 -1
  83. package/src/lib/owned-paths.js.map +1 -1
  84. package/src/lib/plan.d.ts +4 -1
  85. package/src/lib/plan.js +141 -8
  86. package/src/lib/plan.js.map +1 -1
  87. package/src/lib/prompt.d.ts +8 -0
  88. package/src/lib/prompt.js +27 -0
  89. package/src/lib/prompt.js.map +1 -0
  90. package/src/lib/render.d.ts +20 -2
  91. package/src/lib/render.js +31 -8
  92. package/src/lib/render.js.map +1 -1
  93. package/src/lib/sync.d.ts +0 -1
  94. package/src/lib/sync.js +8 -2
  95. package/src/lib/sync.js.map +1 -1
  96. package/src/lib/targets/agents-skills.d.ts +8 -0
  97. package/src/lib/targets/agents-skills.js +18 -0
  98. package/src/lib/targets/agents-skills.js.map +1 -0
  99. package/src/lib/targets/claude-hooks.d.ts +11 -0
  100. package/src/lib/targets/claude-hooks.js +28 -0
  101. package/src/lib/targets/claude-hooks.js.map +1 -0
  102. package/src/lib/targets/claude.d.ts +3 -1
  103. package/src/lib/targets/claude.js +14 -21
  104. package/src/lib/targets/claude.js.map +1 -1
  105. package/src/lib/targets/codex-hooks.d.ts +12 -0
  106. package/src/lib/targets/codex-hooks.js +33 -0
  107. package/src/lib/targets/codex-hooks.js.map +1 -0
  108. package/src/lib/targets/codex.d.ts +5 -3
  109. package/src/lib/targets/codex.js +9 -8
  110. package/src/lib/targets/codex.js.map +1 -1
  111. package/src/lib/targets/copilot.d.ts +3 -3
  112. package/src/lib/targets/copilot.js +6 -29
  113. package/src/lib/targets/copilot.js.map +1 -1
  114. package/src/lib/targets/cursor.d.ts +3 -3
  115. package/src/lib/targets/cursor.js +7 -12
  116. package/src/lib/targets/cursor.js.map +1 -1
  117. package/src/lib/targets/git-hooks.d.ts +24 -0
  118. package/src/lib/targets/git-hooks.js +70 -0
  119. package/src/lib/targets/git-hooks.js.map +1 -0
  120. package/src/lib/targets/hooks-shared.d.ts +37 -0
  121. package/src/lib/targets/hooks-shared.js +95 -0
  122. package/src/lib/targets/hooks-shared.js.map +1 -0
  123. package/src/lib/targets/shared.d.ts +22 -13
  124. package/src/lib/targets/shared.js +32 -15
  125. package/src/lib/targets/shared.js.map +1 -1
  126. package/src/lib/timetrack-command.d.ts +11 -0
  127. package/src/lib/timetrack-command.js +199 -0
  128. package/src/lib/timetrack-command.js.map +1 -0
  129. package/src/lib/timetrack.d.ts +86 -0
  130. package/src/lib/timetrack.js +112 -0
  131. package/src/lib/timetrack.js.map +1 -0
  132. package/src/lib/targets/neutral.d.ts +0 -8
  133. package/src/lib/targets/neutral.js +0 -29
  134. package/src/lib/targets/neutral.js.map +0 -1
@@ -0,0 +1,27 @@
1
+ export declare const git: (options: {
2
+ root: string;
3
+ args: string[];
4
+ }) => string;
5
+ /** Runs a command whose output belongs on the terminal — a push, a fetch, a branch creation. */
6
+ export declare const gitLoud: (options: {
7
+ root: string;
8
+ args: string[];
9
+ }) => string;
10
+ export declare const currentBranch: (root: string) => string;
11
+ export declare const allBranches: (root: string) => string[];
12
+ export declare const isDirty: (root: string) => boolean;
13
+ export declare const localBranchExists: (options: {
14
+ root: string;
15
+ branch: string;
16
+ }) => boolean;
17
+ export declare const remoteBranchExists: (options: {
18
+ root: string;
19
+ remote: string;
20
+ branch: string;
21
+ }) => boolean;
22
+ /** `origin` when it exists, otherwise the only remote — a repo with several and no `origin` is ambiguous. */
23
+ export declare const defaultRemote: (root: string) => string | undefined;
24
+ export declare const remoteUrl: (options: {
25
+ root: string;
26
+ remote: string;
27
+ }) => string;
package/src/lib/git.js ADDED
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.remoteUrl = exports.defaultRemote = exports.remoteBranchExists = exports.localBranchExists = exports.isDirty = exports.allBranches = exports.currentBranch = exports.gitLoud = exports.git = void 0;
4
+ const child_process_1 = require("child_process");
5
+ const git_flow_1 = require("./git-flow");
6
+ const git = (options) => (0, child_process_1.execFileSync)('git', options.args, { cwd: options.root, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();
7
+ exports.git = git;
8
+ /** Runs a command whose output belongs on the terminal — a push, a fetch, a branch creation. */
9
+ const gitLoud = (options) => (0, child_process_1.execFileSync)('git', options.args, { cwd: options.root, encoding: 'utf8', stdio: ['ignore', 'inherit', 'inherit'] });
10
+ exports.gitLoud = gitLoud;
11
+ const currentBranch = (root) => (0, exports.git)({ root, args: ['rev-parse', '--abbrev-ref', 'HEAD'] });
12
+ exports.currentBranch = currentBranch;
13
+ const allBranches = (root) => {
14
+ const refs = (0, exports.git)({ root, args: ['for-each-ref', '--format=%(refname)', 'refs/heads', 'refs/remotes'] });
15
+ const names = refs
16
+ .split('\n')
17
+ .filter((ref) => ref && !ref.endsWith('/HEAD'))
18
+ .map(git_flow_1.stripRefPrefix);
19
+ return [...new Set(names)].sort();
20
+ };
21
+ exports.allBranches = allBranches;
22
+ const isDirty = (root) => (0, exports.git)({ root, args: ['status', '--porcelain'] }).length > 0;
23
+ exports.isDirty = isDirty;
24
+ const refExists = (options) => {
25
+ try {
26
+ (0, exports.git)({ root: options.root, args: ['rev-parse', '--verify', '--quiet', options.ref] });
27
+ return true;
28
+ }
29
+ catch (_a) {
30
+ return false;
31
+ }
32
+ };
33
+ const localBranchExists = (options) => refExists({ root: options.root, ref: `refs/heads/${options.branch}` });
34
+ exports.localBranchExists = localBranchExists;
35
+ const remoteBranchExists = (options) => (0, exports.git)({ root: options.root, args: ['ls-remote', '--heads', options.remote, options.branch] }).length > 0;
36
+ exports.remoteBranchExists = remoteBranchExists;
37
+ /** `origin` when it exists, otherwise the only remote — a repo with several and no `origin` is ambiguous. */
38
+ const defaultRemote = (root) => {
39
+ const remotes = (0, exports.git)({ root, args: ['remote'] })
40
+ .split('\n')
41
+ .filter(Boolean);
42
+ if (remotes.includes('origin'))
43
+ return 'origin';
44
+ return remotes.length === 1 ? remotes[0] : undefined;
45
+ };
46
+ exports.defaultRemote = defaultRemote;
47
+ const remoteUrl = (options) => (0, exports.git)({ root: options.root, args: ['remote', 'get-url', options.remote] });
48
+ exports.remoteUrl = remoteUrl;
49
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../../../../libs/agent-rules/src/lib/git.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ export type GitLabProject = {
2
+ host: string;
3
+ project: string;
4
+ };
5
+ export type GitLabMergeRequest = {
6
+ iid: number;
7
+ title: string;
8
+ sourceBranch: string;
9
+ targetBranch: string;
10
+ url: string;
11
+ };
12
+ /** `git@host:group/sub/project.git`, `ssh://git@host:2222/group/project.git` and the https form. */
13
+ export declare const parseRemoteUrl: (url: string) => GitLabProject | undefined;
14
+ export declare const gitLabToken: () => string | undefined;
15
+ /** Open merge requests whose source **or** target is the branch — both block a rename, differently. */
16
+ export declare const openMergeRequestsFor: (options: {
17
+ project: GitLabProject;
18
+ token: string;
19
+ branch: string;
20
+ }) => Promise<GitLabMergeRequest[]>;
21
+ export declare const retargetMergeRequest: (options: {
22
+ project: GitLabProject;
23
+ token: string;
24
+ iid: number;
25
+ target: string;
26
+ }) => Promise<void>;
27
+ /**
28
+ * The GitLab API can change a merge request's target branch but never its source branch, so an open
29
+ * merge request *from* the branch cannot survive a rename — it has to be closed and reopened, which
30
+ * loses its discussion. `repair` reports these and refuses rather than doing that to someone.
31
+ */
32
+ export declare const blockingMergeRequests: (options: {
33
+ mergeRequests: GitLabMergeRequest[];
34
+ branch: string;
35
+ }) => GitLabMergeRequest[];
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.blockingMergeRequests = exports.retargetMergeRequest = exports.openMergeRequestsFor = exports.gitLabToken = exports.parseRemoteUrl = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const TIMEOUT_MS = 15000;
6
+ /** `git@host:group/sub/project.git`, `ssh://git@host:2222/group/project.git` and the https form. */
7
+ const parseRemoteUrl = (url) => {
8
+ const trimmed = url.trim();
9
+ const scp = /^[^@/\s]+@([^:/\s]+):(.+?)(?:\.git)?\/?$/.exec(trimmed);
10
+ if ((scp === null || scp === void 0 ? void 0 : scp[1]) && scp[2])
11
+ return { host: scp[1], project: scp[2] };
12
+ const withScheme = /^[a-z+]+:\/\/(?:[^@/]+@)?([^/:\s]+)(?::\d+)?\/(.+?)(?:\.git)?\/?$/.exec(trimmed);
13
+ if ((withScheme === null || withScheme === void 0 ? void 0 : withScheme[1]) && withScheme[2])
14
+ return { host: withScheme[1], project: withScheme[2] };
15
+ return undefined;
16
+ };
17
+ exports.parseRemoteUrl = parseRemoteUrl;
18
+ const gitLabToken = () => { var _a, _b; return ((_a = process.env['GITLAB_TOKEN']) === null || _a === void 0 ? void 0 : _a.trim()) || ((_b = process.env['CI_JOB_TOKEN']) === null || _b === void 0 ? void 0 : _b.trim()) || undefined; };
19
+ exports.gitLabToken = gitLabToken;
20
+ const TARGET_BRANCH_FIELD = 'target_branch';
21
+ /* eslint-enable @typescript-eslint/naming-convention */
22
+ const toMergeRequest = (raw) => {
23
+ var _a, _b, _c, _d, _e;
24
+ return ({
25
+ iid: (_a = raw.iid) !== null && _a !== void 0 ? _a : 0,
26
+ title: (_b = raw.title) !== null && _b !== void 0 ? _b : '',
27
+ sourceBranch: (_c = raw.source_branch) !== null && _c !== void 0 ? _c : '',
28
+ targetBranch: (_d = raw.target_branch) !== null && _d !== void 0 ? _d : '',
29
+ url: (_e = raw.web_url) !== null && _e !== void 0 ? _e : '',
30
+ });
31
+ };
32
+ const request = (options) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
33
+ const { project, token, path, method, body } = options;
34
+ const base = `https://${project.host}/api/v4/projects/${encodeURIComponent(project.project)}`;
35
+ const response = yield fetch(`${base}${path}`, {
36
+ method: method !== null && method !== void 0 ? method : 'GET',
37
+ headers: Object.assign({ 'private-token': token, accept: 'application/json' }, (body ? { 'content-type': 'application/json' } : {})),
38
+ body: body ? JSON.stringify(body) : undefined,
39
+ signal: AbortSignal.timeout(TIMEOUT_MS),
40
+ });
41
+ if (response.status === 401 || response.status === 403) {
42
+ throw new Error(`GitLab rejected the token (${response.status}) for ${project.project}. GITLAB_TOKEN needs the "api" scope and Developer access.`);
43
+ }
44
+ if (!response.ok) {
45
+ throw new Error(`GitLab responded ${response.status} ${response.statusText} for ${method !== null && method !== void 0 ? method : 'GET'} ${path}.`);
46
+ }
47
+ return { body: (yield response.json()), nextPage: response.headers.get('x-next-page') || undefined };
48
+ });
49
+ /**
50
+ * Follows `x-next-page` rather than reading the first page only: a rename that silently skipped a
51
+ * merge request on page two would leave exactly the half-finished state `repair` must never produce.
52
+ */
53
+ const listMergeRequests = (options) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
54
+ const { project, token, filter } = options;
55
+ const found = [];
56
+ let page = '1';
57
+ while (page) {
58
+ const result = yield request({
59
+ project,
60
+ token,
61
+ path: `/merge_requests?state=opened&per_page=100&${filter}&page=${page}`,
62
+ });
63
+ found.push(...result.body.map(toMergeRequest));
64
+ page = result.nextPage;
65
+ }
66
+ return found;
67
+ });
68
+ /** Open merge requests whose source **or** target is the branch — both block a rename, differently. */
69
+ const openMergeRequestsFor = (options) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
70
+ const { project, token, branch } = options;
71
+ const encoded = encodeURIComponent(branch);
72
+ const [fromBranch, intoBranch] = yield Promise.all([
73
+ listMergeRequests({ project, token, filter: `source_branch=${encoded}` }),
74
+ listMergeRequests({ project, token, filter: `target_branch=${encoded}` }),
75
+ ]);
76
+ const byIid = new Map([...fromBranch, ...intoBranch].map((mr) => [mr.iid, mr]));
77
+ return [...byIid.values()].sort((a, b) => a.iid - b.iid);
78
+ });
79
+ exports.openMergeRequestsFor = openMergeRequestsFor;
80
+ const retargetMergeRequest = (options) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
81
+ const { project, token, iid, target } = options;
82
+ yield request({
83
+ project,
84
+ token,
85
+ path: `/merge_requests/${iid}`,
86
+ method: 'PUT',
87
+ body: { [TARGET_BRANCH_FIELD]: target },
88
+ });
89
+ });
90
+ exports.retargetMergeRequest = retargetMergeRequest;
91
+ /**
92
+ * The GitLab API can change a merge request's target branch but never its source branch, so an open
93
+ * merge request *from* the branch cannot survive a rename — it has to be closed and reopened, which
94
+ * loses its discussion. `repair` reports these and refuses rather than doing that to someone.
95
+ */
96
+ const blockingMergeRequests = (options) => options.mergeRequests.filter((mr) => mr.sourceBranch === options.branch);
97
+ exports.blockingMergeRequests = blockingMergeRequests;
98
+ //# sourceMappingURL=gitlab.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitlab.js","sourceRoot":"","sources":["../../../../../libs/agent-rules/src/lib/gitlab.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,8 @@ export * from './config';
2
2
  export * from './filter';
3
3
  export * from './frontmatter';
4
4
  export * from './load-content';
5
+ export * from './migrate';
6
+ export * from './output-style';
5
7
  export * from './owned-paths';
6
8
  export * from './plan';
7
9
  export * from './render';
package/src/lib/index.js CHANGED
@@ -5,6 +5,8 @@ tslib_1.__exportStar(require("./config"), exports);
5
5
  tslib_1.__exportStar(require("./filter"), exports);
6
6
  tslib_1.__exportStar(require("./frontmatter"), exports);
7
7
  tslib_1.__exportStar(require("./load-content"), exports);
8
+ tslib_1.__exportStar(require("./migrate"), exports);
9
+ tslib_1.__exportStar(require("./output-style"), exports);
8
10
  tslib_1.__exportStar(require("./owned-paths"), exports);
9
11
  tslib_1.__exportStar(require("./plan"), exports);
10
12
  tslib_1.__exportStar(require("./render"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/agent-rules/src/lib/index.ts"],"names":[],"mappings":";;;AAAA,mDAAyB;AACzB,mDAAyB;AACzB,wDAA8B;AAC9B,yDAA+B;AAC/B,wDAA8B;AAC9B,iDAAuB;AACvB,mDAAyB;AACzB,iDAAuB;AACvB,2DAAiC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/agent-rules/src/lib/index.ts"],"names":[],"mappings":";;;AAAA,mDAAyB;AACzB,mDAAyB;AACzB,wDAA8B;AAC9B,yDAA+B;AAC/B,oDAA0B;AAC1B,yDAA+B;AAC/B,wDAA8B;AAC9B,iDAAuB;AACvB,mDAAyB;AACzB,iDAAuB;AACvB,2DAAiC"}
@@ -0,0 +1,6 @@
1
+ import { RunOptions } from './sync';
2
+ /**
3
+ * Converts a repo to the `AGENTS.md`-canonical layout and re-syncs. Safe to re-run: every step
4
+ * detects the migrated state and skips itself.
5
+ */
6
+ export declare const migrate: (options: RunOptions) => number;
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.migrate = void 0;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const config_1 = require("./config");
7
+ const plan_1 = require("./plan");
8
+ const render_1 = require("./render");
9
+ const sync_1 = require("./sync");
10
+ const CLAUDE_MD = 'CLAUDE.md';
11
+ const AGENTS_MD = 'AGENTS.md';
12
+ const CLAUDE_SKILLS = '.claude/skills';
13
+ const AGENTS_SKILLS = '.agents/skills';
14
+ const log = (message) => console.log(` ${message}`);
15
+ /**
16
+ * `AGENTS.md` becomes the canonical instruction file: whatever `CLAUDE.md` held moves to the top
17
+ * of `AGENTS.md`, and `CLAUDE.md` shrinks to the `@AGENTS.md` import Claude Code documents for
18
+ * exactly this setup.
19
+ */
20
+ const migrateClaudeMd = (options) => {
21
+ const { root, dryRun } = options;
22
+ const claudePath = (0, path_1.join)(root, CLAUDE_MD);
23
+ const agentsPath = (0, path_1.join)(root, AGENTS_MD);
24
+ if ((0, plan_1.claudeMdImportsAgentsMd)(root)) {
25
+ log(`keep ${CLAUDE_MD} — already imports ${AGENTS_MD}`);
26
+ return;
27
+ }
28
+ if (!(0, fs_1.existsSync)(claudePath)) {
29
+ log(`create ${CLAUDE_MD} — "@${AGENTS_MD}" import`);
30
+ if (!dryRun)
31
+ (0, fs_1.writeFileSync)(claudePath, `@${AGENTS_MD}\n`, 'utf8');
32
+ return;
33
+ }
34
+ const claudeContent = (0, fs_1.readFileSync)(claudePath, 'utf8').trim();
35
+ const agentsContent = (0, fs_1.existsSync)(agentsPath) ? (0, fs_1.readFileSync)(agentsPath, 'utf8').trim() : '';
36
+ const merged = [claudeContent, agentsContent].filter((part) => part.length > 0).join('\n\n');
37
+ log(`move ${CLAUDE_MD} content into ${AGENTS_MD}`);
38
+ log(`write ${CLAUDE_MD} — "@${AGENTS_MD}" import`);
39
+ if (dryRun)
40
+ return;
41
+ (0, fs_1.writeFileSync)(agentsPath, `${merged}\n`, 'utf8');
42
+ (0, fs_1.writeFileSync)(claudePath, `@${AGENTS_MD}\n`, 'utf8');
43
+ };
44
+ /**
45
+ * Hand-written skills move to the cross-tool `.agents/skills/` location; a symlink stays behind
46
+ * because Claude Code only scans `.claude/skills/` (and follows symlinks there). Generated
47
+ * `ethlete-` entries are left to `sync`, which owns them.
48
+ */
49
+ const migrateSkills = (options) => {
50
+ const { root, dryRun } = options;
51
+ const claudeSkills = (0, path_1.join)(root, CLAUDE_SKILLS);
52
+ if (!(0, fs_1.existsSync)(claudeSkills))
53
+ return;
54
+ for (const entry of (0, fs_1.readdirSync)(claudeSkills)) {
55
+ const source = (0, path_1.join)(claudeSkills, entry);
56
+ if (entry.startsWith('ethlete-') || (0, fs_1.lstatSync)(source).isSymbolicLink() || !(0, fs_1.lstatSync)(source).isDirectory()) {
57
+ continue;
58
+ }
59
+ const destination = (0, path_1.join)(root, AGENTS_SKILLS, entry);
60
+ if ((0, fs_1.existsSync)(destination)) {
61
+ log(`skip ${CLAUDE_SKILLS}/${entry} — ${AGENTS_SKILLS}/${entry} already exists`);
62
+ continue;
63
+ }
64
+ log(`move ${CLAUDE_SKILLS}/${entry} → ${AGENTS_SKILLS}/${entry} (symlink stays behind)`);
65
+ if (dryRun)
66
+ continue;
67
+ (0, fs_1.mkdirSync)((0, path_1.dirname)(destination), { recursive: true });
68
+ (0, fs_1.renameSync)(source, destination);
69
+ try {
70
+ (0, fs_1.symlinkSync)((0, path_1.relative)((0, path_1.dirname)(source), destination), source, 'dir');
71
+ }
72
+ catch (error) {
73
+ (0, fs_1.renameSync)(destination, source);
74
+ log(`undo ${CLAUDE_SKILLS}/${entry} — creating the symlink failed (${error.message})`);
75
+ }
76
+ }
77
+ };
78
+ const LAYOUT_NOTE = `## Agent file layout
79
+
80
+ \`AGENTS.md\` is canonical; \`CLAUDE.md\` is just an \`@AGENTS.md\` import. Skills live in
81
+ \`.agents/skills/<name>/\`; the entries in \`.claude/skills/\` are symlinks to them (Claude Code
82
+ only scans there) - same file, not a duplicate. Edit and create skills under \`.agents/skills/\`,
83
+ plus a symlink for new ones. \`ethlete-*\` skills and the marker block in this file are generated
84
+ by \`npx ethlete-agents sync\` - never edit them by hand.`;
85
+ const withoutMarkedBlock = (content) => {
86
+ const start = content.indexOf(render_1.START_MARKER);
87
+ const end = content.indexOf(render_1.END_MARKER);
88
+ if (start === -1 || end === -1 || end < start)
89
+ return content;
90
+ return content.slice(0, start) + content.slice(end + render_1.END_MARKER.length);
91
+ };
92
+ /**
93
+ * Without this note an agent that lists both skill directories reads the symlinked entries as
94
+ * duplicated files. Skipped when the repo's own `AGENTS.md` prose already explains the layout.
95
+ */
96
+ const addLayoutNote = (options) => {
97
+ const { root, dryRun } = options;
98
+ const path = (0, path_1.join)(root, AGENTS_MD);
99
+ const existing = (0, fs_1.existsSync)(path) ? (0, fs_1.readFileSync)(path, 'utf8') : '';
100
+ if (withoutMarkedBlock(existing).includes(AGENTS_SKILLS)) {
101
+ log(`keep ${AGENTS_MD} — already documents the ${AGENTS_SKILLS} layout`);
102
+ return;
103
+ }
104
+ log(`write ${AGENTS_MD} — add the agent file layout note`);
105
+ if (dryRun)
106
+ return;
107
+ const start = existing.indexOf(render_1.START_MARKER);
108
+ const contents = start === -1
109
+ ? `${[existing.trimEnd(), LAYOUT_NOTE].filter((part) => part.length > 0).join('\n\n')}\n`
110
+ : `${existing.slice(0, start).trimEnd()}\n\n${LAYOUT_NOTE}\n\n${existing.slice(start)}`;
111
+ (0, fs_1.writeFileSync)(path, contents, 'utf8');
112
+ };
113
+ const migrateConfig = (options) => {
114
+ const { root, dryRun } = options;
115
+ const path = (0, path_1.join)(root, config_1.CONFIG_FILE_NAME);
116
+ const raw = (0, fs_1.existsSync)(path)
117
+ ? JSON.parse((0, fs_1.readFileSync)(path, 'utf8'))
118
+ : { targets: 'auto', vars: {}, exclude: [] };
119
+ const targets = raw['targets'];
120
+ const explicit = Array.isArray(targets) ? targets : undefined;
121
+ const missingCodex = explicit !== undefined && !explicit.includes('codex');
122
+ const missingFlag = raw['claudeMdImportsAgentsMd'] !== true;
123
+ if (!missingCodex && !missingFlag) {
124
+ log(`keep ${config_1.CONFIG_FILE_NAME} — already migrated`);
125
+ return;
126
+ }
127
+ if (missingCodex && explicit)
128
+ raw['targets'] = [...explicit, 'codex'];
129
+ raw['claudeMdImportsAgentsMd'] = true;
130
+ log(`write ${config_1.CONFIG_FILE_NAME} — codex target + claudeMdImportsAgentsMd`);
131
+ if (!dryRun)
132
+ (0, fs_1.writeFileSync)(path, `${JSON.stringify(raw, null, 2)}\n`, 'utf8');
133
+ };
134
+ /**
135
+ * Converts a repo to the `AGENTS.md`-canonical layout and re-syncs. Safe to re-run: every step
136
+ * detects the migrated state and skips itself.
137
+ */
138
+ const migrate = (options) => {
139
+ const { root, dryRun = false } = options;
140
+ console.log(dryRun ? 'Migration plan (dry run):' : 'Migrating to the AGENTS.md + .agents/skills layout:');
141
+ migrateClaudeMd({ root, dryRun });
142
+ migrateSkills({ root, dryRun });
143
+ addLayoutNote({ root, dryRun });
144
+ migrateConfig({ root, dryRun });
145
+ if (dryRun) {
146
+ console.log('\nRe-run without --dry-run to apply, then a sync runs automatically.');
147
+ return 0;
148
+ }
149
+ console.log('\nRunning sync:');
150
+ const result = (0, sync_1.sync)(options);
151
+ console.log('\nDone. Commit the result. Note: the .claude/skills symlinks need symlink support on checkout (Windows: Developer Mode).');
152
+ return result;
153
+ };
154
+ exports.migrate = migrate;
155
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../../../../libs/agent-rules/src/lib/migrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare const outputStyleCommand: (options: {
2
+ argv: string[];
3
+ }) => 1 | 0;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.outputStyleCommand = void 0;
4
+ const output_style_1 = require("./output-style");
5
+ const FLAGS_WITH_VALUE = ['--config-dir'];
6
+ const positionalArgs = (args) => args.filter((entry, index) => { var _a; return !entry.startsWith('--') && !FLAGS_WITH_VALUE.includes((_a = args[index - 1]) !== null && _a !== void 0 ? _a : ''); });
7
+ const flagValue = (args, flag) => {
8
+ const index = args.indexOf(flag);
9
+ return index === -1 ? undefined : args[index + 1];
10
+ };
11
+ const usage = () => `ethlete-agents output-style — install an Ethlete output style into Claude Code
12
+
13
+ An output style replaces Claude Code's own answer style for every session, so it is written
14
+ into the machine's Claude config rather than into a repository.
15
+
16
+ output-style [name] Install the style and switch Claude Code to it
17
+ (default: ${output_style_1.DEFAULT_OUTPUT_STYLE})
18
+
19
+ Options
20
+ --no-activate Write the file, but leave "outputStyle" in settings.json alone
21
+ --remove Delete the style file and stop using it
22
+ --force Overwrite (or delete) a style file this command did not write
23
+ --dry-run Print what would change without writing
24
+ --config-dir <path> Claude's config directory (default: $CLAUDE_CONFIG_DIR, else ~/.claude)
25
+
26
+ Ships: ${(0, output_style_1.availableOutputStyles)().join(', ') || 'nothing'}
27
+
28
+ Claude Code only. Codex has no output-style mechanism - everything it is told comes from
29
+ AGENTS.md, which \`ethlete-agents sync\` already writes.
30
+ `;
31
+ const describe = (file) => ` ${file.action.padEnd(6)} ${file.path}`;
32
+ const outputStyleCommand = (options) => {
33
+ const { argv } = options;
34
+ if (argv.includes('--help') || argv.includes('-h')) {
35
+ console.log(usage());
36
+ return 0;
37
+ }
38
+ const plan = (0, output_style_1.planOutputStyle)({
39
+ name: positionalArgs(argv)[0],
40
+ configDir: flagValue(argv, '--config-dir'),
41
+ activate: !argv.includes('--no-activate'),
42
+ remove: argv.includes('--remove'),
43
+ force: argv.includes('--force'),
44
+ });
45
+ console.log(`Style ${plan.name}`);
46
+ console.log(`Config ${plan.configDir}`);
47
+ if (plan.conflict) {
48
+ console.error(plan.conflict);
49
+ return 1;
50
+ }
51
+ if (plan.files.length === 0) {
52
+ console.log(argv.includes('--remove') ? 'It is not installed here.' : 'Already installed and in use.');
53
+ return 0;
54
+ }
55
+ plan.files.forEach((file) => console.log(describe(file)));
56
+ if (argv.includes('--dry-run')) {
57
+ console.log(`\n${plan.files.length} file(s) would change. Re-run without --dry-run to apply.`);
58
+ return 0;
59
+ }
60
+ (0, output_style_1.applyOutputStylePlan)(plan);
61
+ if (argv.includes('--remove')) {
62
+ console.log('\nRemoved. A session that is already open keeps the style until it restarts.');
63
+ return 0;
64
+ }
65
+ console.log(`\nInstalled. Start a new session, or run \`/output-style ${plan.name}\`, to use it.`);
66
+ return 0;
67
+ };
68
+ exports.outputStyleCommand = outputStyleCommand;
69
+ //# sourceMappingURL=output-style-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-style-command.js","sourceRoot":"","sources":["../../../../../libs/agent-rules/src/lib/output-style-command.ts"],"names":[],"mappings":";;;AAAA,iDAMwB;AAExB,MAAM,gBAAgB,GAAG,CAAC,cAAc,CAAC,CAAC;AAE1C,MAAM,cAAc,GAAG,CAAC,IAAc,EAAE,EAAE,CACxC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,WAAC,OAAA,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,MAAA,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,mCAAI,EAAE,CAAC,CAAA,EAAA,CAAC,CAAC;AAE9G,MAAM,SAAS,GAAG,CAAC,IAAc,EAAE,IAAY,EAAE,EAAE;IACjD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;AACpD,CAAC,CAAC;AAEF,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC;;;;;;sCAMkB,mCAAoB;;;;;;;;;SASjD,IAAA,oCAAqB,GAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS;;;;CAIvD,CAAC;AAEF,MAAM,QAAQ,GAAG,CAAC,IAAsC,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;AAEhG,MAAM,kBAAkB,GAAG,CAAC,OAA2B,EAAE,EAAE;IAChE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IAEzB,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;QAErB,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,IAAI,GAAG,IAAA,8BAAe,EAAC;QAC3B,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC7B,SAAS,EAAE,SAAS,CAAC,IAAI,EAAE,cAAc,CAAC;QAC1C,QAAQ,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC;QACzC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;QACjC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;KAChC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IAEzC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAE7B,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC;QAEvG,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAE1D,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,2DAA2D,CAAC,CAAC;QAE/F,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAA,mCAAoB,EAAC,IAAI,CAAC,CAAC;IAE3B,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,8EAA8E,CAAC,CAAC;QAE5F,OAAO,CAAC,CAAC;IACX,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,4DAA4D,IAAI,CAAC,IAAI,gBAAgB,CAAC,CAAC;IAEnG,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AAnDW,QAAA,kBAAkB,sBAmD7B"}
@@ -0,0 +1,38 @@
1
+ export declare const DEFAULT_OUTPUT_STYLE = "ste-clarity";
2
+ /** Claude Code reads `~/.claude`, or `CLAUDE_CONFIG_DIR` when it is set; an explicit path wins over both. */
3
+ export declare const resolveClaudeConfigDir: (override?: string) => string;
4
+ export declare const availableOutputStyles: (contentRoot?: string) => string[];
5
+ /** `contents` is `null` exactly when the action is `remove`. */
6
+ export type PlannedOutputStyleFile = {
7
+ path: string;
8
+ action: 'create' | 'update' | 'remove';
9
+ contents: string | null;
10
+ };
11
+ export type OutputStylePlan = {
12
+ name: string;
13
+ configDir: string;
14
+ stylePath: string;
15
+ settingsPath: string;
16
+ /** The style Claude Code is set to now, before this plan is applied. */
17
+ activeStyle: string | null;
18
+ files: PlannedOutputStyleFile[];
19
+ /** Set when the installed file is not this command's own; nothing is planned until `force`. */
20
+ conflict: string | null;
21
+ };
22
+ export type OutputStyleOptions = {
23
+ name?: string;
24
+ configDir?: string;
25
+ /** Also point `outputStyle` in `settings.json` at the style (default). */
26
+ activate?: boolean;
27
+ remove?: boolean;
28
+ /** Overwrite or delete a style file this command did not write. */
29
+ force?: boolean;
30
+ contentRoot?: string;
31
+ };
32
+ /**
33
+ * What an install (or a `remove`) would write into Claude Code's user config, without touching
34
+ * disk. A style file that someone else wrote is reported as a conflict rather than overwritten -
35
+ * the name is a plain file name, so a hand-written style can carry it.
36
+ */
37
+ export declare const planOutputStyle: (options?: OutputStyleOptions) => OutputStylePlan;
38
+ export declare const applyOutputStylePlan: (plan: OutputStylePlan) => void;