Directory Controller is a lightweight, cross-platform Python utility designed to bridge the gap between Large Language Models (LLMs) and your local file system.
It solves two specific problems:
- Context Creation: Turning your existing project structure into a clean text file to provide context to an LLM.
- Scaffolding: Taking a text-based directory tree generated by an LLM (ChatGPT, Claude, DeepSeek) and instantly building the actual folders and empty files.
- Universal Parsing: Intelligently parses various tree formats (Standard Tree
βββ, ASCII+--, Markdown Lists-, or Tab indentation). - Smart Detection: Automatically finds structure files (e.g.,
structure.txt,tree.md) without needing specific filenames. - Auto-Scaffolding: Creates directories and empty placeholder files based on the input map.
- Context-Aware: Uses heuristics (file extensions, trailing slashes, indentation lookahead) to distinguish files from folders even if the LLM output is messy.
- Native Windows Support: Now includes a fix to force ANSI color codes to render correctly in the Windows Command Prompt (cmd.exe) and PowerShell.
- Interactive Confirmation: Before modifying your filesystem (Option 2), the script provides a summary of detected nodes and explicitly asks for user confirmation (
y/n). This prevents accidental execution on the wrong file. - Gitignore Integration: Respects your project's
.gitignorefile during scanning, automatically excluding build artifacts, logs, secrets, and temp files. Checks both filenames and relative paths. - Infinite Loop Protection (Symlinks): The scanner now detects Symbolic Links. It identifies them in the output (e.g.,
link -> target) but stops recursion immediately. This prevents the script from freezing on circular file paths or duplicating massive libraries. - Smart Collision Resolution: If you try to move a file to a folder where it already exists, the script will not overwrite it. Instead, it automatically renames the incoming file (e.g.,
script.pyβscript_1.py) to ensure zero data loss. - Binary & Encoding Resilience: The file reader now detects binary files (like images or compiled executables) and skips them instead of crashing. It also cycles through multiple encodings (
utf-8-sig,latin-1) to handle files created in different environments (e.g., Windows Notepad). - Root-Wrap Prevention: Detects if the LLM has hallucinated a root folder that matches your current directory name. It automatically un-nests the structure to prevent
project/project/srcredundancies. - Security Sanitization: Aggressively filters file paths to remove directory traversal attacks (
../) and characters invalid on Windows (<>:"/\|?*).
- Ensure you have Python 3.6+ installed.
- Download
directory-control.py. - Place the script in the root folder of your project.
Run the script from your terminal:
python directory-control.pyYou will be presented with two options:
Best for: Giving context to an LLM.
This scans your current directory to generate a file named directory-structure.txt.
- Clean Output: It automatically filters out standard system junk (
.git,__pycache__,node_modules). - Smart Ignoring: It reads your local
.gitignorefile (if present) and excludes any matching patterns (e.g.,*.log,dist/,coverage/) so you don't overwhelm the LLM with irrelevant file paths. - Use Case: Copy the content of this text file and paste it into ChatGPT/Claude so the AI understands your current project structure.
Best for: Applying an LLM's architecture.
This looks for a structure file (e.g., structure.txt, tree.md) and builds the file system.
- Ask an LLM to generate a project structure.
- Save the LLM's output into a text file (e.g.,
structure.txt) in your project root. - Run the script and select Option 2.
- Verification: The script will parse the file and display a summary (Working Root, Number of Parsed Items) and a warning.
- Confirmation: You must type
yto proceed. - The script will:
- Analyze: Parse the text file and identify nodes.
- Sanitize: Clean up invalid characters and resolve root-wrapping issues.
- Execute: Create missing directories, create empty placeholder files, and move existing files to their new locations (with collision protection).
The script uses a Robust Parsing Engine that ignores decorative characters and focuses on indentation. It supports all of the following styles:
project/
βββ src/
β βββ main.py
β βββ utils.py
βββ README.md
- project
- src
- main.py
- utils.py
- README.md
project
|-- src
| +-- main.py
| +-- utils.py
+-- README.md
# Generated Structure
# Files: 57 | Dirs: 11
numbers/
βββ CHANGELOG.md
βββ CONTRIBUTING.md
βββ Dockerfile
βββ LICENSE.md
βββ README.md
βββ app/
β βββ __init__.py
β βββ api/
β β βββ __init__.py
β β βββ models/
β β β βββ __init__.py
β β β βββ requests.py
β β β βββ responses.py
β β βββ routers/
β β β βββ admin.py
β β β βββ catalan.py
β β β βββ e.py
β β β βββ eulers.py
β β β βββ general.py
β β β βββ legacy.py
β β β βββ lemniscate.py
β β β βββ log10.py
β β β βββ log2.py
β β β βββ log3.py
β β β βββ phi.py
β β β βββ pi.py
β β β βββ sqrt2.py
β β β βββ sqrt3.py
β β β βββ websocket.py
β β β βββ zeta3.py
β β βββ websocket_manager.py
β βββ core/
β β βββ __init_.py
β β βββ config.py
β β βββ constants.py
β β βββ exceptions.py
β β βββ redis_client.py
β βββ main.py
β βββ storage/
β β βββ __init__.py
β β βββ base_storage.py
β β βββ binary_source.py
β β βββ exceptions.py
β β βββ file_source.py
β β βββ manager.py
β β βββ multi_manager.py
β β βββ sqlite_source.py
β βββ utils/
β βββ __init__.py
βββ compose.yml
βββ data/
βββ docs/
β βββ REDIS_WEBSOCKET_QUICK_REF.md
β βββ REDIS_WEBSOCKET_USER_GUIDE.md
βββ frontend/
β βββ index.html
β βββ websocket_test.html
βββ nginx.conf
βββ project.toml
βββ rebuild.sh
βββ requirements-dev.txt
βββ requirements.txt
βββ setup_project.sh
βββ start.sh
βββ stop.sh
βββ tests/
β βββ __init__.py
βββ update_to_redis_websocket.sh
When parsing a text file, the script must decide if a line represents a File or a Directory. Since LLM output varies, the script uses the following logic hierarchy:
- Explicit Syntax: If the name ends with
/or\, it is a Directory. - Extension Check: If the name has a file extension (e.g.,
.py,.json,.js), it is a File. - Indentation Lookahead: If line
Ais followed by lineB, and lineBis indented deeper than lineA, then lineAis treated as a Directory (files cannot contain children). - Common Naming Conventions: If ambiguous, names like
src,dist,bin,assets,config,testsare treated as Directories.
- Non-Destructive Operations:
- This script NEVER deletes files.
- This script NEVER overwrites files. If a move operation conflicts, it renames the file to
filename_1.ext.
- Root Wrapper Detection:
- Problem: You are in
my-app. The LLM outputs a tree starting withmy-app/src/.... - Old Behavior: You ended up with
my-app/my-app/src/.... - New Behavior: The script sees the top-level node matches the CWD name, ignores the top node, and maps
srcdirectly to the current directory.
- Problem: You are in
- Path Sanitization:
- Leading slashes (
/var/www) are stripped to force relative paths (var/www). - Windows-invalid characters (
<,>,:,",|,?,*) are stripped from filenames to prevent OS errors. ..is removed to prevent directory traversal attacks.
- Leading slashes (
- Symlink & Binary Safety:
- The scanner detects symbolic links and refuses to follow them, preventing infinite loops.
- The file reader checks for binary content (Null bytes) to prevent the script from trying to parse images or executables as text.
- System Exclusions: The script explicitly ignores its own source file,
.git,node_modules,.env,.DS_Store, and__pycache__to prevent clutter. - Dynamic Exclusions (Gitignore): The script parses your
.gitignoreusing wildcard matching (fnmatch). It checks patterns against the filename (e.g.,error.log) AND the relative path (e.g.,build/output/main.js).
To get the best results from your LLM, use a prompt like this:
"Generate a directory structure for a [Python/Node/etc] project. Please output the structure as a standard ASCII tree or a Markdown list. Ensure folders end with a slash '/'."
Example of ideal input text file:
/my-app
/backend
server.py
config.py
/frontend
index.html
styles.css
README.md
.env.example
This script is provided "as-is" under the MIT License. It is open source and free to modify.
Disclaimer: Always back up your data before running bulk file operations. While this script includes safety checks and only creates/moves files (never deletes), automated file manipulation always carries inherent risks.