all_in_ruby 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: 4e016ce2d0604883066cae2f675273dc7a239291bcd591324e15eafcc3a2ced8
4
+ data.tar.gz: ed253dfd0c43ee7ee7e2c40546639500b50b2aa3bf97c548d5788386adddcc0a
5
+ SHA512:
6
+ metadata.gz: 46e170a80461bbcdde8c26c73e81e479954199fe2332937f1a5aff96a76de3f33e9db9104440576ec23945a3cef658b018ee5b642a9bb55cd478fad7d3056144
7
+ data.tar.gz: 73e95dfb8c32a8ac29e5fa839d0deac2728d57f4d04ed15087f27df3878a371561cd9f55368a37c99f24dd6371a7e38950c7c9b0bed4cda9ebedafe3bbffa9b3
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 (2026-07-20)
4
+
5
+ - First release
6
+ - `install`, `uninstall`, and `status` commands
7
+ - Supports Claude Code (`CLAUDE.md`) and Codex (`AGENTS.md`), local and global scopes
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 Lucian Ghinda
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # all_in_ruby
2
+
3
+ Tell your AI coding agents to write scripts in Ruby.
4
+
5
+ Adds a "write throwaway and utility scripts in Ruby" instruction to agent instruction files - `CLAUDE.md` for Claude Code, `AGENTS.md` for Codex. Additive and idempotent: your existing instructions are never modified.
6
+
7
+ ## Installation
8
+
9
+ ```sh
10
+ gem install all_in_ruby
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ Add the instruction to the current repo:
16
+
17
+ ```sh
18
+ all-in-ruby install
19
+ ```
20
+
21
+ Or add it globally, for every project:
22
+
23
+ ```sh
24
+ all-in-ruby install --global
25
+ ```
26
+
27
+ This writes to `~/.claude/CLAUDE.md` and `~/.codex/AGENTS.md`. If `CODEX_HOME` is set, it is used instead of `~/.codex`, matching Codex's own resolution.
28
+
29
+ ## Usage
30
+
31
+ Target a single agent:
32
+
33
+ ```sh
34
+ all-in-ruby install --claude
35
+ all-in-ruby install --codex
36
+ ```
37
+
38
+ Check where the instruction is installed:
39
+
40
+ ```sh
41
+ all-in-ruby status
42
+ ```
43
+
44
+ Remove it:
45
+
46
+ ```sh
47
+ all-in-ruby uninstall
48
+ ```
49
+
50
+ ## How It Works
51
+
52
+ The instruction is appended inside marker comments:
53
+
54
+ ```markdown
55
+ <!-- BEGIN all_in_ruby -->
56
+ ## Scripts
57
+
58
+ Write throwaway and utility scripts (data munging, one-off migrations,
59
+ file renames, glue code) in Ruby — even in projects written in another
60
+ language. If it needs a pipe, a loop, a conditional, or more than one
61
+ line, it is a script: write it in Ruby, not Python, Node, or bash.
62
+ Single self-contained commands (`grep`, `git status`) are fine as-is.
63
+
64
+ Use only the Ruby standard library. If a gem would clearly save
65
+ significant effort, stop and ask before using it.
66
+
67
+ Put temporary scripts in a scratch or temp directory, not the repo
68
+ root, and delete them when done unless asked to keep them.
69
+ <!-- END all_in_ruby -->
70
+ ```
71
+
72
+ Existing file content is preserved verbatim. Running `install` twice is a no-op. `uninstall` removes only the marked block.
73
+
74
+ ## History
75
+
76
+ View the [changelog](CHANGELOG.md)
77
+
78
+ ## Contributing
79
+
80
+ Everyone is encouraged to help improve this project. Here are a few ways you can help:
81
+
82
+ - [Report bugs](https://github.com/lucianghinda/all-in-ruby/issues)
83
+ - Fix bugs and [submit pull requests](https://github.com/lucianghinda/all-in-ruby/pulls)
84
+ - Write, clarify, or fix documentation
85
+ - Suggest or add new features
86
+
87
+ To get started with development:
88
+
89
+ ```sh
90
+ git clone https://github.com/lucianghinda/all-in-ruby.git
91
+ cd all-in-ruby
92
+ bundle install
93
+ bundle exec rake test
94
+ ```
data/exe/all-in-ruby ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "all_in_ruby"
4
+
5
+ exit AllInRuby::CLI.new.run(ARGV)
@@ -0,0 +1,78 @@
1
+ require "optparse"
2
+
3
+ module AllInRuby
4
+ class CLI
5
+ COMMANDS = ["install", "uninstall", "status"].freeze
6
+
7
+ STATUS_LABELS = {
8
+ created: "created",
9
+ updated: "instructions added",
10
+ already_installed: "already installed, left untouched",
11
+ removed: "instructions removed",
12
+ not_installed: "not installed",
13
+ installed: "installed"
14
+ }.freeze
15
+
16
+ def initialize(stdout: $stdout, stderr: $stderr, installer: Installer.new)
17
+ @stdout = stdout
18
+ @stderr = stderr
19
+ @installer = installer
20
+ end
21
+
22
+ def run(argv)
23
+ options = {agents: Installer::AGENTS.dup, scope: "local"}
24
+ parser = build_parser(options)
25
+ parser.parse!(argv)
26
+
27
+ command = argv.shift
28
+ unless COMMANDS.include?(command)
29
+ @stderr.puts parser
30
+ return 1
31
+ end
32
+
33
+ results = @installer.public_send(command, agents: options[:agents], scope: options[:scope])
34
+ results.each do |result|
35
+ @stdout.puts "#{result.agent.ljust(6)} #{result.path}: #{STATUS_LABELS.fetch(result.status)}"
36
+ end
37
+ 0
38
+ rescue OptionParser::ParseError => e
39
+ @stderr.puts e.message
40
+ 1
41
+ end
42
+
43
+ private
44
+
45
+ def build_parser(options)
46
+ OptionParser.new do |opts|
47
+ opts.banner = <<~BANNER
48
+ Usage: all-in-ruby COMMAND [options]
49
+
50
+ Adds a "write scripts in Ruby" instruction to AI agent instruction
51
+ files (CLAUDE.md for Claude Code, AGENTS.md for Codex). Additive and
52
+ idempotent: existing content is never modified.
53
+
54
+ Commands:
55
+ install add the instruction block
56
+ uninstall remove the instruction block
57
+ status show where the block is installed
58
+
59
+ Options:
60
+ BANNER
61
+
62
+ opts.on("--global", "Target global files (~/.claude/CLAUDE.md, ~/.codex/AGENTS.md)") do
63
+ options[:scope] = "global"
64
+ end
65
+ opts.on("--claude", "Only Claude Code (CLAUDE.md)") do
66
+ options[:agents] = ["claude"]
67
+ end
68
+ opts.on("--codex", "Only Codex (AGENTS.md)") do
69
+ options[:agents] = ["codex"]
70
+ end
71
+ opts.on("-v", "--version", "Print version") do
72
+ @stdout.puts VERSION
73
+ exit 0
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,80 @@
1
+ require "fileutils"
2
+
3
+ module AllInRuby
4
+ class Installer
5
+ AGENTS = ["claude", "codex"].freeze
6
+ SCOPES = ["local", "global"].freeze
7
+
8
+ Result = Struct.new(:agent, :path, :status)
9
+
10
+ def initialize(root: Dir.pwd, home: Dir.home, env: ENV)
11
+ @root = root
12
+ @home = home
13
+ @env = env
14
+ end
15
+
16
+ def path_for(agent, scope)
17
+ case [agent, scope]
18
+ when ["claude", "local"] then File.join(@root, "CLAUDE.md")
19
+ when ["claude", "global"] then File.join(@home, ".claude", "CLAUDE.md")
20
+ when ["codex", "local"] then File.join(@root, "AGENTS.md")
21
+ when ["codex", "global"] then File.join(codex_home, "AGENTS.md")
22
+ else
23
+ raise ArgumentError, "unknown agent or scope: #{agent}, #{scope}"
24
+ end
25
+ end
26
+
27
+ def install(agents:, scope:)
28
+ each_target(agents, scope) do |path|
29
+ content = File.exist?(path) ? File.read(path) : nil
30
+
31
+ if content && Instruction.installed?(content)
32
+ :already_installed
33
+ elsif content
34
+ separator = content.empty? || content.end_with?("\n\n") ? "" : (content.end_with?("\n") ? "\n" : "\n\n")
35
+ File.write(path, content + separator + Instruction.block)
36
+ :updated
37
+ else
38
+ FileUtils.mkdir_p(File.dirname(path))
39
+ File.write(path, Instruction.block)
40
+ :created
41
+ end
42
+ end
43
+ end
44
+
45
+ def uninstall(agents:, scope:)
46
+ each_target(agents, scope) do |path|
47
+ content = File.exist?(path) ? File.read(path) : nil
48
+
49
+ if content && Instruction.installed?(content)
50
+ File.write(path, Instruction.remove(content))
51
+ :removed
52
+ else
53
+ :not_installed
54
+ end
55
+ end
56
+ end
57
+
58
+ def status(agents:, scope:)
59
+ each_target(agents, scope) do |path|
60
+ content = File.exist?(path) ? File.read(path) : nil
61
+ content && Instruction.installed?(content) ? :installed : :not_installed
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ # Codex resolves its home from $CODEX_HOME, defaulting to ~/.codex
68
+ def codex_home
69
+ codex_home = @env["CODEX_HOME"]
70
+ codex_home && !codex_home.empty? ? codex_home : File.join(@home, ".codex")
71
+ end
72
+
73
+ def each_target(agents, scope)
74
+ agents.map do |agent|
75
+ path = path_for(agent, scope)
76
+ Result.new(agent, path, yield(path))
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,36 @@
1
+ module AllInRuby
2
+ module Instruction
3
+ BEGIN_MARKER = "<!-- BEGIN all_in_ruby -->".freeze
4
+ END_MARKER = "<!-- END all_in_ruby -->".freeze
5
+
6
+ BODY = <<~MARKDOWN.freeze
7
+ ## Scripts
8
+
9
+ Write throwaway and utility scripts (data munging, one-off migrations,
10
+ file renames, glue code) in Ruby — even in projects written in another
11
+ language. If it needs a pipe, a loop, a conditional, or more than one
12
+ line, it is a script: write it in Ruby, not Python, Node, or bash.
13
+ Single self-contained commands (`grep`, `git status`) are fine as-is.
14
+
15
+ Use only the Ruby standard library. If a gem would clearly save
16
+ significant effort, stop and ask before using it.
17
+
18
+ Put temporary scripts in a scratch or temp directory, not the repo
19
+ root, and delete them when done unless asked to keep them.
20
+ MARKDOWN
21
+
22
+ BLOCK = "#{BEGIN_MARKER}\n#{BODY}#{END_MARKER}\n".freeze
23
+
24
+ def self.block
25
+ BLOCK
26
+ end
27
+
28
+ def self.installed?(content)
29
+ content.include?(BEGIN_MARKER)
30
+ end
31
+
32
+ def self.remove(content)
33
+ content.gsub(/\n?#{Regexp.escape(BEGIN_MARKER)}.*?#{Regexp.escape(END_MARKER)}\n?/m, "\n")
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ module AllInRuby
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,8 @@
1
+ require_relative "all_in_ruby/version"
2
+ require_relative "all_in_ruby/instruction"
3
+ require_relative "all_in_ruby/installer"
4
+ require_relative "all_in_ruby/cli"
5
+
6
+ module AllInRuby
7
+ class Error < StandardError; end
8
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: all_in_ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Lucian Ghinda
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: Adds a 'write throwaway and utility scripts in Ruby' instruction to AI
13
+ agent instruction files (CLAUDE.md for Claude Code, AGENTS.md for Codex), locally
14
+ or globally. Additive and idempotent.
15
+ email: dev@ghinda.com
16
+ executables:
17
+ - all-in-ruby
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - CHANGELOG.md
22
+ - LICENSE.txt
23
+ - README.md
24
+ - exe/all-in-ruby
25
+ - lib/all_in_ruby.rb
26
+ - lib/all_in_ruby/cli.rb
27
+ - lib/all_in_ruby/installer.rb
28
+ - lib/all_in_ruby/instruction.rb
29
+ - lib/all_in_ruby/version.rb
30
+ homepage: https://github.com/lucianghinda/all-in-ruby
31
+ licenses:
32
+ - MIT
33
+ metadata:
34
+ homepage_uri: https://github.com/lucianghinda/all-in-ruby
35
+ source_code_uri: https://github.com/lucianghinda/all-in-ruby
36
+ changelog_uri: https://github.com/lucianghinda/all-in-ruby/blob/main/CHANGELOG.md
37
+ bug_tracker_uri: https://github.com/lucianghinda/all-in-ruby/issues
38
+ rubygems_mfa_required: 'true'
39
+ post_install_message: |
40
+ all_in_ruby installed. To add the Ruby-first instruction to your agents, run:
41
+
42
+ all-in-ruby install # CLAUDE.md + AGENTS.md in the current repo
43
+ all-in-ruby install --global # ~/.claude/CLAUDE.md + ~/.codex/AGENTS.md
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '3.1'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubygems_version: 3.7.2
59
+ specification_version: 4
60
+ summary: Tell your AI coding agents to write scripts in Ruby
61
+ test_files: []