Stop repeating yourself and start automating. This lesson is your first step into building specialized AI agents. You'll learn the foundational skill of creating a simple, reusable "French-speaking" agent by spawning the Claude CLI with a custom system prompt. We'll cover the essential mechanics of using Bun.spawn to create an interactive session, how to externalize prompts in markdown files for easy editing, and the TypeScript setup needed to tie it all together. This is the core workflow we'll build on throughout the course.
Bun.spawn to run the claude CLI, inheriting standard I/O to create an interactive session directly in your terminal..md) files. This separates the agent's "personality" from the code..md file with a type: "text" assertion.types.d.ts) to inform TypeScript how to handle .md module imports, resolving any "Cannot find module" errors.claude process.This workflow provides a powerful and scalable pattern for building a suite of specialized AI agents, making your development process with AI more organized and efficient.
Dictating the content for the markdown prompt file:
Please always speak in French.
Querying the French-speaking agent:
How are you doing today?
Initialize a new Bun project:
bun init
Run the agent script:
bun run agents/french.ts
Creating a custom type declaration in types.d.ts to allow importing .md files as modules in TypeScript.
declare module "*.md" {
const content: string;
export default content;
}
Importing the content of a markdown file as a text string using Bun's import attributes.
import prompt from "../prompts/french.md" with {
type: "text"
};
Dynamically creating an array of command-line arguments from a configuration object to be passed to Bun.spawn.
const flags = {
"append-system-prompt": prompt
}
const flagsArray = Object.entries(flags).flatMap(([key, value]) => {
return [`--${key}`, value]
})
Spawning the claude CLI process with the dynamically generated arguments using the spread operator.
Bun.spawn(["claude", ...flagsArray], {
stdio: ["inherit", "inherit", "inherit"],
});
[00:00] We'll initialize a new bun project, just a blank one, and then we'll create a file in an agent's directory and we'll call this French.ts. Now from here we're going to bun spawn and to spawn clod with the standard I O set to inherit. That's just shorthand for a standard in, standard out, standard error. So if we run this, just fire up bun run agents and run French, we'll have a standard cloud code interactive session, which is even integrated with our IDE. You can see it's referencing the French file.
[00:33] So what we can do next is create a prompts directory and create a file called French.md and say please always speak in French and then hop back over here and we can import this prompt from that path with a type of text. I'm going to stop cursor from jumping ahead. And you can see that it can't find this module because the file type of MD. So we'll create a file called types.d.ts and declare that all markdown files just export default content of string which fixes that error. So now we've completely inlined our prompt and I'm going to set up an object called flags.
[01:09] And flags is going to, again jumping ahead, map the flag key to the prompt. And because of the required syntax here, this needs to be an array of strings. We're going to make our flags array where it loops through all the entries. Let me word wrap this. It loops through all the entries of flags and flat maps them so that a dash dash append system prompt is assigned to the value here.
[01:34] I'll just console log this out so it's a bit more obvious what's happening, and exit before it runs. If I run this you can see we get append system prompt and please always speak in French in an array. And if we let this run now where we destructure our array and hop into our terminal, then we'll run our French file again. We'll say, how are you doing today? And you'll see it always responds in French.