apply-whole
v0.1.6
Published
A blazing fast CLI tool to extract code blocks from markdown and write them to your filesystem
Maintainers
Readme
Apply Whole ✨
A blazing fast 🚀 CLI tool, built with Bun, to extract specially formatted code blocks from markdown and write them directly to your filesystem. Perfect for safely applying patches, setup instructions, or documentation snippets as actual code.
Features 📋
- Clipboard or File Input: Reads markdown content from your system clipboard or a specified file.
- Precise Code Extraction: Identifies code blocks using a specific comment format (
// path/to/your/file.ext) placed either on the delimiter line or the line immediately following it. - Filesystem Application: Writes the extracted code to the corresponding file paths.
- Automatic Directory Creation: Creates necessary directories for target files if they don't exist.
- Pre-Analysis: Scans the markdown for formatting issues (like mismatched delimiters or invalid path comments) before applying changes.
- TypeScript Linting: Runs TypeScript checking before and after applying changes to ensure code quality.
- Linting Stats: Reports the number of TypeScript errors and warnings before and after changes are applied.
- Interactive Confirmation: Prompts the user to confirm the detected changes before writing to the filesystem.
- Safe Revert: Automatically reverts all successful changes if the user declines the confirmation prompt.
- Detailed Feedback: Reports analysis issues and provides clear success/failure status for each file write operation.
- Line Change Stats: Shows the number of lines added and deleted for each successfully written file.
- Performance Optimized: Built with a Bun-first approach for maximum speed.
Bun-First Approach 🚀
apply-whole is built with a Bun-first mindset, leveraging Bun's performance and APIs for:
- Optimal Performance: Uses Bun's fast file system APIs and clipboard access.
- Modern JavaScript/TypeScript: Takes advantage of the latest language features.
- Functional Programming: Follows a functional approach with immutable data structures.
- Minimal Dependencies: Relies mostly on built-in capabilities.
While the package may work with Node.js, using Bun is strongly recommended for the intended experience and performance.
Installation 📦
# Using Bun (recommended)
bun add -g apply-whole
# Using npm
npm install -g apply-whole
# Using pnpm
pnpm add -g apply-whole
# Using yarn
yarn global add apply-wholeAfter installation, the apply command will be available globally.
Building from Source
To build and use the development version:
# 1. Clone the repository
git clone https://github.com/alvamind/apply-whole.git
cd apply-whole
# 2. Install dependencies
bun install
# 3. Build the package (optional, often handled by Bun's runner)
# bun run build
# 4. Link for development (makes `apply` command use local code)
bun link
# Now you can run `apply` in any directoryUsage 🛠️
The core command is apply.
1. From Clipboard:
- Copy your markdown content containing the specially formatted code blocks.
- Run the command in your target directory:
apply
2. From File:
- Use the
-ior--inputflag followed by the markdown file path:apply -i path/to/your/document.md
3. Getting Help:
- Display the help message with all options:
apply -hUsage: bun apply [options] # Note: Command is 'apply' Applies code blocks from a markdown source to the filesystem. Code blocks must be formatted using one of the following styles: Style 1: Path on the same line as the opening delimiter \`\`\`[language] // path/to/your/file.ext File content starts here ... \`\`\` Style 2: Path on the line immediately following the opening delimiter \`\`\`[language] // path/to/your/file.ext File content starts here ... \`\`\` Analysis is performed first. If issues like missing delimiters or incorrect start line format are found, they will be reported. The tool will attempt to apply any blocks that appear valid. Options: -i, --input <file> Specify the input markdown file path. If omitted, reads from the system clipboard. --no-lint Skip TypeScript linting before and after applying changes. -h, --help Display this help message and exit.
How It Works: Markdown Format 📝
The tool looks for standard markdown code blocks (using triple backticks ```) where the target file path is specified using a specific comment format.
Required Format (Two Options):
Option 1: Path on the same line as the opening delimiter
```typescript // src/utils/helpers.ts
export const greet = (name: string): string => {
return `Hello, ${name}!`;
};
```Option 2: Path on the line immediately following the opening delimiter
```javascript
// public/scripts/main.js
console.log("Script loaded!");
function initialize() {
// initialization logic
}
initialize();
```Key points:
- Start Delimiter: Use
```optionally followed by a language identifier (e.g.,```typescript). - Path Comment: EITHER the line with the opening delimiter OR the very next line must be a single-line comment (
//) containing the relative or absolute path to the target file (e.g.,// src/component.tsx,// ./styles/main.css). - Code Content: The lines following the path comment (or the line after the path comment, if it's on its own line), up until the closing
```, are treated as the file content. - End Delimiter: The block must end with
```.
Use Case: Working with LLMs (ChatGPT, Gemini, etc.) 🤖
This tool streamlines applying code generated by Large Language Models. Instruct the LLM to format its output for apply-whole to avoid manual copy-pasting.
Workflow Example:
Prompt the LLM:
You: "Generate a simple Bun HTTP server in
server.tsand a correspondingpackage.json. Format the output using markdown code blocks where the file path is specified in a comment like// path/to/file.exton the line immediately after the opening ```."LLM Generates Formatted Output:
LLM:
Here are the files: ```typescript // server.ts import { serve } from "bun"; serve({ fetch(req) { return new Response("Welcome to Bun!"); }, port: 3000, }); console.log("Listening on http://localhost:3000");// package.json { "name": "my-bun-app", "module": "server.ts", "type": "module", "devDependencies": { "@types/bun": "latest" }, "peerDependencies": { "typescript": "^5.0.0" } }Apply the Code:
- Copy the entire markdown response from the LLM.
- Run
applyin your terminal within your project directory:apply - The tool will analyze the blocks, show the intended changes, and prompt for confirmation.
Confirm or Revert:
- Review the proposed changes listed in the terminal.
- Type
y(oryes) and press Enter to apply the changes. - Type
n(orno) and press Enter to safely cancel and revert any potentially staged changes.
Result: If confirmed, the tool creates/updates
server.tsandpackage.json. If declined, no changes are made to your filesystem.
Analysis and Error Handling 🧐
Before proposing changes, apply-whole analyzes the input markdown:
- Delimiter Check: It checks for an even number of
```delimiters. An odd number suggests an unterminated block. - Path Comment Check: It verifies that a valid path comment (
// path/to/file.ext) exists either on the opening delimiter line or the line immediately following it.
If issues are found:
- They are reported to the console, indicating the line number and the problematic line content.
- The tool will still attempt to process and apply any blocks that appear valid based on the rules.
- If no valid blocks can be extracted due to severe formatting errors, the tool will exit without proposing changes.
- If any individual file write operation fails after confirmation (e.g., due to permissions), it will be reported in the final summary, but previously successful writes in the same run will not be automatically reverted.
Example Output with Confirmation:
$ apply # Assuming valid markdown is on the clipboard
▶ Reading from clipboard...
▶ Analyzing markdown content...
Analysis complete. No issues found.
▶ Applying changes for 2 valid code block(s)...
✔ Written: src/server.ts (+10, -0)
✔ Written: package.json (+10, -3)
Summary:
Attempted: 2 file(s) (2 succeeded, 0 failed)
Lines changed: +20, -3
Completed in 25.50ms
Apply these changes? (y/n): y # User confirms
Changes applied successfully.
Finished successfully.Example Output with Revert:
$ apply # Assuming valid markdown is on the clipboard
# ... (Analysis and proposed changes shown) ...
Apply these changes? (y/n): n # User declines
Reverting changes...
Reverted: File src/server.ts deleted. # Or restored if it existed before
Reverted: File package.json restored.
Changes reverted by user.
Finished successfully.TypeScript Linting 🔍
apply-whole includes an integrated TypeScript linting feature that runs before and after your changes are applied:
How it works:
- Initial Check: Before applying changes, the tool runs TypeScript type checking and reports any current errors/warnings.
- Final Check: After applying changes (but before confirmation), it runs TypeScript checking again.
- Diff Reporting: The tool compares the before/after results and shows you if your changes improved or worsened the codebase:
- Red numbers indicate increased errors/warnings
- Green numbers indicate decreased errors/warnings
Example Output:
$ apply -i changes.md
▶ Running TypeScript check...
▶ TypeScript check complete. TypeScript - Errors: 2, Warnings: 1
▶ Reading input...
▶ Analyzing markdown content...
Analysis complete. No issues found.
▶ Applying changes for 1 valid code block(s)...
✔ Written: src/component.tsx (+15, -10)
▶ Running TypeScript check...
▶ TypeScript check complete. TypeScript - Errors: 0, Warnings: 1
▶ Change - Errors: -2, Warnings: +0
Apply these changes? (y/n): y
Changes applied successfully.
▶ Finished successfully.Disabling Linting:
If you'd like to skip the TypeScript checking (for speed or if working in a non-TypeScript project), use the --no-lint flag:
apply -i changes.md --no-lintThis will bypass both the initial and final TypeScript checks.
Contributing 🤝
Contributions are welcome! Feel free to open an issue to report bugs or suggest features, or submit a pull request with improvements. Please ensure code adheres to the functional, immutable, and Bun-first principles of the project.
License 📜
This project is licensed under the MIT License. See the LICENSE file for details.
