clacky 0.5.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/.clackyrules +80 -0
- data/.rspec +3 -0
- data/.rubocop.yml +8 -0
- data/CHANGELOG.md +74 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +21 -0
- data/README.md +272 -0
- data/Rakefile +12 -0
- data/lib/clacky/agent.rb +964 -0
- data/lib/clacky/agent_config.rb +47 -0
- data/lib/clacky/cli.rb +666 -0
- data/lib/clacky/client.rb +159 -0
- data/lib/clacky/config.rb +43 -0
- data/lib/clacky/conversation.rb +41 -0
- data/lib/clacky/hook_manager.rb +61 -0
- data/lib/clacky/progress_indicator.rb +53 -0
- data/lib/clacky/session_manager.rb +124 -0
- data/lib/clacky/thinking_verbs.rb +26 -0
- data/lib/clacky/tool_registry.rb +44 -0
- data/lib/clacky/tools/base.rb +64 -0
- data/lib/clacky/tools/edit.rb +100 -0
- data/lib/clacky/tools/file_reader.rb +79 -0
- data/lib/clacky/tools/glob.rb +93 -0
- data/lib/clacky/tools/grep.rb +169 -0
- data/lib/clacky/tools/run_project.rb +287 -0
- data/lib/clacky/tools/safe_shell.rb +397 -0
- data/lib/clacky/tools/shell.rb +305 -0
- data/lib/clacky/tools/todo_manager.rb +228 -0
- data/lib/clacky/tools/trash_manager.rb +367 -0
- data/lib/clacky/tools/web_fetch.rb +161 -0
- data/lib/clacky/tools/web_search.rb +138 -0
- data/lib/clacky/tools/write.rb +65 -0
- data/lib/clacky/utils/arguments_parser.rb +139 -0
- data/lib/clacky/utils/limit_stack.rb +80 -0
- data/lib/clacky/utils/path_helper.rb +15 -0
- data/lib/clacky/version.rb +5 -0
- data/lib/clacky.rb +38 -0
- data/sig/clacky.rbs +4 -0
- metadata +152 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Clacky
|
|
4
|
+
module Tools
|
|
5
|
+
class Write < Base
|
|
6
|
+
self.tool_name = "write"
|
|
7
|
+
self.tool_description = "Write content to a file. Creates new files or overwrites existing ones."
|
|
8
|
+
self.tool_category = "file_system"
|
|
9
|
+
self.tool_parameters = {
|
|
10
|
+
type: "object",
|
|
11
|
+
properties: {
|
|
12
|
+
path: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "The path of the file to write (absolute or relative)"
|
|
15
|
+
},
|
|
16
|
+
content: {
|
|
17
|
+
type: "string",
|
|
18
|
+
description: "The content to write to the file"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
required: %w[path content]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
def execute(path:, content:)
|
|
25
|
+
# Validate path
|
|
26
|
+
if path.nil? || path.strip.empty?
|
|
27
|
+
return { error: "Path cannot be empty" }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
begin
|
|
31
|
+
# Ensure parent directory exists
|
|
32
|
+
dir = File.dirname(path)
|
|
33
|
+
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
|
|
34
|
+
|
|
35
|
+
# Write content to file
|
|
36
|
+
File.write(path, content)
|
|
37
|
+
|
|
38
|
+
{
|
|
39
|
+
path: File.expand_path(path),
|
|
40
|
+
bytes_written: content.bytesize,
|
|
41
|
+
error: nil
|
|
42
|
+
}
|
|
43
|
+
rescue Errno::EACCES => e
|
|
44
|
+
{ error: "Permission denied: #{e.message}" }
|
|
45
|
+
rescue Errno::ENOSPC => e
|
|
46
|
+
{ error: "No space left on device: #{e.message}" }
|
|
47
|
+
rescue StandardError => e
|
|
48
|
+
{ error: "Failed to write file: #{e.message}" }
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def format_call(args)
|
|
53
|
+
path = args[:path] || args['path']
|
|
54
|
+
"Write(#{Utils::PathHelper.safe_basename(path)})"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def format_result(result)
|
|
58
|
+
return result[:error] if result[:error]
|
|
59
|
+
|
|
60
|
+
bytes = result[:bytes_written] || result['bytes_written'] || 0
|
|
61
|
+
"Written #{bytes} bytes"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module Clacky
|
|
6
|
+
module Utils
|
|
7
|
+
class ArgumentsParser
|
|
8
|
+
# Parse and validate tool call arguments with JSON repair capability
|
|
9
|
+
def self.parse_and_validate(call, tool_registry)
|
|
10
|
+
# 1. Try standard parsing
|
|
11
|
+
begin
|
|
12
|
+
args = JSON.parse(call[:arguments], symbolize_names: true)
|
|
13
|
+
return validate_required_params(call, args, tool_registry)
|
|
14
|
+
rescue JSON::ParserError => e
|
|
15
|
+
# Continue to repair
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# 2. Try simple repair
|
|
19
|
+
repaired = repair_json(call[:arguments])
|
|
20
|
+
|
|
21
|
+
begin
|
|
22
|
+
args = JSON.parse(repaired, symbolize_names: true)
|
|
23
|
+
return validate_required_params(call, args, tool_registry)
|
|
24
|
+
rescue JSON::ParserError, MissingRequiredParamsError => e
|
|
25
|
+
# 3. Repair failed or missing params, return helpful error
|
|
26
|
+
raise_helpful_error(call, tool_registry, e)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
# Simple JSON repair: complete brackets and quotes
|
|
33
|
+
def self.repair_json(json_str)
|
|
34
|
+
result = json_str.strip
|
|
35
|
+
|
|
36
|
+
# Complete unclosed strings
|
|
37
|
+
result += '"' if result.count('"').odd?
|
|
38
|
+
|
|
39
|
+
# Complete unclosed braces
|
|
40
|
+
depth = 0
|
|
41
|
+
result.each_char { |c| depth += 1 if c == '{'; depth -= 1 if c == '}' }
|
|
42
|
+
result += '}' * depth if depth > 0
|
|
43
|
+
|
|
44
|
+
result
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Validate required parameters
|
|
48
|
+
def self.validate_required_params(call, args, tool_registry)
|
|
49
|
+
tool = tool_registry.get(call[:name])
|
|
50
|
+
required = tool.parameters&.dig(:required) || []
|
|
51
|
+
|
|
52
|
+
missing = required.reject { |param|
|
|
53
|
+
args.key?(param.to_sym) || args.key?(param.to_s)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if missing.any?
|
|
57
|
+
raise MissingRequiredParamsError.new(call[:name], missing, args.keys)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
args
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Generate error message with tool definition
|
|
64
|
+
def self.raise_helpful_error(call, tool_registry, original_error)
|
|
65
|
+
tool = tool_registry.get(call[:name])
|
|
66
|
+
error_msg = build_error_message(call, tool, original_error)
|
|
67
|
+
raise StandardError, error_msg
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def self.build_error_message(call, tool, original_error)
|
|
71
|
+
# Extract tool information
|
|
72
|
+
required_params = tool.parameters&.dig(:required) || []
|
|
73
|
+
|
|
74
|
+
# Try to parse provided parameters from incomplete JSON
|
|
75
|
+
provided_params = extract_provided_params(call[:arguments])
|
|
76
|
+
|
|
77
|
+
# Build clear error message
|
|
78
|
+
msg = []
|
|
79
|
+
msg << "Failed to parse arguments for tool '#{call[:name]}'."
|
|
80
|
+
msg << ""
|
|
81
|
+
msg << "Error: #{original_error.message}"
|
|
82
|
+
msg << ""
|
|
83
|
+
|
|
84
|
+
if provided_params.any?
|
|
85
|
+
msg << "Provided parameters: #{provided_params.join(', ')}"
|
|
86
|
+
else
|
|
87
|
+
msg << "No valid parameters could be extracted."
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
msg << "Required parameters: #{required_params.join(', ')}"
|
|
91
|
+
msg << ""
|
|
92
|
+
msg << "Tool definition:"
|
|
93
|
+
msg << format_tool_definition(tool)
|
|
94
|
+
msg << ""
|
|
95
|
+
msg << "Suggestions:"
|
|
96
|
+
msg << "- If the parameter value is too large (e.g., large file content), consider breaking it into smaller operations"
|
|
97
|
+
msg << "- Ensure all required parameters are provided"
|
|
98
|
+
msg << "- Simplify complex parameter values"
|
|
99
|
+
|
|
100
|
+
msg.join("\n")
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Extract parameter names from incomplete JSON
|
|
104
|
+
def self.extract_provided_params(json_str)
|
|
105
|
+
# Simple extraction: find all "key": patterns
|
|
106
|
+
json_str.scan(/"(\w+)"\s*:/).flatten.uniq
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Format tool definition (concise version)
|
|
110
|
+
def self.format_tool_definition(tool)
|
|
111
|
+
lines = []
|
|
112
|
+
lines << " Name: #{tool.name}"
|
|
113
|
+
lines << " Description: #{tool.description}"
|
|
114
|
+
|
|
115
|
+
if tool.parameters[:properties]
|
|
116
|
+
lines << " Parameters:"
|
|
117
|
+
tool.parameters[:properties].each do |param, spec|
|
|
118
|
+
required_mark = tool.parameters[:required]&.include?(param.to_s) ? " (required)" : ""
|
|
119
|
+
lines << " - #{param}#{required_mark}: #{spec[:description]}"
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
lines.join("\n")
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Custom exception for missing required parameters
|
|
128
|
+
class MissingRequiredParamsError < StandardError
|
|
129
|
+
attr_reader :tool_name, :missing_params, :provided_params
|
|
130
|
+
|
|
131
|
+
def initialize(tool_name, missing_params, provided_params)
|
|
132
|
+
@tool_name = tool_name
|
|
133
|
+
@missing_params = missing_params
|
|
134
|
+
@provided_params = provided_params
|
|
135
|
+
super("Missing required parameters: #{missing_params.join(', ')}")
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Clacky
|
|
4
|
+
module Utils
|
|
5
|
+
# Auto-rolling fixed-size array
|
|
6
|
+
# Automatically discards oldest elements when size limit is exceeded
|
|
7
|
+
class LimitStack
|
|
8
|
+
attr_reader :max_size, :items
|
|
9
|
+
|
|
10
|
+
def initialize(max_size: 5000)
|
|
11
|
+
@max_size = max_size
|
|
12
|
+
@items = []
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Add elements (supports single or multiple)
|
|
16
|
+
def push(*elements)
|
|
17
|
+
elements.each do |element|
|
|
18
|
+
@items << element
|
|
19
|
+
trim_if_needed
|
|
20
|
+
end
|
|
21
|
+
self
|
|
22
|
+
end
|
|
23
|
+
alias_method :<<, :push
|
|
24
|
+
|
|
25
|
+
# Add multi-line text (split by lines and add)
|
|
26
|
+
def push_lines(text)
|
|
27
|
+
return self if text.nil? || text.empty?
|
|
28
|
+
|
|
29
|
+
lines = text.is_a?(Array) ? text : text.lines
|
|
30
|
+
lines.each { |line| push(line) }
|
|
31
|
+
self
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Get last N elements
|
|
35
|
+
def last(n = nil)
|
|
36
|
+
n ? @items.last(n) : @items.last
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Get all elements
|
|
40
|
+
def to_a
|
|
41
|
+
@items.dup
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Convert to string (for text content)
|
|
45
|
+
def to_s
|
|
46
|
+
@items.join
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Current size
|
|
50
|
+
def size
|
|
51
|
+
@items.size
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Check if empty
|
|
55
|
+
def empty?
|
|
56
|
+
@items.empty?
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Clear all elements
|
|
60
|
+
def clear
|
|
61
|
+
@items.clear
|
|
62
|
+
self
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Iterate over elements
|
|
66
|
+
def each(&block)
|
|
67
|
+
@items.each(&block)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def trim_if_needed
|
|
73
|
+
if @items.size > @max_size
|
|
74
|
+
# Remove oldest elements, keep only the latest max_size items
|
|
75
|
+
@items.shift(@items.size - @max_size)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Clacky
|
|
4
|
+
module Utils
|
|
5
|
+
module PathHelper
|
|
6
|
+
# Safely get basename from path, return placeholder if path is nil
|
|
7
|
+
def self.safe_basename(path, placeholder: "?")
|
|
8
|
+
return placeholder if path.nil? || path.to_s.empty?
|
|
9
|
+
File.basename(path.to_s)
|
|
10
|
+
rescue StandardError
|
|
11
|
+
placeholder
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/lib/clacky.rb
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "clacky/version"
|
|
4
|
+
require_relative "clacky/config"
|
|
5
|
+
require_relative "clacky/client"
|
|
6
|
+
require_relative "clacky/conversation"
|
|
7
|
+
|
|
8
|
+
# Agent system
|
|
9
|
+
require_relative "clacky/agent_config"
|
|
10
|
+
require_relative "clacky/hook_manager"
|
|
11
|
+
require_relative "clacky/tool_registry"
|
|
12
|
+
require_relative "clacky/thinking_verbs"
|
|
13
|
+
require_relative "clacky/progress_indicator"
|
|
14
|
+
require_relative "clacky/session_manager"
|
|
15
|
+
require_relative "clacky/utils/limit_stack"
|
|
16
|
+
require_relative "clacky/utils/path_helper"
|
|
17
|
+
require_relative "clacky/tools/base"
|
|
18
|
+
|
|
19
|
+
require_relative "clacky/tools/shell"
|
|
20
|
+
require_relative "clacky/tools/file_reader"
|
|
21
|
+
require_relative "clacky/tools/write"
|
|
22
|
+
require_relative "clacky/tools/edit"
|
|
23
|
+
require_relative "clacky/tools/glob"
|
|
24
|
+
require_relative "clacky/tools/grep"
|
|
25
|
+
require_relative "clacky/tools/web_search"
|
|
26
|
+
require_relative "clacky/tools/web_fetch"
|
|
27
|
+
require_relative "clacky/tools/todo_manager"
|
|
28
|
+
require_relative "clacky/tools/run_project"
|
|
29
|
+
require_relative "clacky/tools/safe_shell"
|
|
30
|
+
require_relative "clacky/tools/trash_manager"
|
|
31
|
+
require_relative "clacky/agent"
|
|
32
|
+
|
|
33
|
+
require_relative "clacky/cli"
|
|
34
|
+
|
|
35
|
+
module Clacky
|
|
36
|
+
class Error < StandardError; end
|
|
37
|
+
class AgentInterrupted < StandardError; end
|
|
38
|
+
end
|
data/sig/clacky.rbs
ADDED
metadata
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: clacky
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.5.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- windy
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: faraday
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: thor
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '1.3'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.3'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: tty-prompt
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0.23'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0.23'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: tty-spinner
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0.9'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0.9'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: diffy
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '3.4'
|
|
75
|
+
type: :runtime
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '3.4'
|
|
82
|
+
description: Clacky is a Ruby CLI tool for interacting with Claude AI API, providing
|
|
83
|
+
an easy way to have conversations with Claude from your terminal.
|
|
84
|
+
email:
|
|
85
|
+
- yafei@dao42.com
|
|
86
|
+
executables: []
|
|
87
|
+
extensions: []
|
|
88
|
+
extra_rdoc_files: []
|
|
89
|
+
files:
|
|
90
|
+
- ".clackyrules"
|
|
91
|
+
- ".rspec"
|
|
92
|
+
- ".rubocop.yml"
|
|
93
|
+
- CHANGELOG.md
|
|
94
|
+
- CODE_OF_CONDUCT.md
|
|
95
|
+
- LICENSE.txt
|
|
96
|
+
- README.md
|
|
97
|
+
- Rakefile
|
|
98
|
+
- lib/clacky.rb
|
|
99
|
+
- lib/clacky/agent.rb
|
|
100
|
+
- lib/clacky/agent_config.rb
|
|
101
|
+
- lib/clacky/cli.rb
|
|
102
|
+
- lib/clacky/client.rb
|
|
103
|
+
- lib/clacky/config.rb
|
|
104
|
+
- lib/clacky/conversation.rb
|
|
105
|
+
- lib/clacky/hook_manager.rb
|
|
106
|
+
- lib/clacky/progress_indicator.rb
|
|
107
|
+
- lib/clacky/session_manager.rb
|
|
108
|
+
- lib/clacky/thinking_verbs.rb
|
|
109
|
+
- lib/clacky/tool_registry.rb
|
|
110
|
+
- lib/clacky/tools/base.rb
|
|
111
|
+
- lib/clacky/tools/edit.rb
|
|
112
|
+
- lib/clacky/tools/file_reader.rb
|
|
113
|
+
- lib/clacky/tools/glob.rb
|
|
114
|
+
- lib/clacky/tools/grep.rb
|
|
115
|
+
- lib/clacky/tools/run_project.rb
|
|
116
|
+
- lib/clacky/tools/safe_shell.rb
|
|
117
|
+
- lib/clacky/tools/shell.rb
|
|
118
|
+
- lib/clacky/tools/todo_manager.rb
|
|
119
|
+
- lib/clacky/tools/trash_manager.rb
|
|
120
|
+
- lib/clacky/tools/web_fetch.rb
|
|
121
|
+
- lib/clacky/tools/web_search.rb
|
|
122
|
+
- lib/clacky/tools/write.rb
|
|
123
|
+
- lib/clacky/utils/arguments_parser.rb
|
|
124
|
+
- lib/clacky/utils/limit_stack.rb
|
|
125
|
+
- lib/clacky/utils/path_helper.rb
|
|
126
|
+
- lib/clacky/version.rb
|
|
127
|
+
- sig/clacky.rbs
|
|
128
|
+
homepage: https://github.com/yafeilee/clacky
|
|
129
|
+
licenses:
|
|
130
|
+
- MIT
|
|
131
|
+
metadata:
|
|
132
|
+
homepage_uri: https://github.com/yafeilee/clacky
|
|
133
|
+
source_code_uri: https://github.com/yafeilee/clacky
|
|
134
|
+
changelog_uri: https://github.com/yafeilee/clacky/blob/main/CHANGELOG.md
|
|
135
|
+
rdoc_options: []
|
|
136
|
+
require_paths:
|
|
137
|
+
- lib
|
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
139
|
+
requirements:
|
|
140
|
+
- - ">="
|
|
141
|
+
- !ruby/object:Gem::Version
|
|
142
|
+
version: 3.1.0
|
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
144
|
+
requirements:
|
|
145
|
+
- - ">="
|
|
146
|
+
- !ruby/object:Gem::Version
|
|
147
|
+
version: '0'
|
|
148
|
+
requirements: []
|
|
149
|
+
rubygems_version: 3.6.9
|
|
150
|
+
specification_version: 4
|
|
151
|
+
summary: A command-line interface for Claude AI
|
|
152
|
+
test_files: []
|