MoreRSS

site iconThe Practical DeveloperModify

A constructive and inclusive social network for software developers.
Please copy the RSS to your reader, or quickly subscribe to:

Inoreader Feedly Follow Feedbin Local Reader

Rss preview of Blog of The Practical Developer

Introduction to Swarm: an extensible Typescript code generation framework

2025-11-17 15:36:49

As developers, we all reach a point when writing repetitive boilerplate stops being a minor annoyance and starts having a real impact on our productivity. You find yourself creating the same directory structure, writing the same configuration blocks, copying and pasting similar component patterns, then tweaking each instance slightly. What begins as a few minutes here and there quickly adds up to hours lost on manual scaffolding.

That's where this journey began for me. Initially, I built a collection of scripts to automate component creation for a side project. But the more I used those scripts, the more I realised this problem wasn't unique to my project or the framework I was using.

Today, Swarm is an extensible TypeScript code generation framework built on a plugin-based architecture. The first plugin I created solved my own needs for generating Wasp components, but the core library can be extended to generate code for any framework or platform.

So, dear developer, I'd like to share why Swarm exists, how it came to be and what it might offer you.

Why Wasp?

Before diving into Swarm itself, it's worth sharing the context that led to its creation. While researching framework options for a side project, I discovered Wasp, a full-stack web development framework, through their OpenSaaS starter template. I'd been looking at various paid SaaS starter templates at the time, but Wasp's offering stood out because it was free and included genuinely useful features out of the box.

I've been working with Wasp for almost a year now and in that time, I've become a contributor to the project and been fortunate enough to been recognised as a community expert. I believe the team behind it has built something with genuine potential. But as a relatively early (pre-1.0) project, I encountered certain friction points as I started using it more extensively.

The Challenges

Wasp gives developers considerable freedom in how they organise their projects. That flexibility can feel empowering, but it also imposes cognitive load as you have to decide on a structure yourself, often without clear guidance on what scales well. In my first project, I implemented a feature-based structure that segregated front- and back-end components into cohesive feature directories. Conceptually, I still stand by that decision, but there are definitely implementation details I'd approach differently now.

The configuration file presents another issue. Wasp uses a single configuration file, defined in their own DSL or TypeScript, to declare all server-side components. That includes RPC-style queries, actions (mutations), CRUD operations, background jobs, HTTP API endpoints, and page routes. The file offers a shallow learning curve and it's initially easy to manage, but it's monolithic and defines every component for the application. For complex app, it can grow very large and becomes increasingly difficult to navigate, even with careful organisation.

Then there's the server-side code structure. Wasp tends to recommend organising server operations in monolithic files like actions.ts or queries.ts. This works fine for small project, but as applications grow, these files can become unwieldy. More fundamentally, this pattern contrasts sharply with typical front-end conventions that define one component per file. That inconsistency creates mental overhead when switching between client and server code.

The Journey

Swarm started out as a set of simple scripts I created to automate component creation for my first Wasp project. They worked well enough and I figured other Wasp developers might find them useful, so I decided to package them as a CLI tool that could easily be installed in other projects.

The next realisation was that MCP (Model Context Protocol) support would make these tools easier to use within AI-assisted development workflows. To enable that, I needed to break the core functionality out, with separate CLI and MCP packages, which forced me to think more carefully about the overall architecture.

Once I had both CLI and MCP working, another insight followed: this problem wasn't Wasp-specific. The same pattern of generating type-safe, context-aware boilerplate could apply to any framework. So I refactored everything into a technology-agnostic core handling both CLI command and MCP tool generation, with a separate plugin defining Wasp-specific generators.

Another revelation arrived when it struck me that CLI commands and MCP tools could be generated entirely from Zod schemas. I was already using Zod in a limited capacity throughout the application, but I realised I could define the schema once and get CLI flags, MCP tool parameters and validation for free, making plugin development much simpler.

While ironing out some compatibility bugs between the Zod 4 dependency in Swarm and the Zod 3 dependency in Wasp, I learned about Standard Schema and implemented support for that spec instead, allowing plugin schemas to be built with any library of the author's choice.

State Of The Union

At the time of writing, the Swarm "ecosystem" consists of three main components:

Swarm Core

As previously mentioned, the core framework is built around a plugin-based architecture that supports user-defined generators for different types of content, e.g. APIs, components, configuration or whatever makes sense for your use case. Generators and plugins implement simple, lightweight interfaces and leverage Standard Schema schemas for input validation.

export interface Generator<S extends StandardSchemaV1 = StandardSchemaV1> {
  name: string;
  description: string;
  schema: S;
  generate: (args: Out<S>) => Promise<void>;
}

export interface Plugin {
  name: string;
  providers: Array<GeneratorProvider>;
}

Those schemas drive both the command-line and MCP interfaces. You define a generator with a schema, and Swarm automatically exposes it as a command-line option and as an MCP tool that AI assistants can use, with no separate configuration or manual wiring required.

Swarm also includes a templating system built on Eta, with support for custom template overrides. If you need to tweak the output of a generator, you can place a modified template in a known location and the generator will use it in favour of the built-in version.

The Swarm Wasp Plugin

The Wasp plugin provides generators for all documented Wasp components. That includes API Endpoints and Namespaces, CRUD operations, Actions, Queries, Page Routes, and Background Jobs. All output is type-safe and compatible with your defined Prisma entities.

Beyond code generation, the plugin addresses those issues I mentioned earlier:

  1. It introduces an enhanced configuration system that supports feature-based feature.wasp.ts files alongside the main main.wasp.ts. This contrasts with the traditional monolithic style, creating smaller, more manageable files and ensuring feature configuration is self-contained.
  2. It provides a fluent API through an extended App class that makes configuration files more concise and readable.
  3. It enforces a consistent, feature-based directory structure with a component-per-file pattern that mirrors front-end conventions. In the spirit of Prettier, I wanted to just take away all the concerns with "how" and just be able to focus on the "what".

The Swarm Wasp Starter

The starter template demonstrates how to build Wasp applications using Swarm's code generation functionality. It provides a minimal implementation that's an ideal foundation for building custom starter templates on top of.

It includes modern tooling like Tailwind CSS 4 and shadcn/ui components, with several useful development scripts for common Wasp workflows. And of course, it includes Swarm's full MCP integration ready for AI-assisted development. If you're building a Wasp application and want to see how Swarm can accelerate your development workflow, give it a try!

What's Next?

This introduction covered the motivation, evolution, and current state of Swarm. In Part 2, I'll walk through creating a full-stack Wasp application using the Swarm toolkit. I'll show how the generators work in practice and how they can speed up development while maintaining type safety and consistency.

And if you're a Wasp developer dealing with some of the same friction points I encountered, I'd love to hear your thoughts.

Introduction to Swarm: Building full-stack apps with Wasp

2025-11-17 15:34:35

In Part 1, I shared the evolution of Swarm from a collection of project scripts into a full boilerplate generation framework. In this article, we'll walk through the steps of building a Wasp application using the Swarm Wasp Starter template, and I'll demonstrate how the generators work with real examples.

I'll be referencing the kitchen-sink example project from the Wasp repository throughout this article. It's a comprehensive example that features all major Wasp features, so it serves as a good reference point to understand how Swarm works.

Key Differences

Swarm implements a couple of notable changes to standard Wasp projects that it's useful to be aware of.

Directory Structure

Wasp allows you to organise projects however you like, which is appealing at face-value. But when you're starting and scaling projects, that freedom comes with the cost of cognitive burden attached as you have to determine the best way to organise your files and directories.

Taking inspiration from Prettier, the Wasp plugin aims to remove all the mental effort of deciding how project files should be organised by enforcing a convention-driven, feature-based directory structure. Each feature directory is self-contained, with client and server subdirectories organised in a consistent structure, and a feature.wasp.ts configuration file that lives alongside the components it defines.

Here's what a typical feature directory looks like:

src/features/operations/
├── feature.wasp.ts
├── client/
│   └── pages/
│       ├── Serialization.tsx
│       ├── TaskDetail.tsx
│       └── Tasks.tsx
└── server/
    ├── actions/
    │   ├── createTask.ts
    │   ├── deleteCompletedTasks.ts
    │   ├── toggleAllTasks.ts
    │   └── updateTaskIsDone.ts
    └── queries/
        ├── getNumTasks.ts
        ├── getTask.ts
        └── getTasks.ts

This is in contrast to the standard guidance that recommends a single actions.ts file containing multiple actions, or a queries.ts file containing multiple queries. As the project grows, those files become harder to navigate and may ultimately get split up into sub-files, which again has an associated cost to plan and implement. The Wasp plugin's conventions dictate that each component lives in its own file, which also harmonises server-side components with client-side ones.

The main.wasp.ts file is still required, but it's much smaller as it purely handles application-level configuration like authentication and the root component. Feature-specific configuration now lives in feature.wasp.ts files, which keeps the main file manageable even as you add more features.

Configuration Syntax

Wasp's declarative configuration syntax works fine, but it can be verbose. Swarm's extended App class provides a fluent API that makes configuration more concise and readable.

For example, typical Wasp declarations look like this:

app.route("tasks", {
  path: "/tasks",
  to: app.page("tasks", {
    component: {
      importDefault: "Tasks",
      from: "@src/features/operations/client/pages/Tasks",
    },
  }),
});

app.crud("tasks", {
  entity: "Task",
  operations: {
    create: {
      overrideFn: {
        import: "create",
        from: "@src/features/crud/server/cruds/tasks" },
      },
    },
    getAll: {
      overrideFn: {
        import: "getAll",
        from: "@src/features/crud/server/cruds/tasks" },
      },
    },
  },
);

While the equivalent in Swarm looks like this:

app
  .addRoute("operations", "tasks", {
    path: "/tasks",
    auth: false
  })
  .addCrud("crud", "tasks", {
    entity: "Task",
    create: { override: true },
    getAll: { override: true }
  });

The fluent API lets generators chain these calls together, and Swarm organises them automatically so related declarations are grouped together and sorted alphabetically. It's a small detail, but it makes the configuration files much easier to read.

The generators automatically generate component files in consistent locations, following the plugin's structural conventions, so you don't have to define those yourself. The generated code is also fully type-safe, so if you reference an entity or property that doesn't exist in your Prisma schema, TypeScript will catch it.

Getting Started

The Swarm Wasp Starter template includes Swarm and the Wasp plugin, along with Tailwind CSS 4 and shadcn/ui components. You'll also find a collection of useful npm scripts for common Wasp workflows.

Run this command to create a new project using the starter:

npx @ingenyus/swarm create my-app --template genyus/swarm-wasp-starter

This clones the starter template and populates any templated values. Once installation is complete, navigate into the project directory and set it up:

npm run reset

Using the CLI

The Swarm framework provides CLI commands for each of the generators defined by any active plugins, while the Wasp Starter template provides access to the CLI via the npm run swarm package script.

Let's say we want to replicate the kitchen-sink application, but built using Swarm.

Prisma Schema

The first step is to define any necessary entities in our schema.prisma file:

model User {
  id Int @id @default(autoincrement())

  isOnAfterSignupHookCalled        Boolean @default(false)
  isOnAfterLoginHookCalled         Boolean @default(false)
  isOnAfterEmailVerifiedHookCalled Boolean @default(false)

  tasks                 Task[]
  address               String?
  votes                 TaskVote[]
}

model Task {
  id          Int            @id @default(autoincrement())
  description String
  isDone      Boolean        @default(false)
  user        User           @relation(fields: [userId], references: [id])
  userId      Int
  votes       TaskVote[]
}

model TaskVote {
  id     String @id @default(cuid())
  user   User   @relation(fields: [userId], references: [id])
  userId Int
  task   Task   @relation(fields: [taskId], references: [id])
  taskId Int
}

Then we need to configure basic username authentication to enable auth settings:

main.wasp.ts

app.auth({
  userEntity: "User",
  methods: {
    usernameAndPassword: {},
  },
  // Required, but not used in this tutorial
  onAuthFailedRedirectTo: "/login",
});

Migrate the database and compile the project so Typescript is aware of the new entities:

wasp db migrate-dev --name init && wasp compile

Feature Directory

Before generating any Wasp components, we must first generate a feature directory to contain them:

npm run swarm -- feature --target operations

All Swarm command arguments also support a short form, which you can review by using the -h argument to display the command help. The shortened form of the previous command would be:

npm run swarm -- feature -t operations

Output

This creates the src/features/operations/ directory containing a bare feature.wasp.ts file, ready to start adding components.

feature.wasp.ts

import { App } from "@ingenyus/swarm-wasp";

export default function configureFeature(app: App, feature: string): void {
  app
}

Routes & Pages

Next, we need to generate a login page (in the pre-existing root feature) and we'll also create a route for viewing tasks:

npm run swarm -- route --feature root --path /login --name login
npm run swarm -- route --feature operations --name tasks --path /tasks --auth

Output

These commands generate page components at src/features/operations/client/pages/Tasks.tsx and src/features/root/client/pages/Login.tsx, then adds definitions to the respective feature.wasp.ts files. The --auth flag indicates the route requires authentication, which is reflected in the helper method call.

root/feature.wasp.ts

  app
    // Route definitions
    .addRoute(feature, "login", {
      path: "/login",
      auth: false,
    });

operations/feature.wasp.ts

  app
    // Route definitions
    .addRoute(feature, "tasks", {
      path: "/tasks",
      auth: true,
    });

Login.tsx

import React from "react";

export const Login = () => {
  return (
    <div className="container mx-auto px-4 py-8">
      <h1 className="text-2xl font-bold mb-4">Login</h1>
      {/* TODO: Add page content */}
    </div>
  );
};

Tasks.tsx

import React from "react";

export const Tasks = () => {
  return (
    <div className="container mx-auto px-4 py-8">
      <h1 className="text-2xl font-bold mb-4">Tasks</h1>
      {/* TODO: Add page content */}
    </div>
  );
};

Operations

Next, we can generate queries and actions for Task entity:

npm run swarm -- query --feature operations --operation getAll --data-type Task --name getTasks
npm run swarm -- action --feature operations --operation create --data-type Task --name createTask

Output

These commands create boilerplate for the query and action handlers in src/features/operations/server/queries/getTasks.ts and src/features/operations/server/actions/createTask.ts respectively. The output is properly typed based on your Prisma schema, so you get full type-safety out of the box.

feature.wasp.ts

  app
    // Action definitions
    .addAction(feature, "createTask", {
      entities: ["Task"],
      auth: false,
    })
    // Query definitions
    .addQuery(feature, "getTasks", {
      entities: ["Task"],
      auth: false,
    })

createTask.ts

import { Task } from "wasp/entities";
import { HttpError } from "wasp/server";
import type { CreateTask } from "wasp/server/operations";

export const createTask: CreateTask<Pick<Task, "description" | "userId"> & Partial<Pick<Task, "isDone">>> = async (data, context) => {
  try {
    const createdTask = await context.entities.Task.create({
      data: {
        ...data,
      }
    });

    return createdTask;
  } catch (error) {
    console.error("Failed to create Task:", error);

    throw new HttpError(500, `Failed to create Task${error instanceof Error ? `: ${error.message}` : ''}`);
  }
}; 

getTasks.ts

import { HttpError } from "wasp/server";
import type { GetAllTasks } from "wasp/server/operations";

export const getAllTasks = (async (_args, context) => {
  try {
    const tasks = await context.entities.Task.findMany();

    return tasks;
  } catch (error) {
    console.error("Failed to get all tasks:", error);

    if (error instanceof HttpError) {
      throw error;
    }

    throw new HttpError(500, `Failed to get all tasks${error instanceof Error ? `: ${error.message}` : ''}`);
  }
}) satisfies GetAllTasks<void>;

CRUD Operations

For CRUD operations, the kitchen-sink application offers a separate crud feature. Let's generate that and a set of operations:

npm run swarm -- feature --target crud
npm run swarm -- crud --feature crud --data-type Task --override get getAll create

Output

This configures all the standard CRUD operations, with function overrides for the get, getAll and create operations. CRUD operations are a special case, with all overridden functions being exported from src/features/crud/server/cruds/tasks.ts.

feature.wasp.ts

  app
    // Crud definitions
    .addCrud(feature, "tasks", {
      entity: "Task",
      get: {
        override: true
      },
      getAll: {
        override: true
      },
      create: {
        override: true
      },
      update: {},
      delete: {},
    });

tasks.ts

import { type Task } from "wasp/entities";
import { HttpError } from "wasp/server";
import { type Tasks } from "wasp/server/crud";

export const getTask = (async ({ id }, context) => {
  if (!context.user) {
    throw new HttpError(401);
  }

  try {
    const task = await context.entities.Task.findUnique({
      where: { id },
    });

    if (!task) {
      throw new HttpError(404, `task ${id} not found`);
    }

    return task;
  } catch (error) {
    console.error(`Failed to get task ${id}:`, error);

    if (error instanceof HttpError) {
      throw error;
    }

    throw new HttpError(500, `Failed to get task ${id}${error instanceof Error ? `: ${error.message}` : ''}`);
  }
}) satisfies Tasks.GetQuery<Pick<Task, "id">>;

export const getAllTasks = (async (_args, context) => {
  if (!context.user) {
    throw new HttpError(401);
  }

  try {
    const tasks = await context.entities.Task.findMany();

    return tasks;
  } catch (error) {
    console.error("Failed to get all tasks:", error);

    if (error instanceof HttpError) {
      throw error;
    }

    throw new HttpError(500, `Failed to get all tasks${error instanceof Error ? `: ${error.message}` : ''}`);
  }
}) satisfies Tasks.GetAllQuery<void>;

export const createTask: Tasks.CreateAction<Pick<Task, "description" | "userId"> & Partial<Pick<Task, "isDone">>> = async (data, context) => {
  if (!context.user) {
    throw new HttpError(401);
  }

  try {
    const createdTask = await context.entities.Task.create({
      data: {
        ...data,
      }
    });

    return createdTask;
  } catch (error) {
    console.error("Failed to create Task:", error);

    throw new HttpError(500, `Failed to create Task${error instanceof Error ? `: ${error.message}` : ''}`);
  }
}; 

HTTP API Endpoints

The kitchen-sink example includes various endpoints in the apis feature, so let's add one:

npm run swarm -- feature --target apis
npm run swarm -- api --feature apis --name fooBar --method ALL --path /foo/bar --entities Task

Output

This creates the endpoint handler in src/features/apis/server/apis/fooBar.ts and registers it in your feature configuration. The generator handles the middleware setup and entity access automatically.

feature.wasp.ts

  app
    // Api definitions
    .addApi(feature, "fooBar", {
      method: "ALL",
      route: "/foo/bar",
      entities: ["Task"],
      auth: false,
      customMiddleware: true,
    });

tasks.ts

import type { FooBar } from "wasp/server/api";

export const fooBar: FooBar = async (req, res, context) => {
  // TODO: Implement your API logic here
  res.json({ message: "OK" });
};

Running the app

While the app doesn't yet have any proper business logic, all the boilerplate is valid code and you should be able to confirm the application runs by executing:

npm run dev

After the application opens, navigate to http://localhost:3000/tasks and you should be redirected to the /login page. The page component hasn't been completed yet, but simply verifies that the application can be compiled and executed successfully.

AI-Assisted Development with MCP

The CLI works well when you know exactly what you want to generate. Sometimes it's faster to just describe your intent and let an AI assistant figure out the right commands. That's where MCP comes in.

Start the MCP server with:

npm run swarm:mcp

Once you've configured your AI tool (Cursor, Claude Code, or VS Code Copilot) to connect to the server, you can use natural language prompts. Instead of remembering the exact CLI syntax, you can say something like:

"Create an operations feature with a route to view tasks, queries and actions for the Task entity, and an authenticated API endpoint."

The AI understands your intent and calls the appropriate MCP tools, which map directly to the CLI commands. You get the same generated code, but without having to construct the command yourself.

This becomes really powerful when you're building out a feature incrementally. You might start with a basic structure, then ask the AI to add more components as you think of them. Each request generates the right files in the right places, and everything stays consistent because it's all going through the same generators.

The MCP integration means Swarm's generators are available to any AI tool that supports the protocol. You're not locked into a specific editor or assistant—if it can talk MCP, it can use Swarm.

Putting It All Together

I've created a comparison video that shows a traditional Wasp application side-by-side with one built using Swarm Wasp Starter. Both are based on the kitchen-sink example, so you can see how the same functionality looks in each approach.

The video demonstrates the complete applications, highlighting the differences in structure, configuration, and development workflow. If you're curious about how Swarm changes the day-to-day experience of building Wasp apps, this should give you a clear picture.

If you're building with Wasp, give the Swarm Wasp Starter a try!

Command Line for Total Beginners

2025-11-17 15:33:10

🖥️ A Gentle, Hands-On Guide

🎯 What You Will Learn

By the end of this guide, you’ll be able to:

  • Understand what the terminal is
  • Navigate folders (directories)
  • Create, move, rename, and delete files
  • Read file contents
  • Use basic power tools (ls, cd, pwd, mkdir, rm, cp, mv)
  • Understand absolute vs. relative paths
  • Use help and man pages
  • Understand how commands, flags, and arguments work

🌱 SECTION 1 — What Is the Command Line?

The command line (terminal) is a place where you tell your computer what to do using text commands instead of clicking buttons.

You can open it by:

  • Mac: Applications → Utilities → Terminal
  • Windows: Windows Terminal / Command Prompt / PowerShell
  • Linux: Ctrl+Alt+T

We will use general commands that work on macOS & Linux.
If you're on Windows and want the same commands, install Git Bash or use WSL. See the guide below.

🪟 Note for Windows Users — Install Git Bash First

Windows’ default terminals (Command Prompt, PowerShell) use different commands from macOS/Linux.
To make learning simpler, we’ll use Git Bash, which supports the same commands as macOS/Linux.

👉 Install Git Bash Here:

https://git-scm.com/downloads

Choose “Windows” → Install with default settings.

After installation, open:

Git Bash

From here on, all commands in this guide will work the same whether you are on:

✔ Windows (Git Bash)
✔ macOS (Terminal)
✔ Linux (Terminal)

🧠 Mini Quiz

  1. Is the terminal a graphical or text-based interface?
  2. Do you “click” commands or type them?
  3. What do you open on macOS to access the terminal?

📍 SECTION 2 — Your First Commands

🧪 Activity: Try Your First Commands

1. See where you are

pwd

Means print working directory.

You’ll see something like:
/Users/yourname

2. List what’s in this folder

ls

3. Move into a folder

cd Desktop

4. Move back

cd ..

5. Go to your home folder

cd ~

🧠 Mini Quiz

  1. What command shows your current location?
  2. How do you go “up” one folder?
  3. What does ~ represent?

📁 SECTION 3 — Files and Folders (Create, List, Explore)

Create a folder

mkdir test-folder

Move into it

cd test-folder

Create a file

Different OS options:

macOS / Linux:

touch notes.txt

Windows PowerShell:

ni notes.txt

Now check:

ls

View file contents

cat notes.txt

(It will be empty; that’s fine.)

🧪 Activity: Build a Mini Workspace

Run these commands:

mkdir projects
cd projects
mkdir project1
cd project1
touch index.html
touch script.js
cd ..
mkdir project2

Then explore with:

ls
cd project1
ls
pwd

🧠 Mini Quiz

  1. What command creates a folder?
  2. What command creates a file?
  3. How do you view the content of a file?

🧭 SECTION 4 — Paths (Absolute vs Relative)

Absolute path

A full address:

/Users/yourname/Desktop

Relative path

Based on where you are:

cd ../other-folder

🧪 Activity: Path Scavenger Hunt

  1. Run pwd
  2. Use only cd .. to climb back to your home folder
  3. Use absolute path to jump to Desktop
  4. Use relative path to return to home

Try examples:

cd /Users/<yourname>/Documents

Then:

cd ../Downloads

🧠 Mini Quiz

  1. Which is shorter: relative or absolute paths?
  2. Do absolute paths always start with /?
  3. What does .. mean?

🛠 SECTION 5 — Moving, Copying, Renaming, Deleting

⚠️ These commands are powerful. Practice on test files only.

Rename a file

mv oldname.txt newname.txt

Move a file

mv notes.txt Documents/

Copy a file

cp notes.txt notes-copy.txt

Delete a file

rm notes-copy.txt

Delete a folder (careful!)

rm -r test-folder

🧪 Activity: File Manipulation Challenge

Inside a temporary folder:

  1. Create 3 files
  2. Rename one
  3. Copy one
  4. Move one into a new folder
  5. Delete one

🧠 Mini Quiz

  1. Which command removes files?
  2. What flag do you need to delete folders?
  3. Which command is used for renaming AND moving?

🧩 SECTION 6 — Understanding Command Syntax

Commands typically follow this pattern:

command [options/flags] [arguments]

Examples:

ls -l
ls -a
rm -r foldername

Where:

  • command = program to run
  • flags = change behavior
  • arguments = what to run it on

🧪 Activity: Experiment with Flags

Try:

ls -l
ls -a
ls -la

Observe the differences.

🧠 Mini Quiz

  1. Which part is the flag in ls -a?
  2. Does the order of flags matter?
  3. What are arguments?

🔍 SECTION 7 — Finding Help

Every command has built-in help.

man pages (macOS/Linux)

man ls

Scroll with arrow keys, exit with q.

help flag

ls --help

🧪 Activity: Explore 3 Commands

Run:

man pwd
man mkdir
man rm

Or:

pwd --help

🧠 Mini Quiz

  1. What command shows manual pages?
  2. How do you quit a man page?
  3. What flag often displays help?

📦 SECTION 8 — Practical Daily Workflow

Here’s a realistic flow you’ll use constantly:

pwd
ls
cd foldername
ls
cat somefile.txt
cd ..
mkdir newfolder
mv file.txt newfolder/
rm oldfile.txt

Practice this every day and your comfort will skyrocket.

🧪 FINAL EXERCISE — Build & Manage a Folder Tree

Step 1 — Create a structure

mkdir school
cd school
mkdir math english science
cd math
touch algebra.txt geometry.txt

Step 2 — Navigate around

cd ../english
touch essay1.txt

Step 3 — Manipulate

mv ../math/geometry.txt .
cp essay1.txt essay1-copy.txt
rm ../science

Try exploring the entire tree with:

ls -R

🎉 You’re Ready!

You can now:

  • Navigate the terminal
  • Create and manage files and folders
  • Understand paths
  • Use flags
  • Find help
  • Build and manage folder structures
  • Work comfortably in a development environment

I built a free NFL player guessing game — need feedback!

2025-11-17 15:25:04

I made a Weddle-style NFL guessing game where you try to identify the mystery player in 8 attempts using clues like team, division, height, age, and position.
Looking for feedback on gameplay + suggestions for improvements.
Play here:

🎯 Predict Markets Like a FAANG Data Scientist: 3 ML Models That Outperform MBA Analysts

2025-11-17 15:17:03

💰 LSTM + Attention beats classical methods by 40% in price forecasting accuracy

⚡ XGBoost finds non-obvious market drivers in 5 minutes instead of 3
weeks 📈 Prophet makes seasonal analysis so simple that product managers
can handle it 🔥 All models are already in production at top companies
(code examples inside)

The Problem No One Talks About in Business Schools

You spend hours in Excel building forecasts that are outdated the moment
you present them. Your traditional time series models (ARIMA, I'm
looking at you) break down when the market sneezes.

Here's the brutal truth: While you're fighting with pivot tables,
competitors are using ML models that adapt in real-time.

I learned this the hard way when my Q4 demand forecast was off by
35%. The CMO wasn't happy. My weekend plans weren't either.

The Solution: 3 Production-Ready Models

💡 Model #1: LSTM + Attention Mechanism

What it does: Predicts demand and prices by learning complex
patterns humans miss.

The stats:

  • Accuracy: 85--92%\
  • Forecast horizon: 1--24 months\
  • Best for: Short-term predictions with high volatility

🧠 Code Example

import tensorflow as tf
from tensorflow.keras.layers import LSTM, Attention, Dense
import numpy as np

# Simple LSTM + Attention for demand forecasting
def build_lstm_attention_model(sequence_length, features):
    inputs = tf.keras.Input(shape=(sequence_length, features))

    # LSTM layer - captures temporal dependencies
    lstm_out = LSTM(128, return_sequences=True)(inputs)

    # Attention mechanism - focuses on important time steps
    attention = Attention()([lstm_out, lstm_out])

    # Combine and predict
    flatten = tf.keras.layers.Flatten()(attention)
    outputs = Dense(1, activation='linear')(flatten)

    model = tf.keras.Model(inputs=inputs, outputs=outputs)
    model.compile(optimizer='adam', loss='mse', metrics=['mae'])

    return model

# Usage example
model = build_lstm_attention_model(sequence_length=30, features=5)

# Train on your data
# model.fit(X_train, y_train, epochs=50, batch_size=32)

⚠️ Common mistake: not scaling input data

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
X_scaled = scaler.fit_transform(X_train)

💡 Model #2: XGBoost for Factor Analysis

What it does: Reveals which variables actually drive your market.

The stats:

  • Accuracy: 88--94%\
  • Speed: Handles millions of rows in minutes\
  • Best for: Hidden correlations, feature importance, market drivers

🧠 Code Example

import xgboost as xgb
from sklearn.model_selection import train_test_split
import pandas as pd

def analyze_market_drivers(df, target_column):
    X = df.drop(columns=[target_column])
    y = df[target_column]

    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=42
    )

    model = xgb.XGBRegressor(
        n_estimators=100,
        learning_rate=0.1,
        max_depth=6,
        subsample=0.8,
        colsample_bytree=0.8,
        random_state=42
    )

    model.fit(X_train, y_train)

    importance_df = pd.DataFrame({
        'feature': X.columns,
        'importance': model.feature_importances_
    }).sort_values('importance', ascending=False)

    print("🔥 Top Market Drivers:")
    print(importance_df.head(10))

    return model, importance_df

💡 Model #3: Prophet for Seasonal Analysis

What it does: Builds business-ready forecasts with holiday +
seasonality baked in.

The stats:

  • Ease of use: Can be used by junior analysts\
  • Interpretability: Clear decomposition (trend, seasonality, holidays)\
  • Best for: Executive-ready visuals and planning

🧠 Code Example

from prophet import Prophet
import pandas as pd

df = pd.DataFrame({
    'ds': pd.date_range('2020-01-01', periods=365*3, freq='D'),
    'y': your_sales_data
})

model = Prophet(
    yearly_seasonality=True,
    weekly_seasonality=True,
    daily_seasonality=False,
    changepoint_prior_scale=0.05
)

model.add_country_holidays(country_name='US')
model.fit(df)

future = model.make_future_dataframe(periods=365)
forecast = model.predict(future)

fig = model.plot(forecast)
fig2 = model.plot_components(forecast)

🎁 Bonus: Which Model Should YOU Use?

Use LSTM + Attention if:

  • You have 1000+ observations\
  • Data is volatile and non-linear\
  • Accuracy matters most

Use XGBoost if:

  • You need interpretability\
  • You have mixed data types\
  • Speed matters

Use Prophet if:

  • You need simple, stakeholder-friendly models\
  • Seasonality/holidays dominate your data\
  • You want a production-ready model in 10 minutes

📊 Comparison Table

Model Accuracy Speed Explainability Difficulty

LSTM + Attention ⭐⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐ ⭐⭐⭐⭐⭐⭐
XGBoost ⭐⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐
Prophet ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐⭐ ⭐

Your Next Steps

  1. Pick one model to implement this week\
  2. Use 6--12 months of historical data\
  3. Validate monthly\
  4. Retrain as the market changes