Generate LLM-friendly markdown from your project files.
Project description
Project Context
Generate LLM-friendly markdown from your project files.
Project Context Generator
project-context is a Python tool that generates LLM-friendly markdown documentation of your entire project structure and contents. It creates a single markdown file containing both a visual tree representation of your project and the actual content of your source files, making it easy to share your codebase context with AI assistants.
Key Features
- Intelligent file filtering: Automatically respects
.gitignorefiles and Git tracking status - Flexible inclusion/exclusion: Use regex patterns to precisely control which files are included or excluded
- Customizable output: Support for custom Jinja2 templates to format the output
- Smart content selection: Automatically includes the most common file type in your project for markdown output
- Pre-commit integration: Can automatically generate context files on every commit
Example
Let's say you have a basic Python package with this structure:
hello-world-pkg/
├── .gitignore
├── README.md
├── pyproject.toml
└── src/
└── hello_world/
├── __init__.py
└── main.py
Where src/hello_world/main.py contains:
def main():
print("Hello, World!")
if __name__ == "__main__":
main()
Running project-context from the project root would generate the following output to stdout:
# hello-world-pkg
## Project Structure
hello-world-pkg/
├── .gitignore
├── README.md
├── pyproject.toml
└── src/
└── hello_world/
├── __init__.py
└── main.py
## Project Contents
### src/hello_world/main.py
```
def main():
print("Hello, World!")
if __name__ == "__main__":
main()
```
This single markdown file now contains your entire project context in a format that's perfect for pasting into ChatGPT, Claude, Gemini, or any other LLM when you need help with your code!
Usage
Installation
Using uv (recommended)
uv tool install project-context
Evoke using uvx project-context
Using pip
pip install project-context
Evoke using project-context
Basic Usage
By default, all files tracked by Git are included in the directory tree.
Generate context for the current directory and write it to stdout:
project-context
Save output to a file:
project-context -o CONTEXT.md
Customizing the Output
By default, all files that are tracked by Git are included in the directory tree in the Project structure section, and only the most common file type is included as part of the Project contents section. In the above example, the only file included was src/hello_world/main.py since .py is the most common file type in this project (__init__.py was excluded since it was empty).
Command Line Options
| Flag | Description | Example |
|---|---|---|
--root, -r |
Root directory to use. Defaults to the current working directory. | -r my-repo |
--exclude, -e |
Regex patterns to exclude paths from the tree | -e 'test.*' |
--include, -i |
Only include paths matching these regex patterns | -i '.*\.py$' -i '.*\.y[a]?ml$ |
--always-include, -a |
Always include these paths regardless of exclusion rules | -a 'README.*' |
--contents, -c |
Regex patterns to include paths matching these patterns in contents section | -c '.*\.py$' -c '^README\.*' |
--output, -o |
Output file path (prints to stdout if not specified) | -o CONTEXT.md |
--template, -t |
Path to custom Jinja2 template file | -t my_template.md.j2 |
Important: Be careful to escape your regex args properly. Notice the use of single quotes around regex patterns to avoid issues due to shell expansion.
All regex flags can be specified multiple times to include/exclude multiple patterns, and combined as needed.
For any file in the root directory, the inclusion/exclusion rules are applied in the following order:
Project Structure ("tree") Inclusion/Exclusion Rules
- IF the path matches any pattern in always-include, THEN it is included in the tree
- ELSE IF the path matches any pattern in exclude, THEN it is excluded from the tree
- ELSE IF there are include patterns THEN
- IF the path matches any pattern in include, THEN it is included in the tree
- ELSE it is excluded from the tree
- ELSE IF the path is a file tracked by Git, THEN it is included in the tree
- ELSE IF the path is a file that is ignored using a
.gitignore, THEN it is excluded from the tree - ELSE IF the path is a dot-file (ie its name starts with a
.), THEN it is excluded from the tree - ELSE the path is included in the tree
Project Contents Inclusion/Exclusion Rules
- IF the path is included in the tree, THEN
- IF there are contents patterns, THEN
- IF the path matches any patterns in contents, THEN its contents are included in the contents section
- ELSE the path's contents are excluded from the contents section
- ELSE IF the path suffix is the most common file type in the project, THEN its contents are included in the contents section
- ELSE the path's contents are excluded from the contents section
- IF there are contents patterns, THEN
- ELSE the path's contents are excluded from the contents section
Advanced Usage Examples
Write the context of a subdirectory to a custom dot-file:
project-context -r src/my_project -o src/my_project/.context.md
Include Python files, YAML files, and markdown files in the content section:
project-context -c '.*\.(py|md|yaml)$'
Exclude multiple patterns from the project context:
project-context -e '^\..*' -e '.*\.yaml$'
Exclude all YAML files, except for your .pre-commit-config.yaml:
project-context -e '.*\.yaml$' -a '\.pre-commit-config\.yaml'
Only include typescript files and README files:
project-context -i '.*\.ts$' -a 'README.*'
Generate the output using a custom template and write to file:
project-context -t custom_template.md.j2 -o CONTEXT.md
Pre-commit Hook Integration
For automated context generation on each commit, add this to your .pre-commit-config.yaml:
repos:
- repo: https://github.com/jeffmm/project-context
rev: main # or specific version tag
hooks:
- id: project-context
name: Generate LLM context from project contents
files: '' # change as needed if you only want to update when specific files change
args: ['-o', 'CONTEXT.md'] # default args, update as needed
Important:
Consider adding CONTEXT.md to your .gitignore file if you don't want to track the generated context file in your repository, since it effectively duplicates your project contents.
The pre-commit hook will automatically regenerate the context file whenever you make a commit, ensuring your project context is always up-to-date for sharing with LLMs.
Jinja2 Template Customization
The default output template is:
# {{ root }}
## Project Structure
{{ tree }}
## Project Contents
{{ contents }}
For a well-documented project, the default can work well enough on its own, but you can further customize the output format by providing your own Jinja2 template file. This can be useful for providing additional context or constraints that might improve the quality of AI responses.
project-context defines three variables for rendering the output: root, tree, and contents.
For example, using a template like this would add a header to the context with some project-specific details that can help steer the LLM to produce output that's more aligned to your project's needs:
{# custom_template.md.j2 #}
# {{ root }}
## Project Description
### High-level Overview:
Here is a brief description of the project and its purpose...
### Project Roadmap
Here is the planned roadmap for the project...
### Developer Guidelines
Here are some guidelines and constraints on how the project should be maintained...
## Project Structure
{{ tree }}
## Project Contents
{{ contents }}
Then you can generate the context using your custom template like this:
project-context -t custom_template.md.j2 -o CONTEXT.md
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file project_context-0.2.0.tar.gz.
File metadata
- Download URL: project_context-0.2.0.tar.gz
- Upload date:
- Size: 39.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
623f56fdb9b8b23719ffeec5ea0ef177a06306e0f5d903b21bcac5b8aa02b5bc
|
|
| MD5 |
dfa022687fd4f7984bc7eeeecb1d3519
|
|
| BLAKE2b-256 |
9a4ab6fdc2e958d7a117675ce5092690392ca7c67eff4049f9f406c3de4cb900
|
Provenance
The following attestation bundles were made for project_context-0.2.0.tar.gz:
Publisher:
ci.yaml on jeffmm/project-context
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
project_context-0.2.0.tar.gz -
Subject digest:
623f56fdb9b8b23719ffeec5ea0ef177a06306e0f5d903b21bcac5b8aa02b5bc - Sigstore transparency entry: 237828934
- Sigstore integration time:
-
Permalink:
jeffmm/project-context@d83859c775ca2e914ca100d7bc6bf73a3d24e758 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/jeffmm
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yaml@d83859c775ca2e914ca100d7bc6bf73a3d24e758 -
Trigger Event:
push
-
Statement type:
File details
Details for the file project_context-0.2.0-py3-none-any.whl.
File metadata
- Download URL: project_context-0.2.0-py3-none-any.whl
- Upload date:
- Size: 13.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
93fcd6873b74b9df655dbd8db31fa285b8dca4ec522417489b3afe7ac4c3225c
|
|
| MD5 |
7c7cd5435b44a49869548492266e9d11
|
|
| BLAKE2b-256 |
75545961028115a8d8f53305b4ef7a83d44b86a33149569b874b778bf23a374f
|
Provenance
The following attestation bundles were made for project_context-0.2.0-py3-none-any.whl:
Publisher:
ci.yaml on jeffmm/project-context
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
project_context-0.2.0-py3-none-any.whl -
Subject digest:
93fcd6873b74b9df655dbd8db31fa285b8dca4ec522417489b3afe7ac4c3225c - Sigstore transparency entry: 237828941
- Sigstore integration time:
-
Permalink:
jeffmm/project-context@d83859c775ca2e914ca100d7bc6bf73a3d24e758 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/jeffmm
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yaml@d83859c775ca2e914ca100d7bc6bf73a3d24e758 -
Trigger Event:
push
-
Statement type: