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 +7 -0
- data/CHANGELOG.md +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +94 -0
- data/exe/all-in-ruby +5 -0
- data/lib/all_in_ruby/cli.rb +78 -0
- data/lib/all_in_ruby/installer.rb +80 -0
- data/lib/all_in_ruby/instruction.rb +36 -0
- data/lib/all_in_ruby/version.rb +3 -0
- data/lib/all_in_ruby.rb +8 -0
- metadata +61 -0
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
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,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
|
data/lib/all_in_ruby.rb
ADDED
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: []
|