<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Abhi Builds]]></title><description><![CDATA[Notes from building developer tools, AI systems, backend projects, and open-source software.]]></description><link>https://abhibuilds.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6a81b8a69b3308e9146086aa/e01dbe0c-99cb-460d-813a-dbe43dd58abb.jpg</url><title>Abhi Builds</title><link>https://abhibuilds.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Thu, 17 Sep 2026 03:17:26 GMT</lastBuildDate><atom:link href="https://abhibuilds.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How I Built a Python CLI to Scaffold Complete Projects]]></title><description><![CDATA[Building Spawn, an open-source Python CLI that turns repetitive project setup into a configurable workflow, from templates and dependencies to Git initialization and developer tooling.

The problem wi]]></description><link>https://abhibuilds.hashnode.dev/how-i-built-a-python-cli-to-scaffold-complete-projects</link><guid isPermaLink="true">https://abhibuilds.hashnode.dev/how-i-built-a-python-cli-to-scaffold-complete-projects</guid><dc:creator><![CDATA[Abhiix0]]></dc:creator><pubDate>Sun, 16 Aug 2026 14:23:37 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p>Building Spawn, an open-source Python CLI that turns repetitive project setup into a configurable workflow, from templates and dependencies to Git initialization and developer tooling.</p>
</blockquote>
<h2>The problem with starting a new project</h2>
<p>Starting a new project sounds like the fun part.</p>
<p>In reality, there is usually a small ritual that happens before any actual development:</p>
<pre><code class="language-bash">mkdir my-project
cd my-project

mkdir src tests docs
touch README.md .gitignore

git init

python -m venv .venv
# activate it

# install dependencies
# configure linting
# configure testing
# add CI
# add Docker
# create the usual project files...
</code></pre>
<p>None of these steps are particularly difficult.</p>
<p>That's exactly why they're annoying.</p>
<p>I've done this enough times to realize that I wasn't really solving a new problem every time I started a project.</p>
<p>I was repeating the same setup decisions.</p>
<p>So I started wondering:</p>
<blockquote>
<p><strong>What if the project could just be generated from those decisions?</strong></p>
</blockquote>
<p>That became the idea behind <strong>Spawn</strong>.</p>
<hr />
<h2>What is Spawn?</h2>
<p>Spawn is an open-source Python CLI that generates a project foundation from a short interactive workflow.</p>
<p>Instead of manually creating the structure, initializing Git, setting up <code>uv</code>, installing dependencies, and wiring common development tools, you can start with:</p>
<pre><code class="language-bash">pip install spawnio
</code></pre>
<p>and then:</p>
<pre><code class="language-bash">spawn create
</code></pre>
<p>Spawn asks what you're building and generates the corresponding project foundation.</p>
<p>The goal isn't to write the application for you.</p>
<p>It's to get you from:</p>
<pre><code class="language-text">"I have an idea"
</code></pre>
<p>to:</p>
<pre><code class="language-text">"I have a structured project and can start coding"
</code></pre>
<p>with less repetitive setup in between.</p>
<hr />
<h2>Designing the workflow</h2>
<p>The first design decision was simple:</p>
<p><strong>I didn't want Spawn to be another command that required a long list of flags just to do something basic.</strong></p>
<p>So the default experience is interactive.</p>
<p>Running:</p>
<pre><code class="language-bash">spawn create
</code></pre>
<p>walks through a short sequence of prompts.</p>
<p>The first step is the project name:</p>
<pre><code class="language-text">Project Name: my-api
</code></pre>
<p>Then Spawn lets you choose the type of project you want to create.</p>
<pre><code class="language-text">? Choose a template

» Backend API
  CLI Application
  Automation Tool
  AI Chatbot
  AI Agent
  RAG System
  Data Project
  MCP Server
  Custom Structure
</code></pre>
<p>The exact questions after that depend on the template.</p>
<p>For example, a backend project can ask which framework you want, while a data project can ask whether you're creating an analysis project, dashboard, ETL pipeline, or machine-learning project.</p>
<p>The important part is that the workflow is <strong>intent-based</strong>.</p>
<p>You're not starting with:</p>
<blockquote>
<p>"Which folders should I create?"</p>
</blockquote>
<p>You're starting with:</p>
<blockquote>
<p>"What am I building?"</p>
</blockquote>
<hr />
<h2>Templates based on intent</h2>
<p>Spawn currently provides eight project templates.</p>
<h3>1. Backend API</h3>
<p>Designed for REST APIs, microservices, and backend applications.</p>
<p>For example, a FastAPI project can start with a structure like:</p>
<pre><code class="language-text">my-api/
├── app/
│   ├── api/routes/health.py
│   ├── core/config.py
│   ├── models/
│   ├── schemas/
│   ├── services/
│   └── main.py
├── tests/
│   └── test_health.py
├── .env.example
├── README.md
└── .gitignore
</code></pre>
<p>The supported backend frameworks are:</p>
<ul>
<li>FastAPI</li>
<li>Flask</li>
<li>Django</li>
</ul>
<p>And optional extras include:</p>
<ul>
<li>Ruff</li>
<li>Pytest</li>
<li>Docker</li>
<li>GitHub Actions</li>
</ul>
<hr />
<h3>2. CLI Application</h3>
<p>For developer tools, automation commands, project generators, and setup utilities.</p>
<p>A generated CLI can start with:</p>
<pre><code class="language-text">my-cli/
├── src/
│   ├── commands/
│   ├── prompts/
│   ├── ui/
│   ├── utils/
│   └── main.py
├── tests/
├── README.md
└── .gitignore
</code></pre>
<p>The CLI type can be selected as part of the setup flow.</p>
<hr />
<h3>3. Automation Tool</h3>
<p>For Python automation scripts and utilities that need a proper project structure instead of becoming a single giant <code>script.py</code>.</p>
<hr />
<h3>4. AI Chatbot</h3>
<p>For starting conversational AI projects with a predefined foundation.</p>
<p>The workflow lets you choose the relevant provider and setup options rather than forcing every AI project into exactly the same structure.</p>
<hr />
<h3>5. AI Agent</h3>
<p>For projects that need tool-calling and agent-style workflows.</p>
<p>Spawn currently supports agent setups involving PydanticAI and the OpenAI Agents SDK.</p>
<hr />
<h3>6. RAG System</h3>
<p>For retrieval-augmented generation projects.</p>
<p>The current RAG template uses LlamaIndex and ChromaDB as its foundation.</p>
<hr />
<h3>7. Data Project</h3>
<p>This one has several project types:</p>
<pre><code class="language-text">Data Analysis
Dashboard
ETL Pipeline
Machine Learning
</code></pre>
<p>For example, the generated machine-learning project includes a starter dataset and training workflow using <code>RandomForestClassifier</code>.</p>
<hr />
<h3>8. MCP Server</h3>
<p>Spawn also supports creating MCP servers using the official Python MCP SDK and <code>FastMCP</code>.</p>
<p>The generated project includes a working server with an example tool and resource.</p>
<hr />
<h2>The part I didn't want to compromise on: customization</h2>
<p>Templates are useful.</p>
<p>But templates can also become restrictive.</p>
<p>Eventually, you run into:</p>
<blockquote>
<p>"This is almost what I want... except for these seven folders."</p>
</blockquote>
<p>So I added <strong>Custom Structure</strong>.</p>
<p>Instead of choosing one of the predefined templates, you can provide your own project structure.</p>
<p>Spawn accepts:</p>
<ul>
<li>Unix <code>tree</code> output</li>
<li>Markdown lists</li>
<li>Plain indented hierarchies</li>
</ul>
<p>For example:</p>
<pre><code class="language-text">app/
├── api/
├── services/
└── tests/
README.md
.gitignore
</code></pre>
<p>Spawn parses the structure, previews what it detected, and then creates it.</p>
<p>You can still enable the same setup features:</p>
<pre><code class="language-text">Initialize Git? [Y/n]: Y
Initialize uv? [Y/n]: Y

Dependencies:
fastapi, uvicorn

Optional Setup:
● Ruff
● Pytest
○ Pre-commit
○ Dockerfile
</code></pre>
<p>This was important to me because I didn't want Spawn to say:</p>
<blockquote>
<p>"Use my architecture."</p>
</blockquote>
<p>I wanted it to say:</p>
<blockquote>
<p><strong>"Bring your architecture. I'll handle the boring setup around it."</strong></p>
</blockquote>
<hr />
<h2>Why <code>uv</code> is part of the workflow</h2>
<p>Python project setup often involves more than just creating folders.</p>
<p>There is also environment and dependency management.</p>
<p>Spawn can initialize <code>uv</code>, create the virtual environment, and install selected dependencies.</p>
<p>For example:</p>
<pre><code class="language-bash">uv add fastapi uvicorn
</code></pre>
<p>is handled as part of the generation workflow when dependencies are selected.</p>
<p>This means the generated project isn't just an empty folder tree.</p>
<p>It has an actual development environment ready to use.</p>
<p>The same idea applies to optional development tooling.</p>
<p>If you select Ruff or Pytest, Spawn installs the relevant development dependencies and generates the associated configuration files.</p>
<hr />
<h2>Making the CLI useful for automation</h2>
<p>Interactive workflows are great for humans.</p>
<p>They're not always great for scripts, CI, or AI agents.</p>
<p>So Spawn also supports <strong>non-interactive mode</strong>.</p>
<p>For example:</p>
<pre><code class="language-bash">spawn create \
  --name my-api \
  --template backend-api \
  --framework fastapi \
  --extras ruff,pytest \
  --git
</code></pre>
<p>No prompts.</p>
<p>You can also describe the project in a JSON configuration file:</p>
<pre><code class="language-json">{
  "name": "my-api",
  "template": "backend-api",
  "framework": "fastapi",
  "extras": [
    "ruff",
    "pytest"
  ],
  "git": true,
  "uv": true
}
</code></pre>
<p>Then:</p>
<pre><code class="language-bash">spawn create --config spawn.json
</code></pre>
<p>There is also a <code>--dry-run</code> option for validating the configuration and printing it without creating the project.</p>
<p>This was one of the more important additions to Spawn because a project generator shouldn't only work when someone is sitting at a keyboard answering prompts.</p>
<hr />
<h2>Making generated projects more AI-friendly</h2>
<p>Another thing I wanted to experiment with was giving generated projects useful context for coding agents.</p>
<p>Spawn automatically includes an <code>AGENTS.md</code> file in generated projects.</p>
<p>There is also a <code>--claude-md</code> option that generates a corresponding <code>CLAUDE.md</code>.</p>
<p>The idea is simple:</p>
<p>When an AI coding agent enters a freshly generated project, there should already be some project-level context available instead of starting from a completely blank slate.</p>
<p>It's a small feature, but it fits the direction developer tooling is moving toward.</p>
<hr />
<h2><code>spawn doctor</code></h2>
<p>After building a generator, I wanted to solve another problem:</p>
<blockquote>
<p>What happens after the project already exists?</p>
</blockquote>
<p>That's where:</p>
<pre><code class="language-bash">spawn doctor
</code></pre>
<p>comes in.</p>
<p>It analyzes the project and produces a health score out of 100.</p>
<p>For example:</p>
<pre><code class="language-text">╭─────────────── 🏥 Project Health Report ─────────────────╮
│                                                           │
│  🟡 Good                                                  │
│  Some improvements recommended.                           │
│                                                           │
│  Project Score: 82%                                       │
│                                                           │
│  Documentation — 67                                       │
│  Version Control — 100                                    │
│  Configuration — 75                                       │
│  Testing — 80                                             │
│  Automation — 50                                          │
│  Code Quality — 100                                       │
│                                                           │
╰───────────────────────────────────────────────────────────╯
</code></pre>
<p>It then gives recommendations grouped by priority and identifies a single:</p>
<p><strong>Next Best Step</strong></p>
<p>The checks cover:</p>
<ul>
<li>Documentation</li>
<li>Version Control</li>
<li>Configuration</li>
<li>Testing</li>
<li>Automation</li>
<li>Code Quality</li>
</ul>
<p>The checks are filesystem-based. Spawn doesn't execute the project or send it over the network as part of this health check.</p>
<hr />
<h2>Publishing to GitHub</h2>
<p>Spawn can also help with the first GitHub push after project creation.</p>
<p>If Git was enabled, the workflow can ask:</p>
<pre><code class="language-text">Publish to GitHub? [y/N]: y

Repository URL:
https://github.com/your-username/my-project
</code></pre>
<p>Spawn then stages the files, creates the initial commit, switches the branch to <code>main</code>, adds the remote, and pushes.</p>
<p>One intentional limitation:</p>
<p><strong>The GitHub repository must already exist.</strong></p>
<p>Spawn connects to it. It doesn't create the repository itself.</p>
<hr />
<h2>Installing Spawn</h2>
<p>The easiest way to get started is through PyPI:</p>
<pre><code class="language-bash">pip install spawnio
</code></pre>
<p>You can also install it as a <code>uv</code> tool:</p>
<pre><code class="language-bash">uv tool install spawnio
</code></pre>
<p>Or run it without installing it permanently:</p>
<pre><code class="language-bash">uvx --from spawnio spawn create
</code></pre>
<p>Then:</p>
<pre><code class="language-bash">spawn create
</code></pre>
<p>and you're off.</p>
<hr />
<h2>Where Spawn is today</h2>
<p>Spawn is currently published on PyPI as <code>spawnio</code>.</p>
<p>The project has evolved through several iterations.</p>
<p>Some of the features that have landed along the way include:</p>
<ul>
<li>Intent-based project templates</li>
<li>Custom project structures</li>
<li><code>spawn doctor</code></li>
<li>Non-interactive generation</li>
<li>MCP Server scaffolding</li>
<li>Data project generation</li>
<li>Agent context files</li>
<li>Arrow-key driven prompts</li>
<li>GitHub publishing</li>
<li>PyPI distribution</li>
</ul>
<p>The current version is focused on making the boring first 5–10 minutes of a project much shorter.</p>
<p>But there is still plenty to improve.</p>
<hr />
<h2>What I want to improve next</h2>
<p>I don't want Spawn to become a giant collection of random templates.</p>
<p>The goal is to make it genuinely useful.</p>
<p>That means I need feedback from people who actually build projects.</p>
<p>Some questions I'm currently thinking about:</p>
<ul>
<li>What project types should be added?</li>
<li>Which templates are actually useful?</li>
<li>Which setup steps should be automated?</li>
<li>What does Spawn currently get wrong?</li>
<li>Should more tools be supported as optional extras?</li>
<li>What would make the non-interactive mode better for agents and automation?</li>
<li>What would make you choose Spawn over creating a project manually?</li>
</ul>
<p>Those answers are probably more valuable than anything I can come up with alone.</p>
<hr />
<h2>Open source means I don't have to guess</h2>
<p>Spawn is open source, and contributions are welcome.</p>
<p>If you want to add a new project intent, the project has a template system for doing exactly that.</p>
<p>A new intent can be added under:</p>
<pre><code class="language-text">src/spawn/templates/your_intent/
</code></pre>
<p>and registered through the template registry.</p>
<p>Tests should be added alongside the new functionality.</p>
<p>Before submitting a PR:</p>
<pre><code class="language-bash">uv run pytest
uv run ruff check .
</code></pre>
<p>If you have an idea for a new template, find a bug, or think the whole concept is unnecessary, I'd genuinely like to hear about it.</p>
<p>Especially the last one.</p>
<p>A developer tool should earn its place in someone's workflow.</p>
<hr />
<h2>Try it</h2>
<p>If repetitive Python project setup annoys you as much as it annoyed me:</p>
<pre><code class="language-bash">pip install spawnio
</code></pre>
<p>Then:</p>
<pre><code class="language-bash">spawn create
</code></pre>
<p>The project is open source:</p>
<p><strong>GitHub:</strong>
<a href="https://github.com/Abhiix0/spawn">https://github.com/Abhiix0/spawn</a></p>
<p><strong>PyPI:</strong>
<a href="https://pypi.org/project/spawnio/">https://pypi.org/project/spawnio/</a></p>
<hr />
<h2>I'd love your feedback</h2>
<p>This is the part I'm most interested in.</p>
<p>If you build Python projects, <strong>what is the setup step you find yourself repeating every single time?</strong></p>
<p>Maybe it's:</p>
<ul>
<li>project structure</li>
<li>dependency setup</li>
<li>Docker</li>
<li>CI</li>
<li>testing</li>
<li>linting</li>
<li>environment configuration</li>
<li>Git setup</li>
<li>something completely different</li>
</ul>
<p>Tell me what it is.</p>
<p>I'm building Spawn, but I'd rather build the tool developers actually want than the tool I <em>think</em> they want.</p>
<hr />
<p><strong>Thanks for reading.</strong></p>
<p>Now back to building. 🐍</p>
]]></content:encoded></item></channel></rss>