aircana 4.0.0.rc2 → 4.0.0.rc4
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 +4 -4
- data/.rspec_status +183 -199
- data/CLAUDE.md +37 -31
- data/README.md +4 -13
- data/lib/aircana/cli/app.rb +0 -31
- data/lib/aircana/cli/commands/generate.rb +19 -14
- data/lib/aircana/cli/commands/init.rb +16 -37
- data/lib/aircana/cli/commands/kb.rb +12 -2
- data/lib/aircana/cli/help_formatter.rb +1 -2
- data/lib/aircana/configuration.rb +12 -1
- data/lib/aircana/generators/hooks_generator.rb +2 -2
- data/lib/aircana/templates/hooks/refresh_skills.erb +121 -0
- data/lib/aircana/version.rb +1 -1
- metadata +4 -11
- data/commands/apply-feedback.md +0 -15
- data/commands/ask-expert.md +0 -42
- data/commands/execute.md +0 -13
- data/commands/plan.md +0 -33
- data/commands/record.md +0 -17
- data/commands/review.md +0 -12
- data/hooks/hooks.json +0 -31
- data/lib/aircana/cli/commands/hooks.rb +0 -276
data/README.md
CHANGED
@@ -549,15 +549,15 @@ export AWS_REGION="us-east-1"
|
|
549
549
|
|
550
550
|
The message template supports `{{message}}` placeholder which gets replaced with the Claude Code notification text.
|
551
551
|
|
552
|
-
#### 3.
|
552
|
+
#### 3. Initialize Plugin
|
553
|
+
|
554
|
+
The notification_sqs hook is automatically generated when you initialize your plugin:
|
553
555
|
|
554
556
|
```bash
|
555
|
-
aircana generate
|
556
557
|
aircana init
|
557
|
-
aircana hooks enable notification_sqs
|
558
558
|
```
|
559
559
|
|
560
|
-
|
560
|
+
The hook will be automatically enabled and ready to use.
|
561
561
|
|
562
562
|
### Verify Configuration
|
563
563
|
|
@@ -590,15 +590,6 @@ aircana kb add-url [KB-NAME] [URL] # Add a web URL to a knowledge base
|
|
590
590
|
aircana kb list # List all configured knowledge bases
|
591
591
|
```
|
592
592
|
|
593
|
-
### Hook Management
|
594
|
-
```bash
|
595
|
-
aircana hooks list # List all available and installed hooks
|
596
|
-
aircana hooks enable [HOOK] # Enable a specific hook
|
597
|
-
aircana hooks disable [HOOK] # Disable a specific hook
|
598
|
-
aircana hooks create # Create custom hook
|
599
|
-
aircana hooks status # Show hook configuration status
|
600
|
-
```
|
601
|
-
|
602
593
|
### System
|
603
594
|
```bash
|
604
595
|
aircana generate # Generate plugin components from templates
|
data/lib/aircana/cli/app.rb
CHANGED
@@ -10,7 +10,6 @@ require_relative "commands/init"
|
|
10
10
|
require_relative "subcommand"
|
11
11
|
require_relative "help_formatter"
|
12
12
|
require_relative "commands/kb"
|
13
|
-
require_relative "commands/hooks"
|
14
13
|
require_relative "commands/plugin"
|
15
14
|
|
16
15
|
module Aircana
|
@@ -74,39 +73,9 @@ module Aircana
|
|
74
73
|
end
|
75
74
|
end
|
76
75
|
|
77
|
-
class HooksSubcommand < Subcommand
|
78
|
-
desc "list", "List all available and installed hooks"
|
79
|
-
def list
|
80
|
-
Hooks.list
|
81
|
-
end
|
82
|
-
|
83
|
-
desc "enable HOOK_NAME", "Enable a specific hook"
|
84
|
-
def enable(hook_name)
|
85
|
-
Hooks.enable(hook_name)
|
86
|
-
end
|
87
|
-
|
88
|
-
desc "disable HOOK_NAME", "Disable a specific hook"
|
89
|
-
def disable(hook_name)
|
90
|
-
Hooks.disable(hook_name)
|
91
|
-
end
|
92
|
-
|
93
|
-
desc "create", "Create a new custom hook"
|
94
|
-
def create
|
95
|
-
Hooks.create
|
96
|
-
end
|
97
|
-
|
98
|
-
desc "status", "Show current hook configuration status"
|
99
|
-
def status
|
100
|
-
Hooks.status
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
76
|
desc "kb", "Create and manage knowledge bases for Claude Code skills"
|
105
77
|
subcommand "kb", KBSubcommand
|
106
78
|
|
107
|
-
desc "hooks", "Manage Claude Code hooks"
|
108
|
-
subcommand "hooks", HooksSubcommand
|
109
|
-
|
110
79
|
class PluginSubcommand < Subcommand
|
111
80
|
desc "info", "Display plugin information"
|
112
81
|
def info
|
@@ -1,11 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require_relative "../../generators/
|
5
|
-
require_relative "../../generators/
|
6
|
-
require_relative "../../generators/
|
7
|
-
require_relative "../../generators/
|
8
|
-
require_relative "../../generators/
|
3
|
+
# Commands that reference old agent system - commented out for now
|
4
|
+
# require_relative "../../generators/plan_command_generator"
|
5
|
+
# require_relative "../../generators/record_command_generator"
|
6
|
+
# require_relative "../../generators/execute_command_generator"
|
7
|
+
# require_relative "../../generators/review_command_generator"
|
8
|
+
# require_relative "../../generators/apply_feedback_command_generator"
|
9
|
+
# require_relative "../../generators/ask_expert_command_generator"
|
9
10
|
require_relative "../../generators/hooks_generator"
|
10
11
|
|
11
12
|
module Aircana
|
@@ -13,14 +14,18 @@ module Aircana
|
|
13
14
|
module Generate
|
14
15
|
class << self
|
15
16
|
def generators
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
# No default commands for now - they referenced the old agent system
|
18
|
+
@generators ||= []
|
19
|
+
|
20
|
+
# TODO: Re-enable these when we have a new command system
|
21
|
+
# @generators ||= [
|
22
|
+
# Aircana::Generators::PlanCommandGenerator.new,
|
23
|
+
# Aircana::Generators::RecordCommandGenerator.new,
|
24
|
+
# Aircana::Generators::ExecuteCommandGenerator.new,
|
25
|
+
# Aircana::Generators::ReviewCommandGenerator.new,
|
26
|
+
# Aircana::Generators::ApplyFeedbackCommandGenerator.new,
|
27
|
+
# Aircana::Generators::AskExpertCommandGenerator.new
|
28
|
+
# ]
|
24
29
|
end
|
25
30
|
|
26
31
|
def run
|
@@ -57,10 +57,10 @@ module Aircana
|
|
57
57
|
Aircana.configuration.instance_variable_set(:@plugin_manifest_dir,
|
58
58
|
File.join(target_dir, ".claude-plugin"))
|
59
59
|
Aircana.configuration.instance_variable_set(:@commands_dir, File.join(target_dir, "commands"))
|
60
|
-
Aircana.configuration.instance_variable_set(:@
|
60
|
+
Aircana.configuration.instance_variable_set(:@skills_dir, File.join(target_dir, "skills"))
|
61
|
+
Aircana.configuration.instance_variable_set(:@kb_knowledge_dir, File.join(target_dir, "skills"))
|
61
62
|
Aircana.configuration.instance_variable_set(:@hooks_dir, File.join(target_dir, "hooks"))
|
62
63
|
Aircana.configuration.instance_variable_set(:@scripts_dir, File.join(target_dir, "scripts"))
|
63
|
-
Aircana.configuration.instance_variable_set(:@agent_knowledge_dir, File.join(target_dir, "agents"))
|
64
64
|
|
65
65
|
yield
|
66
66
|
ensure
|
@@ -71,11 +71,17 @@ module Aircana
|
|
71
71
|
File.join(original_plugin_root, ".claude-plugin"))
|
72
72
|
Aircana.configuration.instance_variable_set(:@commands_dir,
|
73
73
|
File.join(original_plugin_root, "commands"))
|
74
|
-
|
74
|
+
# Restore skills_dir based on whether original_plugin_root is a plugin
|
75
|
+
original_plugin_mode = File.exist?(File.join(original_plugin_root, ".claude-plugin", "plugin.json"))
|
76
|
+
original_skills_dir = if original_plugin_mode
|
77
|
+
File.join(original_plugin_root, "skills")
|
78
|
+
else
|
79
|
+
File.join(original_plugin_root, ".claude", "skills")
|
80
|
+
end
|
81
|
+
Aircana.configuration.instance_variable_set(:@skills_dir, original_skills_dir)
|
82
|
+
Aircana.configuration.instance_variable_set(:@kb_knowledge_dir, original_skills_dir)
|
75
83
|
Aircana.configuration.instance_variable_set(:@hooks_dir, File.join(original_plugin_root, "hooks"))
|
76
84
|
Aircana.configuration.instance_variable_set(:@scripts_dir, File.join(original_plugin_root, "scripts"))
|
77
|
-
Aircana.configuration.instance_variable_set(:@agent_knowledge_dir,
|
78
|
-
File.join(original_plugin_root, "agents"))
|
79
85
|
end
|
80
86
|
end
|
81
87
|
|
@@ -109,7 +115,7 @@ module Aircana
|
|
109
115
|
|
110
116
|
def create_plugin_structure(target_dir)
|
111
117
|
# Create plugin directories
|
112
|
-
[".claude-plugin", "commands", "agents", "hooks", "scripts"].each do |dir|
|
118
|
+
[".claude-plugin", "commands", "agents", "skills", "hooks", "scripts"].each do |dir|
|
113
119
|
dir_path = File.join(target_dir, dir)
|
114
120
|
Aircana.create_dir_if_needed(dir_path)
|
115
121
|
Aircana.human_logger.info("Created directory: #{dir}/")
|
@@ -132,7 +138,6 @@ module Aircana
|
|
132
138
|
Aircana.create_dir_if_needed(commands_dir)
|
133
139
|
|
134
140
|
copy_command_files(commands_dir)
|
135
|
-
install_default_agents
|
136
141
|
end
|
137
142
|
|
138
143
|
def copy_command_files(destination_dir)
|
@@ -142,33 +147,6 @@ module Aircana
|
|
142
147
|
end
|
143
148
|
end
|
144
149
|
|
145
|
-
def install_default_agents
|
146
|
-
agents_dir = Aircana.configuration.agents_dir
|
147
|
-
Aircana.create_dir_if_needed(agents_dir)
|
148
|
-
|
149
|
-
copy_agent_files(agents_dir)
|
150
|
-
end
|
151
|
-
|
152
|
-
def copy_agent_files(destination_dir)
|
153
|
-
agent_files_pattern = File.join(Aircana.configuration.output_dir, "agents", "*.md")
|
154
|
-
Dir.glob(agent_files_pattern).each do |file|
|
155
|
-
agent_name = File.basename(file, ".md")
|
156
|
-
next unless default_agent?(agent_name)
|
157
|
-
|
158
|
-
destination_file = File.join(destination_dir, File.basename(file))
|
159
|
-
# Skip copying if source and destination are the same
|
160
|
-
next if File.expand_path(file) == File.expand_path(destination_file)
|
161
|
-
|
162
|
-
Aircana.human_logger.success("Installing default agent: #{agent_name}")
|
163
|
-
FileUtils.cp(file, destination_dir)
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
def default_agent?(agent_name)
|
168
|
-
require_relative "../../generators/agents_generator"
|
169
|
-
Aircana::Generators::AgentsGenerator.available_default_agents.include?(agent_name)
|
170
|
-
end
|
171
|
-
|
172
150
|
def install_hooks
|
173
151
|
scripts_dir = Aircana.configuration.scripts_dir
|
174
152
|
return unless Dir.exist?(scripts_dir)
|
@@ -201,7 +179,7 @@ module Aircana
|
|
201
179
|
"post_tool_use" => { event: "PostToolUse", matcher: nil },
|
202
180
|
"user_prompt_submit" => { event: "UserPromptSubmit", matcher: nil },
|
203
181
|
"session_start" => { event: "SessionStart", matcher: nil },
|
204
|
-
"
|
182
|
+
"refresh_skills" => { event: "SessionStart", matcher: nil },
|
205
183
|
"notification_sqs" => { event: "Notification", matcher: nil },
|
206
184
|
"rubocop_pre_commit" => { event: "PreToolUse", matcher: "Bash" },
|
207
185
|
"rspec_test" => { event: "PostToolUse", matcher: "Bash" },
|
@@ -265,11 +243,12 @@ module Aircana
|
|
265
243
|
Aircana.human_logger.info("\nPlugin structure:")
|
266
244
|
Aircana.human_logger.info(" .claude-plugin/plugin.json - Plugin metadata")
|
267
245
|
Aircana.human_logger.info(" commands/ - Slash commands")
|
268
|
-
Aircana.human_logger.info(" agents/ -
|
246
|
+
Aircana.human_logger.info(" agents/ - Knowledge base manifests")
|
247
|
+
Aircana.human_logger.info(" skills/ - Knowledge base SKILL.md files")
|
269
248
|
Aircana.human_logger.info(" hooks/ - Event hook configurations")
|
270
249
|
Aircana.human_logger.info(" scripts/ - Hook scripts and utilities")
|
271
250
|
Aircana.human_logger.info("\nNext steps:")
|
272
|
-
Aircana.human_logger.info(" - Create
|
251
|
+
Aircana.human_logger.info(" - Create knowledge bases: aircana kb create")
|
273
252
|
Aircana.human_logger.info(" - Install plugin in Claude Code")
|
274
253
|
Aircana.human_logger.info(" - Run: aircana plugin info")
|
275
254
|
end
|
@@ -284,11 +284,21 @@ module Aircana
|
|
284
284
|
end
|
285
285
|
|
286
286
|
def remote_knowledge_pattern
|
287
|
-
|
287
|
+
# Pattern depends on whether we're in a plugin
|
288
|
+
if Aircana.configuration.plugin_mode?
|
289
|
+
"skills/*/*.md"
|
290
|
+
else
|
291
|
+
".claude/skills/*/*.md"
|
292
|
+
end
|
288
293
|
end
|
289
294
|
|
290
295
|
def local_knowledge_negation_pattern
|
291
|
-
|
296
|
+
# Negation pattern depends on whether we're in a plugin
|
297
|
+
if Aircana.configuration.plugin_mode?
|
298
|
+
"!skills/*/*.md"
|
299
|
+
else
|
300
|
+
"!.claude/skills/*/*.md"
|
301
|
+
end
|
292
302
|
end
|
293
303
|
|
294
304
|
def gitignore_has_pattern?(gitignore_path, pattern)
|
@@ -69,17 +69,28 @@ module Aircana
|
|
69
69
|
@output_dir = File.join(@global_dir, "aircana.out")
|
70
70
|
end
|
71
71
|
|
72
|
+
# rubocop:disable Metrics/MethodLength
|
72
73
|
def setup_plugin_paths
|
73
74
|
# Plugin root can be set via AIRCANA_PLUGIN_ROOT (for hooks) or CLAUDE_PLUGIN_ROOT,
|
74
75
|
# otherwise defaults to the current project directory
|
75
76
|
@plugin_root = ENV.fetch("AIRCANA_PLUGIN_ROOT", ENV.fetch("CLAUDE_PLUGIN_ROOT", @project_dir))
|
76
77
|
@plugin_manifest_dir = File.join(@plugin_root, ".claude-plugin")
|
77
78
|
@commands_dir = File.join(@plugin_root, "commands")
|
78
|
-
|
79
|
+
|
80
|
+
# Skills directory location depends on whether we're in a plugin
|
81
|
+
# Plugin mode: skills/ (Claude Code standard location)
|
82
|
+
# Non-plugin mode: .claude/skills/ (local development/one-off usage)
|
83
|
+
@skills_dir = if plugin_mode?
|
84
|
+
File.join(@plugin_root, "skills")
|
85
|
+
else
|
86
|
+
File.join(@plugin_root, ".claude", "skills")
|
87
|
+
end
|
88
|
+
|
79
89
|
@hooks_dir = File.join(@plugin_root, "hooks")
|
80
90
|
@scripts_dir = File.join(@plugin_root, "scripts")
|
81
91
|
@kb_knowledge_dir = @skills_dir
|
82
92
|
end
|
93
|
+
# rubocop:enable Metrics/MethodLength
|
83
94
|
|
84
95
|
def setup_claude_code_paths
|
85
96
|
@claude_code_config_path = File.join(Dir.home, ".claude")
|
@@ -11,7 +11,7 @@ module Aircana
|
|
11
11
|
post_tool_use
|
12
12
|
user_prompt_submit
|
13
13
|
session_start
|
14
|
-
|
14
|
+
refresh_skills
|
15
15
|
notification_sqs
|
16
16
|
rubocop_pre_commit
|
17
17
|
rspec_test
|
@@ -21,7 +21,7 @@ module Aircana
|
|
21
21
|
# Default hooks that are auto-installed
|
22
22
|
DEFAULT_HOOK_TYPES = %w[
|
23
23
|
session_start
|
24
|
-
|
24
|
+
refresh_skills
|
25
25
|
notification_sqs
|
26
26
|
].freeze
|
27
27
|
|
@@ -0,0 +1,121 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
# Auto-refresh remote knowledge bases on session start
|
3
|
+
# Runs at most once per 24 hours to avoid API rate limits
|
4
|
+
# Only refreshes remote KBs, skips local KBs
|
5
|
+
|
6
|
+
set -e
|
7
|
+
|
8
|
+
# Create log directory if it doesn't exist
|
9
|
+
mkdir -p ~/.aircana
|
10
|
+
LOG_FILE="$HOME/.aircana/hooks.log"
|
11
|
+
|
12
|
+
# Claude Code provides this environment variable
|
13
|
+
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT}"
|
14
|
+
|
15
|
+
if [ -z "$PLUGIN_ROOT" ]; then
|
16
|
+
echo "$(date): Warning - CLAUDE_PLUGIN_ROOT not set, skipping KB refresh" >> "$LOG_FILE"
|
17
|
+
echo "{}"
|
18
|
+
exit 0
|
19
|
+
fi
|
20
|
+
|
21
|
+
TIMESTAMP_FILE="${PLUGIN_ROOT}/.last_refresh"
|
22
|
+
REFRESH_INTERVAL_SECONDS=86400 # 24 hours
|
23
|
+
|
24
|
+
# Check if we've refreshed recently
|
25
|
+
if [ -f "$TIMESTAMP_FILE" ]; then
|
26
|
+
LAST_REFRESH=$(cat "$TIMESTAMP_FILE")
|
27
|
+
CURRENT_TIME=$(date +%s)
|
28
|
+
TIME_DIFF=$((CURRENT_TIME - LAST_REFRESH))
|
29
|
+
|
30
|
+
if [ $TIME_DIFF -lt $REFRESH_INTERVAL_SECONDS ]; then
|
31
|
+
HOURS_SINCE=$((TIME_DIFF / 3600))
|
32
|
+
echo "$(date): Knowledge bases refreshed ${HOURS_SINCE}h ago, skipping refresh" >> "$LOG_FILE"
|
33
|
+
echo "{}"
|
34
|
+
exit 0
|
35
|
+
fi
|
36
|
+
fi
|
37
|
+
|
38
|
+
# Tell aircana where the plugin lives
|
39
|
+
export AIRCANA_PLUGIN_ROOT="$PLUGIN_ROOT"
|
40
|
+
|
41
|
+
echo "$(date): Starting knowledge base refresh from plugin root: $PLUGIN_ROOT" >> "$LOG_FILE"
|
42
|
+
|
43
|
+
# Find all knowledge bases in agents directory
|
44
|
+
AGENTS_DIR="${PLUGIN_ROOT}/agents"
|
45
|
+
|
46
|
+
if [ ! -d "$AGENTS_DIR" ]; then
|
47
|
+
echo "$(date): No agents directory found, skipping refresh" >> "$LOG_FILE"
|
48
|
+
echo "{}"
|
49
|
+
exit 0
|
50
|
+
fi
|
51
|
+
|
52
|
+
# Track if we refreshed any KBs
|
53
|
+
REFRESHED_COUNT=0
|
54
|
+
SKIPPED_COUNT=0
|
55
|
+
|
56
|
+
# Iterate through each KB directory
|
57
|
+
for kb_dir in "${AGENTS_DIR}"/*/ ; do
|
58
|
+
# Skip if no directories found
|
59
|
+
[ -d "$kb_dir" ] || continue
|
60
|
+
|
61
|
+
kb_name=$(basename "$kb_dir")
|
62
|
+
manifest_file="${kb_dir}manifest.json"
|
63
|
+
|
64
|
+
# Skip if no manifest exists
|
65
|
+
if [ ! -f "$manifest_file" ]; then
|
66
|
+
echo "$(date): No manifest found for KB '$kb_name', skipping" >> "$LOG_FILE"
|
67
|
+
continue
|
68
|
+
fi
|
69
|
+
|
70
|
+
# Determine KB type from manifest (default to remote if not specified)
|
71
|
+
kb_type="remote"
|
72
|
+
|
73
|
+
# Try to parse with jq if available, otherwise use grep
|
74
|
+
if command -v jq >/dev/null 2>&1; then
|
75
|
+
kb_type=$(jq -r '.kb_type // "remote"' "$manifest_file" 2>/dev/null || echo "remote")
|
76
|
+
else
|
77
|
+
# Fallback: grep for kb_type field
|
78
|
+
if grep -q '"kb_type"[[:space:]]*:[[:space:]]*"local"' "$manifest_file" 2>/dev/null; then
|
79
|
+
kb_type="local"
|
80
|
+
fi
|
81
|
+
fi
|
82
|
+
|
83
|
+
# Only refresh remote KBs
|
84
|
+
if [ "$kb_type" = "local" ]; then
|
85
|
+
echo "$(date): Skipping local KB '$kb_name'" >> "$LOG_FILE"
|
86
|
+
SKIPPED_COUNT=$((SKIPPED_COUNT + 1))
|
87
|
+
continue
|
88
|
+
fi
|
89
|
+
|
90
|
+
# Refresh remote KB
|
91
|
+
echo "$(date): Refreshing remote KB '$kb_name'" >> "$LOG_FILE"
|
92
|
+
if aircana kb refresh "$kb_name" >> "$LOG_FILE" 2>&1; then
|
93
|
+
echo "$(date): Successfully refreshed KB '$kb_name'" >> "$LOG_FILE"
|
94
|
+
REFRESHED_COUNT=$((REFRESHED_COUNT + 1))
|
95
|
+
else
|
96
|
+
echo "$(date): Warning - Failed to refresh KB '$kb_name'" >> "$LOG_FILE"
|
97
|
+
fi
|
98
|
+
done
|
99
|
+
|
100
|
+
# Update timestamp on completion (even if some refreshes failed)
|
101
|
+
date +%s > "$TIMESTAMP_FILE"
|
102
|
+
|
103
|
+
# Log summary
|
104
|
+
echo "$(date): KB refresh completed - refreshed: $REFRESHED_COUNT, skipped (local): $SKIPPED_COUNT" >> "$LOG_FILE"
|
105
|
+
|
106
|
+
# Return success with context
|
107
|
+
if [ $REFRESHED_COUNT -gt 0 ]; then
|
108
|
+
CONTEXT="Refreshed $REFRESHED_COUNT remote knowledge base(s)"
|
109
|
+
else
|
110
|
+
CONTEXT="No remote knowledge bases to refresh"
|
111
|
+
fi
|
112
|
+
|
113
|
+
ESCAPED_CONTEXT=$(echo -n "$CONTEXT" | sed 's/"/\\"/g')
|
114
|
+
cat << EOF
|
115
|
+
{
|
116
|
+
"hookSpecificOutput": {
|
117
|
+
"hookEventName": "SessionStart",
|
118
|
+
"additionalContext": "$ESCAPED_CONTEXT"
|
119
|
+
}
|
120
|
+
}
|
121
|
+
EOF
|
data/lib/aircana/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aircana
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.0.
|
4
|
+
version: 4.0.0.rc4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Weston Dransfield
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: httparty
|
@@ -115,15 +115,8 @@ files:
|
|
115
115
|
- README.md
|
116
116
|
- Rakefile
|
117
117
|
- SECURITY.md
|
118
|
-
- commands/apply-feedback.md
|
119
|
-
- commands/ask-expert.md
|
120
|
-
- commands/execute.md
|
121
|
-
- commands/plan.md
|
122
|
-
- commands/record.md
|
123
|
-
- commands/review.md
|
124
118
|
- compose.yml
|
125
119
|
- exe/aircana
|
126
|
-
- hooks/hooks.json
|
127
120
|
- lib/aircana.rb
|
128
121
|
- lib/aircana/cli.rb
|
129
122
|
- lib/aircana/cli/app.rb
|
@@ -132,7 +125,6 @@ files:
|
|
132
125
|
- lib/aircana/cli/commands/doctor_helpers.rb
|
133
126
|
- lib/aircana/cli/commands/dump_context.rb
|
134
127
|
- lib/aircana/cli/commands/generate.rb
|
135
|
-
- lib/aircana/cli/commands/hooks.rb
|
136
128
|
- lib/aircana/cli/commands/init.rb
|
137
129
|
- lib/aircana/cli/commands/kb.rb
|
138
130
|
- lib/aircana/cli/commands/plugin.rb
|
@@ -177,6 +169,7 @@ files:
|
|
177
169
|
- lib/aircana/templates/hooks/notification_sqs.erb
|
178
170
|
- lib/aircana/templates/hooks/post_tool_use.erb
|
179
171
|
- lib/aircana/templates/hooks/pre_tool_use.erb
|
172
|
+
- lib/aircana/templates/hooks/refresh_skills.erb
|
180
173
|
- lib/aircana/templates/hooks/rspec_test.erb
|
181
174
|
- lib/aircana/templates/hooks/rubocop_pre_commit.erb
|
182
175
|
- lib/aircana/templates/hooks/session_start.erb
|
@@ -207,7 +200,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
207
200
|
- !ruby/object:Gem::Version
|
208
201
|
version: '0'
|
209
202
|
requirements: []
|
210
|
-
rubygems_version: 3.6.
|
203
|
+
rubygems_version: 3.6.9
|
211
204
|
specification_version: 4
|
212
205
|
summary: CLI for creating and managing Claude Code plugins with per-agent knowledge
|
213
206
|
bases
|
data/commands/apply-feedback.md
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
INSTRUCTIONS : Use the Task tool with subagent_type 'apply-feedback' to apply code review feedback from the previous /air-review command.
|
2
|
-
|
3
|
-
Pass the review feedback from the conversation context to the apply-feedback agent.
|
4
|
-
|
5
|
-
The apply-feedback agent will:
|
6
|
-
1. Parse review feedback from the previous review
|
7
|
-
2. Create todo list of changes prioritized by severity
|
8
|
-
3. Present plan to user for approval
|
9
|
-
4. Apply approved changes
|
10
|
-
5. Re-run unit tests to verify changes
|
11
|
-
6. Fix any test failures
|
12
|
-
7. Amend the HEAD commit with improvements using 'git commit --amend --no-edit'
|
13
|
-
8. Summarize changes made
|
14
|
-
|
15
|
-
IMPORTANT: This command reads the review output from the conversation context, so it must be run in the same conversation as /air-review.
|
data/commands/ask-expert.md
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
INSTRUCTIONS : You are coordinating expert consultation to answer a question by leveraging multiple specialized sub-agents. Follow this precise workflow:
|
2
|
-
|
3
|
-
STEP 1: QUESTION VALIDATION
|
4
|
-
Ask the user: \"What is your question?\" and wait for their response before proceeding.
|
5
|
-
|
6
|
-
STEP 2: COORDINATION PHASE
|
7
|
-
Use the Task tool with subagent_type 'sub-agent-coordinator' to analyze the question and identify relevant sub-agents. Provide the coordinator with the complete question context.
|
8
|
-
|
9
|
-
STEP 3: PARALLEL EXPERT CONSULTATION
|
10
|
-
Based on the coordinator's recommendations, use the Task tool to consult each identified relevant sub-agent in parallel. For each agent:
|
11
|
-
- Use the appropriate subagent_type for each recommended agent
|
12
|
-
- Provide the original question plus any agent-specific context the coordinator suggested
|
13
|
-
- Execute multiple Task tool calls in a single message for parallel processing
|
14
|
-
|
15
|
-
STEP 4: SYNTHESIS AND RESPONSE
|
16
|
-
After receiving responses from all consulted agents:
|
17
|
-
- Analyze and synthesize the expert feedback
|
18
|
-
- Identify common themes, conflicting viewpoints, and complementary insights
|
19
|
-
- Provide a comprehensive answer that leverages the collective expertise
|
20
|
-
- Cite which agents contributed specific insights where relevant
|
21
|
-
- Note any areas where experts disagreed and provide your assessment
|
22
|
-
|
23
|
-
STEP 5: FOLLOW-UP GUIDANCE
|
24
|
-
If the question requires further clarification or the expert responses suggest additional considerations:
|
25
|
-
- Suggest specific follow-up questions
|
26
|
-
- Recommend additional agents to consult if needed
|
27
|
-
- Provide guidance on next steps based on the expert consensus
|
28
|
-
|
29
|
-
IMPORTANT EXECUTION NOTES:
|
30
|
-
- Always start with the sub-agent-coordinator for proper agent selection
|
31
|
-
- Use parallel Task tool execution when consulting multiple agents (single message with multiple tool calls)
|
32
|
-
- Ensure each agent receives context appropriate to their expertise domain
|
33
|
-
- Synthesize responses rather than simply concatenating them
|
34
|
-
- Maintain focus on providing actionable, comprehensive answers
|
35
|
-
|
36
|
-
EXAMPLE PARALLEL EXECUTION:
|
37
|
-
If coordinator recommends agents A, B, and C, send one message with three Task tool calls:
|
38
|
-
1. Task(subagent_type='agent-A', prompt='[question + A-specific context]')
|
39
|
-
2. Task(subagent_type='agent-B', prompt='[question + B-specific context]')
|
40
|
-
3. Task(subagent_type='agent-C', prompt='[question + C-specific context]')
|
41
|
-
|
42
|
-
This approach ensures you leverage the full expertise available while maintaining efficient coordination.
|
data/commands/execute.md
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
INSTRUCTIONS : Use the Task tool with subagent_type 'executor' to execute the implementation plan from a Jira ticket.
|
2
|
-
|
3
|
-
INSTRUCTIONS FOR EXECUTOR AGENT:
|
4
|
-
Ask the user to provide a Jira ticket key/ID to execute.
|
5
|
-
|
6
|
-
The executor agent will:
|
7
|
-
1. Read the plan from the Jira ticket via the 'jira' sub-agent
|
8
|
-
2. Review and validate the plan structure
|
9
|
-
3. Create a detailed execution todo list in Claude Code planning mode
|
10
|
-
4. Present the plan for your approval
|
11
|
-
5. Execute the approved implementation tasks
|
12
|
-
|
13
|
-
IMPORTANT: All Jira operations are delegated to the 'jira' sub-agent using Task tool with subagent_type 'jira'.
|
data/commands/plan.md
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
INSTRUCTIONS : First, ask the user to specify relevant files, directories, or areas of the codebase to examine for this planning task.
|
2
|
-
|
3
|
-
Then use the Task tool with subagent_type 'planner' to invoke the planner agent with the following explicit instructions:
|
4
|
-
|
5
|
-
STEP 1: CREATE TODO LIST FILE
|
6
|
-
First, create a todo list file with the following tasks enumerated in order:
|
7
|
-
|
8
|
-
1. Ask user for relevant files and context (if not already provided)
|
9
|
-
2. Use Task tool with subagent_type 'jira' to verify Jira ticket information (or ask user to create/provide ticket)
|
10
|
-
3. Perform targeted initial research on user-specified files
|
11
|
-
4. Consult relevant sub-agents with research context (run in parallel when possible)
|
12
|
-
5. Create high-level strategic implementation plan
|
13
|
-
6. Iterate with user feedback
|
14
|
-
7. Suggest user runs '/air-record' command to save the plan to Jira ticket
|
15
|
-
|
16
|
-
STEP 2: EXECUTE EACH TASK IN ORDER
|
17
|
-
Work through each task in the todo list sequentially:
|
18
|
-
- Mark each task as 'in_progress' when you start it
|
19
|
-
- Mark each task as 'completed' when finished
|
20
|
-
- Continue until all tasks are done
|
21
|
-
|
22
|
-
IMPORTANT CONTEXT-SHARING PROTOCOL:
|
23
|
-
- When consulting sub-agents, explicitly provide: files already searched, files already read, key findings, and specific focus area
|
24
|
-
- This prevents sub-agents from duplicating research work
|
25
|
-
|
26
|
-
IMPORTANT PLAN CONSTRAINTS:
|
27
|
-
- Focus on strategic, high-level implementation guidance
|
28
|
-
- NO rollout plans, effort estimates, or exhaustive code implementations
|
29
|
-
- Small code examples (5-10 lines) are OK to illustrate concepts
|
30
|
-
|
31
|
-
User specified relevant files/areas: [User will specify]
|
32
|
-
|
33
|
-
Ask the user to provide a Jira ticket or task description.
|
data/commands/record.md
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
INSTRUCTIONS : Use the Task tool with subagent_type 'jira' to append the implementation plan to the Jira ticket description using Jira MCP tools.
|
2
|
-
|
3
|
-
INSTRUCTIONS FOR JIRA AGENT:
|
4
|
-
1. Read the implementation plan from the current context (look for recent planning output)
|
5
|
-
2. Get the current ticket description using mcp__jira__getJiraIssue with fields=["description"]
|
6
|
-
3. Append the plan to the existing description under a new "## Implementation Plan" heading
|
7
|
-
4. Update the ticket using mcp__jira__editJiraIssue with the combined description
|
8
|
-
5. Format the appended plan section with:
|
9
|
-
- Consulted sub-agents
|
10
|
-
- Relevant files analyzed
|
11
|
-
- Planning timestamp
|
12
|
-
- Implementation steps as todo list using `[ ]` format
|
13
|
-
6. Provide the ticket URL for easy access
|
14
|
-
|
15
|
-
CRITICAL: The jira sub-agent must append to the ticket description using mcp__jira__editJiraIssue (NOT create files or comments).
|
16
|
-
|
17
|
-
IMPORTANT: Delegate all Jira operations to the 'jira' sub-agent using Task tool with subagent_type 'jira'. The Jira ticket key/ID is already in context.
|
data/commands/review.md
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
INSTRUCTIONS : Use the Task tool with subagent_type 'reviewer' to conduct an adversarial code review of the HEAD commit.
|
2
|
-
|
3
|
-
The reviewer agent will:
|
4
|
-
1. Get HEAD commit details and changes
|
5
|
-
2. Analyze changed files to identify technical domains
|
6
|
-
3. Use the sub-agent-coordinator to select relevant expert agents
|
7
|
-
4. Present changes to experts in parallel for review
|
8
|
-
5. Synthesize feedback organized by severity
|
9
|
-
6. Store review output for the apply-feedback command
|
10
|
-
7. Suggest running '/air-apply-feedback' to apply recommended changes
|
11
|
-
|
12
|
-
IMPORTANT: The review agent will automatically review the HEAD commit. No arguments needed.
|