11#! /bin/bash
22
3- # context - Code Context Generator
3+ # context - Simplified Code Context Generator
44# Generates contextual information from a codebase to send to an LLM
55
66# Default values
7- FILES =()
8- EXCLUDE=" "
7+ INCLUDE =()
8+ EXCLUDE=()
99MAX_SIZE=" 500KB"
10- DEPTH=1
1110INCLUDE_GIT=false
12- GIT_DEPTH=3
13- SUMMARY=false
1411SHOW_FILE_SIZES=false
15- TRUNCATE_LARGE=" "
16- INCLUDE_LS_FILES=true
17- LS_FILES_LIMIT=100
12+ SHOW_LS_FILES=true
1813
1914# Parse arguments
2015while [[ " $# " -gt 0 ]]; do
2116 case $1 in
22- --files =* ) FILES +=(" ${1#* =} " ); shift ;;
23- --exclude=* ) EXCLUDE= " ${1#* =} " ; shift ;;
17+ --include =* ) INCLUDE +=(" ${1#* =} " ); shift ;;
18+ --exclude=* ) EXCLUDE+=( " ${1#* =} " ) ; shift ;;
2419 --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 ;;
3423 --help|-h)
35- echo " Usage: ./context [options] [file1 file2 ...]"
24+ echo " Usage: ./context [options] [include-pattern1 include-pattern2 ...]"
3625 echo " "
3726 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\" )"
3928 echo " --exclude=<pattern> File pattern to exclude (e.g., \" node_modules/**\" )"
4029 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"
5033 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"
5146 exit 0
5247 ;;
5348 --* ) echo " Unknown parameter: $1 " ; exit 1 ;;
54- * ) FILES +=(" $1 " ); shift ;;
49+ * ) INCLUDE +=(" $1 " ); shift ;;
5550 esac
5651done
5752
@@ -70,30 +65,28 @@ convert_to_bytes() {
7065}
7166
7267MAX_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
7768
7869# Get all matching files
7970find_files () {
8071 local all_files=" "
8172
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 "
8576 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 \" "
9078 local found_files=$( eval $find_cmd )
9179 if [ -n " $found_files " ]; then
9280 all_files=" $all_files " $' \n ' " $found_files "
9381 fi
9482 fi
9583 done
9684
85+ # Process exclusions
86+ for exclude_pattern in " ${EXCLUDE[@]} " ; do
87+ all_files=$( echo " $all_files " | grep -v " $exclude_pattern " )
88+ done
89+
9790 echo " $all_files " | grep -v " ^$" | sort | uniq
9891}
9992
@@ -119,11 +112,35 @@ human_readable_size() {
119112# Start Markdown output
120113echo " # Code Context"
121114echo " "
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 " "
124128 echo " "
125129fi
126130
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+
127144# Process each file
128145for file in $ALL_FILES ; do
129146 if [ ! -f " $file " ]; then
@@ -134,92 +151,24 @@ for file in $ALL_FILES; do
134151 TOTAL_SIZE=$(( TOTAL_SIZE + file_size))
135152
136153 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
138155 exit 1
139156 fi
140157
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 " )
155159
156160 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 "
165164 fi
165+ echo " "
166166
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##* .} "
169169 echo " $file_content "
170- if [ " $truncated " = true ]; then
171- echo " "
172- echo " ... [File truncated due to size limit] ..."
173- fi
174170 echo " \`\`\` "
175171 echo " "
176172done
177173
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-
225174exit 0
0 commit comments