oneskill 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,176 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of Your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
package/README.md ADDED
@@ -0,0 +1,171 @@
1
+ <div align="center">
2
+
3
+ # OneSkill Meta-Manager
4
+
5
+ **The universal bridge for AI Agent Skills.**
6
+ Discover, install, and map capabilities from the OpenSkills registry to your environment.
7
+
8
+ [![](https://img.shields.io/npm/v/oneskill?color=brightgreen)](https://www.npmjs.com/package/oneskill)
9
+ [![](https://img.shields.io/npm/l/oneskill)](LICENSE)
10
+
11
+ [**🇺🇸 English**](#-english) | [**🇨🇳 中文指南**](#-中文指南)
12
+
13
+ </div>
14
+
15
+ ---
16
+
17
+ <a name="-english"></a>
18
+
19
+ ## ⚡️ What is OneSkill?
20
+
21
+ **OneSkill** is a meta-tool designed for AI Agents (and humans) to easily extend their capabilities. It serves as a search engine and workflow manager for the [OpenSkills](https://github.com/Starttoaster/openskills) ecosystem.
22
+
23
+ While `openskills` handles the raw installation of files, **OneSkill** provides:
24
+ 1. **Intelligent Search**: Find the right tool for the job using natural language or keywords.
25
+ 2. **Workflow Guidance**: A standardized process for Agents to acquire new skills safely.
26
+ 3. **Environment Mapping**: Crucially, it bridges the gap between `openskills` (standard structure) and consumers like **Gemini CLI** (custom structure).
27
+
28
+ ## 🚀 Quick Start
29
+
30
+ You don't need to install it permanently. Just run it with `npx`.
31
+
32
+ ```bash
33
+ # Search for a skill (e.g., to browse the web)
34
+ npx oneskill search "puppeteer browser"
35
+
36
+ # Search for database tools sorted by popularity
37
+ npx oneskill search "database" --sort stars
38
+ ```
39
+
40
+ ## 🛠 Workflow
41
+
42
+ The standard lifecycle for adding a new capability to your Agent:
43
+
44
+ 1. **Search**: Find a skill.
45
+ ```bash
46
+ npx oneskill search "github integration"
47
+ ```
48
+ 2. **Install**: Use the standard `openskills` installer.
49
+ ```bash
50
+ npx openskills install anthropics/skills
51
+ ```
52
+ 3. **Map (Important for Gemini)**: If you are using **Gemini CLI**, you must map the installed skills to your configuration.
53
+ ```bash
54
+ # Maps installed skills to Gemini's config
55
+ npx oneskill map --target gemini
56
+ ```
57
+
58
+ ## 📖 Command Reference
59
+
60
+ ### `search`
61
+ Search the global registry for skills.
62
+ ```bash
63
+ npx oneskill search <query> [options]
64
+
65
+ # Options:
66
+ # --category <name> Filter by category
67
+ # --sort <field> Sort by 'stars', 'created', or 'updated'
68
+ # --limit <number> Limit results (default: 10)
69
+ ```
70
+
71
+ ### `map`
72
+ Generates configuration for specific agent environments.
73
+ ```bash
74
+ npx oneskill map --target <env>
75
+
76
+ # Targets:
77
+ # gemini Generate/Update Gemini CLI config
78
+ ```
79
+
80
+ ### `list`
81
+ List locally mapped skills (wrapper around openskills list).
82
+ ```bash
83
+ npx oneskill list
84
+ ```
85
+
86
+ ---
87
+
88
+ <br>
89
+ <br>
90
+
91
+ <a name="-中文指南"></a>
92
+
93
+ ## 🇨🇳 中文指南
94
+
95
+ [**⬆️ Back to English**](#-english)
96
+
97
+ **OneSkill** 是一个为 AI Agent 设计的通用技能管理工具。它作为 [OpenSkills](https://github.com/Starttoaster/openskills) 生态系统的搜索引擎和工作流管理器,帮助你发现、安装并将能力映射到你的运行环境中。
98
+
99
+ ### 核心功能
100
+
101
+ 1. **智能搜索**: 支持通过自然语言或关键词搜索注册表中的 Skill。
102
+ 2. **工作流引导**: 为 Agent 提供了一套标准的扩展能力流程(搜索 -> 确认 -> 安装)。
103
+ 3. **环境映射**: 解决了安装路径与运行环境不一致的问题。特别是对于 **Gemini CLI** 用户,OneSkill 能自动将下载的 Skill 映射到 Gemini 的配置文件中。
104
+
105
+ ### 🚀 快速开始
106
+
107
+ 无需全局安装,直接使用 `npx` 运行即可:
108
+
109
+ ```bash
110
+ # 搜索技能 (例如:想要网页浏览能力)
111
+ npx oneskill search "puppeteer browser"
112
+
113
+ # 搜索数据库相关技能,并按星级排序
114
+ npx oneskill search "database" --sort stars
115
+ ```
116
+
117
+ ### 🛠 使用流程
118
+
119
+ 为你的 Agent 添加新能力的推荐步骤:
120
+
121
+ 1. **搜索 (Search)**: 查找你需要的技能。
122
+ ```bash
123
+ npx oneskill search "github integration"
124
+ ```
125
+
126
+ 2. **安装 (Install)**: 使用 `openskills` 标准命令进行下载。
127
+ ```bash
128
+ npx openskills install anthropics/skills
129
+ ```
130
+
131
+ 3. **映射 (Map)**: **(Gemini 用户必读)**
132
+ `openskills` 默认将文件下载到通用目录,Gemini CLI 无法直接读取。必须执行映射命令:
133
+ ```bash
134
+ # 自动识别已安装的 Skill 并配置到 Gemini
135
+ npx oneskill map --target gemini
136
+ ```
137
+ *如果你的 Skill 是全局安装的 (加了 --global),这里也需要加 --global。*
138
+
139
+ ### 📖 命令参考
140
+
141
+ #### `search` (搜索)
142
+ 在全局注册表中搜索技能。
143
+ ```bash
144
+ npx oneskill search <查询词> [选项]
145
+
146
+ # 选项:
147
+ # --category <name> 按分类筛选
148
+ # --sort <field> 排序方式: 'stars' (星级), 'created' (创建时间), 'updated' (更新时间)
149
+ # --limit <number> 限制返回数量 (默认: 10)
150
+ ```
151
+
152
+ #### `map` (映射)
153
+ 为特定环境生成配置。
154
+ ```bash
155
+ npx oneskill map --target <环境>
156
+
157
+ # 支持的目标:
158
+ # gemini 更新 Gemini CLI 的配置与路径映射
159
+ ```
160
+
161
+ #### `list` (列表)
162
+ 查看本地已安装的技能。
163
+ ```bash
164
+ npx oneskill list
165
+ ```
166
+
167
+ ---
168
+
169
+ <div align="center">
170
+ <sub>Built with ❤️ by the OneSkill Community</sub>
171
+ </div>
package/SKILL.md ADDED
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: oneskill
3
+ description: Discover skills, iterate on queries, and automate skill installations for any environment.
4
+ ---
5
+
6
+ # OneSkill Meta-Manager
7
+
8
+ Use this skill to discover new capabilities, refine search queries, and streamline skill setup using OpenSkills. This provides a unified way to expand your environment's features.
9
+
10
+ ## When to Use
11
+
12
+ - When a user asks for capabilities you do not currently have.
13
+ - When a task is complex, domain-specific, or repeatedly blocked after 2 attempts.
14
+ - When a better skill likely exists (e.g., web browsing, GitHub integration, database management, cloud infrastructure).
15
+
16
+ ## Workflow
17
+
18
+ 1. Search the registry:
19
+ - Run: `npx oneskill search "<query>" [options]`
20
+ - Supported options: `--category`, `--limit`, `--offset`, `--sort`.
21
+ - Examples:
22
+ - `npx oneskill search "browser" --sort stars`
23
+ - `npx oneskill search "" --category database --limit 5`
24
+ 2. Analyze results:
25
+ - Identify the best match or refine the query and search again.
26
+ 3. Confirm with the user:
27
+ - Explain what the skill does and where it comes from.
28
+ 4. Install after explicit approval (use openskills):
29
+ - Run: `npx openskills install <slug-or-repo>`
30
+ - Example: `npx openskills install anthropics/skills`
31
+ 5. Handle environment-specific setup:
32
+ - **Gemini CLI Users:** `openskills` does not automatically configure Gemini. You MUST run the mapping command after installation:
33
+ - `npx oneskill map --target gemini` (add `--global` if installed globally)
34
+ 6. Apply the new skill to finish the original request.
35
+
36
+ ## OpenSkills Basics
37
+
38
+ - `npx openskills install <source> [options]` # Install from GitHub, local path, or private repo
39
+ - `npx openskills sync [-y] [-o <path>]` # Update AGENTS.md (or custom output)
40
+ - `npx openskills list` # Show installed skills
41
+ - `npx openskills read <name>` # Load skill (for agents)
42
+ - `npx openskills update [name...]` # Update installed skills (default: all)
43
+ - `npx openskills manage` # Remove skills (interactive)
44
+ - `npx openskills remove <name>` # Remove specific skill
45
+
46
+ Examples:
47
+ - `npx openskills install anthropics/skills`
48
+ - `npx openskills sync`
49
+
50
+ Defaults: Installs are project-local (`./.claude/skills`, or `./.agent/skills` with `--universal`). Use `--global` for `~/.claude/skills`.
51
+
52
+ ## Safety Reminders
53
+
54
+ - Do not install without explicit user confirmation.
55
+ - Avoid `--force-map` unless the user agrees to overwrite an existing target.
56
+ - Use openskills for installation/updates; OneSkill only searches and maps for Gemini.
57
+ - For Gemini, run `npx oneskill map --target gemini` after installs.
58
+ - Default install/map is project-local, same as openskills; use `--global` for global installs.
59
+ - When installing OneSkill itself, recommend `--global` so it is available across projects.
package/dist/cli.js ADDED
@@ -0,0 +1,411 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cli.ts
4
+ import { Command } from "commander";
5
+
6
+ // src/core/registry.ts
7
+ var DEFAULT_REGISTRY_URL = "https://skillsdirectory.com/api/registry";
8
+ function getRegistryBase(override) {
9
+ return (override || process.env.ONESKILL_REGISTRY_URL || DEFAULT_REGISTRY_URL).replace(/\/$/, "");
10
+ }
11
+ async function fetchJson(url) {
12
+ const res = await fetch(url, { headers: { "accept": "application/json" } });
13
+ if (!res.ok) {
14
+ const text = await res.text();
15
+ throw new Error(`Registry request failed (${res.status}): ${text.slice(0, 200)}`);
16
+ }
17
+ return res.json();
18
+ }
19
+ function normalizeSkill(item) {
20
+ const slug = String(item.slug || item.id || item.name || "");
21
+ const name = String(item.name || item.title || slug || "");
22
+ const description = String(item.description || item.summary || "");
23
+ const repository = String(item.repository || item.repo || item.url || "");
24
+ const verified = typeof item.verified === "boolean" ? item.verified : void 0;
25
+ const stars = typeof item.stars === "number" ? item.stars : typeof item.github?.stars === "number" ? item.github.stars : void 0;
26
+ const tags = Array.isArray(item.tags) ? item.tags.map(String) : void 0;
27
+ const authorObj = item.author;
28
+ const authorName = typeof item.author === "string" ? String(item.author) : authorObj?.name ? String(authorObj.name) : void 0;
29
+ const author = authorName ? { name: authorName, url: authorObj?.url ? String(authorObj.url) : void 0 } : void 0;
30
+ const signals = {
31
+ lastUpdated: item.lastUpdated ? String(item.lastUpdated) : void 0,
32
+ license: item.license ? String(item.license) : typeof item.github?.license === "string" ? String(item.github.license) : void 0,
33
+ riskHints: Array.isArray(item.riskHints) ? item.riskHints.map(String) : void 0
34
+ };
35
+ return {
36
+ schemaVersion: "1",
37
+ slug,
38
+ name,
39
+ description,
40
+ repository,
41
+ verified,
42
+ stars,
43
+ tags,
44
+ author,
45
+ signals
46
+ };
47
+ }
48
+ function normalizeSearchPayload(payload) {
49
+ if (!payload || typeof payload !== "object") return [];
50
+ const data = payload;
51
+ const candidates = (Array.isArray(data.skills) ? data.skills : null) || (Array.isArray(data.items) ? data.items : null) || (Array.isArray(data.results) ? data.results : null) || (Array.isArray(data.data) ? data.data : null) || (Array.isArray(payload) ? payload : null);
52
+ if (!candidates) return [];
53
+ return candidates.filter((item) => item && typeof item === "object").map((item) => normalizeSkill(item));
54
+ }
55
+ async function searchRegistry(params, overrideUrl) {
56
+ const base = getRegistryBase(overrideUrl);
57
+ const url = new URL(base);
58
+ if (params.q) url.searchParams.set("q", params.q);
59
+ if (params.category) url.searchParams.set("category", params.category);
60
+ if (typeof params.limit === "number") url.searchParams.set("limit", String(params.limit));
61
+ if (typeof params.offset === "number") url.searchParams.set("offset", String(params.offset));
62
+ if (params.sort) url.searchParams.set("sort", params.sort);
63
+ const raw = await fetchJson(url.toString());
64
+ const items = normalizeSearchPayload(raw);
65
+ return { items, raw };
66
+ }
67
+ async function fetchRegistryInfo(slug, overrideUrl) {
68
+ const base = getRegistryBase(overrideUrl);
69
+ const url = `${base}/${encodeURIComponent(slug)}`;
70
+ const raw = await fetchJson(url);
71
+ if (raw && typeof raw === "object") {
72
+ const record = raw;
73
+ const candidate = record.skill || record.item || record;
74
+ if (candidate && typeof candidate === "object") {
75
+ return { item: normalizeSkill(candidate), raw };
76
+ }
77
+ }
78
+ throw new Error("Registry info failed");
79
+ }
80
+
81
+ // src/utils/json.ts
82
+ function printJson(data) {
83
+ process.stdout.write(JSON.stringify(data, null, 2) + "\n");
84
+ }
85
+
86
+ // src/commands/search.ts
87
+ async function runSearch(query, options) {
88
+ const result = await searchRegistry(
89
+ {
90
+ q: query,
91
+ category: options.category,
92
+ limit: options.limit,
93
+ offset: options.offset,
94
+ sort: options.sort
95
+ },
96
+ options.registry
97
+ );
98
+ const raw = result.raw;
99
+ printJson({
100
+ schemaVersion: "1",
101
+ query,
102
+ registry: raw?.registry,
103
+ version: raw?.version,
104
+ pagination: raw?.pagination,
105
+ items: result.items
106
+ });
107
+ }
108
+
109
+ // src/commands/info.ts
110
+ async function runInfo(slug, options) {
111
+ const result = await fetchRegistryInfo(slug, options.registry);
112
+ printJson({ schemaVersion: "1", item: result.item });
113
+ }
114
+
115
+ // src/commands/list.ts
116
+ import { spawnSync as spawnSync2 } from "child_process";
117
+
118
+ // src/core/openskills.ts
119
+ import { readFileSync, existsSync } from "fs";
120
+ import { dirname, resolve } from "path";
121
+ import { createRequire } from "module";
122
+ import { spawnSync } from "child_process";
123
+ var require2 = createRequire(import.meta.url);
124
+ function resolveOpenskillsCli() {
125
+ const pkgPath = require2.resolve("openskills/package.json");
126
+ const pkgDir = dirname(pkgPath);
127
+ const content = readFileSync(pkgPath, "utf-8");
128
+ const parsed = JSON.parse(content);
129
+ const bin = parsed.bin;
130
+ let candidate = null;
131
+ if (typeof bin === "string") {
132
+ candidate = resolve(pkgDir, bin);
133
+ } else if (bin && typeof bin === "object") {
134
+ const first = Object.values(bin)[0];
135
+ if (first) candidate = resolve(pkgDir, first);
136
+ } else if (parsed.main) {
137
+ candidate = resolve(pkgDir, parsed.main);
138
+ }
139
+ if (candidate && existsSync(candidate)) {
140
+ return candidate;
141
+ }
142
+ const result = spawnSync("npm", ["run", "build"], {
143
+ cwd: pkgDir,
144
+ stdio: "inherit"
145
+ });
146
+ if (result.status !== 0) {
147
+ throw new Error("Failed to build openskills");
148
+ }
149
+ if (candidate && existsSync(candidate)) {
150
+ return candidate;
151
+ }
152
+ throw new Error("Unable to resolve openskills CLI entry");
153
+ }
154
+
155
+ // src/commands/list.ts
156
+ async function runList(_options) {
157
+ const cliPath = resolveOpenskillsCli();
158
+ const args = [cliPath, "list"];
159
+ const result = spawnSync2(process.execPath, args, {
160
+ cwd: process.cwd(),
161
+ stdio: "inherit"
162
+ });
163
+ if (result.status !== 0) {
164
+ throw new Error("openskills list failed");
165
+ }
166
+ }
167
+
168
+ // src/core/root.ts
169
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
170
+ import { dirname as dirname2, join, resolve as resolve2 } from "path";
171
+ var MARKER_DIRS = [".git", ".agent", ".claude", ".gemini", ".codex"];
172
+ function hasOneskillConfig(pkgPath) {
173
+ try {
174
+ const content = readFileSync2(pkgPath, "utf-8");
175
+ const parsed = JSON.parse(content);
176
+ return Boolean(parsed.oneskill);
177
+ } catch {
178
+ return false;
179
+ }
180
+ }
181
+ function hasMarkers(dir) {
182
+ for (const marker of MARKER_DIRS) {
183
+ if (existsSync2(join(dir, marker))) return marker;
184
+ }
185
+ if (existsSync2(join(dir, "AGENTS.md"))) return "AGENTS.md";
186
+ const pkgPath = join(dir, "package.json");
187
+ if (existsSync2(pkgPath) && hasOneskillConfig(pkgPath)) return "package.json:oneskill";
188
+ return null;
189
+ }
190
+ function detectRoot(startDir) {
191
+ let current = resolve2(startDir);
192
+ while (true) {
193
+ const reason = hasMarkers(current);
194
+ if (reason) return { root: current, reason };
195
+ const parent = dirname2(current);
196
+ if (parent === current) {
197
+ return { root: resolve2(startDir), reason: "fallback:cwd" };
198
+ }
199
+ current = parent;
200
+ }
201
+ }
202
+
203
+ // src/commands/doctor.ts
204
+ async function runDoctor(options) {
205
+ const rootInfo = detectRoot(options.root || process.cwd());
206
+ const root = rootInfo.root;
207
+ const paths = {
208
+ agent: `${root}/.agent/skills`,
209
+ claude: `${root}/.claude/skills`,
210
+ gemini: `${root}/.gemini/skills`,
211
+ codex: `${root}/.codex/skills`,
212
+ oneskillLogs: `${root}/.oneskill/logs`
213
+ };
214
+ printJson({ schemaVersion: "1", root: rootInfo.root, reason: rootInfo.reason, paths });
215
+ }
216
+
217
+ // src/commands/sync.ts
218
+ import { spawnSync as spawnSync3 } from "child_process";
219
+ async function runSync(options) {
220
+ const cliPath = resolveOpenskillsCli();
221
+ const args = [cliPath, "sync"];
222
+ if (options.yes) {
223
+ args.push("--yes");
224
+ }
225
+ if (options.output) {
226
+ args.push("--output", options.output);
227
+ }
228
+ const result = spawnSync3(process.execPath, args, {
229
+ cwd: process.cwd(),
230
+ stdio: "inherit"
231
+ });
232
+ if (result.status !== 0) {
233
+ throw new Error("openskills sync failed");
234
+ }
235
+ }
236
+
237
+ // src/core/map.ts
238
+ import { existsSync as existsSync5, readdirSync } from "fs";
239
+ import { basename, join as join3 } from "path";
240
+ import { homedir } from "os";
241
+
242
+ // src/core/mapping.ts
243
+ import { existsSync as existsSync4, lstatSync, readlinkSync, rmSync, symlinkSync, cpSync, writeFileSync as writeFileSync2 } from "fs";
244
+ import { join as join2, resolve as resolve4 } from "path";
245
+
246
+ // src/core/fs.ts
247
+ import { mkdirSync, readFileSync as readFileSync3, writeFileSync, existsSync as existsSync3 } from "fs";
248
+ import { dirname as dirname3, resolve as resolve3, sep } from "path";
249
+ function ensureDir(path) {
250
+ mkdirSync(path, { recursive: true });
251
+ }
252
+ function isPathInside(targetPath, baseDir) {
253
+ const resolvedTarget = resolve3(targetPath);
254
+ const resolvedBase = resolve3(baseDir);
255
+ const baseWithSep = resolvedBase.endsWith(sep) ? resolvedBase : resolvedBase + sep;
256
+ return resolvedTarget === resolvedBase || resolvedTarget.startsWith(baseWithSep);
257
+ }
258
+
259
+ // src/core/mapping.ts
260
+ var TARGET_DIRS = {
261
+ codex: ".codex/skills",
262
+ gemini: ".gemini/skills",
263
+ claude: ".claude/skills",
264
+ agent: ".agent/skills"
265
+ };
266
+ function getTargetBase(root, target, options) {
267
+ if (target === "codex" && options?.codexHome) {
268
+ return resolve4(options.codexHome, "skills");
269
+ }
270
+ return join2(root, TARGET_DIRS[target]);
271
+ }
272
+ function readLinkTarget(path) {
273
+ try {
274
+ return readlinkSync(path);
275
+ } catch {
276
+ return null;
277
+ }
278
+ }
279
+ function mapSkill(root, target, skillName, storePath, options) {
280
+ const baseDir = getTargetBase(root, target, options);
281
+ const targetPath = join2(baseDir, skillName);
282
+ if (target !== "codex" && !isPathInside(targetPath, root)) {
283
+ throw new Error(`Target path escapes root: ${targetPath}`);
284
+ }
285
+ ensureDir(baseDir);
286
+ if (existsSync4(targetPath)) {
287
+ const stat = lstatSync(targetPath);
288
+ if (stat.isSymbolicLink()) {
289
+ const linkTarget = readLinkTarget(targetPath);
290
+ if (linkTarget && resolve4(linkTarget) === resolve4(storePath)) {
291
+ return { target, path: targetPath, mode: process.platform === "win32" ? "junction" : "symlink", updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
292
+ }
293
+ if (!options?.forceMap) {
294
+ throw new Error(`Target already exists (symlink): ${targetPath}`);
295
+ }
296
+ } else {
297
+ if (!options?.forceMap) {
298
+ throw new Error(`Target already exists: ${targetPath}`);
299
+ }
300
+ }
301
+ rmSync(targetPath, { recursive: true, force: true });
302
+ }
303
+ const linkType = process.platform === "win32" ? "junction" : "dir";
304
+ try {
305
+ symlinkSync(storePath, targetPath, linkType);
306
+ return { target, path: targetPath, mode: process.platform === "win32" ? "junction" : "symlink", updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
307
+ } catch (error) {
308
+ if (!options?.forceMap) {
309
+ }
310
+ }
311
+ cpSync(storePath, targetPath, { recursive: true, dereference: false });
312
+ writeFileSync2(
313
+ join2(targetPath, ".oneskill-meta.json"),
314
+ JSON.stringify({ source: storePath, mappedAt: (/* @__PURE__ */ new Date()).toISOString(), mode: "copy" }, null, 2) + "\n",
315
+ "utf-8"
316
+ );
317
+ return { target, path: targetPath, mode: "copy", updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
318
+ }
319
+
320
+ // src/core/map.ts
321
+ function getSourceBase(root, options) {
322
+ const baseRoot = options.global ? homedir() : root;
323
+ const folder = options.universal ? ".agent/skills" : ".claude/skills";
324
+ return join3(baseRoot, folder);
325
+ }
326
+ function getTargetRoot(root, options) {
327
+ return options.global ? homedir() : root;
328
+ }
329
+ function mapInstalledSkills(options) {
330
+ if (options.target !== "gemini") {
331
+ throw new Error("map currently supports only --target gemini");
332
+ }
333
+ const rootInfo = detectRoot(process.cwd());
334
+ const sourceBase = getSourceBase(rootInfo.root, options);
335
+ const targetRoot = getTargetRoot(rootInfo.root, options);
336
+ if (!existsSync5(sourceBase)) {
337
+ return { mapped: 0, sourceBase, targetRoot };
338
+ }
339
+ const entries = readdirSync(sourceBase, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join3(sourceBase, entry.name));
340
+ let mapped = 0;
341
+ for (const dir of entries) {
342
+ const name = basename(dir);
343
+ mapSkill(targetRoot, "gemini", name, dir, { forceMap: options.forceMap });
344
+ mapped += 1;
345
+ }
346
+ return { mapped, sourceBase, targetRoot };
347
+ }
348
+
349
+ // src/commands/map.ts
350
+ async function runMap(options) {
351
+ if (!options.target) {
352
+ throw new Error("map requires --target gemini");
353
+ }
354
+ const result = mapInstalledSkills({
355
+ target: options.target,
356
+ global: options.global,
357
+ universal: options.universal,
358
+ forceMap: options.forceMap
359
+ });
360
+ printJson({ schemaVersion: "1", ...result });
361
+ }
362
+
363
+ // src/core/versions.ts
364
+ import { readFileSync as readFileSync4 } from "fs";
365
+ import { dirname as dirname4, join as join4 } from "path";
366
+ import { fileURLToPath } from "url";
367
+ import { createRequire as createRequire2 } from "module";
368
+ var require3 = createRequire2(import.meta.url);
369
+ function getOneskillVersion() {
370
+ const __dirname = dirname4(fileURLToPath(import.meta.url));
371
+ const pkgPath = join4(__dirname, "../../package.json");
372
+ try {
373
+ const content = readFileSync4(pkgPath, "utf-8");
374
+ const parsed = JSON.parse(content);
375
+ return parsed.version || "0.0.0";
376
+ } catch {
377
+ return "0.0.0";
378
+ }
379
+ }
380
+
381
+ // src/cli.ts
382
+ var program = new Command();
383
+ program.name("oneskill").description("Meta-skill manager for AI coding agents").version(getOneskillVersion());
384
+ program.command("search <query>").description("Search the skill registry").option("--registry <url>", "Registry base URL override").option("--category <slug>", "Filter by category slug").option("--limit <n>", "Results per page (max 100)", (value) => Number.parseInt(value, 10)).option("--offset <n>", "Pagination offset", (value) => Number.parseInt(value, 10)).option("--sort <value>", "Sort by: votes, recent, stars").action(async (query, options) => {
385
+ await runSearch(query, options);
386
+ });
387
+ program.command("info <slug>").description("Fetch skill info from registry").option("--registry <url>", "Registry base URL override").action(async (slug, options) => {
388
+ await runInfo(slug, options);
389
+ });
390
+ program.command("sync").description("Forward to openskills sync").option("-y, --yes", "Skip interactive selection, sync all skills").option("-o, --output <path>", "Output file path (default: AGENTS.md)").action(async (options) => {
391
+ await runSync(options);
392
+ });
393
+ program.command("map").description("Map installed skills into Gemini directory").option("--target <target>", "Target environment (gemini only)").option("--global", "Map from global openskills install", false).option("--universal", "Map from universal (.agent/skills)", false).option("--force-map", "Overwrite target mapping if it exists", false).action(async (options) => {
394
+ await runMap({
395
+ target: options.target,
396
+ global: options.global,
397
+ universal: options.universal,
398
+ forceMap: options.forceMap
399
+ });
400
+ });
401
+ program.command("list").description("List managed skills").option("--root <path>", "Override workspace root").action(async (options) => {
402
+ await runList(options);
403
+ });
404
+ program.command("doctor").description("Diagnose OneSkill environment").option("--root <path>", "Override workspace root").action(async (options) => {
405
+ await runDoctor(options);
406
+ });
407
+ program.parseAsync(process.argv).catch((error) => {
408
+ console.error(error instanceof Error ? error.message : String(error));
409
+ process.exitCode = 1;
410
+ });
411
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/core/registry.ts","../src/utils/json.ts","../src/commands/search.ts","../src/commands/info.ts","../src/commands/list.ts","../src/core/openskills.ts","../src/core/root.ts","../src/commands/doctor.ts","../src/commands/sync.ts","../src/core/map.ts","../src/core/mapping.ts","../src/core/fs.ts","../src/commands/map.ts","../src/core/versions.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { runSearch } from './commands/search.js';\nimport { runInfo } from './commands/info.js';\nimport { runList } from './commands/list.js';\nimport { runDoctor } from './commands/doctor.js';\nimport { runSync } from './commands/sync.js';\nimport { runMap } from './commands/map.js';\nimport { getOneskillVersion } from './core/versions.js';\n\nconst program = new Command();\n\nprogram\n .name('oneskill')\n .description('Meta-skill manager for AI coding agents')\n .version(getOneskillVersion());\n\nprogram\n .command('search <query>')\n .description('Search the skill registry')\n .option('--registry <url>', 'Registry base URL override')\n .option('--category <slug>', 'Filter by category slug')\n .option('--limit <n>', 'Results per page (max 100)', (value) => Number.parseInt(value, 10))\n .option('--offset <n>', 'Pagination offset', (value) => Number.parseInt(value, 10))\n .option('--sort <value>', 'Sort by: votes, recent, stars')\n .action(async (query: string, options: { registry?: string; category?: string; limit?: number; offset?: number; sort?: string }) => {\n await runSearch(query, options);\n });\n\nprogram\n .command('info <slug>')\n .description('Fetch skill info from registry')\n .option('--registry <url>', 'Registry base URL override')\n .action(async (slug: string, options: { registry?: string }) => {\n await runInfo(slug, options);\n });\n\nprogram\n .command('sync')\n .description('Forward to openskills sync')\n .option('-y, --yes', 'Skip interactive selection, sync all skills')\n .option('-o, --output <path>', 'Output file path (default: AGENTS.md)')\n .action(async (options: { yes?: boolean; output?: string }) => {\n await runSync(options);\n });\n\nprogram\n .command('map')\n .description('Map installed skills into Gemini directory')\n .option('--target <target>', 'Target environment (gemini only)')\n .option('--global', 'Map from global openskills install', false)\n .option('--universal', 'Map from universal (.agent/skills)', false)\n .option('--force-map', 'Overwrite target mapping if it exists', false)\n .action(async (options: { target?: string; global?: boolean; universal?: boolean; forceMap?: boolean }) => {\n await runMap({\n target: options.target as 'gemini' | undefined,\n global: options.global,\n universal: options.universal,\n forceMap: options.forceMap,\n });\n });\n\nprogram\n .command('list')\n .description('List managed skills')\n .option('--root <path>', 'Override workspace root')\n .action(async (options: { root?: string }) => {\n await runList(options);\n });\n\nprogram\n .command('doctor')\n .description('Diagnose OneSkill environment')\n .option('--root <path>', 'Override workspace root')\n .action(async (options: { root?: string }) => {\n await runDoctor(options);\n });\n\nprogram.parseAsync(process.argv).catch((error) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n});\n","import type { RegistryInfoResponse, RegistrySearchResponse, SkillListItem } from './types.js';\n\nconst DEFAULT_REGISTRY_URL = 'https://skillsdirectory.com/api/registry';\n\nexport interface SearchParams {\n q?: string;\n category?: string;\n limit?: number;\n offset?: number;\n sort?: string;\n}\n\nfunction getRegistryBase(override?: string): string {\n return (override || process.env.ONESKILL_REGISTRY_URL || DEFAULT_REGISTRY_URL).replace(/\\/$/, '');\n}\n\nasync function fetchJson(url: string): Promise<unknown> {\n const res = await fetch(url, { headers: { 'accept': 'application/json' } });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Registry request failed (${res.status}): ${text.slice(0, 200)}`);\n }\n return res.json();\n}\n\nfunction normalizeSkill(item: Record<string, unknown>): SkillListItem {\n const slug = String(item.slug || item.id || item.name || '');\n const name = String(item.name || item.title || slug || '');\n const description = String(item.description || item.summary || '');\n const repository = String(item.repository || item.repo || item.url || '');\n const verified = typeof item.verified === 'boolean' ? item.verified : undefined;\n const stars =\n typeof item.stars === 'number'\n ? item.stars\n : typeof (item.github as { stars?: unknown } | undefined)?.stars === 'number'\n ? (item.github as { stars: number }).stars\n : undefined;\n const tags = Array.isArray(item.tags) ? item.tags.map(String) : undefined;\n const authorObj = item.author as { name?: unknown; url?: unknown } | undefined;\n const authorName = typeof item.author === 'string' ? String(item.author) : authorObj?.name ? String(authorObj.name) : undefined;\n const author = authorName\n ? { name: authorName, url: authorObj?.url ? String(authorObj.url) : undefined }\n : undefined;\n\n const signals = {\n lastUpdated: item.lastUpdated ? String(item.lastUpdated) : undefined,\n license:\n item.license ? String(item.license)\n : typeof (item.github as { license?: unknown } | undefined)?.license === 'string'\n ? String((item.github as { license: string }).license)\n : undefined,\n riskHints: Array.isArray(item.riskHints) ? item.riskHints.map(String) : undefined,\n };\n\n return {\n schemaVersion: '1',\n slug,\n name,\n description,\n repository,\n verified,\n stars,\n tags,\n author,\n signals,\n };\n}\n\nfunction normalizeSearchPayload(payload: unknown): SkillListItem[] {\n if (!payload || typeof payload !== 'object') return [];\n const data = payload as Record<string, unknown>;\n const candidates =\n (Array.isArray(data.skills) ? data.skills : null) ||\n (Array.isArray(data.items) ? data.items : null) ||\n (Array.isArray(data.results) ? data.results : null) ||\n (Array.isArray(data.data) ? data.data : null) ||\n (Array.isArray(payload) ? (payload as unknown[]) : null);\n\n if (!candidates) return [];\n return candidates\n .filter((item) => item && typeof item === 'object')\n .map((item) => normalizeSkill(item as Record<string, unknown>));\n}\n\nexport async function searchRegistry(params: SearchParams, overrideUrl?: string): Promise<RegistrySearchResponse> {\n const base = getRegistryBase(overrideUrl);\n const url = new URL(base);\n if (params.q) url.searchParams.set('q', params.q);\n if (params.category) url.searchParams.set('category', params.category);\n if (typeof params.limit === 'number') url.searchParams.set('limit', String(params.limit));\n if (typeof params.offset === 'number') url.searchParams.set('offset', String(params.offset));\n if (params.sort) url.searchParams.set('sort', params.sort);\n const raw = await fetchJson(url.toString());\n const items = normalizeSearchPayload(raw);\n return { items, raw };\n}\n\nexport async function fetchRegistryInfo(slug: string, overrideUrl?: string): Promise<RegistryInfoResponse> {\n const base = getRegistryBase(overrideUrl);\n const url = `${base}/${encodeURIComponent(slug)}`;\n const raw = await fetchJson(url);\n if (raw && typeof raw === 'object') {\n const record = raw as Record<string, unknown>;\n const candidate = (record.skill as Record<string, unknown> | undefined) || (record.item as Record<string, unknown> | undefined) || record;\n if (candidate && typeof candidate === 'object') {\n return { item: normalizeSkill(candidate as Record<string, unknown>), raw };\n }\n }\n throw new Error('Registry info failed');\n}\n","export function printJson(data: unknown): void {\n process.stdout.write(JSON.stringify(data, null, 2) + '\\n');\n}\n","import { searchRegistry } from '../core/registry.js';\nimport { printJson } from '../utils/json.js';\n\nexport interface SearchCommandOptions {\n registry?: string;\n category?: string;\n limit?: number;\n offset?: number;\n sort?: string;\n}\n\nexport async function runSearch(query: string, options: SearchCommandOptions): Promise<void> {\n const result = await searchRegistry(\n {\n q: query,\n category: options.category,\n limit: options.limit,\n offset: options.offset,\n sort: options.sort,\n },\n options.registry\n );\n const raw = result.raw as { registry?: unknown; version?: unknown; pagination?: unknown } | undefined;\n printJson({\n schemaVersion: '1',\n query,\n registry: raw?.registry,\n version: raw?.version,\n pagination: raw?.pagination,\n items: result.items,\n });\n}\n","import { fetchRegistryInfo } from '../core/registry.js';\nimport { printJson } from '../utils/json.js';\n\nexport interface InfoCommandOptions {\n registry?: string;\n}\n\nexport async function runInfo(slug: string, options: InfoCommandOptions): Promise<void> {\n const result = await fetchRegistryInfo(slug, options.registry);\n printJson({ schemaVersion: '1', item: result.item });\n}\n","import { spawnSync } from 'child_process';\nimport { resolveOpenskillsCli } from '../core/openskills.js';\n\nexport interface ListCommandOptions {}\n\nexport async function runList(_options: ListCommandOptions): Promise<void> {\n const cliPath = resolveOpenskillsCli();\n const args = [cliPath, 'list'];\n const result = spawnSync(process.execPath, args, {\n cwd: process.cwd(),\n stdio: 'inherit',\n });\n if (result.status !== 0) {\n throw new Error('openskills list failed');\n }\n}\n","import { readFileSync, existsSync } from 'fs';\nimport { dirname, resolve } from 'path';\nimport { createRequire } from 'module';\nimport { spawnSync } from 'child_process';\n\nconst require = createRequire(import.meta.url);\n\nexport function resolveOpenskillsCli(): string {\n const pkgPath = require.resolve('openskills/package.json');\n const pkgDir = dirname(pkgPath);\n const content = readFileSync(pkgPath, 'utf-8');\n const parsed = JSON.parse(content) as { bin?: Record<string, string> | string; main?: string };\n const bin = parsed.bin;\n let candidate: string | null = null;\n if (typeof bin === 'string') {\n candidate = resolve(pkgDir, bin);\n } else if (bin && typeof bin === 'object') {\n const first = Object.values(bin)[0];\n if (first) candidate = resolve(pkgDir, first);\n } else if (parsed.main) {\n candidate = resolve(pkgDir, parsed.main);\n }\n\n if (candidate && existsSync(candidate)) {\n return candidate;\n }\n\n // Build openskills locally if the CLI entry is missing.\n const result = spawnSync('npm', ['run', 'build'], {\n cwd: pkgDir,\n stdio: 'inherit',\n });\n if (result.status !== 0) {\n throw new Error('Failed to build openskills');\n }\n\n if (candidate && existsSync(candidate)) {\n return candidate;\n }\n\n throw new Error('Unable to resolve openskills CLI entry');\n}\n","import { existsSync, readFileSync } from 'fs';\nimport { dirname, join, resolve } from 'path';\nimport type { RootDetection } from './types.js';\n\nconst MARKER_DIRS = ['.git', '.agent', '.claude', '.gemini', '.codex'];\n\nfunction hasOneskillConfig(pkgPath: string): boolean {\n try {\n const content = readFileSync(pkgPath, 'utf-8');\n const parsed = JSON.parse(content) as { oneskill?: unknown };\n return Boolean(parsed.oneskill);\n } catch {\n return false;\n }\n}\n\nfunction hasMarkers(dir: string): string | null {\n for (const marker of MARKER_DIRS) {\n if (existsSync(join(dir, marker))) return marker;\n }\n if (existsSync(join(dir, 'AGENTS.md'))) return 'AGENTS.md';\n const pkgPath = join(dir, 'package.json');\n if (existsSync(pkgPath) && hasOneskillConfig(pkgPath)) return 'package.json:oneskill';\n return null;\n}\n\nexport function detectRoot(startDir: string): RootDetection {\n let current = resolve(startDir);\n while (true) {\n const reason = hasMarkers(current);\n if (reason) return { root: current, reason };\n const parent = dirname(current);\n if (parent === current) {\n return { root: resolve(startDir), reason: 'fallback:cwd' };\n }\n current = parent;\n }\n}\n","import { detectRoot } from '../core/root.js';\nimport { printJson } from '../utils/json.js';\n\nexport interface DoctorCommandOptions {\n root?: string;\n}\n\nexport async function runDoctor(options: DoctorCommandOptions): Promise<void> {\n const rootInfo = detectRoot(options.root || process.cwd());\n const root = rootInfo.root;\n const paths = {\n agent: `${root}/.agent/skills`,\n claude: `${root}/.claude/skills`,\n gemini: `${root}/.gemini/skills`,\n codex: `${root}/.codex/skills`,\n oneskillLogs: `${root}/.oneskill/logs`,\n };\n printJson({ schemaVersion: '1', root: rootInfo.root, reason: rootInfo.reason, paths });\n}\n","import { spawnSync } from 'child_process';\nimport { resolveOpenskillsCli } from '../core/openskills.js';\n\nexport interface SyncCommandOptions {\n yes?: boolean;\n output?: string;\n}\n\nexport async function runSync(options: SyncCommandOptions): Promise<void> {\n const cliPath = resolveOpenskillsCli();\n const args = [cliPath, 'sync'];\n if (options.yes) {\n args.push('--yes');\n }\n if (options.output) {\n args.push('--output', options.output);\n }\n const result = spawnSync(process.execPath, args, {\n cwd: process.cwd(),\n stdio: 'inherit',\n });\n if (result.status !== 0) {\n throw new Error('openskills sync failed');\n }\n}\n","import { existsSync, readdirSync } from 'fs';\nimport { basename, join } from 'path';\nimport { homedir } from 'os';\nimport { mapSkill } from './mapping.js';\nimport { detectRoot } from './root.js';\nimport type { TargetEnvironment } from './types.js';\n\nexport interface MapOptions {\n target: TargetEnvironment;\n global?: boolean;\n universal?: boolean;\n forceMap?: boolean;\n}\n\nfunction getSourceBase(root: string, options: MapOptions): string {\n const baseRoot = options.global ? homedir() : root;\n const folder = options.universal ? '.agent/skills' : '.claude/skills';\n return join(baseRoot, folder);\n}\n\nfunction getTargetRoot(root: string, options: MapOptions): string {\n return options.global ? homedir() : root;\n}\n\nexport function mapInstalledSkills(options: MapOptions): { mapped: number; sourceBase: string; targetRoot: string } {\n if (options.target !== 'gemini') {\n throw new Error('map currently supports only --target gemini');\n }\n const rootInfo = detectRoot(process.cwd());\n const sourceBase = getSourceBase(rootInfo.root, options);\n const targetRoot = getTargetRoot(rootInfo.root, options);\n\n if (!existsSync(sourceBase)) {\n return { mapped: 0, sourceBase, targetRoot };\n }\n\n const entries = readdirSync(sourceBase, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => join(sourceBase, entry.name));\n\n let mapped = 0;\n for (const dir of entries) {\n const name = basename(dir);\n mapSkill(targetRoot, 'gemini', name, dir, { forceMap: options.forceMap });\n mapped += 1;\n }\n\n return { mapped, sourceBase, targetRoot };\n}\n","import { existsSync, lstatSync, readlinkSync, rmSync, symlinkSync, cpSync, writeFileSync } from 'fs';\nimport { join, resolve } from 'path';\nimport { ensureDir, isPathInside } from './fs.js';\nimport type { SkillMappingRecord, TargetEnvironment } from './types.js';\n\nconst TARGET_DIRS: Record<TargetEnvironment, string> = {\n codex: '.codex/skills',\n gemini: '.gemini/skills',\n claude: '.claude/skills',\n agent: '.agent/skills',\n};\n\nexport interface MapOptions {\n forceMap?: boolean;\n codexHome?: string;\n}\n\nfunction getTargetBase(root: string, target: TargetEnvironment, options?: MapOptions): string {\n if (target === 'codex' && options?.codexHome) {\n return resolve(options.codexHome, 'skills');\n }\n return join(root, TARGET_DIRS[target]);\n}\n\nfunction readLinkTarget(path: string): string | null {\n try {\n return readlinkSync(path);\n } catch {\n return null;\n }\n}\n\nexport function mapSkill(\n root: string,\n target: TargetEnvironment,\n skillName: string,\n storePath: string,\n options?: MapOptions\n): SkillMappingRecord {\n const baseDir = getTargetBase(root, target, options);\n const targetPath = join(baseDir, skillName);\n\n if (target !== 'codex' && !isPathInside(targetPath, root)) {\n throw new Error(`Target path escapes root: ${targetPath}`);\n }\n\n ensureDir(baseDir);\n\n if (existsSync(targetPath)) {\n const stat = lstatSync(targetPath);\n if (stat.isSymbolicLink()) {\n const linkTarget = readLinkTarget(targetPath);\n if (linkTarget && resolve(linkTarget) === resolve(storePath)) {\n return { target, path: targetPath, mode: process.platform === 'win32' ? 'junction' : 'symlink', updatedAt: new Date().toISOString() };\n }\n if (!options?.forceMap) {\n throw new Error(`Target already exists (symlink): ${targetPath}`);\n }\n } else {\n if (!options?.forceMap) {\n throw new Error(`Target already exists: ${targetPath}`);\n }\n }\n rmSync(targetPath, { recursive: true, force: true });\n }\n\n const linkType = process.platform === 'win32' ? 'junction' : 'dir';\n try {\n symlinkSync(storePath, targetPath, linkType);\n return { target, path: targetPath, mode: process.platform === 'win32' ? 'junction' : 'symlink', updatedAt: new Date().toISOString() };\n } catch (error) {\n if (!options?.forceMap) {\n // Fall through to copy on Windows permission errors or other failures.\n }\n }\n\n cpSync(storePath, targetPath, { recursive: true, dereference: false });\n writeFileSync(\n join(targetPath, '.oneskill-meta.json'),\n JSON.stringify({ source: storePath, mappedAt: new Date().toISOString(), mode: 'copy' }, null, 2) + '\\n',\n 'utf-8'\n );\n\n return { target, path: targetPath, mode: 'copy', updatedAt: new Date().toISOString() };\n}\n","import { mkdirSync, readFileSync, writeFileSync, existsSync } from 'fs';\nimport { dirname, resolve, sep } from 'path';\n\nexport function ensureDir(path: string): void {\n mkdirSync(path, { recursive: true });\n}\n\nexport function readJsonFile<T>(path: string): T | null {\n if (!existsSync(path)) return null;\n const content = readFileSync(path, 'utf-8');\n return JSON.parse(content) as T;\n}\n\nexport function writeJsonFile(path: string, data: unknown): void {\n ensureDir(dirname(path));\n writeFileSync(path, JSON.stringify(data, null, 2) + '\\n', 'utf-8');\n}\n\nexport function isPathInside(targetPath: string, baseDir: string): boolean {\n const resolvedTarget = resolve(targetPath);\n const resolvedBase = resolve(baseDir);\n const baseWithSep = resolvedBase.endsWith(sep) ? resolvedBase : resolvedBase + sep;\n return resolvedTarget === resolvedBase || resolvedTarget.startsWith(baseWithSep);\n}\n","import type { TargetEnvironment } from '../core/types.js';\nimport { mapInstalledSkills } from '../core/map.js';\nimport { printJson } from '../utils/json.js';\n\nexport interface MapCommandOptions {\n target?: TargetEnvironment;\n global?: boolean;\n universal?: boolean;\n forceMap?: boolean;\n}\n\nexport async function runMap(options: MapCommandOptions): Promise<void> {\n if (!options.target) {\n throw new Error('map requires --target gemini');\n }\n const result = mapInstalledSkills({\n target: options.target,\n global: options.global,\n universal: options.universal,\n forceMap: options.forceMap,\n });\n printJson({ schemaVersion: '1', ...result });\n}\n","import { readFileSync } from 'fs';\nimport { dirname, join } from 'path';\nimport { fileURLToPath } from 'url';\nimport { createRequire } from 'module';\n\nconst require = createRequire(import.meta.url);\n\nexport function getOneskillVersion(): string {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const pkgPath = join(__dirname, '../../package.json');\n try {\n const content = readFileSync(pkgPath, 'utf-8');\n const parsed = JSON.parse(content) as { version?: string };\n return parsed.version || '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n\nexport function getOpenskillsVersion(): string {\n try {\n const pkgPath = require.resolve('openskills/package.json');\n const content = readFileSync(pkgPath, 'utf-8');\n const parsed = JSON.parse(content) as { version?: string };\n return parsed.version || '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n"],"mappings":"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","names":["spawnSync","require","spawnSync","existsSync","readFileSync","dirname","resolve","spawnSync","spawnSync","existsSync","join","existsSync","writeFileSync","join","resolve","readFileSync","existsSync","dirname","resolve","resolve","resolve","join","existsSync","writeFileSync","join","existsSync","readFileSync","dirname","join","createRequire","require"]}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "oneskill",
3
+ "version": "0.1.0",
4
+ "description": "Meta-skill manager for AI coding agents",
5
+ "type": "module",
6
+ "main": "./dist/cli.js",
7
+ "bin": {
8
+ "oneskill": "dist/cli.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "README.md",
13
+ "SKILL.md"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsup",
17
+ "dev": "tsup --watch",
18
+ "typecheck": "tsc --noEmit",
19
+ "test": "vitest run"
20
+ },
21
+ "keywords": [
22
+ "skills",
23
+ "ai",
24
+ "agents",
25
+ "meta-skill",
26
+ "codex",
27
+ "gemini",
28
+ "claude"
29
+ ],
30
+ "author": "OneSkill Contributors",
31
+ "license": "Apache-2.0",
32
+ "engines": {
33
+ "node": ">=20.6.0"
34
+ },
35
+ "dependencies": {
36
+ "chalk": "^5.6.2",
37
+ "commander": "^12.1.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^24.9.1",
41
+ "tsup": "^8.5.0",
42
+ "typescript": "^5.9.3",
43
+ "vitest": "^4.0.3"
44
+ }
45
+ }