Layer project Dockerfile on top of base image
Always builds ramekin-agent first, so .ramekin/Dockerfile can
FROM ramekin-agent and add only project-specific dependencies.

Assisted-by: Claude Opus 4.6 via pi
change mnomkpkvqwryrruvtoxoouxrvzrkkskq
commit f362914cea45583350150fdfa93511fa7874cf7a
author Alpha Chen <alpha@kejadlen.dev>
date
parent ntmklzoq
diff --git a/README.md b/README.md
index 94c9b8c..ac0416f 100644
--- a/README.md
+++ b/README.md
@@ -37,7 +37,12 @@ A built-in pi extension (`ramekin.ts`) is mounted into the agent container. It a
 
 ### Custom Dockerfile
 
-Place a `Dockerfile` at `.ramekin/Dockerfile` in your workspace to override the default agent image. The workspace is used as the build context, so `COPY` instructions work relative to the project root.
+Place a `Dockerfile` at `.ramekin/Dockerfile` in your workspace to extend the base agent image. Use `FROM ramekin-agent` to layer on top — the base image includes Node.js, pi, git, ripgrep, and fd. The workspace is used as the build context, so `COPY` instructions work relative to the project root.
+
+```dockerfile
+FROM ramekin-agent
+RUN apt-get update && apt-get install -y ruby && rm -rf /var/lib/apt/lists/*
+```
 
 ## Development
 
diff --git a/src/main.rs b/src/main.rs
index 3fba218..0f48e14 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -75,14 +75,27 @@ fn run() -> Result<()> {
 
     let compose_file = cache_dir.join("compose.yml");
 
-    // Use .ramekin/Dockerfile from workspace if it exists, otherwise use the embedded one
+    // Always build the base image first
+    info!("building base image");
+    let base_dockerfile = cache_dir.join("Dockerfile");
+    let status = Command::new("docker")
+        .args(["build", "-t", "ramekin-agent", "-f"])
+        .arg(&base_dockerfile)
+        .arg(&cache_dir)
+        .status()
+        .wrap_err("failed to build base image")?;
+
+    if !status.success() {
+        bail!("base image build failed ({})", status);
+    }
+
+    // If a project Dockerfile exists, build it on top of the base image
     let custom_dockerfile = workspace.join(".ramekin/Dockerfile");
     let (dockerfile, build_context) = if custom_dockerfile.exists() {
-        info!("using custom Dockerfile from .ramekin/Dockerfile");
+        info!("building project image from .ramekin/Dockerfile");
         (custom_dockerfile, workspace.clone())
     } else {
-        info!("using built-in Dockerfile");
-        (cache_dir.join("Dockerfile"), cache_dir.clone())
+        (base_dockerfile, cache_dir.clone())
     };
 
     let docker_compose = |args: &[&str]| -> Result<Command> {