cm-cli 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b6e6e86fcbd6edf5d8e931afcddbcfb0d53cb03dff807204a64910304661fa76
4
+ data.tar.gz: 0a2aeaa930b5c1bff2d79601b3da635d44bee1f3382146870aee57ca45bf22cb
5
+ SHA512:
6
+ metadata.gz: f71f5551ab6211acc4077a467b54de5852bdc5565a7770449a5f6efb30d7ca7da5968c52b91fbcd35b0fcab6a15381d39de68f01db66e25278c9cf49afe7b16d
7
+ data.tar.gz: 34ffbc2c4e0effaa1fdf0c97d657260f11b9f553d3f92832db48ae06523e914b5b7242273e235299bd6043c36f2dad093bd23d8a4a6596fcd6449aa488391ce8
data/CHANGELOG.md ADDED
@@ -0,0 +1,6 @@
1
+ ## [0.1.0] - 2026-03-03
2
+
3
+ - Initial release as cm-cli (renamed from gate-cli)
4
+ - Support pulling Claude skills and MCP configurations
5
+ - Command-line interface with commander
6
+ - Public gem source on RubyGems.org
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,72 @@
1
+ # CM CLI 开发文档
2
+
3
+ ## 项目结构
4
+
5
+ ```
6
+ cm-cli/
7
+ ├── bin/
8
+ │ └── cm # CLI 入口
9
+ ├── lib/
10
+ │ └── cm/
11
+ │ ├── cli.rb # CLI 命令定义
12
+ │ └── version.rb # 版本号
13
+ │ └── cm.rb # 主模块
14
+ ├── cm-cli.gemspec # gem 包定义
15
+ ├── Gemfile # 依赖管理
16
+ ├── Gemfile.lock
17
+ ├── README.md
18
+ ├── CHANGELOG.md
19
+ ├── CONTRIBUTING.md
20
+ └── RELEASE.md # 发布文档
21
+ ```
22
+
23
+ ## 开发
24
+
25
+ ### 安装依赖
26
+
27
+ ```bash
28
+ bundle install
29
+ ```
30
+
31
+ ### 本地运行
32
+
33
+ ```bash
34
+ bundle exec cm version
35
+ bundle exec cm pull
36
+ ```
37
+
38
+ ### 构建 gem
39
+
40
+ ```bash
41
+ gem build cm-cli.gemspec
42
+ ```
43
+
44
+ ### 运行测试
45
+
46
+ ```bash
47
+ bundle exec rspec # 如果添加了测试
48
+ ```
49
+
50
+ ### 代码检查
51
+
52
+ ```bash
53
+ bundle exec rubocop
54
+ ```
55
+
56
+ ## 发布
57
+
58
+ 参见 [RELEASE.md](./RELEASE.md)
59
+
60
+ ## 贡献
61
+
62
+ 欢迎提交 Issue 和 Pull Request!
63
+
64
+ 1. Fork 本项目
65
+ 2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
66
+ 3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
67
+ 4. 推送到分支 (`git push origin feature/AmazingFeature`)
68
+ 5. 开启 Pull Request
69
+
70
+ ## 许可证
71
+
72
+ MIT License
data/README.md ADDED
@@ -0,0 +1,85 @@
1
+ # CM CLI
2
+
3
+ CLI 工具用于一键拉取 Claude Skill 和 MCP 资源
4
+
5
+ [![RubyGems Version](https://img.shields.io/gem/v/cm-cli)](https://rubygems.org/gems/cm-cli)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-brightgreen)](https://opensource.org/licenses/MIT)
7
+
8
+ ## 安装
9
+
10
+ ```bash
11
+ gem install cm-cli
12
+ ```
13
+
14
+ ## 使用方法
15
+
16
+ ### 拉取所有资源
17
+
18
+ ```bash
19
+ cm pull
20
+ ```
21
+
22
+ ### 只拉取 Skills
23
+
24
+ ```bash
25
+ cm pull skills
26
+ ```
27
+
28
+ ### 只拉取 MCP 配置
29
+
30
+ ```bash
31
+ cm pull mcp
32
+ ```
33
+
34
+ ### 列出已拉取的资源
35
+
36
+ ```bash
37
+ cm list
38
+ ```
39
+
40
+ ### 查看配置
41
+
42
+ ```bash
43
+ cm config
44
+ ```
45
+
46
+ ### 查看版本
47
+
48
+ ```bash
49
+ cm version
50
+ ```
51
+
52
+ ## 功能特点
53
+
54
+ - 从 GitHub 自动拉取 Claude Skills
55
+ - 从 GitHub 自动拉取 MCP 配置文件
56
+ - 自动注册到 Claude 配置
57
+ - 支持增量更新
58
+ - 命令行界面友好
59
+
60
+ ## 开发
61
+
62
+ ```bash
63
+ # 安装依赖
64
+ bundle install
65
+
66
+ # 本地运行
67
+ bundle exec cm version
68
+
69
+ # 构建 gem
70
+ gem build cm-cli.gemspec
71
+ ```
72
+
73
+ ## 贡献
74
+
75
+ 欢迎提交 Issue 和 Pull Request!
76
+
77
+ 1. Fork 本项目
78
+ 2. 创建特性分支
79
+ 3. 提交更改
80
+ 4. 推送到分支
81
+ 5. 开启 Pull Request
82
+
83
+ ## 许可证
84
+
85
+ MIT License
data/bin/cm ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "../lib/cm"
5
+
6
+ Cm.start
data/lib/cm/cli.rb ADDED
@@ -0,0 +1,304 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "commander/import"
4
+ require " FileUtils"
5
+ require "open-uri"
6
+ require "yaml"
7
+
8
+ program :name, "cm"
9
+ program :version, Cm::VERSION
10
+ program :description, "CLI tool for pulling Claude Skill and MCP resources"
11
+
12
+ default_command :help
13
+
14
+ class << self
15
+ private
16
+
17
+ def skills_dir
18
+ File.expand_path("~/.claude/skills")
19
+ end
20
+
21
+ def mcp_dir
22
+ File.expand_path("~/.claude/mcp")
23
+ end
24
+
25
+ def config_file
26
+ File.expand_path("~/.claude/config.yaml")
27
+ end
28
+
29
+ def github_api_url(path)
30
+ "https://api.github.com/repos#{path}"
31
+ end
32
+
33
+ def fetch_github_files(owner, repo, path = "")
34
+ url = github_api_url("/#{owner}/#{repo}/contents/#{path}")
35
+ headers = { "Accept" => "application/vnd.github.v3+json", "User-Agent" => "cm-cli" }
36
+
37
+ response = URI.open(url, headers: headers)
38
+ JSON.parse(response.read)
39
+ rescue => e
40
+ puts error "Failed to fetch from GitHub: #{e.message}"
41
+ []
42
+ end
43
+
44
+ def download_file(url, local_path)
45
+ FileUtils.mkdir_p(File.dirname(local_path))
46
+ URI.open(url, "rb") { |read| File.open(local_path, "wb") { |write| write.write(read.read) } }
47
+ rescue => e
48
+ puts error "Failed to download #{url}: #{e.message}"
49
+ false
50
+ end
51
+
52
+ def info(msg)
53
+ puts "\e[32m[INFO]\e[0m #{msg}"
54
+ end
55
+
56
+ def success(msg)
57
+ puts "\e[32m[SUCCESS]\e[0m #{msg}"
58
+ end
59
+
60
+ def error(msg)
61
+ puts "\e[31m[ERROR]\e[0m #{msg}"
62
+ end
63
+
64
+ def warn(msg)
65
+ puts "\e[33m[WARN]\e[0m #{msg}"
66
+ end
67
+
68
+ def ensure_dir(dir)
69
+ FileUtils.mkdir_p(dir) unless File.directory?(dir)
70
+ end
71
+ end
72
+
73
+ desc "pull", "Pull Claude resources (skills and MCP)"
74
+ long_desc: "Pull all Claude skills and MCP configurations from configured repositories"
75
+ command :pull do |c|
76
+ c.action do |args, options|
77
+ ensure_dir(skills_dir)
78
+ ensure_dir(mcp_dir)
79
+
80
+ puts "\n#{'=' * 50}"
81
+ info "Starting to pull Claude resources..."
82
+ puts "#{'=' * 50}\n"
83
+
84
+ # Default repositories
85
+ repositories = [
86
+ # Format: { "owner/repo" => { skills_path: "path", mcp_path: "path" } }
87
+ { repo: "claude-dev/skills", path: "", type: "skills" },
88
+ { repo: "anthropics/claude-code", path: "mcp", type: "mcp" }
89
+ ]
90
+
91
+ pulled_skills = 0
92
+ pulled_mcp = 0
93
+
94
+ repositories.each do |config|
95
+ owner, repo = config[:repo].split("/")
96
+ path = config[:path]
97
+ type = config[:type]
98
+
99
+ puts "\n[Processing: #{config[:repo]}]"
100
+
101
+ begin
102
+ files = fetch_github_files(owner, repo, path)
103
+
104
+ files.each do |file|
105
+ next if file["type"] != "file" || !file["name"].end_with?(".md", ".json", ".rb", ".py")
106
+
107
+ local_path = case type
108
+ when "skills"
109
+ File.join(skills_dir, file["name"])
110
+ when "mcp"
111
+ File.join(mcp_dir, file["name"])
112
+ end
113
+
114
+ if download_file(file["download_url"], local_path)
115
+ puts " Downloaded: #{file['name']}"
116
+ case type
117
+ when "skills" then pulled_skills += 1
118
+ when "mcp" then pulled_mcp += 1
119
+ end
120
+ end
121
+ end
122
+ rescue => e
123
+ error "Failed to process #{config[:repo]}: #{e.message}"
124
+ end
125
+ end
126
+
127
+ puts "\n\n#{'=' * 50}"
128
+ success "Pull completed!"
129
+ puts " Skills pulled: #{pulled_skills}"
130
+ puts " MCP configs pulled: #{pulled_mcp}"
131
+ puts "#{'=' * 50}\n"
132
+
133
+ # Update config if it exists
134
+ if File.file?(config_file)
135
+ puts "\nChecking config file..."
136
+ config = YAML.load_file(config_file) rescue {}
137
+
138
+ # Ensure skills and mcp paths are configured
139
+ config["skills"] ||= []
140
+ config["mcp"] ||= {}
141
+
142
+ if config["skills"].empty? || !config["skills"].include?(skills_dir)
143
+ config["skills"] << skills_dir unless config["skills"].include?(skills_dir)
144
+ end
145
+
146
+ File.write(config_file, config.to_yaml)
147
+ info "Config updated: #{config_file}"
148
+ end
149
+ end
150
+ end
151
+
152
+ desc "pull skills", "Pull only Claude skills"
153
+ long_desc: "Pull skills from configured repositories into ~/.claude/skills"
154
+ command :skills do |c|
155
+ c.action do |args, options|
156
+ ensure_dir(skills_dir)
157
+
158
+ puts "\n#{'=' * 50}"
159
+ info "Pulling Claude skills..."
160
+ puts "#{'=' * 50}\n"
161
+
162
+ # Default skill repositories
163
+ skill_repos = [
164
+ { owner: "claude-dev", repo: "skills" },
165
+ { owner: "anthropics", repo: "claude-code", path: "skills" }
166
+ ]
167
+
168
+ pulled = 0
169
+
170
+ skill_repos.each do |repo_config|
171
+ owner = repo_config[:owner]
172
+ repo = repo_config[:repo]
173
+ path = repo_config[:path] || ""
174
+
175
+ puts "\n[Fetching: #{owner}/#{repo}]"
176
+
177
+ begin
178
+ files = fetch_github_files(owner, repo, path)
179
+
180
+ files.each do |file|
181
+ next if file["type"] != "file" || !file["name"].end_with?(".md", ".rb", ".py")
182
+
183
+ local_path = File.join(skills_dir, file["name"])
184
+
185
+ if download_file(file["download_url"], local_path)
186
+ puts " ✓ #{file['name']}"
187
+ pulled += 1
188
+ end
189
+ end
190
+ rescue => e
191
+ error "Failed to fetch #{owner}/#{repo}: #{e.message}"
192
+ end
193
+ end
194
+
195
+ puts "\n\n#{'=' * 50}"
196
+ success "Skills pull completed: #{pulled} files"
197
+ puts "#{'=' * 50}\n"
198
+ end
199
+ end
200
+
201
+ desc "pull mcp", "Pull only MCP configurations"
202
+ long_desc: "Pull MCP server configurations into ~/.claude/mcp"
203
+ command :mcp do |c|
204
+ c.action do |args, options|
205
+ ensure_dir(mcp_dir)
206
+
207
+ puts "\n#{'=' * 50}"
208
+ info "Pulling MCP configurations..."
209
+ puts "#{'=' * 50}\n"
210
+
211
+ # Default MCP repositories
212
+ mcp_repos = [
213
+ { owner: "anthropics", repo: "claude-code", path: "mcp" }
214
+ ]
215
+
216
+ pulled = 0
217
+
218
+ mcp_repos.each do |repo_config|
219
+ owner = repo_config[:owner]
220
+ repo = repo_config[:repo]
221
+ path = repo_config[:path] || ""
222
+
223
+ puts "\n[Fetching: #{owner}/#{repo}]"
224
+
225
+ begin
226
+ files = fetch_github_files(owner, repo, path)
227
+
228
+ files.each do |file|
229
+ next if file["type"] != "file" || !file["name"].end_with?(".json")
230
+
231
+ local_path = File.join(mcp_dir, file["name"])
232
+
233
+ if download_file(file["download_url"], local_path)
234
+ puts " ✓ #{file['name']}"
235
+ pulled += 1
236
+ end
237
+ end
238
+ rescue => e
239
+ error "Failed to fetch #{owner}/#{repo}: #{e.message}"
240
+ end
241
+ end
242
+
243
+ puts "\n\n#{'=' * 50}"
244
+ success "MCP pull completed: #{pulled} files"
245
+ puts "#{'=' * 50}\n"
246
+ end
247
+ end
248
+
249
+ desc "list", "List pulled resources"
250
+ command :list do |c|
251
+ c.action do |args, options|
252
+ puts "\n#{'=' * 50}"
253
+ puts "Pulled Claude Resources"
254
+ puts "#{'=' * 50}\n"
255
+
256
+ # List skills
257
+ if File.directory?(skills_dir)
258
+ puts "\nSkills (#{skills_dir}):"
259
+ skills = Dir.glob(File.join(skills_dir, "*.{md,rb,py}"))
260
+ if skills.empty?
261
+ puts " (none)"
262
+ else
263
+ skills.each { |s| puts " - #{File.basename(s)}" }
264
+ end
265
+ end
266
+
267
+ # List MCP
268
+ if File.directory?(mcp_dir)
269
+ puts "\nMCP Configs (#{mcp_dir}):"
270
+ mcp_files = Dir.glob(File.join(mcp_dir, "*.json"))
271
+ if mcp_files.empty?
272
+ puts " (none)"
273
+ else
274
+ mcp_files.each { |f| puts " - #{File.basename(f)}" }
275
+ end
276
+ end
277
+
278
+ puts "\n#{'=' * 50}\n"
279
+ end
280
+ end
281
+
282
+ desc "config", "Show or update configuration"
283
+ command :config do |c|
284
+ c.action do |args, options|
285
+ if args.empty?
286
+ puts "\n#{'=' * 50}"
287
+ puts "CM CLI Configuration"
288
+ puts "#{'=' * 50}\n"
289
+ puts "Skills directory: #{skills_dir}"
290
+ puts "MCP directory: #{mcp_dir}"
291
+ puts "Config file: #{config_file}"
292
+ puts
293
+ else
294
+ error "Usage: cm config (shows current configuration)"
295
+ end
296
+ end
297
+ end
298
+
299
+ desc "version", "Show version"
300
+ command :version do |c|
301
+ c.action do |args, options|
302
+ puts "cm-cli version #{Cm::VERSION}"
303
+ end
304
+ end
data/lib/cm/version.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cm
4
+ VERSION = "0.1.0"
5
+ end
data/lib/cm.rb ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "cm/version"
4
+ require_relative "cm/cli"
5
+
6
+ module Cm
7
+ class Error < StandardError; end
8
+
9
+ def self.start
10
+ CLI.start(ARGV)
11
+ end
12
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cm-cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - FullTrust
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-03-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: commander
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '13.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '13.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.50'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.50'
55
+ description: A CLI tool that helps you pull Claude skills and MCP servers with one
56
+ click
57
+ email:
58
+ - dev@fulltrust.link
59
+ executables:
60
+ - cm
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - CHANGELOG.md
65
+ - CONTRIBUTING.md
66
+ - README.md
67
+ - bin/cm
68
+ - lib/cm.rb
69
+ - lib/cm/cli.rb
70
+ - lib/cm/version.rb
71
+ homepage: https://github.com/fulltrust/cm-cli
72
+ licenses:
73
+ - MIT
74
+ metadata:
75
+ homepage_uri: https://github.com/fulltrust/cm-cli
76
+ source_code_uri: https://github.com/fulltrust/cm-cli
77
+ changelog_uri: https://github.com/fulltrust/cm-cli/CHANGELOG.md
78
+ documentation_uri: https://github.com/fulltrust/cm-cli#readme
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: 3.0.0
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubygems_version: 3.1.6
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: CLI tool for pulling Claude Skill and MCP resources
98
+ test_files: []