codeForLLM is a small command-line tool that converts a source-code directory into a single Markdown file that can be given to an LLM.
The main idea is simple:
Source code directory
│
▼
codeForLLM
│
├── respects .gitignore
├── skips binary files
├── scans source files
├── redacts secrets
│
▼
codebase.md
The resulting Markdown file contains the source tree as Markdown code blocks, making it convenient to provide an entire codebase as context to an AI assistant.
it can be installed directly with pip:
python3 -m pip install "git+https://github.com/Mahfa/codeForLLM.git"After installation, the codeForLLM command is available from the terminal.
Run the tool against a project directory:
codeForLLM ./my-projectBy default, this creates:
codebase.md
You can specify the output file:
codeForLLM ./my-project -o all.mdFor example:
my-project/
├── README.md
├── setup.py
├── requirements.txt
├── src/
│ ├── main.py
│ └── utils.py
└── .gitignore
Running:
codeForLLM ./my-project -o all.mdproduces a Markdown document containing sections similar to:
# Source Code: my-project
### `setup.py`
```py
from setuptools import setup
...
```
### `src/main.py`
```py
def main():
...
```When asking an LLM to understand an existing project, it is often useful to provide the source code as one document.
Instead of manually copying files one by one, codeForLLM collects the project into a single Markdown file.
This is useful for:
- Code reviews
- Debugging
- Architecture discussions
- Refactoring
- Documentation generation
- Understanding an unfamiliar project
- Asking an LLM to explain an entire codebase
- Feeding source code into AI coding tools
codeForLLM respects .gitignore files.
The root .gitignore is loaded, and nested .gitignore files are also recognized while walking through the project.
The .git directory is always ignored.
This means files and directories that are intentionally excluded from the repository are not automatically included in the generated Markdown.
For example, if your project contains:
node_modules/
build/
dist/
.env
*.logthose paths will be excluded when they match the active ignore rules.
One of the most important features of codeForLLM is automatic secret redaction.
Source code frequently contains credentials such as:
password = "my-real-password"
api_key = "my-real-api-key"
client_secret = "my-real-secret"Sending these values to an LLM can unintentionally expose credentials.
Before writing source code into the generated Markdown file, codeForLLM scans the content and replaces recognized sensitive values with descriptive placeholders.
For example:
database_password = "SuperSecretPassword123"
api_key = "sk_live_abcdef123456"becomes:
database_password = "<REDACTED_PASSWORD>"
api_key = "<REDACTED_API_KEY>"The purpose of using descriptive placeholders instead of a generic string such as THIS_IS_A_SECRET_I_REMOVE_IT is to preserve useful context for the LLM.
For example:
database_password = "<REDACTED_PASSWORD>"tells the LLM both:
- There is a value here.
- The value is a password.
This allows the LLM to understand the structure of the application without receiving the actual credential.
The sanitizer recognizes several common categories, including:
- Passwords
- API keys
- Secrets
- Access tokens
- Authentication tokens
- Bearer tokens
- Authorization values
- Refresh tokens
- Session tokens
- Private keys
- Signing keys
- Encryption keys
- Credentials
- Database connection credentials
- JWTs
- AWS access keys
- Google API keys
- GitHub tokens
- Slack tokens
- Credentials embedded in URLs
Private-key blocks such as:
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
are replaced with:
<REDACTED_PRIVATE_KEY>
This:
database:
username: "admin"
password: "secret-password"becomes:
database:
username: "admin"
password: "<REDACTED_PASSWORD>"And:
Authorization: Bearer eyJhbGciOi...becomes:
Authorization: Bearer <REDACTED_BEARER_TOKEN>Secret redaction happens only while generating the Markdown document.
The original source files are not changed.
For example:
project/
├── config.py ← unchanged
├── main.py ← unchanged
└── ...
Only the generated file contains the redacted versions:
all.md ← secrets removed
This is important because codeForLLM is intended to create a safe representation of your source code for sharing with an LLM.
Secret redaction is enabled by default.
If you explicitly want the original source content in the generated Markdown, use:
codeForLLM ./my-project -o all.md --no-redactUsing --no-redact can put passwords, API keys, tokens, private keys, and other credentials into the generated Markdown file.
Only use it when you understand the security implications.
The first argument is the source directory:
codeForLLM ./my-projectUse -o or --output to select the Markdown output file:
codeForLLM ./my-project -o all.mdThe default output file is:
codebase.md
Use:
--no-redactto disable secret sanitization:
codeForLLM ./my-project --no-redactThe tool performs the following steps:
- Resolves the source directory.
- Loads the root
.gitignore. - Always ignores the
.gitdirectory. - Walks through the source tree.
- Loads nested
.gitignorefiles when encountered. - Removes ignored directories from traversal.
- Skips ignored files.
- Skips hidden files such as
.gitignoreand.DS_Store. - Reads text source files as UTF-8.
- Detects and redacts recognized secrets.
- Determines the file's extension.
- Writes the file into the Markdown document as a fenced code block.
- Skips files that cannot be decoded as UTF-8, which generally avoids including binary files.
Each source file becomes a Markdown section:
### `path/to/file.py`
```py
# source code
```The generated document starts with:
# Source Code: project-nameThis makes the resulting file easy for both humans and LLMs to navigate.
Secret redaction is designed to reduce accidental credential exposure, but it should not be considered a perfect security boundary.
No pattern-based scanner can guarantee detection of every possible secret.
For example, a secret may be:
- Stored under an unusual variable name
- Split across multiple values
- Encoded or encrypted
- Constructed dynamically
- Stored in an unusual file format
- Embedded in data that looks like normal application data
Therefore, you should still review the generated Markdown before sharing it with an external service or LLM.
A good workflow is:
Source repository
│
▼
codeForLLM
│
▼
all.md
│
▼
Review generated file
│
▼
Send to LLM
Install:
python3 -m pip install "git+https://github.com/Mahfa/codeForLLM.git"Generate the Markdown:
codeForLLM ./my-project -o all.mdInspect it:
less all.mdThen provide all.md to your preferred LLM or AI coding workflow.
The package requires Python 3 and uses pathspec for .gitignore matching.
The package is installed from the Git repository with pip, so pip will install the declared Python dependency automatically.
The project currently has a small structure:
codeForLLM/
├── codeForLLM/
│ ├── __init__.py
│ └── main.py
├── setup.py
└── ...
The command-line entry point is:
codeForLLM = codeForLLM.main:main
The goal of codeForLLM is not to replace source-control tools, code search systems, or dedicated AI coding environments.
It is a simple bridge between a source-code directory and an LLM.
The desired workflow is:
Your repository
│
│ codeForLLM
▼
One readable Markdown file
│
│ review / share
▼
LLM
The generated document keeps the original file paths and programming-language information while removing many common forms of sensitive information.