aircana 1.2.0 → 1.4.0.rc1
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 +184 -194
- data/CLAUDE.md +0 -2
- data/README.md +47 -6
- data/lib/aircana/cli/app.rb +0 -2
- data/lib/aircana/cli/commands/agents.rb +3 -0
- data/lib/aircana/cli/commands/doctor.rb +11 -5
- data/lib/aircana/cli/commands/doctor_checks.rb +48 -0
- data/lib/aircana/cli/commands/install.rb +4 -5
- data/lib/aircana/generators/agents_generator.rb +1 -1
- data/lib/aircana/generators/helpers.rb +1 -2
- data/lib/aircana/generators/hooks_generator.rb +2 -0
- data/lib/aircana/generators/relevant_files_command_generator.rb +1 -1
- data/lib/aircana/system_checker.rb +11 -0
- data/lib/aircana/templates/agents/base_agent.erb +4 -3
- data/lib/aircana/templates/agents/defaults/planner.erb +49 -120
- data/lib/aircana/templates/hooks/notification_sqs.erb +75 -0
- data/lib/aircana/templates/hooks/pre_tool_use.erb +32 -7
- data/lib/aircana/version.rb +1 -1
- metadata +3 -5
- data/lib/aircana/cli/commands/plan.rb +0 -69
- data/lib/aircana/cli/commands/work.rb +0 -69
- data/lib/aircana/templates/agents/defaults/worker.erb +0 -185
@@ -126,6 +126,54 @@ module Aircana
|
|
126
126
|
end
|
127
127
|
end
|
128
128
|
end
|
129
|
+
|
130
|
+
module SQSIntegration
|
131
|
+
def check_sqs_integration
|
132
|
+
Aircana.human_logger.info "\nSQS Integration:"
|
133
|
+
|
134
|
+
check_sqs_dependencies
|
135
|
+
check_sqs_configuration
|
136
|
+
end
|
137
|
+
|
138
|
+
def check_sqs_dependencies
|
139
|
+
check_command("aws", "SQS operations", required: false)
|
140
|
+
check_command("jq", "JSON processing for notifications", required: false)
|
141
|
+
end
|
142
|
+
|
143
|
+
def check_sqs_configuration
|
144
|
+
sqs_queue_url = ENV.fetch("AIRCANA_SQS_QUEUE_URL", nil)
|
145
|
+
sqs_message_template = ENV.fetch("AIRCANA_SQS_MESSAGE_TEMPLATE", nil)
|
146
|
+
aws_region = ENV.fetch("AWS_REGION", "us-east-1")
|
147
|
+
|
148
|
+
if sqs_configured?(sqs_queue_url, sqs_message_template)
|
149
|
+
log_success("SQS Config", "Environment variables configured")
|
150
|
+
log_sqs_config_details(sqs_queue_url, sqs_message_template, aws_region) if @verbose
|
151
|
+
else
|
152
|
+
log_info("SQS Config", "Not configured")
|
153
|
+
log_sqs_configuration_remedy
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def sqs_configured?(queue_url, message_template)
|
158
|
+
!queue_url.nil? && !queue_url.empty? &&
|
159
|
+
!message_template.nil? && !message_template.empty?
|
160
|
+
end
|
161
|
+
|
162
|
+
def log_sqs_config_details(queue_url, message_template, aws_region)
|
163
|
+
log_info(" AIRCANA_SQS_QUEUE_URL", queue_url.length > 50 ? "#{queue_url[0..47]}..." : queue_url)
|
164
|
+
log_info(" AIRCANA_SQS_MESSAGE_TEMPLATE",
|
165
|
+
message_template.length > 40 ? "#{message_template[0..37]}..." : message_template)
|
166
|
+
log_info(" AWS_REGION", aws_region)
|
167
|
+
end
|
168
|
+
|
169
|
+
def log_sqs_configuration_remedy
|
170
|
+
log_remedy("Set AIRCANA_SQS_QUEUE_URL and AIRCANA_SQS_MESSAGE_TEMPLATE for SQS notifications")
|
171
|
+
log_remedy("Example:")
|
172
|
+
log_remedy(' export AIRCANA_SQS_QUEUE_URL="https://sqs.us-east-1.amazonaws.com/account/queue"')
|
173
|
+
log_remedy(' export AIRCANA_SQS_MESSAGE_TEMPLATE=\'{"text":"{{message}}}\'')
|
174
|
+
log_remedy(' export AWS_REGION="us-east-1" # Optional, defaults to us-east-1')
|
175
|
+
end
|
176
|
+
end
|
129
177
|
end
|
130
178
|
end
|
131
179
|
end
|
@@ -9,7 +9,7 @@ module Aircana
|
|
9
9
|
module Install
|
10
10
|
class << self
|
11
11
|
def run
|
12
|
-
|
12
|
+
generate_files
|
13
13
|
ensure_project_config_exists
|
14
14
|
install_commands_to_claude
|
15
15
|
install_hooks_to_claude
|
@@ -17,10 +17,8 @@ module Aircana
|
|
17
17
|
|
18
18
|
private
|
19
19
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
Aircana.human_logger.warn("No generated output files-auto generating now...")
|
20
|
+
def generate_files
|
21
|
+
Aircana.human_logger.info("Generating files before installation...")
|
24
22
|
Generate.run
|
25
23
|
end
|
26
24
|
|
@@ -118,6 +116,7 @@ module Aircana
|
|
118
116
|
"post_tool_use" => { event: "PostToolUse", matcher: nil },
|
119
117
|
"user_prompt_submit" => { event: "UserPromptSubmit", matcher: nil },
|
120
118
|
"session_start" => { event: "SessionStart", matcher: nil },
|
119
|
+
"notification_sqs" => { event: "Notification", matcher: nil },
|
121
120
|
"rubocop_pre_commit" => { event: "PreToolUse", matcher: "Bash" },
|
122
121
|
"rspec_test" => { event: "PostToolUse", matcher: "Bash" },
|
123
122
|
"bundle_install" => { event: "PostToolUse", matcher: "Bash" }
|
@@ -7,7 +7,7 @@ module Aircana
|
|
7
7
|
class AgentsGenerator < BaseGenerator
|
8
8
|
attr_reader :agent_name, :short_description, :description, :model, :color, :default_agent
|
9
9
|
|
10
|
-
AVAILABLE_DEFAULT_AGENTS =
|
10
|
+
AVAILABLE_DEFAULT_AGENTS = ["planner"].freeze
|
11
11
|
|
12
12
|
class << self
|
13
13
|
def create_default_agent(agent_name)
|
@@ -11,6 +11,7 @@ module Aircana
|
|
11
11
|
post_tool_use
|
12
12
|
user_prompt_submit
|
13
13
|
session_start
|
14
|
+
notification_sqs
|
14
15
|
rubocop_pre_commit
|
15
16
|
rspec_test
|
16
17
|
bundle_install
|
@@ -19,6 +20,7 @@ module Aircana
|
|
19
20
|
# Default hooks that are auto-installed
|
20
21
|
DEFAULT_HOOK_TYPES = %w[
|
21
22
|
session_start
|
23
|
+
notification_sqs
|
22
24
|
].freeze
|
23
25
|
|
24
26
|
class << self
|
@@ -25,7 +25,7 @@ module Aircana
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def default_output_path
|
28
|
-
File.join(Aircana.configuration.output_dir, "commands", "
|
28
|
+
File.join(Aircana.configuration.output_dir, "commands", "air-add-relevant-files.md")
|
29
29
|
end
|
30
30
|
|
31
31
|
def relevant_project_files_path
|
@@ -37,6 +37,17 @@ module Aircana
|
|
37
37
|
}.freeze
|
38
38
|
|
39
39
|
OPTIONAL_COMMANDS = {
|
40
|
+
"aws" => {
|
41
|
+
purpose: "SQS notifications via AWS CLI",
|
42
|
+
fallback: "SQS notifications will be disabled",
|
43
|
+
install: {
|
44
|
+
"macOS" => "brew install awscli",
|
45
|
+
"Ubuntu/Debian" => "apt install awscli",
|
46
|
+
"Fedora/CentOS" => "dnf install awscli",
|
47
|
+
"Arch" => "pacman -S aws-cli",
|
48
|
+
"Other" => "https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html"
|
49
|
+
}
|
50
|
+
},
|
40
51
|
"bat" => {
|
41
52
|
purpose: "enhanced file previews",
|
42
53
|
fallback: "head/cat for basic previews",
|
@@ -4,12 +4,11 @@ description: <%= short_description %>
|
|
4
4
|
model: <%= model %>
|
5
5
|
color: <%= color %>
|
6
6
|
---
|
7
|
-
<%= description %>
|
8
7
|
|
9
8
|
<%= helpers.model_instructions("ALWAYS check your knowledge base FIRST for every query, task, or question you receive. Your knowledge is stored in: @#{knowledge_path}
|
10
9
|
|
11
10
|
MANDATORY WORKFLOW:
|
12
|
-
1. BEFORE responding to ANY
|
11
|
+
1. BEFORE responding to ANY request - search and read relevant files in your knowledge base
|
13
12
|
2. Base your responses primarily on information found in your knowledge base
|
14
13
|
3. If knowledge base contains relevant information, cite specific files/sections
|
15
14
|
4. Only use general knowledge when your knowledge base lacks specific information
|
@@ -27,4 +26,6 @@ This knowledge base contains:
|
|
27
26
|
- Team standards and best practices
|
28
27
|
- Technical specifications and requirements
|
29
28
|
|
30
|
-
Always consult this knowledge base before making recommendations or providing guidance.
|
29
|
+
Always consult this knowledge base before making recommendations or providing guidance.
|
30
|
+
|
31
|
+
<%= description %>
|
@@ -1,126 +1,55 @@
|
|
1
1
|
---
|
2
2
|
name: planner
|
3
|
-
description:
|
3
|
+
description: Strategic project planning agent that integrates with Jira and collaborates with other sub-agents to create comprehensive implementation plans
|
4
4
|
model: inherit
|
5
5
|
color: blue
|
6
6
|
---
|
7
|
-
# Planner Agent
|
8
7
|
|
9
|
-
You are
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
-
|
39
|
-
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
-
|
52
|
-
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
- These files provide crucial context before expert consultation
|
58
|
-
- Read and analyze provided relevant files
|
59
|
-
- Extract key patterns, frameworks, and architectural decisions
|
60
|
-
|
61
|
-
### Step D: Expert Agent Coordination
|
62
|
-
- Based on ticket requirements, relevant files, and knowledge base findings, identify expert agents
|
63
|
-
- **BEFORE consulting experts**: Review knowledge base for existing expert guidance on similar topics
|
64
|
-
- Use Claude Code's Task tool to consult expert agents in parallel
|
65
|
-
- Ask each expert to provide key details for the plan in their domain of expertise
|
66
|
-
- **Combine knowledge base findings with expert recommendations** for comprehensive planning
|
67
|
-
|
68
|
-
### Step E: Plan Generation
|
69
|
-
- Consolidate expert recommendations into cohesive execution plan
|
70
|
-
- Create detailed todo list including:
|
71
|
-
- Implementation steps
|
72
|
-
- Unit test writing requirements
|
73
|
-
- Test execution and iteration cycles
|
74
|
-
- Present plan to user for approval and adjustments
|
75
|
-
|
76
|
-
### Step F: Plan Storage
|
77
|
-
- Format plan with required sections (see below)
|
78
|
-
- If new ticket needed, ask for Jira project and create ticket
|
79
|
-
- Update/create Jira ticket with complete plan in description. Do not search yourself
|
80
|
-
for an appropriate Jira project. Always ask the user what Jira project the ticket
|
81
|
-
should be created in.
|
82
|
-
|
83
|
-
## Plan Format
|
84
|
-
|
85
|
-
Store plans in Jira ticket descriptions using this exact structure:
|
86
|
-
|
87
|
-
```markdown
|
88
|
-
# AGENT PLAN #
|
89
|
-
|
90
|
-
## Relevant Files
|
91
|
-
- path/to/file1.rb
|
92
|
-
- path/to/file2.rb
|
93
|
-
- directory/file3.rb
|
94
|
-
|
95
|
-
## Expert Agents
|
96
|
-
- agent-name-1
|
97
|
-
- agent-name-2
|
98
|
-
|
99
|
-
## Execution Plan
|
100
|
-
[Detailed implementation steps from expert analysis]
|
101
|
-
|
102
|
-
## Todo List
|
103
|
-
- [ ] Task 1
|
104
|
-
- [ ] Task 2
|
105
|
-
- [ ] Write unit tests for [specific functionality]
|
106
|
-
- [ ] Run tests and iterate until all pass
|
107
|
-
- [ ] Final integration testing
|
108
|
-
```
|
109
|
-
|
110
|
-
## Key Instructions
|
111
|
-
|
112
|
-
1. **Always ask for relevant files BEFORE consulting expert agents**
|
113
|
-
2. **Use the exact "# AGENT PLAN #" header for plan sections**
|
114
|
-
3. **Include test writing and execution in every todo list**
|
115
|
-
4. **Present plans to users for approval before saving**
|
116
|
-
5. **Use MCP Jira tools for all ticket operations**
|
117
|
-
6. **Coordinate expert agents using Claude Code's Task tool**
|
118
|
-
|
119
|
-
## Error Handling
|
120
|
-
|
121
|
-
- If Jira access fails, guide user to check MCP Jira configuration
|
122
|
-
- If no expert agents found, proceed with general analysis
|
123
|
-
- If file access fails, note in plan and continue
|
124
|
-
- Always provide fallback options when tools fail
|
125
|
-
|
126
|
-
Start every planning session by confirming: "I'm ready to help you create an implementation plan. Do you have a Jira ticket ID to plan for, or would you like to create a new ticket?"
|
8
|
+
<%= helpers.model_instructions("You are a Strategic Project Planning Agent that creates comprehensive implementation plans by integrating with Jira tickets and leveraging other specialized sub-agents' knowledge.
|
9
|
+
|
10
|
+
MANDATORY WORKFLOW:
|
11
|
+
1. JIRA TICKET VERIFICATION:
|
12
|
+
- If no Jira ticket was provided, ask if the user wants to create a new ticket or provide a ticket number
|
13
|
+
- If a Jira ticket is provided, use the built-in `jira` mcp tool to fetch the ticket details
|
14
|
+
- If user doesn't have the jira mcp tool installed, prompt them to run `aircana doctor` for setup details
|
15
|
+
|
16
|
+
2. REQUIREMENTS GATHERING:
|
17
|
+
- If ticket details are available, read the description from Jira
|
18
|
+
- If no ticket or description, ask the user for a description of the issue
|
19
|
+
- Ask the user to provide references to any files they know might be part of the solution
|
20
|
+
- Read all referenced files to understand the codebase context
|
21
|
+
|
22
|
+
3. SUB-AGENT CONSULTATION:
|
23
|
+
- Consider the ticket description and potentially relevant files
|
24
|
+
- Identify all available sub-agents installed in Claude Code that may be helpful for planning
|
25
|
+
- For each relevant agent, present the ticket description and ask specifically for input on the solution using their knowledge base
|
26
|
+
- Run these sub-agent consultation processes in parallel when possible
|
27
|
+
- Gather insights from specialized domains (testing, security, frontend, backend, etc.)
|
28
|
+
|
29
|
+
4. PLANNING MODE EXECUTION:
|
30
|
+
- Enter Claude Code planning mode
|
31
|
+
- Synthesize information from ticket description, relevant files, and sub-agent consultations
|
32
|
+
- Create a comprehensive implementation plan
|
33
|
+
- Present the proposed plan to the user for input and iteration
|
34
|
+
|
35
|
+
5. PLAN FINALIZATION:
|
36
|
+
- Iterate with the user to refine and finalize the plan
|
37
|
+
- Ensure all technical considerations and sub-agent recommendations are incorporated
|
38
|
+
- Validate the plan addresses all requirements from the Jira ticket
|
39
|
+
|
40
|
+
6. JIRA INTEGRATION:
|
41
|
+
- Create or update the Jira ticket with a new markdown attachment describing the final plan
|
42
|
+
- The plan should be in markdown format with proper frontmatter including:
|
43
|
+
* List of consulted sub-agents (frontmatter)
|
44
|
+
* List of relevant files referenced (frontmatter)
|
45
|
+
- The markdown body should contain:
|
46
|
+
* Detailed implementation steps as a todo list using `[]` format for easy LLM consumption
|
47
|
+
* Technical considerations and dependencies
|
48
|
+
|
49
|
+
IMPORTANT INSTRUCTIONS:
|
50
|
+
- Always start by checking for Jira ticket information
|
51
|
+
- Leverage the expertise of available sub-agents rather than working in isolation
|
52
|
+
- Use proper markdown formatting for Jira attachments
|
53
|
+
- Focus on creating implementable, step-by-step plans", important: true) %>
|
54
|
+
|
55
|
+
Always identify available sub-agents and leverage their specialized knowledge to create more comprehensive and accurate plans.
|
@@ -0,0 +1,75 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
# Aircana SQS notification hook
|
3
|
+
# Sends Claude Code notifications to SQS
|
4
|
+
|
5
|
+
# Read JSON input from stdin
|
6
|
+
INPUT=$(cat)
|
7
|
+
|
8
|
+
# Set up logging
|
9
|
+
mkdir -p ~/.aircana
|
10
|
+
LOG_FILE="$HOME/.aircana/sqs_notifications.log"
|
11
|
+
|
12
|
+
# Log the notification input for debugging
|
13
|
+
echo "$(date): Notification Hook Input:" >> $LOG_FILE
|
14
|
+
echo "$INPUT" >> $LOG_FILE
|
15
|
+
echo "---" >> $LOG_FILE
|
16
|
+
|
17
|
+
# Check if jq is available
|
18
|
+
if ! command -v jq &> /dev/null; then
|
19
|
+
echo "$(date): Error - jq not found. Cannot parse notification." >> $LOG_FILE
|
20
|
+
exit 0
|
21
|
+
fi
|
22
|
+
|
23
|
+
# Check if aws CLI is available
|
24
|
+
if ! command -v aws &> /dev/null; then
|
25
|
+
echo "$(date): Error - aws CLI not found. Cannot send to SQS." >> $LOG_FILE
|
26
|
+
exit 0
|
27
|
+
fi
|
28
|
+
|
29
|
+
# Parse the notification message
|
30
|
+
MESSAGE=$(echo "$INPUT" | jq -r '.message // empty')
|
31
|
+
|
32
|
+
# Skip empty messages
|
33
|
+
if [ -z "$MESSAGE" ] || [ "$MESSAGE" = "null" ]; then
|
34
|
+
echo "$(date): No message found in notification" >> $LOG_FILE
|
35
|
+
exit 0
|
36
|
+
fi
|
37
|
+
|
38
|
+
# Check required environment variables
|
39
|
+
if [ -z "$AIRCANA_SQS_QUEUE_URL" ]; then
|
40
|
+
echo "$(date): AIRCANA_SQS_QUEUE_URL not set, skipping SQS notification" >> $LOG_FILE
|
41
|
+
exit 0
|
42
|
+
fi
|
43
|
+
|
44
|
+
if [ -z "$AIRCANA_SQS_MESSAGE_TEMPLATE" ]; then
|
45
|
+
echo "$(date): AIRCANA_SQS_MESSAGE_TEMPLATE not set, skipping SQS notification" >> $LOG_FILE
|
46
|
+
exit 0
|
47
|
+
fi
|
48
|
+
|
49
|
+
# Create the message body by substituting {{message}} in the template
|
50
|
+
MESSAGE_BODY=$(echo "$AIRCANA_SQS_MESSAGE_TEMPLATE" | sed "s|{{message}}|$MESSAGE|g")
|
51
|
+
|
52
|
+
# Log the message being sent
|
53
|
+
echo "$(date): Sending SQS message:" >> $LOG_FILE
|
54
|
+
echo "Queue URL: $AIRCANA_SQS_QUEUE_URL" >> $LOG_FILE
|
55
|
+
echo "Message Body: $MESSAGE_BODY" >> $LOG_FILE
|
56
|
+
|
57
|
+
# Send message to SQS using aws CLI
|
58
|
+
AWS_REGION=${AWS_REGION:-us-east-1}
|
59
|
+
SQS_RESULT=$(aws --region "$AWS_REGION" sqs send-message \
|
60
|
+
--queue-url "$AIRCANA_SQS_QUEUE_URL" \
|
61
|
+
--message-body "$MESSAGE_BODY" 2>&1)
|
62
|
+
|
63
|
+
# Log the result
|
64
|
+
if [ $? -eq 0 ]; then
|
65
|
+
echo "$(date): Successfully sent SQS message" >> $LOG_FILE
|
66
|
+
echo "Response: $SQS_RESULT" >> $LOG_FILE
|
67
|
+
else
|
68
|
+
echo "$(date): Failed to send SQS message" >> $LOG_FILE
|
69
|
+
echo "Error: $SQS_RESULT" >> $LOG_FILE
|
70
|
+
fi
|
71
|
+
|
72
|
+
echo "---" >> $LOG_FILE
|
73
|
+
|
74
|
+
# Return success - don't block Claude Code if SQS fails
|
75
|
+
exit 0
|
@@ -2,25 +2,33 @@
|
|
2
2
|
# Pre-tool-use hook generated by Aircana
|
3
3
|
# This hook runs before any tool is executed
|
4
4
|
|
5
|
-
#
|
6
|
-
|
7
|
-
|
5
|
+
# Read JSON input from stdin
|
6
|
+
INPUT=$(cat)
|
7
|
+
|
8
|
+
# Parse JSON to extract tool information
|
9
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
|
10
|
+
TOOL_INPUT=$(echo "$INPUT" | jq -r '.tool_input // empty')
|
11
|
+
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // empty')
|
12
|
+
CWD=$(echo "$INPUT" | jq -r '.cwd // empty')
|
8
13
|
|
9
14
|
# Log the tool usage (optional)
|
10
|
-
echo "$(date): About to use tool: $TOOL_NAME" >> ~/.aircana/hooks.log
|
15
|
+
echo "$(date): Session $SESSION_ID - About to use tool: $TOOL_NAME in $CWD" >> ~/.aircana/hooks.log
|
11
16
|
|
12
17
|
# Basic validation example
|
13
18
|
case "$TOOL_NAME" in
|
14
19
|
"Bash")
|
15
20
|
# Add validation for bash commands
|
16
|
-
|
21
|
+
COMMAND=$(echo "$TOOL_INPUT" | jq -r '.command // empty')
|
22
|
+
if echo "$COMMAND" | grep -q "rm -rf /"; then
|
17
23
|
cat << EOF
|
18
24
|
{
|
19
25
|
"hookSpecificOutput": {
|
20
26
|
"hookEventName": "PreToolUse",
|
21
27
|
"permissionDecision": "deny",
|
22
28
|
"permissionDecisionReason": "Dangerous command detected: rm -rf /"
|
23
|
-
}
|
29
|
+
},
|
30
|
+
"continue": false,
|
31
|
+
"stopReason": "Blocked dangerous command"
|
24
32
|
}
|
25
33
|
EOF
|
26
34
|
exit 0
|
@@ -28,7 +36,23 @@ EOF
|
|
28
36
|
;;
|
29
37
|
"Edit"|"Write")
|
30
38
|
# Validate file operations
|
39
|
+
FILE_PATH=$(echo "$TOOL_INPUT" | jq -r '.file_path // empty')
|
31
40
|
# Add custom validation logic here
|
41
|
+
# Example: Check if trying to modify system files
|
42
|
+
if echo "$FILE_PATH" | grep -q "^/etc/\|^/usr/\|^/bin/\|^/sbin/"; then
|
43
|
+
cat << EOF
|
44
|
+
{
|
45
|
+
"hookSpecificOutput": {
|
46
|
+
"hookEventName": "PreToolUse",
|
47
|
+
"permissionDecision": "ask",
|
48
|
+
"permissionDecisionReason": "Attempting to modify system file: $FILE_PATH"
|
49
|
+
},
|
50
|
+
"continue": true,
|
51
|
+
"systemMessage": "Warning: About to modify a system file"
|
52
|
+
}
|
53
|
+
EOF
|
54
|
+
exit 0
|
55
|
+
fi
|
32
56
|
;;
|
33
57
|
esac
|
34
58
|
|
@@ -38,6 +62,7 @@ cat << EOF
|
|
38
62
|
"hookSpecificOutput": {
|
39
63
|
"hookEventName": "PreToolUse",
|
40
64
|
"permissionDecision": "allow"
|
41
|
-
}
|
65
|
+
},
|
66
|
+
"continue": true
|
42
67
|
}
|
43
68
|
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: 1.
|
4
|
+
version: 1.4.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Weston Dransfield
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-09-
|
10
|
+
date: 2025-09-27 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: httparty
|
@@ -130,9 +130,7 @@ files:
|
|
130
130
|
- lib/aircana/cli/commands/generate.rb
|
131
131
|
- lib/aircana/cli/commands/hooks.rb
|
132
132
|
- lib/aircana/cli/commands/install.rb
|
133
|
-
- lib/aircana/cli/commands/plan.rb
|
134
133
|
- lib/aircana/cli/commands/project.rb
|
135
|
-
- lib/aircana/cli/commands/work.rb
|
136
134
|
- lib/aircana/cli/help_formatter.rb
|
137
135
|
- lib/aircana/cli/shell_command.rb
|
138
136
|
- lib/aircana/cli/subcommand.rb
|
@@ -163,9 +161,9 @@ files:
|
|
163
161
|
- lib/aircana/system_checker.rb
|
164
162
|
- lib/aircana/templates/agents/base_agent.erb
|
165
163
|
- lib/aircana/templates/agents/defaults/planner.erb
|
166
|
-
- lib/aircana/templates/agents/defaults/worker.erb
|
167
164
|
- lib/aircana/templates/commands/add_relevant_files.erb
|
168
165
|
- lib/aircana/templates/hooks/bundle_install.erb
|
166
|
+
- lib/aircana/templates/hooks/notification_sqs.erb
|
169
167
|
- lib/aircana/templates/hooks/post_tool_use.erb
|
170
168
|
- lib/aircana/templates/hooks/pre_tool_use.erb
|
171
169
|
- lib/aircana/templates/hooks/rspec_test.erb
|
@@ -1,69 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "generate"
|
4
|
-
require_relative "install"
|
5
|
-
require_relative "../../generators/agents_generator"
|
6
|
-
|
7
|
-
module Aircana
|
8
|
-
module CLI
|
9
|
-
module Plan
|
10
|
-
class << self
|
11
|
-
def run
|
12
|
-
ensure_planner_agent_installed
|
13
|
-
launch_claude_with_planner
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def ensure_planner_agent_installed
|
19
|
-
planner_agent_path = File.join(
|
20
|
-
Aircana.configuration.claude_code_config_path,
|
21
|
-
"agents",
|
22
|
-
"planner.md"
|
23
|
-
)
|
24
|
-
|
25
|
-
return if File.exist?(planner_agent_path)
|
26
|
-
|
27
|
-
Aircana.human_logger.info("Planner agent not found. Generating and installing...")
|
28
|
-
Generate.run
|
29
|
-
Install.run
|
30
|
-
end
|
31
|
-
|
32
|
-
def launch_claude_with_planner
|
33
|
-
prompt = "Start a planning session with the 'planner' sub-agent"
|
34
|
-
|
35
|
-
Aircana.human_logger.info("Launching Claude Code with planner agent...")
|
36
|
-
|
37
|
-
claude_path = find_claude_path
|
38
|
-
if claude_path
|
39
|
-
system("#{claude_path} \"#{prompt}\"")
|
40
|
-
else
|
41
|
-
handle_claude_not_found(prompt)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def handle_claude_not_found(prompt)
|
46
|
-
error_message = "Claude Code command not found. " \
|
47
|
-
"Please make sure Claude Code is installed and in your PATH."
|
48
|
-
Aircana.human_logger.error(error_message)
|
49
|
-
Aircana.human_logger.info("You can manually start Claude Code and run: #{prompt}")
|
50
|
-
end
|
51
|
-
|
52
|
-
def find_claude_path
|
53
|
-
# Try common locations for Claude Code binary (same as ClaudeClient)
|
54
|
-
possible_paths = [
|
55
|
-
File.expand_path("~/.claude/local/claude"),
|
56
|
-
`/usr/bin/which claude`.strip,
|
57
|
-
"/usr/local/bin/claude"
|
58
|
-
]
|
59
|
-
|
60
|
-
possible_paths.each do |path|
|
61
|
-
return path if !path.empty? && File.executable?(path)
|
62
|
-
end
|
63
|
-
|
64
|
-
nil
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|