A command-line utility that intelligently gathers and concatenates file contents into a single, formatted text blob - perfect for creating context-rich prompts for Large Language Models (LLMs).
- 🚀 Simple & Fast: Works out-of-the-box with sensible defaults
- 🎯 Smart Filtering: Automatically respects
.gitignoreand common ignore patterns - 🔧 Highly Customizable: Powerful templating system for output formatting
- 🔗 Unix-friendly: Composable with other CLI tools via stdin/stdout
- 📁 Flexible Input: Supports files, directories, and glob patterns
- 🌐 Cross-platform: Consistent behavior across different operating systems
npm install -g ctxcat- Download the latest release from the releases page.
- Extract the binary to a directory in your
$PATH(e.g./usr/local/bin).
# Concatenate all files in src/ directory
ctxcat src/
# Copy to clipboard (macOS)
ctxcat src/ | pbcopy
# Use glob patterns (recommended - quote them!)
ctxcat "src/**/*.js""test/**/*.test.js"# Combine with other tools
find . -name "*.md"| ctxcatctxcat [OPTIONS] [PATH...]PATH...: Files, directories, or glob patterns to process- If no paths provided, reads newline-separated file paths from stdin
| Flag | Description |
|---|---|
--no-recursive, -nr | Disable recursive directory traversal |
| Flag | Description |
|---|---|
--exclude <pattern>, -e <pattern> | Exclude files matching glob pattern (repeatable) |
--no-gitignore | Don't respect .gitignore files |
--ignore-file <filepath> | Use custom ignore file (.gitignore syntax) |
--no-binary-check | Don't skip binary files |
| Flag | Description |
|---|---|
--output <filepath>, -o <filepath> | Write output to file instead of stdout |
--template <string> | Custom output template (see templating section) |
| Flag | Description |
|---|---|
--help, -h | Show help message |
--version, -v | Show version number |
Customize the output format using the --template flag with these variables:
| Variable | Description | Example |
|---|---|---|
{content} | Full file content | console.log('hello'); |
{path} | Relative file path | src/components/Button.js |
{absPath} | Absolute file path | User/project/src/components/Button.js |
{basename} | Filename with extension | Button.js |
{filename} | Filename without extension | Button |
{extension} | File extension (no dot) | js |
=== File Start: {path} ===
```{extension}
{content}
```
=== File End: {path} ===
Create a .ctxcat.template.txt file for default templates. ctxcat searches for this file in:
- Current working directory
- User's home directory
~/.config/ctxcat/template.txt
Note: The --template flag always overrides configuration files.
Rules are applied in this order (first match wins):
--excludepatterns → Always excluded (highest priority)- Custom ignore files → Excluded if matched
.gitignorefiles → Excluded if matched (unless--no-gitignore)- Default inclusion → Included if no exclusion rules match
ctxcat includes its own powerful glob engine with cross-platform support:
*matches any characters except path separators**matches any characters including path separators (recursive)?matches any single character[abc]matches any character in brackets
Recommended:
ctxcat "src/**/*.js""test/**/*.test.js"Also works (shell-expanded):
ctxcat src/*.js test/*.jsQuoting ensures ctxcat's glob engine handles the pattern, providing consistent behavior across different shells and platforms.
# Process all files in src directory
ctxcat src/
# Process specific files
ctxcat package.json README.md src/main.js
# Process with glob patterns
ctxcat "**/*.{js,ts,json}"# Exclude specific patterns
ctxcat src/ -e "**/__pycache__/**" -e "*.log"# Use custom ignore file
ctxcat . --ignore-file .contextignore
# Disable gitignore
ctxcat . --no-gitignore# Simple template
ctxcat src/ --template "### {path}\n{content}\n---\n"# Detailed template
ctxcat src/ --template "File: {path} ({extension})\n{content}\n\n"# Copy to clipboard
ctxcat src/ | pbcopy
# Save to file
ctxcat src/ -o context.txt
# Find specific files and process
find . -name "*.config.js"| ctxcat
# Chain with other tools
ctxcat src/ | wc -l# Create LLM context for a React project
ctxcat "src/**/*.{js,jsx,ts,tsx}""*.{json,md}" --exclude "node_modules/**"# Documentation files only
ctxcat "**/*.md""docs/**/*.txt"# Configuration files across project
find . -name "*.config.*" -o -name ".*rc*"| ctxcat- Most UI doesn't support pasting large amount of text into their UI. You can create this bash script to create a temp file and then copy it's reference to your clipboard. Then you can paste it as file into your UI.
#!/bin/bash# A script that saves stdout to a uniquely named file in a dedicated# directory and copies it to the clipboard. It cleans up the *previously*# created file on each new run.## Usage:# some_command | ./this_script.sh
STORAGE_DIR="$HOME/.clipboard_files"
TRACKER_FILE="$STORAGE_DIR/last_file.txt"
mkdir -p "$STORAGE_DIR"if [ -s"$TRACKER_FILE" ];then
LAST_FILE_PATH=$(cat "$TRACKER_FILE")if [ -f"$LAST_FILE_PATH" ];then
rm "$LAST_FILE_PATH"fifi
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
NEW_FILE_PATH="$STORAGE_DIR/clip_${TIMESTAMP}.md"
cat - >"$NEW_FILE_PATH"
osascript -e "set the clipboard to (POSIX file \"$NEW_FILE_PATH\")"echo"$NEW_FILE_PATH">"$TRACKER_FILE"echo":white_check_mark: File copied to clipboard: ${NEW_FILE_PATH##*/}"echo" You can now paste it. The previous file has been cleaned up."#!/bin/bash# A script that saves stdout to a uniquely named file in a dedicated# directory and copies it to the clipboard on Linux. It cleans up the# previously created file on each new run.## Usage:# some_command | ./this_script.sh
STORAGE_DIR="$HOME/.clipboard_files"
TRACKER_FILE="$STORAGE_DIR/last_file.txt"check_dependencies() {
if!command -v xclip &> /dev/null
thenecho"Error: 'xclip' is not installed."echo"Please install it using your distribution's package manager, e.g.:"echo" sudo apt install xclip (for Debian/Ubuntu)"echo" sudo yum install xclip (for CentOS/RHEL)"echo" sudo pacman -S xclip (for Arch Linux)"exit 1
fi
}
check_dependencies
mkdir -p "$STORAGE_DIR"if [ -s"$TRACKER_FILE" ];then
LAST_FILE_PATH=$(cat "$TRACKER_FILE")if [ -f"$LAST_FILE_PATH" ];then
rm "$LAST_FILE_PATH"fifi
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
NEW_FILE_PATH="$STORAGE_DIR/clip_${TIMESTAMP}.md"
cat - >"$NEW_FILE_PATH"
xclip -selection clipboard <"$NEW_FILE_PATH"echo"$NEW_FILE_PATH">"$TRACKER_FILE"echo":white_check_mark: File copied to clipboard: ${NEW_FILE_PATH##*/}"echo" You can now paste it. The previous file has been cleaned up."Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
