How I Created an AI-Powered Code Editor in Node.js Using Gemini
sahil

sahil @itxsahil

About: 👋 Hi, I’m Sahil Khan, a Full-Stack Developer passionate about building modern web apps and scalable systems. I love sharing insights and writing about web development on Dev.to. 🚀

Joined:
Jan 27, 2024

How I Created an AI-Powered Code Editor in Node.js Using Gemini

Publish Date: May 18
1 0

Over the past few months, it became pretty normal to hear about AI agentic workflows. I was getting at least two notifications a day about them from almost every social media platform. So, I decided to dive in and try things out myself.

After reading some blogs and articles, I realized that everyone was building AI-based services. So,I decided to build my own AI-powered code editor, inspired by tools like Cursor


What I Built

A Node.js-based CLI tool powered by Google's Gemini, capable of turning natural language prompts into real code, directory structures, and package setups.

Example: Create a server for a to-do application
→ This tool will:

  1. Create files and folders
  2. Initialize package.json and install external packages
  3. Write actual runnable code

Tech Stack

  • Node.js
  • Google Generative AI (Gemini API) – For generating code from prompts (free to use)
  • readline-sync – For CLI input
  • fs – For file manipulation
  • path – For resolving file paths
  • child_process – For running shell commands

Getting Started

First, initialize your Node.js project:

npm init -y
Enter fullscreen mode Exit fullscreen mode

Then, install the required packages:

npm install readline-sync @google/generative-ai
Enter fullscreen mode Exit fullscreen mode

Import all required modules:

const readlineSync = require("readline-sync");
const fs = require("fs");
const path = require("path");
const { GoogleGenerativeAI } = require("@google/generative-ai");
const { exec } = require("child_process");
Enter fullscreen mode Exit fullscreen mode

Setting Up Gemini

const API_KEY = "YOUR_GEMINI_API_KEY";
const genAI = new GoogleGenerativeAI(API_KEY);
const model = genAI.getGenerativeModel({ model: "gemini-2.0-flash" });
Enter fullscreen mode Exit fullscreen mode

Core Functionalities

1. Create Directory

function createDirectory(directoryName) {
  if (!directoryName) return;
  if (!fs.existsSync(directoryName)) {
    fs.mkdirSync(directoryName, { recursive: true });
    console.log(`✅ Created directory: ${directoryName}`);
  } else {
    console.log(`⚠️ Directory already exists: ${directoryName}`);
  }
}
Enter fullscreen mode Exit fullscreen mode

What it does: Checks if a directory exists, and if not, creates it recursively.


2. Create File

function createFile(fileName) {
  if (!fileName) return;
  const dir = path.dirname(fileName);
  if (dir !== "." && !fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }
  if (!fs.existsSync(fileName)) {
    fs.writeFileSync(fileName, "");
    console.log(`✅ Created file: ${fileName}`);
  } else {
    console.log(`⚠️ File already exists: ${fileName}`);
  }
}
Enter fullscreen mode Exit fullscreen mode

What it does: Ensures the file path exists and then creates an empty file if it doesn't already exist.


3. Write AI-Generated Code

async function writeCode(fileName, description, language) {
  if (!fileName || !description) return;

  const prompt = `
Generate clean, production-ready code based on this description in:
"${description} in ${language}"

Respond with code only, no explanation. Include internal comments if necessary.
`;

  const result = await model.generateContent(prompt);
  const codeText = result.response.text().trim();
  const codeMatch = codeText.match(/```
{% endraw %}
(?:\w+)?\n([\s\S]*?)\n
{% raw %}
```/);
  const finalCode = codeMatch ? codeMatch[1] : codeText;

  fs.writeFileSync(fileName, finalCode);
  console.log(` Code written to: ${fileName}`);

  console.log(`Preview:`);
  const lines = finalCode.split("\n").slice(0, 10);
  console.log(lines.join("\n"));
  if (finalCode.split("\n").length > 10) {
    console.log("... (truncated)");
  }
}
Enter fullscreen mode Exit fullscreen mode

What it does: Sends the prompt to Gemini, receives the code, extracts it, and writes it to the specified file. Also prints a preview.


4. Run Package Manager Commands

async function cliExec(path, command) {
  exec(`cd ${path} && ${command}`, (err, stdout, stderr) => {
    if (err) {
      console.error(err);
      return;
    }
    console.log(stdout);
  });
}
Enter fullscreen mode Exit fullscreen mode

What it does: Runs shell commands (like npm install) in the specified directory using child_process.exec.


Prompt Engineering

async function getInstructionsFromGemini(input) {
  const prompt = `
You are a smart assistant for a coding CLI tool. Your base language is JS. Interpret the following user request:

"${input}"

Return a JSON array of actions like:

[
  { "action": "createDirectory", "directoryName": "folder_name" },
  { "action": "createFile", "fileName": "path/to/file.js" },
  { "action": "writeCode", "fileName": "path/to/file.js", "description": "description", "language": "JavaScript" }
]

Only respond with the JSON array. No explanations, no code blocks.
`;

  const result = await model.generateContent(prompt);
  const raw = result.response.text().trim();

  try {
    const jsonMatch = raw.match(/```
{% endraw %}
(?:json)?\s*([\s\S]*?)\s*
{% raw %}
```|([\s\S]*)/);
    const jsonString = jsonMatch ? jsonMatch[1] || jsonMatch[2] : raw;
    return JSON.parse(jsonString);
  } catch (err) {
    console.error(`Failed to parse Gemini response: ${raw}`);
    return null;
  }
}
Enter fullscreen mode Exit fullscreen mode

What it does: Converts the natural language user prompt into a structured array of actions by prompting Gemini with clear JSON output instructions.


Executing Actions

async function executeAction(action) {
  switch (action.action) {
    case "createDirectory":
      createDirectory(action.directoryName);
      break;
    case "createFile":
      createFile(action.fileName);
      break;
    case "writeCode":
      await writeCode(action.fileName, action.description, action.language);
      break;
    case "cliExec":
      await cliExec(action.path, action.command);
      break;
    default:
      console.log(`Unknown action: ${action.action}`);
  }
}
Enter fullscreen mode Exit fullscreen mode

What it does: This is the heart of the agentic loop. Based on the action type returned by Gemini, it calls the appropriate handler (e.g., createDirectory, writeCode).


Main CLI Chat Loop

async function runEditor() {
  while (true) {
    const userInput = readlineSync.question(`AI Editor> `);

    if (userInput.toLowerCase() === "exit") {
      console.log(`Goodbye!`);
      break;
    }

    try {
      const actions = await getInstructionsFromGemini(userInput);
      if (!actions || !Array.isArray(actions)) {
        console.log(`Could not understand the instruction.`);
        continue;
      }

      for (const action of actions) {
        await executeAction(action);
      }
    } catch (error) {
      console.error(`Error: ${error.message}`);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

What it does: Repeatedly reads user input and processes it using Gemini. On each prompt, it gets structured instructions, then performs the actions in sequence. Type exit to quit.


Final Styled Version

To make the CLI more user-friendly, I added some color using ANSI codes:

const colors = {
  reset: "\x1b[0m",
  red: "\x1b[31m",
  green: "\x1b[32m",
  yellow: "\x1b[33m",
  cyan: "\x1b[36m",
  magenta: "\x1b[35m"
};
Enter fullscreen mode Exit fullscreen mode

And here’s how the app welcomes you:

console.log(`${colors.cyan}======================================`);
console.log(`        Smart AI Code Editor`);
console.log(`======================================${colors.reset}`);
console.log(`${colors.yellow}Type anything like:${colors.reset}`);
console.log(`"create a folder named utils and add index.js"`);
console.log(`"generate a python script that reads a csv and plots a graph"`);
console.log(`Type 'exit' to quit.`);
console.log(`${colors.cyan}======================================${colors.reset}\n`);
Enter fullscreen mode Exit fullscreen mode

Final Thoughts

This little project helped me learn:

  • How to work with agentic workflows
  • Using LLMs in CLI-based tools
  • Handling file systems, JSON parsing, and process execution in Node.js
  • Prompt engineering for best results from Gemini

If you’ve made it this far, thank you! Feel free to fork this and create your own AI tooling.

And, These are some images of the Agent in work

Run script

Input

Output

Files

Comments 0 total

    Add comment