aircana 0.1.0 → 1.1.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 +164 -104
- data/.rubocop.yml +34 -0
- data/CLAUDE.md +54 -9
- data/README.md +31 -19
- data/lib/aircana/cli/app.rb +93 -26
- data/lib/aircana/cli/commands/agents.rb +75 -4
- data/lib/aircana/cli/commands/files.rb +65 -0
- data/lib/aircana/cli/commands/generate.rb +19 -0
- data/lib/aircana/cli/commands/hooks.rb +276 -0
- data/lib/aircana/cli/commands/install.rb +113 -0
- data/lib/aircana/cli/commands/project.rb +156 -0
- data/lib/aircana/cli/help_formatter.rb +90 -0
- data/lib/aircana/cli/subcommand.rb +2 -1
- data/lib/aircana/configuration.rb +2 -1
- data/lib/aircana/contexts/confluence.rb +76 -3
- data/lib/aircana/contexts/manifest.rb +148 -0
- data/lib/aircana/generators/agents_generator.rb +1 -1
- data/lib/aircana/generators/hooks_generator.rb +82 -0
- data/lib/aircana/generators/project_config_generator.rb +54 -0
- data/lib/aircana/symlink_manager.rb +158 -0
- data/lib/aircana/system_checker.rb +10 -0
- data/lib/aircana/templates/hooks/bundle_install.erb +63 -0
- data/lib/aircana/templates/hooks/post_tool_use.erb +49 -0
- data/lib/aircana/templates/hooks/pre_tool_use.erb +43 -0
- data/lib/aircana/templates/hooks/rspec_test.erb +72 -0
- data/lib/aircana/templates/hooks/rubocop_pre_commit.erb +55 -0
- data/lib/aircana/templates/hooks/session_start.erb +127 -0
- data/lib/aircana/templates/hooks/user_prompt_submit.erb +46 -0
- data/lib/aircana/version.rb +1 -1
- metadata +19 -5
@@ -0,0 +1,127 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
# Multi-root project support hook for Aircana
|
3
|
+
# This hook runs when a new Claude Code session starts
|
4
|
+
|
5
|
+
PROJECT_JSON=".aircana/project.json"
|
6
|
+
CLAUDE_AGENTS_DIR=".claude/agents"
|
7
|
+
AIRCANA_AGENTS_DIR=".aircana/agents"
|
8
|
+
|
9
|
+
# Create log directory if it doesn't exist
|
10
|
+
mkdir -p ~/.aircana
|
11
|
+
|
12
|
+
# Log session start
|
13
|
+
echo "$(date): New Claude Code session started in $(pwd)" >> ~/.aircana/hooks.log
|
14
|
+
|
15
|
+
# Check if jq is available
|
16
|
+
if ! command -v jq &> /dev/null; then
|
17
|
+
echo "$(date): Warning - jq not found. Multi-root support disabled." >> ~/.aircana/hooks.log
|
18
|
+
echo "{}"
|
19
|
+
exit 0
|
20
|
+
fi
|
21
|
+
|
22
|
+
# Check if project.json exists
|
23
|
+
if [ ! -f "$PROJECT_JSON" ]; then
|
24
|
+
echo "$(date): No project.json found, skipping multi-root setup" >> ~/.aircana/hooks.log
|
25
|
+
echo "{}"
|
26
|
+
exit 0
|
27
|
+
fi
|
28
|
+
|
29
|
+
echo "$(date): Processing multi-root configuration from $PROJECT_JSON" >> ~/.aircana/hooks.log
|
30
|
+
|
31
|
+
# Ensure directories exist
|
32
|
+
mkdir -p "$CLAUDE_AGENTS_DIR" 2>/dev/null
|
33
|
+
mkdir -p "$AIRCANA_AGENTS_DIR" 2>/dev/null
|
34
|
+
|
35
|
+
# Clean up existing symlinks (only remove symlinks, not real files)
|
36
|
+
find "$CLAUDE_AGENTS_DIR" -type l -delete 2>/dev/null
|
37
|
+
find "$AIRCANA_AGENTS_DIR" -type l -delete 2>/dev/null
|
38
|
+
|
39
|
+
# Parse folders from project.json
|
40
|
+
FOLDERS=$(jq -r '.folders[]?.path // empty' "$PROJECT_JSON" 2>/dev/null)
|
41
|
+
|
42
|
+
if [ -z "$FOLDERS" ]; then
|
43
|
+
echo "$(date): No folders configured in project.json" >> ~/.aircana/hooks.log
|
44
|
+
echo "{}"
|
45
|
+
exit 0
|
46
|
+
fi
|
47
|
+
|
48
|
+
# Track what we've linked for reporting
|
49
|
+
LINKED_AGENTS=0
|
50
|
+
LINKED_KNOWLEDGE=0
|
51
|
+
|
52
|
+
# Create symlinks for each configured folder
|
53
|
+
for folder in $FOLDERS; do
|
54
|
+
# Validate folder exists
|
55
|
+
if [ ! -d "$folder" ]; then
|
56
|
+
echo "$(date): Warning - folder '$folder' not found, skipping" >> ~/.aircana/hooks.log
|
57
|
+
continue
|
58
|
+
fi
|
59
|
+
|
60
|
+
echo "$(date): Processing folder: $folder" >> ~/.aircana/hooks.log
|
61
|
+
|
62
|
+
# Get folder name for prefix (replace slashes with underscores for nested paths)
|
63
|
+
PREFIX=$(echo "$folder" | tr '/' '_')
|
64
|
+
|
65
|
+
# Link agents from sub-folder .claude/agents
|
66
|
+
if [ -d "$folder/.claude/agents" ]; then
|
67
|
+
for agent_file in "$folder/.claude/agents"/*.md; do
|
68
|
+
if [ ! -f "$agent_file" ]; then
|
69
|
+
continue
|
70
|
+
fi
|
71
|
+
|
72
|
+
AGENT_NAME=$(basename "$agent_file" .md)
|
73
|
+
LINK_NAME="${PREFIX}_${AGENT_NAME}.md"
|
74
|
+
TARGET_PATH="$CLAUDE_AGENTS_DIR/$LINK_NAME"
|
75
|
+
|
76
|
+
# Create relative path from .claude/agents to the agent file
|
77
|
+
RELATIVE_PATH=$(realpath --relative-to="$CLAUDE_AGENTS_DIR" "$agent_file" 2>/dev/null)
|
78
|
+
|
79
|
+
if [ -n "$RELATIVE_PATH" ]; then
|
80
|
+
ln -sf "$RELATIVE_PATH" "$TARGET_PATH"
|
81
|
+
echo "$(date): Linked agent: $LINK_NAME -> $RELATIVE_PATH" >> ~/.aircana/hooks.log
|
82
|
+
((LINKED_AGENTS++))
|
83
|
+
fi
|
84
|
+
done
|
85
|
+
fi
|
86
|
+
|
87
|
+
# Link knowledge from sub-folder .aircana/agents
|
88
|
+
if [ -d "$folder/.aircana/agents" ]; then
|
89
|
+
for agent_dir in "$folder/.aircana/agents"/*; do
|
90
|
+
if [ ! -d "$agent_dir" ]; then
|
91
|
+
continue
|
92
|
+
fi
|
93
|
+
|
94
|
+
AGENT_NAME=$(basename "$agent_dir")
|
95
|
+
LINK_NAME="${PREFIX}_${AGENT_NAME}"
|
96
|
+
TARGET_PATH="$AIRCANA_AGENTS_DIR/$LINK_NAME"
|
97
|
+
|
98
|
+
# Create relative path from .aircana/agents to the knowledge directory
|
99
|
+
RELATIVE_PATH=$(realpath --relative-to="$AIRCANA_AGENTS_DIR" "$agent_dir" 2>/dev/null)
|
100
|
+
|
101
|
+
if [ -n "$RELATIVE_PATH" ]; then
|
102
|
+
ln -sf "$RELATIVE_PATH" "$TARGET_PATH"
|
103
|
+
echo "$(date): Linked knowledge: $LINK_NAME -> $RELATIVE_PATH" >> ~/.aircana/hooks.log
|
104
|
+
((LINKED_KNOWLEDGE++))
|
105
|
+
fi
|
106
|
+
done
|
107
|
+
fi
|
108
|
+
done
|
109
|
+
|
110
|
+
# Report results
|
111
|
+
echo "$(date): Multi-root setup complete - linked $LINKED_AGENTS agents and $LINKED_KNOWLEDGE knowledge bases" >> ~/.aircana/hooks.log
|
112
|
+
|
113
|
+
# Return success with optional context
|
114
|
+
if [ $LINKED_AGENTS -gt 0 ] || [ $LINKED_KNOWLEDGE -gt 0 ]; then
|
115
|
+
CONTEXT="Multi-root: Linked $LINKED_AGENTS agents and $LINKED_KNOWLEDGE knowledge bases from configured folders."
|
116
|
+
ESCAPED_CONTEXT=$(echo -n "$CONTEXT" | sed 's/"/\\"/g')
|
117
|
+
cat << EOF
|
118
|
+
{
|
119
|
+
"hookSpecificOutput": {
|
120
|
+
"hookEventName": "SessionStart",
|
121
|
+
"additionalContext": "$ESCAPED_CONTEXT"
|
122
|
+
}
|
123
|
+
}
|
124
|
+
EOF
|
125
|
+
else
|
126
|
+
echo "{}"
|
127
|
+
fi
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
# User prompt submit hook generated by Aircana
|
3
|
+
# This hook runs when the user submits a prompt
|
4
|
+
|
5
|
+
# Get the user prompt
|
6
|
+
USER_PROMPT="$1"
|
7
|
+
|
8
|
+
# Add context information based on project state
|
9
|
+
CONTEXT_ADDITIONS=""
|
10
|
+
|
11
|
+
# Check if this is a Ruby project and add relevant info
|
12
|
+
if [ -f "Gemfile" ]; then
|
13
|
+
CONTEXT_ADDITIONS="${CONTEXT_ADDITIONS}\n\nProject Context: This is a Ruby project with Gemfile present."
|
14
|
+
|
15
|
+
# Check for common Ruby frameworks
|
16
|
+
if grep -q "rails" Gemfile 2>/dev/null; then
|
17
|
+
CONTEXT_ADDITIONS="${CONTEXT_ADDITIONS} Rails framework detected."
|
18
|
+
fi
|
19
|
+
|
20
|
+
if grep -q "rspec" Gemfile 2>/dev/null; then
|
21
|
+
CONTEXT_ADDITIONS="${CONTEXT_ADDITIONS} RSpec testing framework in use."
|
22
|
+
fi
|
23
|
+
fi
|
24
|
+
|
25
|
+
# Check for relevant files context
|
26
|
+
if [ -d ".aircana/relevant_files" ] && [ "$(ls -A .aircana/relevant_files 2>/dev/null)" ]; then
|
27
|
+
RELEVANT_COUNT=$(ls .aircana/relevant_files | wc -l)
|
28
|
+
CONTEXT_ADDITIONS="${CONTEXT_ADDITIONS}\n\nRelevant Files: $RELEVANT_COUNT files currently in context."
|
29
|
+
fi
|
30
|
+
|
31
|
+
# Output JSON response with additional context
|
32
|
+
if [ -n "$CONTEXT_ADDITIONS" ]; then
|
33
|
+
# Escape context for JSON
|
34
|
+
ESCAPED_CONTEXT=$(echo -n "$CONTEXT_ADDITIONS" | sed 's/"/\\"/g' | tr '\n' ' ' | sed 's/ */ /g')
|
35
|
+
cat << EOF
|
36
|
+
{
|
37
|
+
"hookSpecificOutput": {
|
38
|
+
"hookEventName": "UserPromptSubmit",
|
39
|
+
"additionalContext": "$ESCAPED_CONTEXT"
|
40
|
+
}
|
41
|
+
}
|
42
|
+
EOF
|
43
|
+
else
|
44
|
+
# No additional context needed
|
45
|
+
echo "{}"
|
46
|
+
fi
|
data/lib/aircana/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aircana
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.1.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Weston Dransfield
|
@@ -93,9 +93,8 @@ dependencies:
|
|
93
93
|
- - "~>"
|
94
94
|
- !ruby/object:Gem::Version
|
95
95
|
version: '0.9'
|
96
|
-
description:
|
97
|
-
|
98
|
-
Claude Code agents, and optionally syncknowledge from Confluence.
|
96
|
+
description: Aircana provides context management and workflow utilities for software
|
97
|
+
engineering with AI agents, including file organization and template generation.
|
99
98
|
email:
|
100
99
|
- weston@dransfield.dev
|
101
100
|
executables:
|
@@ -127,10 +126,14 @@ files:
|
|
127
126
|
- lib/aircana/cli/commands/doctor_checks.rb
|
128
127
|
- lib/aircana/cli/commands/doctor_helpers.rb
|
129
128
|
- lib/aircana/cli/commands/dump_context.rb
|
129
|
+
- lib/aircana/cli/commands/files.rb
|
130
130
|
- lib/aircana/cli/commands/generate.rb
|
131
|
+
- lib/aircana/cli/commands/hooks.rb
|
131
132
|
- lib/aircana/cli/commands/install.rb
|
132
133
|
- lib/aircana/cli/commands/plan.rb
|
134
|
+
- lib/aircana/cli/commands/project.rb
|
133
135
|
- lib/aircana/cli/commands/work.rb
|
136
|
+
- lib/aircana/cli/help_formatter.rb
|
134
137
|
- lib/aircana/cli/shell_command.rb
|
135
138
|
- lib/aircana/cli/subcommand.rb
|
136
139
|
- lib/aircana/configuration.rb
|
@@ -140,23 +143,34 @@ files:
|
|
140
143
|
- lib/aircana/contexts/confluence_logging.rb
|
141
144
|
- lib/aircana/contexts/confluence_setup.rb
|
142
145
|
- lib/aircana/contexts/local.rb
|
146
|
+
- lib/aircana/contexts/manifest.rb
|
143
147
|
- lib/aircana/contexts/relevant_files.rb
|
144
148
|
- lib/aircana/fzf_helper.rb
|
145
149
|
- lib/aircana/generators.rb
|
146
150
|
- lib/aircana/generators/agents_generator.rb
|
147
151
|
- lib/aircana/generators/base_generator.rb
|
148
152
|
- lib/aircana/generators/helpers.rb
|
153
|
+
- lib/aircana/generators/hooks_generator.rb
|
154
|
+
- lib/aircana/generators/project_config_generator.rb
|
149
155
|
- lib/aircana/generators/relevant_files_command_generator.rb
|
150
156
|
- lib/aircana/generators/relevant_files_verbose_results_generator.rb
|
151
157
|
- lib/aircana/human_logger.rb
|
152
158
|
- lib/aircana/initializers.rb
|
153
159
|
- lib/aircana/llm/claude_client.rb
|
154
160
|
- lib/aircana/progress_tracker.rb
|
161
|
+
- lib/aircana/symlink_manager.rb
|
155
162
|
- lib/aircana/system_checker.rb
|
156
163
|
- lib/aircana/templates/agents/base_agent.erb
|
157
164
|
- lib/aircana/templates/agents/defaults/planner.erb
|
158
165
|
- lib/aircana/templates/agents/defaults/worker.erb
|
159
166
|
- lib/aircana/templates/commands/add_relevant_files.erb
|
167
|
+
- lib/aircana/templates/hooks/bundle_install.erb
|
168
|
+
- lib/aircana/templates/hooks/post_tool_use.erb
|
169
|
+
- lib/aircana/templates/hooks/pre_tool_use.erb
|
170
|
+
- lib/aircana/templates/hooks/rspec_test.erb
|
171
|
+
- lib/aircana/templates/hooks/rubocop_pre_commit.erb
|
172
|
+
- lib/aircana/templates/hooks/session_start.erb
|
173
|
+
- lib/aircana/templates/hooks/user_prompt_submit.erb
|
160
174
|
- lib/aircana/templates/relevant_files_verbose_results.erb
|
161
175
|
- lib/aircana/version.rb
|
162
176
|
- sig/aircana.rbs
|
@@ -185,5 +199,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
185
199
|
requirements: []
|
186
200
|
rubygems_version: 3.6.9
|
187
201
|
specification_version: 4
|
188
|
-
summary:
|
202
|
+
summary: Humble workflow and context utilities for engineering with agents
|
189
203
|
test_files: []
|