Module: Tina4::AI
- Defined in:
- lib/tina4/ai.rb
Overview
Tina4 AI – Install AI coding assistant context files.
Simple menu-driven installer for AI tool context files. The user picks which tools they use, we install the appropriate files.
selection = Tina4::AI.(".")
Tina4::AI.install_selected(".", selection)
Constant Summary collapse
- AI_TOOLS =
Ordered list of supported AI tools
[ { name: "claude-code", description: "Claude Code", context_file: "CLAUDE.md", config_dir: ".claude" }, { name: "cursor", description: "Cursor", context_file: ".cursorules", config_dir: ".cursor" }, { name: "copilot", description: "GitHub Copilot", context_file: ".github/copilot-instructions.md", config_dir: ".github" }, { name: "windsurf", description: "Windsurf", context_file: ".windsurfrules", config_dir: nil }, { name: "aider", description: "Aider", context_file: "CONVENTIONS.md", config_dir: nil }, { name: "cline", description: "Cline", context_file: ".clinerules", config_dir: nil }, { name: "codex", description: "OpenAI Codex", context_file: "AGENTS.md", config_dir: nil } ].freeze
Class Method Summary collapse
-
.generate_context(tool_name = "claude-code") ⇒ String
Generate per-tool Tina4 Ruby context document.
-
.install_all(root = ".") ⇒ Array<String>
Install context for all AI tools (non-interactive).
-
.install_claude_skills(root) ⇒ Array<String>
Copy Claude Code skill files from the framework’s templates.
-
.install_for_tool(root, tool, context) ⇒ Array<String>
Install context file for a single tool.
-
.install_selected(root, selection) ⇒ Array<String>
Install context files for the selected tools.
-
.install_tina4_ai ⇒ Object
Install tina4-ai package (provides mdview for markdown viewing).
-
.is_installed(root, tool) ⇒ Boolean
Check if a tool’s context file already exists.
-
.show_menu(root = ".") ⇒ String
Print the numbered menu and return user input.
Class Method Details
.generate_context(tool_name = "claude-code") ⇒ String
Generate per-tool Tina4 Ruby context document.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/tina4/ai.rb', line 111 def generate_context(tool_name = "claude-code") case tool_name when "claude-code" generate_claude_code_context when "cursor" generate_cursor_context when "copilot" generate_copilot_context when "windsurf" generate_windsurf_context when "aider" generate_aider_context when "cline" generate_cline_context when "codex" generate_codex_context else generate_claude_code_context end end |
.install_all(root = ".") ⇒ Array<String>
Install context for all AI tools (non-interactive).
103 104 105 |
# File 'lib/tina4/ai.rb', line 103 def install_all(root = ".") install_selected(root, "all") end |
.install_claude_skills(root) ⇒ Array<String>
Copy Claude Code skill files from the framework’s templates.
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/tina4/ai.rb', line 168 def install_claude_skills(root) created = [] # Determine the framework root (where lib/tina4/ lives) framework_root = File.("../../..", __FILE__) # Copy skill directories from .claude/skills/ in the framework to the project framework_skills_dir = File.join(framework_root, ".claude", "skills") if Dir.exist?(framework_skills_dir) target_skills_dir = File.join(root, ".claude", "skills") FileUtils.mkdir_p(target_skills_dir) Dir.children(framework_skills_dir).each do |entry| skill_dir = File.join(framework_skills_dir, entry) next unless File.directory?(skill_dir) target_dir = File.join(target_skills_dir, entry) FileUtils.rm_rf(target_dir) if Dir.exist?(target_dir) FileUtils.cp_r(skill_dir, target_dir) rel = target_dir.sub("#{root}/", "") created << rel puts " \e[32m✓\e[0m Updated #{rel}" end end # Copy claude-commands if they exist commands_source = File.join(framework_root, "templates", "ai", "claude-commands") if Dir.exist?(commands_source) commands_dir = File.join(root, ".claude", "commands") FileUtils.mkdir_p(commands_dir) Dir.glob(File.join(commands_source, "*.md")).each do |skill_file| target = File.join(commands_dir, File.basename(skill_file)) FileUtils.cp(skill_file, target) rel = target.sub("#{root}/", "") created << rel end end created end |
.install_for_tool(root, tool, context) ⇒ Array<String>
Install context file for a single tool.
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/tina4/ai.rb', line 138 def install_for_tool(root, tool, context) created = [] context_path = File.join(root, tool[:context_file]) # Create directories if tool[:config_dir] FileUtils.mkdir_p(File.join(root, tool[:config_dir])) end FileUtils.mkdir_p(File.dirname(context_path)) # Always overwrite -- user chose to install action = File.exist?(context_path) ? "Updated" : "Installed" File.write(context_path, context) rel = context_path.sub("#{root}/", "") created << rel puts " \e[32m✓\e[0m #{action} #{rel}" # Claude-specific extras if tool[:name] == "claude-code" skills = install_claude_skills(root) created.concat(skills) end created end |
.install_selected(root, selection) ⇒ Array<String>
Install context files for the selected tools.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/tina4/ai.rb', line 66 def install_selected(root, selection) root_path = File.(root) created = [] if selection.downcase == "all" indices = (0...AI_TOOLS.length).to_a do_tina4_ai = true else parts = selection.split(",").map(&:strip).reject(&:empty?) indices = [] do_tina4_ai = false parts.each do |p| n = Integer(p) rescue next if n == 8 do_tina4_ai = true elsif n >= 1 && n <= AI_TOOLS.length indices << (n - 1) end end end indices.each do |idx| tool = AI_TOOLS[idx] context = generate_context(tool[:name]) files = install_for_tool(root_path, tool, context) created.concat(files) end install_tina4_ai if do_tina4_ai created end |
.install_tina4_ai ⇒ Object
Install tina4-ai package (provides mdview for markdown viewing).
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/tina4/ai.rb', line 209 def install_tina4_ai puts " Installing tina4-ai tools..." %w[pip3 pip].each do |cmd| next unless system("which #{cmd} > /dev/null 2>&1") result = `#{cmd} install --upgrade tina4-ai 2>&1` if $?.success? puts " \e[32m✓\e[0m Installed tina4-ai (mdview)" return else puts " \e[33m!\e[0m #{cmd} failed: #{result.strip[0..100]}" end end puts " \e[33m!\e[0m Python/pip not available -- skip tina4-ai" end |
.is_installed(root, tool) ⇒ Boolean
Check if a tool’s context file already exists.
32 33 34 |
# File 'lib/tina4/ai.rb', line 32 def is_installed(root, tool) File.exist?(File.join(File.(root), tool[:context_file])) end |
.show_menu(root = ".") ⇒ String
Print the numbered menu and return user input.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/tina4/ai.rb', line 40 def (root = ".") root = File.(root) green = "\e[32m" reset = "\e[0m" puts "\n Tina4 AI Context Installer\n" AI_TOOLS.each_with_index do |tool, i| marker = is_installed(root, tool) ? " #{green}[installed]#{reset}" : "" puts format(" %d. %-20s %s%s", i + 1, tool[:description], tool[:context_file], marker) end # tina4-ai tools option tina4_ai_installed = system("which mdview > /dev/null 2>&1") marker = tina4_ai_installed ? " #{green}[installed]#{reset}" : "" puts " 8. Install tina4-ai tools (requires Python)#{marker}" puts print " Select (comma-separated, or 'all'): " $stdin.gets&.strip || "" end |