diff --git a/.changeset/few-chicken-exercise.md b/.changeset/few-chicken-exercise.md
new file mode 100644
index 0000000000000000000000000000000000000000..9ddded96a7caba549466ef47f17fa789ef937899
--- /dev/null
+++ b/.changeset/few-chicken-exercise.md
@@ -0,0 +1,5 @@
+---
+"create-llama": patch
+---
+
+Add "Start in VSCode" option to postInstallAction
diff --git a/.changeset/plenty-onions-relate.md b/.changeset/plenty-onions-relate.md
new file mode 100644
index 0000000000000000000000000000000000000000..8b940e8a298af6a860b2e413a3c0b050efed811f
--- /dev/null
+++ b/.changeset/plenty-onions-relate.md
@@ -0,0 +1,5 @@
+---
+"create-llama": patch
+---
+
+Add devcontainers to generated code
diff --git a/packages/create-llama/create-app.ts b/packages/create-llama/create-app.ts
index 1b5ed303d099d83deb247c10e59aa55ed36b273a..2f7db13a7f8c85a855efc045e3aa94006348ef29 100644
--- a/packages/create-llama/create-app.ts
+++ b/packages/create-llama/create-app.ts
@@ -11,6 +11,7 @@ import fs from "fs";
 import terminalLink from "terminal-link";
 import type { InstallTemplateArgs } from "./helpers";
 import { installTemplate } from "./helpers";
+import { writeDevcontainer } from "./helpers/devcontainer";
 import { templatesDir } from "./helpers/dir";
 import { toolsRequireConfig } from "./helpers/tools";
 
@@ -121,6 +122,8 @@ export async function createApp({
     console.log();
   }
 
+  await writeDevcontainer(root, templatesDir, framework, frontend);
+
   if (toolsRequireConfig(tools)) {
     console.log(
       yellow(
diff --git a/packages/create-llama/helpers/devcontainer.ts b/packages/create-llama/helpers/devcontainer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cb008b97736fa25b55f1ca443438d91017e0aa67
--- /dev/null
+++ b/packages/create-llama/helpers/devcontainer.ts
@@ -0,0 +1,61 @@
+import fs from "fs";
+import path from "path";
+import { TemplateFramework } from "./types";
+
+function renderDevcontainerContent(
+  templatesDir: string,
+  framework: TemplateFramework,
+  frontend: boolean,
+) {
+  const devcontainerJson: any = JSON.parse(
+    fs.readFileSync(path.join(templatesDir, "devcontainer.json"), "utf8"),
+  );
+
+  // Modify postCreateCommand
+  if (frontend) {
+    devcontainerJson.postCreateCommand =
+      framework === "fastapi"
+        ? "cd backend && poetry install && cd ../frontend && npm install"
+        : "cd backend && npm install && cd ../frontend && npm install";
+  } else {
+    devcontainerJson.postCreateCommand =
+      framework === "fastapi" ? "poetry install" : "npm install";
+  }
+
+  // Modify containerEnv
+  if (framework === "fastapi") {
+    if (frontend) {
+      devcontainerJson.containerEnv = {
+        ...devcontainerJson.containerEnv,
+        PYTHONPATH: "${PYTHONPATH}:${workspaceFolder}/backend",
+      };
+    } else {
+      devcontainerJson.containerEnv = {
+        ...devcontainerJson.containerEnv,
+        PYTHONPATH: "${PYTHONPATH}:${workspaceFolder}",
+      };
+    }
+  }
+
+  return JSON.stringify(devcontainerJson, null, 2);
+}
+
+export const writeDevcontainer = async (
+  root: string,
+  templatesDir: string,
+  framework: TemplateFramework,
+  frontend: boolean,
+) => {
+  console.log("Adding .devcontainer");
+  const devcontainerContent = renderDevcontainerContent(
+    templatesDir,
+    framework,
+    frontend,
+  );
+  const devcontainerDir = path.join(root, ".devcontainer");
+  fs.mkdirSync(devcontainerDir);
+  await fs.promises.writeFile(
+    path.join(devcontainerDir, "devcontainer.json"),
+    devcontainerContent,
+  );
+};
diff --git a/packages/create-llama/helpers/llama-pack.ts b/packages/create-llama/helpers/llama-pack.ts
index 16cd801fa3e24cbfc666eb85c00b389dc6f61d3c..887201d9fcdd2a0ddcdac8199cbc655a186924df 100644
--- a/packages/create-llama/helpers/llama-pack.ts
+++ b/packages/create-llama/helpers/llama-pack.ts
@@ -142,7 +142,7 @@ export const installLlamapackProject = async ({
   await copyLlamapackEmptyProject({ root });
   await copyData({ root });
   await installLlamapackExample({ root, llamapack });
-  if (postInstallAction !== "none") {
+  if (postInstallAction === "runApp" || postInstallAction === "dependencies") {
     installPythonDependencies({ noRoot: true });
   }
 };
diff --git a/packages/create-llama/helpers/python.ts b/packages/create-llama/helpers/python.ts
index 3ebde783b17a4b8922e6fdb027ec3f058b33df49..285beb9a8b377b1c757c84765fca5e5766bba9f4 100644
--- a/packages/create-llama/helpers/python.ts
+++ b/packages/create-llama/helpers/python.ts
@@ -266,7 +266,7 @@ export const installPythonTemplate = async ({
   );
   await addDependencies(root, addOnDependencies);
 
-  if (postInstallAction !== "none") {
+  if (postInstallAction === "runApp" || postInstallAction === "dependencies") {
     installPythonDependencies();
   }
 };
diff --git a/packages/create-llama/helpers/types.ts b/packages/create-llama/helpers/types.ts
index 52ef94b914a9fd2591e6ec0d912536dc410881b1..7422773731e9bcb79e6f153a4c4366274ecd1d3e 100644
--- a/packages/create-llama/helpers/types.ts
+++ b/packages/create-llama/helpers/types.ts
@@ -6,7 +6,11 @@ export type TemplateFramework = "nextjs" | "express" | "fastapi";
 export type TemplateEngine = "simple" | "context";
 export type TemplateUI = "html" | "shadcn";
 export type TemplateVectorDB = "none" | "mongo" | "pg" | "pinecone";
-export type TemplatePostInstallAction = "none" | "dependencies" | "runApp";
+export type TemplatePostInstallAction =
+  | "none"
+  | "VSCode"
+  | "dependencies"
+  | "runApp";
 export type TemplateDataSource = {
   type: TemplateDataSourceType;
   config: TemplateDataSourceConfig;
diff --git a/packages/create-llama/helpers/typescript.ts b/packages/create-llama/helpers/typescript.ts
index cfadc67b1f96dd3e16c97fb5f938612067517168..bab6812f762dff286759f82d250ee9fd7a3bb00d 100644
--- a/packages/create-llama/helpers/typescript.ts
+++ b/packages/create-llama/helpers/typescript.ts
@@ -228,7 +228,7 @@ export const installTSTemplate = async ({
     JSON.stringify(packageJson, null, 2) + os.EOL,
   );
 
-  if (postInstallAction !== "none") {
+  if (postInstallAction === "runApp" || postInstallAction === "dependencies") {
     await installTSDependencies(packageJson, packageManager, isOnline);
   }
 };
diff --git a/packages/create-llama/index.ts b/packages/create-llama/index.ts
index 804eae6cce367d9bbc78ea1c15c9539afa56e81f..47e78c26a480a6293b64efb24094430f6b792b0c 100644
--- a/packages/create-llama/index.ts
+++ b/packages/create-llama/index.ts
@@ -1,11 +1,13 @@
 #!/usr/bin/env node
 /* eslint-disable import/no-extraneous-dependencies */
+import { execSync } from "child_process";
 import Commander from "commander";
 import Conf from "conf";
 import fs from "fs";
 import path from "path";
 import { bold, cyan, green, red, yellow } from "picocolors";
 import prompts from "prompts";
+import terminalLink from "terminal-link";
 import checkForUpdate from "update-check";
 import { createApp } from "./create-app";
 import { getPkgManager } from "./helpers/get-pkg-manager";
@@ -298,7 +300,31 @@ async function run(): Promise<void> {
   });
   conf.set("preferences", preferences);
 
-  if (program.postInstallAction === "runApp") {
+  if (program.postInstallAction === "VSCode") {
+    console.log(`Starting VSCode in ${root}...`);
+    try {
+      execSync(`code . --new-window --goto README.md`, {
+        stdio: "inherit",
+        cwd: root,
+      });
+    } catch (error) {
+      console.log(
+        red(
+          `Failed to start VSCode in ${root}. 
+Got error: ${(error as Error).message}.\n`,
+        ),
+      );
+      console.log(
+        `Make sure you have VSCode installed and added to your PATH. 
+Please check ${cyan(
+          terminalLink(
+            "This documentation",
+            `https://code.visualstudio.com/docs/setup/setup-overview`,
+          ),
+        )} for more information.`,
+      );
+    }
+  } else if (program.postInstallAction === "runApp") {
     console.log(`Running app in ${root}...`);
     await runApp(
       root,
diff --git a/packages/create-llama/questions.ts b/packages/create-llama/questions.ts
index 6835bb36357cc285e0b164249515f739d1df41ef..af5f17d69fd3b12cdaca5f83d7bbcd57b0fb6f35 100644
--- a/packages/create-llama/questions.ts
+++ b/packages/create-llama/questions.ts
@@ -215,6 +215,10 @@ export const askQuestions = async (
             title: "Just generate code (~1 sec)",
             value: "none",
           },
+          {
+            title: "Start in VSCode (~1 sec)",
+            value: "VSCode",
+          },
           {
             title: "Generate code and install dependencies (~2 min)",
             value: "dependencies",
diff --git a/packages/create-llama/templates/devcontainer.json b/packages/create-llama/templates/devcontainer.json
new file mode 100644
index 0000000000000000000000000000000000000000..f87545ffbae3cb2d5779eb581b3c336bce487c59
--- /dev/null
+++ b/packages/create-llama/templates/devcontainer.json
@@ -0,0 +1,35 @@
+{
+  "image": "mcr.microsoft.com/vscode/devcontainers/typescript-node:dev-20-bullseye",
+  "features": {
+    "ghcr.io/devcontainers-contrib/features/turborepo-npm:1": {},
+    "ghcr.io/devcontainers-contrib/features/typescript:2": {},
+    "ghcr.io/devcontainers/features/python:1": {
+      "version": "3.11",
+      "toolsToInstall": ["flake8", "black", "mypy", "poetry"]
+    }
+  },
+  "customizations": {
+    "codespaces": {
+      "openFiles": ["README.md"]
+    },
+    "vscode": {
+      "extensions": [
+        "ms-vscode.typescript-language-features",
+        "esbenp.prettier-vscode",
+        "ms-python.python",
+        "ms-python.black-formatter",
+        "ms-python.vscode-flake8",
+        "ms-python.vscode-pylance"
+      ],
+      "settings": {
+        "python.formatting.provider": "black",
+        "python.languageServer": "Pylance",
+        "python.analysis.typeCheckingMode": "basic"
+      }
+    }
+  },
+  "containerEnv": {
+    "POETRY_VIRTUALENVS_CREATE": "false"
+  },
+  "forwardPorts": [3000, 8000]
+}