I use the Gemini web chat interface quite extensively. One thing that is tedious is giving it all the context it needs to do a proper job. Context engineering is not an easy task, but on the other hand we now have context limits of ~1 million token, which allows us to just dump in everything we have in many cases. And when we do that in the web interface, we can avoid extra costs that would be charged when using the API!
The functions below pack your current work (diffs, full repos, or specific commits) into XML/Diff files, which are then load into your clipboard as File Uploads. My workflow with them is something like this:
- Run
pack_repo_contextin a terminal - Open https://gemini.google.com Show archive.org snapshot in a new tab
- Press
Ctrl+V - Ask a question
- Repeat
Prerequisites
- The
xclipapt package -
repomix
Show archive.org snapshot
installed (we use
npx repomix@latestbelow)
Usage
| Function | Use Cases |
|---|---|
pack_repo_context |
Packs the entire repo (with some exclusions!) into 1-5 XML files. Can be used for all kind of tasks from "How does this project work?" to large refactors. |
pack_git_diff_main |
Generates a diff between the current work and main. Can be used for Code reviews, test generation etc. |
pack_git_diff_head |
Generates a diff of uncommitted changes. Can be used to get assistance on current work. |
pack_git_show |
Generates a diff for the last commit on your current branch. Can sometimes be useful to iterate on already committed work. |
Configuration
Bash Functions
# ~/.bashrc or wherever else you place your bash functions
IGNORED_BINARY_EXTS=(
"png" "jpg" "jpeg" "gif" "ico" "svg"
"woff" "woff2" "ttf" "eot"
"pdf" "PDF" "d2" "bmml" "xsd" "xsl"
"jar" "gz" "map" "enc" "m4v" "yml"
"key" "sqlite3" "rdb"
)
_copy_file_uris() {
local uri_list=""
local count=0
for file_path in "$@"; do
if [[ -f "$file_path" ]]; then
uri_list="${uri_list}file://$(readlink -f "$file_path")\n"
((count++))
fi
done
if [ $count -eq 0 ]; then
echo "No files created or found to copy."
return 1
fi
printf "$uri_list" | head -c -1 | xclip -selection clipboard -t text/uri-list
echo "📋 Copied $count file(s) to clipboard."
}
___repomix_ignores() {
local excludes=""
for ext in "${IGNORED_BINARY_EXTS[@]}"; do
excludes="$excludes,**/*.$ext"
done
echo "${excludes:1}"
}
___git_excludes() {
excludes=()
for ext in "${IGNORED_BINARY_EXTS[@]}"; do
excludes+=(":!*.$ext")
done
}
pack_repo_context() {
local dyn_ignores=$(___repomix_ignores)
local out_dir="tmp"
local base_name="repomix-out"
mkdir -p "$out_dir"
rm -f "$out_dir/$base_name"*.xml
npx repomix@latest \
--ignore "$dyn_ignores" \
--output "$out_dir/$base_name.xml" \
--split-output "2mb" \
--quiet
local files=()
if compgen -G "$out_dir/$base_name*.xml" > /dev/null; then
files=("$out_dir/$base_name"*.xml)
else
files=("$out_dir/$base_name.xml")
fi
_copy_file_uris "${files[@]}"
}
pack_git_diff_main() {
local out_file="tmp/git-diff-main.diff"
local excludes
___git_excludes
mkdir -p tmp
git diff main -- "${excludes[@]}" > "$out_file"
_copy_file_uris "$out_file"
}
pack_git_diff_head() {
local out_file="tmp/git-diff-head.diff"
local excludes
___git_excludes
mkdir -p tmp
git diff HEAD -- "${excludes[@]}" > "$out_file"
_copy_file_uris "$out_file"
}
pack_git_show() {
local out_file="tmp/git-show.diff"
local excludes
___git_excludes
mkdir -p tmp
if [ $# -eq 0 ]; then
git show -- "${excludes[@]}" > "$out_file"
else
git show "$@" -- "${excludes[@]}" > "$out_file"
fi
_copy_file_uris "$out_file"
}
Repomix Config
LLMs parse XML quite well. Reduce whitespace and comments to save tokens. Ignore some files explicitly.
# ~/.config/repomix/repomix.config.json
{
"output": {
"dir": "tmp",
"style": "xml",
"removeEmptyLines": true,
"removeComments": true,
"parsableStyle": true,
"compress": false
},
"ignore": {
"customPatterns": [
"db/migrate/*.rb",
".env*",
"bin/*",
"public/packs/*",
"public/packs-test/*",
"spec/fixtures/*",
"gurney.yml",
".geordi.yml"
]
}
}
Alternative bash alias
The bash functions above are only an iteration from my previous bash alias. It became quite unreadable over time and and copies the raw XML to the clipboard (not files). If you prefer less magic in your .bashrc, feel free to use it instead:
alias pack_repo_context='npx repomix@latest --remove-empty-lines --remove-comments --ignore "db/migrate/*.rb,.env*,bin/*,*/**/*.key,*/**/*.sqlite3,*/**/*.svg,*/**/*.woff2,*/**/*.eot,*/**/*.ttf,*/**/*.woff,*/**/*.rdb,*.rdb,*/**/*.gif,*/**/*.jpg,*/**/*.jpeg,*/**/*.d2,*/**/*.bmml,*/**/*.xsd,*/**/*.xsl,*/**/*.jar,*/**/*.gz*,*/**/*.map,public/packs/*,public/packs-test/*,spec/fixtures/*,**/*.png,**/*.pdf,**/*.jpg,**/*.ico,spec/**/*.yml,**/*.enc,**/*.PDF,gurney.yml,.geordi.yml," -o tmp/repomix.xml --quiet --copy'