1
1
#! /bin/bash
2
2
3
- # context - Code Context Generator
3
+ # context - Simplified Code Context Generator
4
4
# Generates contextual information from a codebase to send to an LLM
5
5
6
6
# Default values
7
- FILES =()
8
- EXCLUDE=" "
7
+ INCLUDE =()
8
+ EXCLUDE=()
9
9
MAX_SIZE=" 500KB"
10
- DEPTH=1
11
10
INCLUDE_GIT=false
12
- GIT_DEPTH=3
13
- SUMMARY=false
14
11
SHOW_FILE_SIZES=false
15
- TRUNCATE_LARGE=" "
16
- INCLUDE_LS_FILES=true
17
- LS_FILES_LIMIT=100
12
+ SHOW_LS_FILES=true
18
13
19
14
# Parse arguments
20
15
while [[ " $# " -gt 0 ]]; do
21
16
case $1 in
22
- --files =* ) FILES +=(" ${1#* =} " ); shift ;;
23
- --exclude=* ) EXCLUDE= " ${1#* =} " ; shift ;;
17
+ --include =* ) INCLUDE +=(" ${1#* =} " ); shift ;;
18
+ --exclude=* ) EXCLUDE+=( " ${1#* =} " ) ; shift ;;
24
19
--max-size=* ) MAX_SIZE=" ${1#* =} " ; shift ;;
25
- --depth=* ) DEPTH=" ${1#* =} " ; shift ;;
26
- --include-git) INCLUDE_GIT=true; shift ;;
27
- --git-depth=* ) GIT_DEPTH=" ${1#* =} " ; shift ;;
28
- --summary) SUMMARY=true; shift ;;
29
- --show-file-sizes) SHOW_FILE_SIZES=true; shift ;;
30
- --truncate-large=* ) TRUNCATE_LARGE=" ${1#* =} " ; shift ;;
31
- --ls-files) INCLUDE_LS_FILES=true; shift ;;
32
- --no-ls-files) INCLUDE_LS_FILES=false; shift ;;
33
- --ls-files-limit=* ) LS_FILES_LIMIT=" ${1#* =} " ; shift ;;
20
+ --git) INCLUDE_GIT=true; shift ;;
21
+ --show-sizes) SHOW_FILE_SIZES=true; shift ;;
22
+ --no-ls-files) SHOW_LS_FILES=false; shift ;;
34
23
--help|-h)
35
- echo " Usage: ./context [options] [file1 file2 ...]"
24
+ echo " Usage: ./context [options] [include-pattern1 include-pattern2 ...]"
36
25
echo " "
37
26
echo " Options:"
38
- echo " --files =<pattern> File pattern to include (e.g., \" src/*.js\" )"
27
+ echo " --include =<pattern> File pattern to include (e.g., \" src/*.js\" )"
39
28
echo " --exclude=<pattern> File pattern to exclude (e.g., \" node_modules/**\" )"
40
29
echo " --max-size=<size> Maximum context size in KB/MB (e.g., \" 500KB\" )"
41
- echo " --depth=<num> Dependency traversal depth (default: 1)"
42
- echo " --include-git Include git information (recent commits, authors)"
43
- echo " --git-depth=<num> Number of recent commits to include (default: 3)"
44
- echo " --summary Include short summary of each file"
45
- echo " --show-file-sizes Include file sizes in output"
46
- echo " --truncate-large=<size> Truncate files larger than specified size (e.g., \" 50KB\" )"
47
- echo " --ls-files Include git ls-files output (default: true)"
48
- echo " --no-ls-files Don't include git ls-files output"
49
- echo " --ls-files-limit=<num> Limit the number of files shown in ls-files (default: 100)"
30
+ echo " --git Include basic git information (recent commits, branch)"
31
+ echo " --show-sizes Include file sizes in output"
32
+ echo " --no-ls-files Don't include git ls-files output in repository map"
50
33
echo " --help, -h Show this help message"
34
+ echo " "
35
+ echo " Pattern matching:"
36
+ echo " Patterns use bash 'find' command syntax with -path flag"
37
+ echo " Examples:"
38
+ echo " \" *.js\" - All JavaScript files in current directory"
39
+ echo " \" src/*.js\" - All JavaScript files in src directory"
40
+ echo " \" src/**/*.js\" - All JavaScript files in src and subdirectories"
41
+ echo " \" !test/*\" - Exclude all files in test directory"
42
+ echo " "
43
+ echo " Examples:"
44
+ echo " ./context --include=\" src/*.js\" --exclude=\" *.test.js\" "
45
+ echo " ./context \" src/*.js\" \" *.md\" --max-size=1MB"
51
46
exit 0
52
47
;;
53
48
--* ) echo " Unknown parameter: $1 " ; exit 1 ;;
54
- * ) FILES +=(" $1 " ); shift ;;
49
+ * ) INCLUDE +=(" $1 " ); shift ;;
55
50
esac
56
51
done
57
52
@@ -70,30 +65,28 @@ convert_to_bytes() {
70
65
}
71
66
72
67
MAX_SIZE_BYTES=$( convert_to_bytes " $MAX_SIZE " )
73
- TRUNCATE_SIZE_BYTES=0
74
- if [ -n " $TRUNCATE_LARGE " ]; then
75
- TRUNCATE_SIZE_BYTES=$( convert_to_bytes " $TRUNCATE_LARGE " )
76
- fi
77
68
78
69
# Get all matching files
79
70
find_files () {
80
71
local all_files=" "
81
72
82
- for file_pattern in " ${FILES [@]} " ; do
83
- if [ -f " $file_pattern " ]; then
84
- all_files=" $all_files " $' \n ' " $file_pattern "
73
+ for pattern in " ${INCLUDE [@]} " ; do
74
+ if [ -f " $pattern " ]; then
75
+ all_files=" $all_files " $' \n ' " $pattern "
85
76
else
86
- local find_cmd=" find . -type f -path \" $file_pattern \" "
87
- if [ -n " $EXCLUDE " ]; then
88
- find_cmd=" $find_cmd -not -path \" $EXCLUDE \" "
89
- fi
77
+ local find_cmd=" find . -type f -path \" $pattern \" "
90
78
local found_files=$( eval $find_cmd )
91
79
if [ -n " $found_files " ]; then
92
80
all_files=" $all_files " $' \n ' " $found_files "
93
81
fi
94
82
fi
95
83
done
96
84
85
+ # Process exclusions
86
+ for exclude_pattern in " ${EXCLUDE[@]} " ; do
87
+ all_files=$( echo " $all_files " | grep -v " $exclude_pattern " )
88
+ done
89
+
97
90
echo " $all_files " | grep -v " ^$" | sort | uniq
98
91
}
99
92
@@ -119,11 +112,35 @@ human_readable_size() {
119
112
# Start Markdown output
120
113
echo " # Code Context"
121
114
echo " "
122
- if [ ${# FILES[@]} -gt 0 ]; then
123
- echo " ## Files"
115
+
116
+ # Include git information if requested
117
+ if [ " $INCLUDE_GIT " = true ] && command -v git > /dev/null 2>&1 && git rev-parse --is-inside-work-tree > /dev/null 2>&1 ; then
118
+ echo " ## Repository Information"
119
+ echo " "
120
+ echo " Branch: $( git branch --show-current) "
121
+ echo " "
122
+ echo " Recent commits:"
123
+ echo " "
124
+ git log -n 3 --pretty=format:" * %h: %s (%an, %ar)" | while read line; do
125
+ echo " $line "
126
+ done
127
+ echo " "
124
128
echo " "
125
129
fi
126
130
131
+ # Include git ls-files by default for repository map
132
+ if [ " $SHOW_LS_FILES " = true ] && command -v git > /dev/null 2>&1 && git rev-parse --is-inside-work-tree > /dev/null 2>&1 ; then
133
+ echo " ## Repository Map"
134
+ echo " "
135
+ git ls-files | sort | while read -r file; do
136
+ echo " - $file "
137
+ done
138
+ echo " "
139
+ fi
140
+
141
+ echo " ## Files"
142
+ echo " "
143
+
127
144
# Process each file
128
145
for file in $ALL_FILES ; do
129
146
if [ ! -f " $file " ]; then
@@ -134,92 +151,24 @@ for file in $ALL_FILES; do
134
151
TOTAL_SIZE=$(( TOTAL_SIZE + file_size))
135
152
136
153
if [ $TOTAL_SIZE -gt $MAX_SIZE_BYTES ]; then
137
- echo " Error: Total context size ( $TOTAL_SIZE bytes) exceeds maximum allowed size ($( human_readable_size $MAX_SIZE_BYTES ) ). Reduce file scope or increase --max-size." >&2
154
+ echo " Error: Total context size exceeds maximum allowed size ($( human_readable_size $MAX_SIZE_BYTES ) ). Reduce file scope or increase --max-size." >&2
138
155
exit 1
139
156
fi
140
157
141
- truncated=false
142
- file_content=" "
143
-
144
- if [ $TRUNCATE_SIZE_BYTES -gt 0 ] && [ $file_size -gt $TRUNCATE_SIZE_BYTES ]; then
145
- file_content=$( head -c $TRUNCATE_SIZE_BYTES " $file " )
146
- truncated=true
147
- else
148
- file_content=$( cat " $file " )
149
- fi
150
-
151
- file_summary=" "
152
- if [ " $SUMMARY " = true ]; then
153
- file_summary=$( head -n 20 " $file " | grep -E " ^(//|#|/*) " | head -n 5 | sed ' s/^[\/\#\* ]*//' )
154
- fi
158
+ file_content=$( cat " $file " )
155
159
156
160
if [ " $SHOW_FILE_SIZES " = true ]; then
157
- echo " Size: $( human_readable_size $file_size ) "
158
- echo " "
159
- fi
160
-
161
- if [ " $SUMMARY " = true ] && [ -n " $file_summary " ]; then
162
- echo " Summary:"
163
- echo " $file_summary "
164
- echo " "
161
+ echo " ### $file ($( human_readable_size $file_size ) )"
162
+ else
163
+ echo " ### $file "
165
164
fi
165
+ echo " "
166
166
167
- # Use proper markdown code block with three backticks
168
- echo " \`\`\` ${file##* .} $file "
167
+ # Use proper markdown code block with file extension for syntax highlighting
168
+ echo " \`\`\` ${file##* .} "
169
169
echo " $file_content "
170
- if [ " $truncated " = true ]; then
171
- echo " "
172
- echo " ... [File truncated due to size limit] ..."
173
- fi
174
170
echo " \`\`\` "
175
171
echo " "
176
172
done
177
173
178
- # Include git information if requested
179
- if [ " $INCLUDE_GIT " = true ] && command -v git > /dev/null 2>&1 && git rev-parse --is-inside-work-tree > /dev/null 2>&1 ; then
180
- echo " ## Git Information"
181
- echo " "
182
- echo " ### Recent Commits"
183
- echo " "
184
- git log -n $GIT_DEPTH --pretty=format:" * %h: %s (%an, %ar)" | while read line; do
185
- echo " $line "
186
- done
187
- echo " "
188
- echo " ### Branch Information"
189
- echo " "
190
- echo " Current branch: $( git branch --show-current) "
191
- echo " "
192
- fi
193
-
194
- # Include git ls-files output if requested
195
- if [ " $INCLUDE_LS_FILES " = true ] && command -v git > /dev/null 2>&1 && git rev-parse --is-inside-work-tree > /dev/null 2>&1 ; then
196
- GIT_FILES=$( git ls-files | sort)
197
- GIT_FILES_COUNT=$( echo " $GIT_FILES " | wc -l)
198
-
199
- if [ $GIT_FILES_COUNT -gt $LS_FILES_LIMIT ]; then
200
- GIT_FILES=$( echo " $GIT_FILES " | head -n $LS_FILES_LIMIT )
201
- GIT_FILES_TRUNCATED=true
202
- else
203
- GIT_FILES_TRUNCATED=false
204
- fi
205
-
206
- echo " ## Repository Files"
207
- echo " "
208
- echo " $GIT_FILES " | while read -r file; do
209
- echo " - $file "
210
- done
211
- if [ " $GIT_FILES_TRUNCATED " = true ]; then
212
- echo " - ... (and $(( $GIT_FILES_COUNT - $LS_FILES_LIMIT )) more files)"
213
- fi
214
- echo " "
215
- fi
216
-
217
- # Include default prompt if available
218
- if [ -f " prompts/context_prompt.txt" ]; then
219
- echo " ## Instructions for LLM"
220
- echo " "
221
- cat " prompts/context_prompt.txt"
222
- echo " "
223
- fi
224
-
225
174
exit 0
0 commit comments