ruby-skills 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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +46 -0
- data/.yardopts +5 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +110 -0
- data/LICENSE +0 -0
- data/README.md +120 -0
- data/Rakefile +17 -0
- data/bin/ruby-skills +6 -0
- data/lib/ruby_skills/adapters/base.rb +57 -0
- data/lib/ruby_skills/adapters/claude.rb +19 -0
- data/lib/ruby_skills/adapters/codex.rb +19 -0
- data/lib/ruby_skills/adapters/cursor.rb +19 -0
- data/lib/ruby_skills/adapters/vscode.rb +19 -0
- data/lib/ruby_skills/cli.rb +146 -0
- data/lib/ruby_skills/config.rb +72 -0
- data/lib/ruby_skills/installer.rb +87 -0
- data/lib/ruby_skills/lockfile.rb +84 -0
- data/lib/ruby_skills/manifest.rb +91 -0
- data/lib/ruby_skills/remover.rb +50 -0
- data/lib/ruby_skills/resolver.rb +107 -0
- data/lib/ruby_skills/updater.rb +32 -0
- data/lib/ruby_skills/version.rb +8 -0
- data/lib/ruby_skills.rb +20 -0
- data/ruby-skills.gemspec +51 -0
- metadata +169 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubySkills
|
|
4
|
+
# Installs skills declared in the Skillfile.
|
|
5
|
+
#
|
|
6
|
+
# Resolves each skill, copies it into +.ruby-skills+, notifies tool
|
|
7
|
+
# adapters, and records the result in +Skills.lock+.
|
|
8
|
+
#
|
|
9
|
+
# @example Install every declared skill
|
|
10
|
+
# RubySkills::Installer.new.install
|
|
11
|
+
#
|
|
12
|
+
# @example Install one skill
|
|
13
|
+
# RubySkills::Installer.new.install("rails-performance")
|
|
14
|
+
#
|
|
15
|
+
# @see RubySkills::Manifest
|
|
16
|
+
# @see RubySkills::Resolver
|
|
17
|
+
# @since 0.1.0
|
|
18
|
+
class Installer
|
|
19
|
+
# @param config [RubySkills::Config] project paths used during install
|
|
20
|
+
def initialize(config: Config.new)
|
|
21
|
+
@config = config
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Install one skill or every skill declared in the Skillfile.
|
|
25
|
+
#
|
|
26
|
+
# @param skill_name [String, nil] skill to install, or +nil+ to install all
|
|
27
|
+
# @return [void]
|
|
28
|
+
# @raise [RubySkills::Error] if the Skillfile is missing or a skill cannot be installed
|
|
29
|
+
def install(skill_name = nil)
|
|
30
|
+
load_skills(skill_name).each do |skill|
|
|
31
|
+
install_skill(skill)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
# @api private
|
|
38
|
+
# @param skill_name [String, nil]
|
|
39
|
+
# @return [Array<RubySkills::Manifest::Skill>]
|
|
40
|
+
# @raise [RubySkills::Error] if the named skill is not in the Skillfile
|
|
41
|
+
def load_skills(skill_name)
|
|
42
|
+
manifest = Manifest.new.load!
|
|
43
|
+
|
|
44
|
+
return manifest.skills if skill_name.nil?
|
|
45
|
+
|
|
46
|
+
skill = manifest.skills.find { |declared| declared.name == skill_name }
|
|
47
|
+
raise RubySkills::Error, "Skill `#{skill_name}` is not in the Skillfile" unless skill
|
|
48
|
+
|
|
49
|
+
[skill]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @api private
|
|
53
|
+
# @param skill [RubySkills::Manifest::Skill]
|
|
54
|
+
# @return [void]
|
|
55
|
+
def install_skill(skill)
|
|
56
|
+
resolved = Resolver.new.resolve(skill)
|
|
57
|
+
destination = @config.skills_path.join(resolved.name)
|
|
58
|
+
|
|
59
|
+
FileUtils.rm_rf(destination)
|
|
60
|
+
FileUtils.mkdir_p(@config.skills_path)
|
|
61
|
+
FileUtils.cp_r(resolved.path, destination)
|
|
62
|
+
|
|
63
|
+
adapters.each do |adapter|
|
|
64
|
+
adapter.new.install(resolved.name, destination)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
Lockfile.new(config: @config).add(
|
|
68
|
+
resolved.name,
|
|
69
|
+
version: skill.version || "unspecified",
|
|
70
|
+
source: resolved.source
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
puts "✓ Installed #{resolved.name}"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# @api private
|
|
77
|
+
# @return [Array<Class>] adapter classes notified when a skill is installed
|
|
78
|
+
def adapters
|
|
79
|
+
[
|
|
80
|
+
Adapters::Claude,
|
|
81
|
+
Adapters::Codex,
|
|
82
|
+
Adapters::Cursor,
|
|
83
|
+
Adapters::Vscode
|
|
84
|
+
]
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubySkills
|
|
4
|
+
# Reads and writes the project +Skills.lock+ file.
|
|
5
|
+
#
|
|
6
|
+
# The lockfile records installed skill names, versions, and sources so
|
|
7
|
+
# later installs and removals stay consistent.
|
|
8
|
+
#
|
|
9
|
+
# @example List installed skills
|
|
10
|
+
# RubySkills::Lockfile.new.skills
|
|
11
|
+
#
|
|
12
|
+
# @see RubySkills::Config#lockfile_path
|
|
13
|
+
# @since 0.1.0
|
|
14
|
+
class Lockfile
|
|
15
|
+
# @param config [RubySkills::Config] project paths used to locate Skills.lock
|
|
16
|
+
def initialize(config: Config.new)
|
|
17
|
+
@config = config
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Installed skills stored in the lockfile.
|
|
21
|
+
#
|
|
22
|
+
# @return [Hash{String => Hash}] skill names mapped to +version+ and +source+
|
|
23
|
+
def skills
|
|
24
|
+
return {} unless @config.lockfile_path.exist?
|
|
25
|
+
|
|
26
|
+
data = YAML.safe_load_file(
|
|
27
|
+
@config.lockfile_path,
|
|
28
|
+
permitted_classes: [],
|
|
29
|
+
aliases: true
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
data.fetch("skills", {})
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Record an installed skill in the lockfile.
|
|
36
|
+
#
|
|
37
|
+
# @param name [String] skill identifier
|
|
38
|
+
# @param version [String] installed skill version
|
|
39
|
+
# @param source [String] origin used to install the skill
|
|
40
|
+
# @return [void]
|
|
41
|
+
def add(name, version:, source:)
|
|
42
|
+
data = load_data
|
|
43
|
+
|
|
44
|
+
data["skills"][name] = {
|
|
45
|
+
"version" => version,
|
|
46
|
+
"source" => source
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
write(data)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Drop a skill from the lockfile.
|
|
53
|
+
#
|
|
54
|
+
# @param name [String] skill identifier to remove
|
|
55
|
+
# @return [void]
|
|
56
|
+
def remove(name)
|
|
57
|
+
data = load_data
|
|
58
|
+
|
|
59
|
+
data["skills"].delete(name)
|
|
60
|
+
|
|
61
|
+
write(data)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
# @api private
|
|
67
|
+
# @return [Hash] lockfile payload with a +version+ header and +skills+ map
|
|
68
|
+
def load_data
|
|
69
|
+
{
|
|
70
|
+
"version" => 1,
|
|
71
|
+
"skills" => skills
|
|
72
|
+
}
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# @api private
|
|
76
|
+
# @param data [Hash] lockfile payload to persist
|
|
77
|
+
# @return [void]
|
|
78
|
+
def write(data)
|
|
79
|
+
@config.lockfile_path.write(
|
|
80
|
+
YAML.dump(data)
|
|
81
|
+
)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubySkills
|
|
4
|
+
# Loads and evaluates a project +Skillfile+.
|
|
5
|
+
#
|
|
6
|
+
# The Skillfile is Ruby DSL. Each +skill+ declaration becomes a
|
|
7
|
+
# {RubySkills::Manifest::Skill} stored in {#skills}.
|
|
8
|
+
#
|
|
9
|
+
# @example Load the Skillfile from the current project
|
|
10
|
+
# manifest = RubySkills::Manifest.new.load!
|
|
11
|
+
# manifest.skills
|
|
12
|
+
#
|
|
13
|
+
# @since 0.1.0
|
|
14
|
+
class Manifest
|
|
15
|
+
# Declared skill entry loaded from a Skillfile.
|
|
16
|
+
#
|
|
17
|
+
# @!attribute [rw] name
|
|
18
|
+
# @return [String] skill identifier
|
|
19
|
+
# @!attribute [rw] github
|
|
20
|
+
# @return [String, nil] GitHub repository in +owner/name+ form
|
|
21
|
+
# @!attribute [rw] path
|
|
22
|
+
# @return [String, nil] local filesystem path to the skill
|
|
23
|
+
# @!attribute [rw] version
|
|
24
|
+
# @return [String, nil] optional pinned version
|
|
25
|
+
Skill = Struct.new(
|
|
26
|
+
:name,
|
|
27
|
+
:github,
|
|
28
|
+
:path,
|
|
29
|
+
:version,
|
|
30
|
+
keyword_init: true
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# @return [Array<Skill>] skills declared in the Skillfile
|
|
34
|
+
attr_reader :skills
|
|
35
|
+
|
|
36
|
+
# @param path [Pathname, String] path to the Skillfile
|
|
37
|
+
def initialize(path: default_skill_path)
|
|
38
|
+
@path = path
|
|
39
|
+
@skills = []
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Read and evaluate the Skillfile, populating {#skills}.
|
|
43
|
+
#
|
|
44
|
+
# @return [Manifest] self
|
|
45
|
+
# @raise [RubySkills::Error] if the Skillfile is missing or invalid
|
|
46
|
+
def load!
|
|
47
|
+
unless @path.exist?
|
|
48
|
+
raise RubySkills::Error,
|
|
49
|
+
"Skillfile not found. Run `ruby-skills init` first."
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
instance_eval(@path.read, @path.to_s, 1)
|
|
53
|
+
|
|
54
|
+
self
|
|
55
|
+
rescue SyntaxError => e
|
|
56
|
+
raise RubySkills::Error, "Invalid Skillfile: #{e.message}"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Declare a skill in the Skillfile DSL.
|
|
60
|
+
#
|
|
61
|
+
# Exactly one source must be provided: +github+ or +path+.
|
|
62
|
+
#
|
|
63
|
+
# @param name [String] skill identifier
|
|
64
|
+
# @param github [String, nil] GitHub repository in +owner/name+ form
|
|
65
|
+
# @param path [String, nil] local filesystem path to the skill
|
|
66
|
+
# @param version [String, nil] optional pinned version
|
|
67
|
+
# @return [void]
|
|
68
|
+
# @raise [RubySkills::Error] if neither +github+ nor +path+ is given
|
|
69
|
+
def skill(name, github: nil, path: nil, version: nil)
|
|
70
|
+
unless github || path
|
|
71
|
+
raise RubySkills::Error,
|
|
72
|
+
"#{name}: either github or path: must be provided"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
@skills << Skill.new(
|
|
76
|
+
name: name,
|
|
77
|
+
github: github,
|
|
78
|
+
path: path,
|
|
79
|
+
version: version
|
|
80
|
+
)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
# @api private
|
|
86
|
+
# @return [Pathname] default path used when none is given to {#initialize}
|
|
87
|
+
def default_skill_path
|
|
88
|
+
Config.new.skills_path
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubySkills
|
|
4
|
+
# Uninstalls a skill from the project, adapters, and lockfile.
|
|
5
|
+
#
|
|
6
|
+
# @example Remove an installed skill
|
|
7
|
+
# RubySkills::Remover.new.remove("rails-performance")
|
|
8
|
+
#
|
|
9
|
+
# @see RubySkills::Lockfile
|
|
10
|
+
# @see RubySkills::Adapters
|
|
11
|
+
# @since 0.1.0
|
|
12
|
+
class Remover
|
|
13
|
+
# @param config [RubySkills::Config] project paths used to locate skills
|
|
14
|
+
def initialize(config: Config.new)
|
|
15
|
+
@config = config
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Remove an installed skill from disk, tool adapters, and the lockfile.
|
|
19
|
+
#
|
|
20
|
+
# @param name [String] skill identifier to remove
|
|
21
|
+
# @return [void]
|
|
22
|
+
# @raise [RubySkills::Error] if the skill is not installed
|
|
23
|
+
def remove(name)
|
|
24
|
+
path = @config.skills_path.join(name)
|
|
25
|
+
|
|
26
|
+
unless path.exist?
|
|
27
|
+
raise RubySkills::Error,
|
|
28
|
+
"Skill `#{name}` is not installed"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
adapters.each do |adapter|
|
|
32
|
+
adapter.new.remove(name)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
FileUtils.rm_rf(path)
|
|
36
|
+
|
|
37
|
+
Lockfile.new.remove(name)
|
|
38
|
+
|
|
39
|
+
puts "✓ Removed #{name}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
# @api private
|
|
45
|
+
# @return [Array<Class>] adapter classes notified when a skill is removed
|
|
46
|
+
def adapters
|
|
47
|
+
RubySkills::Adapters.all
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "tmpdir"
|
|
4
|
+
|
|
5
|
+
module RubySkills
|
|
6
|
+
# Turns a declared skill into a local directory that can be installed.
|
|
7
|
+
#
|
|
8
|
+
# Local skills are resolved from {RubySkills::Manifest::Skill#path}.
|
|
9
|
+
# Remote skills are cloned from GitHub into a temporary directory.
|
|
10
|
+
#
|
|
11
|
+
# @example Resolve a declared skill
|
|
12
|
+
# skill = RubySkills::Manifest::Skill.new(
|
|
13
|
+
# name: "rails-performance",
|
|
14
|
+
# path: "./skills/rails-performance"
|
|
15
|
+
# )
|
|
16
|
+
# RubySkills::Resolver.new.resolve(skill)
|
|
17
|
+
#
|
|
18
|
+
# @see RubySkills::Manifest::Skill
|
|
19
|
+
# @since 0.1.0
|
|
20
|
+
class Resolver
|
|
21
|
+
# Skill directory ready to be installed.
|
|
22
|
+
#
|
|
23
|
+
# @!attribute [rw] name
|
|
24
|
+
# @return [String] skill identifier
|
|
25
|
+
# @!attribute [rw] path
|
|
26
|
+
# @return [Pathname] local directory containing the skill
|
|
27
|
+
# @!attribute [rw] source
|
|
28
|
+
# @return [String] origin used to resolve the skill
|
|
29
|
+
ResolvedSkill = Struct.new(
|
|
30
|
+
:name,
|
|
31
|
+
:path,
|
|
32
|
+
:source,
|
|
33
|
+
keyword_init: true
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# Resolve a skill from a local path or a remote repository.
|
|
37
|
+
#
|
|
38
|
+
# @param skill [RubySkills::Manifest::Skill] declared skill to resolve
|
|
39
|
+
# @return [ResolvedSkill] skill directory ready to install
|
|
40
|
+
# @raise [RubySkills::Error] if the skill has no usable source
|
|
41
|
+
def resolve(skill)
|
|
42
|
+
if skill.path
|
|
43
|
+
resolve_local(skill)
|
|
44
|
+
elsif skill.github
|
|
45
|
+
resolve_remote(skill)
|
|
46
|
+
else
|
|
47
|
+
raise RubySkills::Error,
|
|
48
|
+
"Unable to resolve #{skill.name}"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
# @api private
|
|
55
|
+
# @param skill [RubySkills::Manifest::Skill]
|
|
56
|
+
# @return [ResolvedSkill]
|
|
57
|
+
# @raise [RubySkills::Error] if the local skill path is not a directory
|
|
58
|
+
def resolve_local(skill)
|
|
59
|
+
path = Pathname.new(skill.path).expand_path
|
|
60
|
+
|
|
61
|
+
unless path.directory?
|
|
62
|
+
raise RubySkills::Error,
|
|
63
|
+
"Skill path does not exist: #{path}"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
ResolvedSkill.new(
|
|
67
|
+
name: skill.name,
|
|
68
|
+
path: path,
|
|
69
|
+
source: "path:#{path}"
|
|
70
|
+
)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# @api private
|
|
74
|
+
# @param skill [RubySkills::Manifest::Skill]
|
|
75
|
+
# @return [ResolvedSkill] skill cloned into a temporary directory
|
|
76
|
+
# @raise [RubySkills::Error] if the GitHub repository cannot be cloned
|
|
77
|
+
def resolve_remote(skill)
|
|
78
|
+
directory = Pathname.new(
|
|
79
|
+
Dir.mktmpdir("ruby-skills")
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
repository = "https://github.com/#{skill.github}.git"
|
|
83
|
+
|
|
84
|
+
success = system(
|
|
85
|
+
"git",
|
|
86
|
+
"clone",
|
|
87
|
+
"--depth",
|
|
88
|
+
"1",
|
|
89
|
+
repository,
|
|
90
|
+
directory.to_s,
|
|
91
|
+
out: File::NULL,
|
|
92
|
+
err: File::NULL
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
unless success
|
|
96
|
+
raise RubySkills::Error,
|
|
97
|
+
"Unable to clone #{skill.github}"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
ResolvedSkill.new(
|
|
101
|
+
name: skill.name,
|
|
102
|
+
path: directory,
|
|
103
|
+
source: "github:#{skill.github}"
|
|
104
|
+
)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubySkills
|
|
4
|
+
# Reinstalls skills to pick up newer versions.
|
|
5
|
+
#
|
|
6
|
+
# Delegates the work to {RubySkills::Installer}. When +skill_name+ is
|
|
7
|
+
# omitted, every skill in the Skillfile is updated.
|
|
8
|
+
#
|
|
9
|
+
# @example Update a single skill
|
|
10
|
+
# RubySkills::Updater.new.update("rails-performance")
|
|
11
|
+
#
|
|
12
|
+
# @example Update every declared skill
|
|
13
|
+
# RubySkills::Updater.new.update
|
|
14
|
+
#
|
|
15
|
+
# @see RubySkills::Installer
|
|
16
|
+
# @since 0.1.0
|
|
17
|
+
class Updater
|
|
18
|
+
# Update one skill or every skill declared in the Skillfile.
|
|
19
|
+
#
|
|
20
|
+
# @param skill_name [String, nil] skill to update, or +nil+ to update all
|
|
21
|
+
# @return [void]
|
|
22
|
+
def update(skill_name = nil)
|
|
23
|
+
Installer.new.install(skill_name)
|
|
24
|
+
|
|
25
|
+
if skill_name
|
|
26
|
+
puts "✓ Updated #{skill_name}"
|
|
27
|
+
else
|
|
28
|
+
puts "✓ All skills updated"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/lib/ruby_skills.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "yaml"
|
|
4
|
+
require "fileutils"
|
|
5
|
+
require "pathname"
|
|
6
|
+
|
|
7
|
+
# Package manager for installing, updating, removing and sharing AI
|
|
8
|
+
# development skills in Ruby and Rails projects.
|
|
9
|
+
#
|
|
10
|
+
# @see RubySkills::CLI
|
|
11
|
+
# @see RubySkills::Config
|
|
12
|
+
# @since 0.1.0
|
|
13
|
+
module RubySkills
|
|
14
|
+
# Base error for all Ruby Skills failures.
|
|
15
|
+
class Error < StandardError; end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
Dir.glob("ruby_skills/**/*.rb", base: __dir__).sort.each do |path|
|
|
19
|
+
require path.delete_suffix(".rb")
|
|
20
|
+
end
|
data/ruby-skills.gemspec
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "lib/ruby_skills/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "ruby-skills"
|
|
7
|
+
spec.version = RubySkills::VERSION
|
|
8
|
+
spec.authors = ["Renato Franco"]
|
|
9
|
+
spec.email = ["renator.franco93@gmail.com"]
|
|
10
|
+
|
|
11
|
+
spec.summary = "Package, share, and install Ruby engineering knowledge."
|
|
12
|
+
spec.description = <<~DESCRIPTION
|
|
13
|
+
Ruby Skills is a package manager for distributing engineering
|
|
14
|
+
knowledge to Ruby development tools and coding agents.
|
|
15
|
+
DESCRIPTION
|
|
16
|
+
|
|
17
|
+
spec.homepage = "https://rubyskills.org"
|
|
18
|
+
spec.license = "MIT"
|
|
19
|
+
|
|
20
|
+
spec.required_ruby_version = ">= 3.1.0"
|
|
21
|
+
|
|
22
|
+
spec.metadata = {
|
|
23
|
+
"homepage_uri" => spec.homepage,
|
|
24
|
+
"source_code_uri" => "https://github.com/renatofranco/ruby-skills",
|
|
25
|
+
"rubygems_mfa_required" => "true"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
spec.files = Dir.chdir(__dir__) {
|
|
29
|
+
`git ls-files -z`.split("\x0").reject do |file|
|
|
30
|
+
file.start_with?(
|
|
31
|
+
"test/",
|
|
32
|
+
"spec/",
|
|
33
|
+
"features/",
|
|
34
|
+
".git",
|
|
35
|
+
".github"
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
spec.bindir = "bin"
|
|
41
|
+
spec.executables = ["ruby-skills"]
|
|
42
|
+
spec.require_paths = ["lib"]
|
|
43
|
+
|
|
44
|
+
spec.add_dependency "thor", "~> 1.3"
|
|
45
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
|
46
|
+
spec.add_development_dependency "rspec", "~> 3.12"
|
|
47
|
+
spec.add_development_dependency "rubocop", "~> 1.58"
|
|
48
|
+
spec.add_development_dependency "rubocop-performance", "~> 1.20"
|
|
49
|
+
spec.add_development_dependency "rubocop-rspec", "~> 3.0"
|
|
50
|
+
spec.add_development_dependency "yard", "~> 0.9"
|
|
51
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ruby-skills
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Renato Franco
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: thor
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.3'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '1.3'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rake
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '13.0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '13.0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rspec
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '3.12'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '3.12'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rubocop
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '1.58'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '1.58'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: rubocop-performance
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '1.20'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '1.20'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: rubocop-rspec
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '3.0'
|
|
89
|
+
type: :development
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - "~>"
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '3.0'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: yard
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - "~>"
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0.9'
|
|
103
|
+
type: :development
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - "~>"
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0.9'
|
|
110
|
+
description: |
|
|
111
|
+
Ruby Skills is a package manager for distributing engineering
|
|
112
|
+
knowledge to Ruby development tools and coding agents.
|
|
113
|
+
email:
|
|
114
|
+
- renator.franco93@gmail.com
|
|
115
|
+
executables:
|
|
116
|
+
- ruby-skills
|
|
117
|
+
extensions: []
|
|
118
|
+
extra_rdoc_files: []
|
|
119
|
+
files:
|
|
120
|
+
- ".rspec"
|
|
121
|
+
- ".rubocop.yml"
|
|
122
|
+
- ".yardopts"
|
|
123
|
+
- Gemfile
|
|
124
|
+
- Gemfile.lock
|
|
125
|
+
- LICENSE
|
|
126
|
+
- README.md
|
|
127
|
+
- Rakefile
|
|
128
|
+
- bin/ruby-skills
|
|
129
|
+
- lib/ruby_skills.rb
|
|
130
|
+
- lib/ruby_skills/adapters/base.rb
|
|
131
|
+
- lib/ruby_skills/adapters/claude.rb
|
|
132
|
+
- lib/ruby_skills/adapters/codex.rb
|
|
133
|
+
- lib/ruby_skills/adapters/cursor.rb
|
|
134
|
+
- lib/ruby_skills/adapters/vscode.rb
|
|
135
|
+
- lib/ruby_skills/cli.rb
|
|
136
|
+
- lib/ruby_skills/config.rb
|
|
137
|
+
- lib/ruby_skills/installer.rb
|
|
138
|
+
- lib/ruby_skills/lockfile.rb
|
|
139
|
+
- lib/ruby_skills/manifest.rb
|
|
140
|
+
- lib/ruby_skills/remover.rb
|
|
141
|
+
- lib/ruby_skills/resolver.rb
|
|
142
|
+
- lib/ruby_skills/updater.rb
|
|
143
|
+
- lib/ruby_skills/version.rb
|
|
144
|
+
- ruby-skills.gemspec
|
|
145
|
+
homepage: https://rubyskills.org
|
|
146
|
+
licenses:
|
|
147
|
+
- MIT
|
|
148
|
+
metadata:
|
|
149
|
+
homepage_uri: https://rubyskills.org
|
|
150
|
+
source_code_uri: https://github.com/renatofranco/ruby-skills
|
|
151
|
+
rubygems_mfa_required: 'true'
|
|
152
|
+
rdoc_options: []
|
|
153
|
+
require_paths:
|
|
154
|
+
- lib
|
|
155
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
156
|
+
requirements:
|
|
157
|
+
- - ">="
|
|
158
|
+
- !ruby/object:Gem::Version
|
|
159
|
+
version: 3.1.0
|
|
160
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
161
|
+
requirements:
|
|
162
|
+
- - ">="
|
|
163
|
+
- !ruby/object:Gem::Version
|
|
164
|
+
version: '0'
|
|
165
|
+
requirements: []
|
|
166
|
+
rubygems_version: 4.0.10
|
|
167
|
+
specification_version: 4
|
|
168
|
+
summary: Package, share, and install Ruby engineering knowledge.
|
|
169
|
+
test_files: []
|