heymark 1.1.2 → 1.2.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/README.md CHANGED
@@ -1,170 +1,170 @@
1
- # Heymark
2
-
3
- Heymark is a tool that manages Skill documentation for AI coding tools in a single location and automatically converts it into each tool format.
4
- A Markdown source written once can be reused across multiple agent tools.
5
-
6
- 1. [Overview](#overview)
7
- 2. [Features](#features)
8
- 3. [Supported Agent Tools](#supported-agent-tools)
9
- 4. [Tech Stack](#tech-stack)
10
- 5. [Heymark Usage](#heymark-usage)
11
- 6. [Heymark Development](#heymark-development)
12
-
13
- ## Overview
14
-
15
- Managing Skill files separately for each AI tool leads to fragmented documentation and higher maintenance costs.
16
- Heymark follows the Single Source of Truth principle and converts one Markdown source into multiple tool formats.
17
- A Skill written once can be used immediately in Cursor, Claude Code, GitHub Copilot, OpenAI Codex, and Antigravity.
18
-
19
- ## Features
20
-
21
- - Single source management: Manage Skills for multiple AI tools with one Markdown file
22
- - Automatic format conversion: Convert into each tool's native format (YAML frontmatter, AGENTS.md, etc.)
23
- - Selective conversion: Convert only the tools you need
24
- - NPM package distribution: Run with `npx` without installation
25
- - Plugin structure: Extend supported tools by adding conversion modules
26
-
27
- ## Supported Agent Tools
28
-
29
- | Tool | Output Format | Key Features |
30
- | :------------- | :--------------------------------------- | :------------------------------------------------------- |
31
- | Cursor | `.cursor/rules/*.mdc` | YAML frontmatter (`description`, `globs`, `alwaysApply`) |
32
- | Claude Code | `.claude/skills/*/SKILL.md` | Skill directory structure + YAML frontmatter |
33
- | GitHub Copilot | `.github/instructions/*.instructions.md` | Multi-pattern mapping via `applyTo` |
34
- | OpenAI Codex | `.agents/skills/*/SKILL.md` | Skill directory structure + YAML frontmatter |
35
- | Antigravity | `.agent/skills/*/SKILL.md` | Skill directory structure + YAML frontmatter |
36
-
37
- ## Tech Stack
38
-
39
- - Runtime: Node.js
40
- - Language: JavaScript
41
- - Core: File system API, YAML frontmatter parsing
42
-
43
- ## Heymark Usage
44
-
45
- ### 1. Prepare the Skill Markdown Archive Repository
46
-
47
- Create Markdown files in a Skill source directory (external or personal GitHub repository) and define metadata with YAML frontmatter.
48
-
49
- ```markdown
50
- ---
51
- description: "AI assistant behavior guidelines"
52
- globs: "**/*.ts,**/*.tsx"
53
- alwaysApply: true
54
- ---
55
-
56
- # Skill Title
57
-
58
- Skill content...
59
- ```
60
-
61
- You can keep the repository structure simple, as shown below.
62
-
63
- ```text
64
- my-skills-repository/
65
- ai-behavior.md
66
- code-conventions.md
67
- api-skills.md
68
- ```
69
-
70
- Skill sources are read from a remote GitHub repository (Public/Private).
71
-
72
- ### 2. Initial Setup
73
-
74
- For first-time use, configure the Skill source repository once.
75
-
76
- ```bash
77
- # Configure Skill source (.heymark/config.json will be created)
78
- npx heymark init <GitHub-Repository-URL>
79
- ```
80
-
81
- ```bash
82
- # HTTPS (for private repositories, Git credentials/token setup is required)
83
- npx heymark init https://github.com/org/my-rules.git
84
-
85
- # SSH (recommended for private repositories)
86
- npx heymark init git@github.com:org/my-rules.git
87
-
88
- # When .md files are in a subdirectory of the repository
89
- npx heymark init https://github.com/org/my-rules.git --dir rules --branch main
90
- ```
91
-
92
- ### 3. Run
93
-
94
- You can run it directly with `npx` without installation.
95
- Skills are fetched from an external GitHub repository, and Markdown files in that repository are converted into each AI tool format and generated in the current project.
96
-
97
- ```bash
98
- # Fetch from the external Skill repository configured in .heymark/config.json and convert to all tool formats
99
- # (delete previously generated files and recreate them)
100
- npx heymark
101
-
102
- # Use a different external repository for this run only (ignore .heymark/config.json)
103
- npx heymark --source https://github.com/org/other-rules.git
104
-
105
- # Convert only specific tools
106
- npx heymark -t cursor,claude
107
-
108
- # Preview (check conversion result without creating files)
109
- npx heymark --preview
110
-
111
- # Delete tool-specific files generated previously
112
- npx heymark --clean
113
-
114
- # CLI help
115
- npx heymark --help
116
- ```
117
-
118
- ## Heymark Development
119
-
120
- ### 1. Local Execution
121
-
122
- ```bash
123
- # Configure Skill source (first-time only, GitHub repository URL)
124
- node scripts/sync.js init https://github.com/org/my-rules.git
125
-
126
- # Convert to all tool formats
127
- node scripts/sync.js
128
-
129
- # Use a different repository for this run only
130
- node scripts/sync.js --source https://github.com/org/other-rules.git
131
-
132
- # Convert only specific tools
133
- node scripts/sync.js -t cursor,claude
134
-
135
- # Preview (check without creating files)
136
- node scripts/sync.js --preview
137
-
138
- # Delete generated files
139
- node scripts/sync.js --clean
140
- ```
141
-
142
- ### 2. Release
143
-
144
- ```bash
145
- # NPM login
146
- npm login
147
- # Username: your-npm-username
148
- # Email: your-email@example.com
149
-
150
- # 1. Test after updating Skills
151
- node scripts/sync.js --preview
152
-
153
- # 2. Update version (Git tag is created automatically)
154
- npm version patch # or minor, major
155
-
156
- # 3. Push to GitHub
157
- git push --follow-tags # push commits and tags together
158
-
159
- # 4. Publish to NPM
160
- npm publish
161
- ```
162
-
163
- ### 3. Versioning
164
-
165
- - `patch` (1.0.0 -> 1.0.1): Bug fixes, typo fixes
166
- - `minor` (1.0.0 -> 1.1.0): New Skills, feature improvements
167
- - `major` (1.0.0 -> 2.0.0): Breaking changes
168
- - The `npm version` command automatically creates a Git tag.
169
- - `git push --follow-tags` pushes normal commits and tags together. (Recommended)
170
- - Alternatively, you can run `git push && git push --tags` to push commits first and then push all tags separately.
1
+ # Heymark
2
+
3
+ Heymark is a tool that manages Skill documentation for AI coding tools in a single location and automatically converts it into each tool format.
4
+ A Markdown source written once can be reused across multiple agent tools.
5
+
6
+ 1. [Overview](#overview)
7
+ 2. [Features](#features)
8
+ 3. [Supported Agent Tools](#supported-agent-tools)
9
+ 4. [Tech Stack](#tech-stack)
10
+ 5. [Heymark Usage](#heymark-usage)
11
+ 6. [Heymark Development](#heymark-development)
12
+
13
+ ## Overview
14
+
15
+ Managing Skill files separately for each AI tool leads to fragmented documentation and higher maintenance costs.
16
+ Heymark follows the Single Source of Truth principle and converts one Markdown source into multiple tool formats.
17
+ A Skill written once can be used immediately in Cursor, Claude Code, GitHub Copilot, OpenAI Codex, and Antigravity.
18
+
19
+ ## Features
20
+
21
+ - Single source management: Manage Skills for multiple AI tools with one Markdown file
22
+ - Automatic format conversion: Convert into each tool's native format (YAML frontmatter, AGENTS.md, etc.)
23
+ - Selective conversion: Convert only the tools you need
24
+ - NPM package distribution: Run with `npx` without installation
25
+ - Plugin structure: Extend supported tools by adding conversion modules
26
+
27
+ ## Supported Agent Tools
28
+
29
+ | Tool | Output Format | Key Features |
30
+ | :---------- | :--------------------------------------- | :------------------------------------------------------- |
31
+ | Cursor | `.cursor/rules/*.mdc` | YAML frontmatter (`description`, `globs`, `alwaysApply`) |
32
+ | Claude Code | `.claude/skills/*/SKILL.md` | Skill directory structure + YAML frontmatter |
33
+ | Copilot | `.github/instructions/*.instructions.md` | Multi-pattern mapping via `applyTo` |
34
+ | Codex | `.agents/skills/*/SKILL.md` | Skill directory structure + YAML frontmatter |
35
+ | Antigravity | `.agent/skills/*/SKILL.md` | Skill directory structure + YAML frontmatter |
36
+
37
+ ## Tech Stack
38
+
39
+ - Runtime: Node.js
40
+ - Language: JavaScript
41
+ - Core: File system API, YAML frontmatter parsing
42
+
43
+ ## Heymark Usage
44
+
45
+ ### 1. Prepare the Skill Markdown Archive Repository
46
+
47
+ Create Markdown files in a Skill source directory (external or personal GitHub repository) and define metadata with YAML frontmatter.
48
+
49
+ ```markdown
50
+ ---
51
+ description: "AI assistant behavior guidelines"
52
+ globs: "**/*.ts,**/*.tsx"
53
+ alwaysApply: true
54
+ ---
55
+
56
+ # Skill Title
57
+
58
+ Skill content...
59
+ ```
60
+
61
+ You can keep the repository structure simple, as shown below.
62
+
63
+ ```text
64
+ my-skills-repository/
65
+ ai-behavior.md
66
+ code-conventions.md
67
+ api-skills.md
68
+ ```
69
+
70
+ Skill sources are read from a remote GitHub repository (Public/Private).
71
+
72
+ ### 2. Initial Setup
73
+
74
+ For first-time use, configure the Skill source repository once.
75
+
76
+ ```bash
77
+ # Configure Skill source (.heymark/config.json will be created)
78
+ npx heymark init <GitHub-Repository-URL>
79
+ ```
80
+
81
+ ```bash
82
+ # HTTPS (for private repositories, Git credentials/token setup is required)
83
+ npx heymark init https://github.com/org/my-rules.git
84
+
85
+ # SSH (recommended for private repositories)
86
+ npx heymark init git@github.com:org/my-rules.git
87
+
88
+ # When .md files are in a subdirectory of the repository
89
+ npx heymark init https://github.com/org/my-rules.git --dir rules --branch main
90
+ ```
91
+
92
+ ### 3. Run
93
+
94
+ You can run it directly with `npx` without installation.
95
+ Skills are fetched from an external GitHub repository, and Markdown files in that repository are converted into each AI tool format and generated in the current project.
96
+
97
+ ```bash
98
+ # Fetch from the external Skill repository configured in .heymark/config.json and convert to all tool formats
99
+ # (delete previously generated files and recreate them)
100
+ npx heymark
101
+
102
+ # Use a different external repository for this run only (ignore .heymark/config.json)
103
+ npx heymark --source https://github.com/org/other-rules.git
104
+
105
+ # Convert only specific tools
106
+ npx heymark -t cursor,claude
107
+
108
+ # Preview (check conversion result without creating files)
109
+ npx heymark --preview
110
+
111
+ # Delete tool-specific files generated previously
112
+ npx heymark --clean
113
+
114
+ # CLI help
115
+ npx heymark --help
116
+ ```
117
+
118
+ ## Heymark Development
119
+
120
+ ### 1. Local Execution
121
+
122
+ ```bash
123
+ # Configure Skill source (first-time only, GitHub repository URL)
124
+ node scripts/sync.js init https://github.com/org/my-rules.git
125
+
126
+ # Convert to all tool formats
127
+ node scripts/sync.js
128
+
129
+ # Use a different repository for this run only
130
+ node scripts/sync.js --source https://github.com/org/other-rules.git
131
+
132
+ # Convert only specific tools
133
+ node scripts/sync.js -t cursor,claude
134
+
135
+ # Preview (check without creating files)
136
+ node scripts/sync.js --preview
137
+
138
+ # Delete generated files
139
+ node scripts/sync.js --clean
140
+ ```
141
+
142
+ ### 2. Release
143
+
144
+ ```bash
145
+ # NPM login
146
+ npm login
147
+ # Username: your-npm-username
148
+ # Email: your-email@example.com
149
+
150
+ # 1. Test after updating Skills
151
+ node scripts/sync.js --preview
152
+
153
+ # 2. Update version (Git tag is created automatically)
154
+ npm version patch # or minor, major
155
+
156
+ # 3. Push to GitHub
157
+ git push --follow-tags # push commits and tags together
158
+
159
+ # 4. Publish to NPM
160
+ npm publish
161
+ ```
162
+
163
+ ### 3. Versioning
164
+
165
+ - `patch` (1.0.0 -> 1.0.1): Bug fixes, typo fixes
166
+ - `minor` (1.0.0 -> 1.1.0): New Skills, feature improvements
167
+ - `major` (1.0.0 -> 2.0.0): Breaking changes
168
+ - The `npm version` command automatically creates a Git tag.
169
+ - `git push --follow-tags` pushes normal commits and tags together. (Recommended)
170
+ - Alternatively, you can run `git push && git push --tags` to push commits first and then push all tags separately.
package/package.json CHANGED
@@ -1,57 +1,56 @@
1
- {
2
- "name": "heymark",
3
- "version": "1.1.2",
4
- "description": "Centralized AI coding tool conventions with auto-conversion to multiple formats",
5
- "main": "scripts/sync.js",
6
- "bin": {
7
- "heymark": "scripts/sync.js"
8
- },
9
- "scripts": {
10
- "sync": "node scripts/sync.js",
11
- "init": "node scripts/sync.js init",
12
- "test": "echo \"Error: no test specified\" && exit 1"
13
- },
14
- "keywords": [
15
- "ai",
16
- "coding",
17
- "conventions",
18
- "cursor",
19
- "claude",
20
- "copilot",
21
- "codex",
22
- "rules"
23
- ],
24
- "author": {
25
- "name": "i2na",
26
- "email": "yena.e121@gmail.com",
27
- "url": "https://github.com/i2na"
28
- },
29
- "contributors": [
30
- {
31
- "name": "i2na",
32
- "email": "yena.e121@gmail.com",
33
- "url": "https://github.com/i2na"
34
- },
35
- {
36
- "name": "yezzero",
37
- "email": "yeyeonggim06@gmail.com",
38
- "url": "https://github.com/yezzero"
39
- }
40
- ],
41
- "license": "MIT",
42
- "engines": {
43
- "node": ">=14.0.0"
44
- },
45
- "files": [
46
- "scripts/",
47
- "rules/",
48
- "README.md"
49
- ],
50
- "repository": {
51
- "type": "git",
52
- "url": "git+https://github.com/MosslandOpenDevs/heymark.git"
53
- },
54
- "publishConfig": {
55
- "access": "public"
56
- }
57
- }
1
+ {
2
+ "name": "heymark",
3
+ "version": "1.2.0",
4
+ "description": "Rules & Skills Hub for AI Coding Assistants",
5
+ "type": "commonjs",
6
+ "main": "scripts/sync.js",
7
+ "bin": "scripts/sync.js",
8
+ "keywords": [
9
+ "ai-coding-assistant",
10
+ "ai-agent",
11
+ "ai-skill",
12
+ "ai-rule",
13
+ "skill-management",
14
+ "cursor",
15
+ "claude-code",
16
+ "copilot",
17
+ "codex",
18
+ "antigravity"
19
+ ],
20
+ "homepage": "https://github.com/MosslandOpenDevs/heymark#readme",
21
+ "bugs": {
22
+ "url": "https://github.com/MosslandOpenDevs/heymark/issues",
23
+ "email": "yena@moss.land"
24
+ },
25
+ "license": "MIT",
26
+ "author": {
27
+ "name": "i-2na",
28
+ "email": "yena@moss.land",
29
+ "url": "https://github.com/i2na"
30
+ },
31
+ "contributors": [
32
+ {
33
+ "name": "i-2na",
34
+ "email": "yena@moss.land",
35
+ "url": "https://github.com/i2na"
36
+ },
37
+ {
38
+ "name": "yezzero",
39
+ "email": "yeyeonggim06@gmail.com",
40
+ "url": "https://github.com/yezzero"
41
+ }
42
+ ],
43
+ "engines": {
44
+ "node": ">=14.0.0"
45
+ },
46
+ "files": [
47
+ "scripts/"
48
+ ],
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "git+https://github.com/MosslandOpenDevs/heymark.git"
52
+ },
53
+ "publishConfig": {
54
+ "access": "public"
55
+ }
56
+ }
@@ -1,73 +1,110 @@
1
- "use strict";
2
-
3
- const fs = require("fs");
4
- const path = require("path");
5
-
6
- const CONFIG_DIR = ".heymark";
7
- const CONFIG_FILENAME = "config.json";
8
- /** 프로젝트 루트 기준 설정 파일 경로 (표시용) */
9
- const CONFIG_RELATIVE = path.join(CONFIG_DIR, CONFIG_FILENAME);
10
-
11
- /**
12
- * rulesSource: GitHub 저장소 URL (https://github.com/org/repo 또는 git@github.com:org/repo.git)
13
- * branch: 브랜치 (기본 main)
14
- * rulesSourceDir: 저장소 내부에서 .md가 있는 하위 디렉터리 (기본 "" = 루트)
15
- * @typedef {{ rulesSource: string, branch?: string, rulesSourceDir?: string }} RuleBookConfig
16
- */
17
-
18
- /**
19
- * 프로젝트 루트에서 .heymark/config.json을 읽습니다.
20
- * @param {string} projectRoot - 프로젝트 루트 (보통 process.cwd())
21
- * @returns {RuleBookConfig | null}
22
- */
23
- function loadConfig(projectRoot) {
24
- const configPath = path.join(projectRoot, CONFIG_DIR, CONFIG_FILENAME);
25
- if (!fs.existsSync(configPath)) return null;
26
-
27
- try {
28
- const raw = fs.readFileSync(configPath, "utf8");
29
- const data = JSON.parse(raw);
30
- if (!data || typeof data.rulesSource !== "string" || !data.rulesSource.trim()) {
31
- return null;
32
- }
33
- return {
34
- rulesSource: data.rulesSource.trim(),
35
- branch:
36
- typeof data.branch === "string" && data.branch.trim() ? data.branch.trim() : "main",
37
- rulesSourceDir:
38
- typeof data.rulesSourceDir === "string" ? data.rulesSourceDir.trim() : "",
39
- };
40
- } catch {
41
- return null;
42
- }
43
- }
44
-
45
- /**
46
- * 초기 설정 파일을 생성합니다. (원격 GitHub 저장소 URL 사용) .heymark/config.json에 저장합니다.
47
- * @param {string} projectRoot
48
- * @param {RuleBookConfig} config - { rulesSource: repoUrl, branch?, rulesSourceDir? }
49
- */
50
- function writeConfig(projectRoot, config) {
51
- const configDir = path.join(projectRoot, CONFIG_DIR);
52
- if (!fs.existsSync(configDir)) {
53
- fs.mkdirSync(configDir, { recursive: true });
54
- }
55
- const configPath = path.join(configDir, CONFIG_FILENAME);
56
- const toWrite = {
57
- rulesSource: config.rulesSource,
58
- branch: config.branch || "main",
59
- };
60
- if (config.rulesSourceDir) {
61
- toWrite.rulesSourceDir = config.rulesSourceDir;
62
- }
63
- fs.writeFileSync(configPath, JSON.stringify(toWrite, null, 2), "utf8");
64
- return configPath;
65
- }
66
-
67
- module.exports = {
68
- CONFIG_DIR,
69
- CONFIG_FILENAME,
70
- CONFIG_RELATIVE,
71
- loadConfig,
72
- writeConfig,
73
- };
1
+ "use strict";
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+
6
+ const CONFIG_DIR = ".heymark";
7
+ const CONFIG_FILENAME = "config.json";
8
+ const DEFAULT_BRANCH = "main";
9
+ const CONFIG_RELATIVE = path.join(CONFIG_DIR, CONFIG_FILENAME);
10
+
11
+ /**
12
+ * @typedef {{ rulesSource: string, branch?: string, rulesSourceDir?: string }} RuleBookConfig
13
+ */
14
+
15
+ /**
16
+ * Resolve config file path from project root.
17
+ * @param {string} projectRoot
18
+ * @returns {string}
19
+ */
20
+ function getConfigPath(projectRoot) {
21
+ return path.join(projectRoot, CONFIG_DIR, CONFIG_FILENAME);
22
+ }
23
+
24
+ /**
25
+ * Normalize and validate config payload.
26
+ * @param {unknown} value
27
+ * @returns {RuleBookConfig | null}
28
+ */
29
+ function normalizeConfig(value) {
30
+ if (!value || typeof value !== "object") {
31
+ return null;
32
+ }
33
+
34
+ const raw =
35
+ /** @type {{ rulesSource?: unknown, branch?: unknown, rulesSourceDir?: unknown }} */ (
36
+ value
37
+ );
38
+ if (typeof raw.rulesSource !== "string" || !raw.rulesSource.trim()) {
39
+ return null;
40
+ }
41
+
42
+ return {
43
+ rulesSource: raw.rulesSource.trim(),
44
+ branch:
45
+ typeof raw.branch === "string" && raw.branch.trim()
46
+ ? raw.branch.trim()
47
+ : DEFAULT_BRANCH,
48
+ rulesSourceDir: typeof raw.rulesSourceDir === "string" ? raw.rulesSourceDir.trim() : "",
49
+ };
50
+ }
51
+
52
+ /**
53
+ * Read config from project root.
54
+ * @param {string} projectRoot
55
+ * @returns {RuleBookConfig | null}
56
+ */
57
+ function loadConfig(projectRoot) {
58
+ const configPath = getConfigPath(projectRoot);
59
+ if (!fs.existsSync(configPath)) {
60
+ return null;
61
+ }
62
+
63
+ try {
64
+ const raw = fs.readFileSync(configPath, "utf8");
65
+ return normalizeConfig(JSON.parse(raw));
66
+ } catch {
67
+ return null;
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Create initial config file in .heymark/config.json.
73
+ * @param {string} projectRoot
74
+ * @param {RuleBookConfig} config
75
+ * @returns {string}
76
+ */
77
+ function writeConfig(projectRoot, config) {
78
+ const configDir = path.join(projectRoot, CONFIG_DIR);
79
+ if (!fs.existsSync(configDir)) {
80
+ fs.mkdirSync(configDir, { recursive: true });
81
+ }
82
+
83
+ const normalized = normalizeConfig(config);
84
+ if (!normalized) {
85
+ throw new Error("Invalid config payload");
86
+ }
87
+
88
+ const configPath = path.join(configDir, CONFIG_FILENAME);
89
+ const toWrite = {
90
+ rulesSource: normalized.rulesSource,
91
+ branch: normalized.branch || DEFAULT_BRANCH,
92
+ };
93
+ if (normalized.rulesSourceDir) {
94
+ toWrite.rulesSourceDir = normalized.rulesSourceDir;
95
+ }
96
+
97
+ fs.writeFileSync(configPath, JSON.stringify(toWrite, null, 2), "utf8");
98
+ return configPath;
99
+ }
100
+
101
+ module.exports = {
102
+ CONFIG_DIR,
103
+ CONFIG_FILENAME,
104
+ CONFIG_RELATIVE,
105
+ DEFAULT_BRANCH,
106
+ getConfigPath,
107
+ loadConfig,
108
+ normalizeConfig,
109
+ writeConfig,
110
+ };