File Combiner
TUTOR WITH THEFOCUS.AI
Copy this prompt into Claude, ChatGPT, or any external AI assistant. It points the assistant to the course instructions and links it to your student profile to track your progress and customize observations.
You are not enrolled yet. Enroll to generate a Student ID to track lesson completions and store learning notes.
Project: File Combiner
Source: 1-combind/
Model: gemma4:26b
Type: TypeScript (Bun runtime)
What It Does
The file combiner is the glue of our automation pipeline. It takes multiple files and wraps them in XML-like tags, producing a single output that can be fed to Ollama as context.
./1-combind/code -m "Fix this bug" prompt.txt error.txt code.py
Output:
<message>Fix this bug</message>
<prompt.txt>Write a bash script...</prompt.txt>
<error.txt>SyntaxError: line 42...</error.txt>
<code.py>#!/usr/bin/env python3...</code.py>
This is how we feed context back to the model during the self-improving loop — the original prompt, the generated code, and the error output all go in as tagged sections.
The Prompt
write a standalone typescript script that has a shebang header using bun
it takes a list of files as arguments and concatenes them together marking them
example
script [-m "message"] file1 file2 file3
will output
<message>message</message>
<file1>{{contents of file1}}</file1>
<file2>{{cotents of file2}}</file2>
<file3>{{contents of file1}}</file3>
the -m message is optional
output only code
The Code
#!/usr/bin/env bun
const args = Bun.argv.slice(2);
let message = "";
const files: string[] = [];
// Parse arguments
for (let i = 0; i < args.length; i++) {
if (args[i] === "-m" && i + 1 < args.length) {
message = args[i + 1];
i++; // Skip the next argument as it's the message content
} else {
files.push(args[i]);
}
}
async function run() {
// Output message if provided
if (message) {
console.log(`<message>${message}</message>`);
}
// Process each file
for (const filePath of files) {
try {
const file = Bun.file(filePath);
if (!(await file.exists())) {
console.error(`Error: File not found: ${filePath}`);
continue;
}
const content = await file.text();
// Using the filename as the tag name
console.log(`<${filePath}>${content}</${filePath}>`);
} catch (error) {
console.error(
`Error processing ${filePath}:`,
error instanceof Error ? error.message : error,
);
}
}
}
run();
How to Use
chmod +x 1-combind/code
# Combine a prompt and some files
./1-combind/code prompt.txt file1.py file2.md
# With a message
./1-combind/code -m "Here's the error" prompt.txt code.py error.txt
# Pipe directly to Ollama
./1-combind/code -m "Fix this" prompt.md code.py | ollama run gemma4:26b
The Test
The test file demonstrates the -m flag:
#!/bin/bash
./1-combind/code -m "This is a message" 0-weather/prompt.md
Expected output:
<message>This is a message</message>
<0-weather/prompt.md>write a bash script that uses wget to get the weather in new york city</0-weather/prompt.md>
Key Lessons
- Bun for TypeScript. The model chose Bun runtime for its simple file I/O (
Bun.file(path).text()). - Tagging provides structure. The XML-like tags (
<filename>content</filename>) give the model clear boundaries between different pieces of context. - The
-mflag is the channel. It provides human intent (“Fix this bug”) alongside raw file contents. - This is the feedback pipe. In our self-improving loop, this tool packs prompt + code + error into one message for the model.
Next: Data Extractor →