mulmoclaude 0.5.1 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,100 @@
1
+ FROM node:22-slim
2
+
3
+ # Sandbox tool set (see #162). Grouped into layers by purpose so the
4
+ # rationale is obvious from the diff:
5
+ #
6
+ # 1. Core CLI — read local git history, fetch over HTTP, pipeline JSON,
7
+ # run Makefile-driven workspaces, handle archives, query SQLite.
8
+ # `ca-certificates` is needed because `node:22-slim` ships without
9
+ # a trust store. `ripgrep` backs Claude's grep tool.
10
+ # 2. Data analysis + plotting — Python with pandas/numpy/matplotlib
11
+ # and `requests` for API fetches. Graphviz for structural diagrams.
12
+ # ImageMagick for raster ops. Covers the "investment / data / chart"
13
+ # and "visualize this workflow" use cases in the issue.
14
+ # 3. Document + media conversion — pandoc bridges Markdown ↔ PDF/DOCX/
15
+ # HTML/EPUB for report output. ffmpeg covers audio/video transcode
16
+ # and probing. poppler-utils extracts text / images from PDFs.
17
+ # 4. Small extras — `tree` for directory listing, `bc` for arbitrary-
18
+ # precision arithmetic, `less` for pagers.
19
+ #
20
+ # Deferred on purpose:
21
+ #
22
+ # - `@mermaid-js/mermaid-cli` — pulls in headless Chromium (~300MB).
23
+ # Revisit as a separate layer if diagram generation becomes common.
24
+ # - `texlive-*` — ~150MB+ for marginal PDF quality gains over pandoc's
25
+ # default LaTeX-free path; add when a user actually needs math/
26
+ # journal-style typesetting.
27
+ # - `gh` CLI — now installed (Layer 1b). Auth via SANDBOX_MOUNT_CONFIGS=gh
28
+ # which mounts ~/.config/gh:ro into the container (#259).
29
+ #
30
+ # Runtime `pip install` is intentionally NOT wired up. Everything the
31
+ # agent might need for data work is preinstalled at build time so
32
+ # supply-chain risk stays out of the sandbox.
33
+
34
+ # Layer 1: core CLI + SSH client (needed for SSH agent forwarding #259)
35
+ RUN apt-get update && apt-get install -y --no-install-recommends \
36
+ git \
37
+ curl \
38
+ jq \
39
+ make \
40
+ ca-certificates \
41
+ openssh-client \
42
+ sqlite3 \
43
+ zip \
44
+ unzip \
45
+ ripgrep \
46
+ && rm -rf /var/lib/apt/lists/*
47
+
48
+ # Layer 1b: GitHub CLI (#164). Installed from the official apt repo.
49
+ # Auth is provided at runtime via SANDBOX_MOUNT_CONFIGS=gh which
50
+ # bind-mounts ~/.config/gh:ro (#259). On macOS where the token lives
51
+ # in the system keyring, the server falls back to GH_TOKEN env var.
52
+ RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
53
+ -o /usr/share/keyrings/githubcli-archive-keyring.gpg \
54
+ && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
55
+ > /etc/apt/sources.list.d/github-cli.list \
56
+ && apt-get update && apt-get install -y --no-install-recommends gh \
57
+ && rm -rf /var/lib/apt/lists/*
58
+
59
+ # Layer 2: data analysis + plotting
60
+ RUN apt-get update && apt-get install -y --no-install-recommends \
61
+ python3 \
62
+ python3-pip \
63
+ graphviz \
64
+ imagemagick \
65
+ && rm -rf /var/lib/apt/lists/* \
66
+ && pip3 install --no-cache-dir --break-system-packages \
67
+ pandas \
68
+ numpy \
69
+ matplotlib \
70
+ requests
71
+
72
+ # Layer 3: document + media conversion
73
+ # LibreOffice core + Impress + Writer enable server-side PPTX→PDF and
74
+ # DOCX→PDF conversion for the attachment pipeline (#386). Only the
75
+ # headless renderer is used (`--headless --convert-to pdf`).
76
+ RUN apt-get update && apt-get install -y --no-install-recommends \
77
+ pandoc \
78
+ ffmpeg \
79
+ poppler-utils \
80
+ libreoffice-core \
81
+ libreoffice-impress \
82
+ libreoffice-writer \
83
+ && rm -rf /var/lib/apt/lists/*
84
+
85
+ # Layer 4: small extras
86
+ RUN apt-get update && apt-get install -y --no-install-recommends \
87
+ tree \
88
+ bc \
89
+ less \
90
+ && rm -rf /var/lib/apt/lists/*
91
+
92
+ RUN npm install -g @anthropic-ai/claude-code tsx
93
+
94
+ COPY sandbox-entrypoint.sh /sandbox-entrypoint.sh
95
+ RUN chmod +x /sandbox-entrypoint.sh
96
+
97
+ # No `USER node` — the entrypoint starts as root to fix /etc/passwd
98
+ # and socket permissions, then drops to HOST_UID:HOST_GID via setpriv.
99
+ WORKDIR /home/node/mulmoclaude
100
+ ENTRYPOINT ["/sandbox-entrypoint.sh"]
@@ -104,7 +104,7 @@ Options:
104
104
  }
105
105
 
106
106
  if (args.includes("--version")) {
107
- console.log("mulmoclaude 0.5.1");
107
+ console.log("mulmoclaude 0.5.3");
108
108
  process.exit(0);
109
109
  }
110
110
 
@@ -31,7 +31,7 @@
31
31
  // ── Publish ───────────────────────────────────────────────────
32
32
  // cd packages/mulmoclaude && npm publish --access public
33
33
 
34
- import { cpSync, existsSync, rmSync } from "fs";
34
+ import { copyFileSync, cpSync, existsSync, rmSync } from "fs";
35
35
  import { join, dirname } from "path";
36
36
  import { fileURLToPath } from "url";
37
37
 
@@ -42,11 +42,16 @@ const rootDir = join(pkgDir, "..", "..");
42
42
  // ── Clean ───────────────────────────────────────────────────
43
43
 
44
44
  // Include `dist` so leftovers from the older pre-built-JS layout are
45
- // wiped on re-run.
45
+ // wiped on re-run. Stale sandbox files are removed too so a renamed
46
+ // or deleted source file doesn't ride along into the tarball.
46
47
  for (const dir of ["dist", "client", "server", "src"]) {
47
48
  const target = join(pkgDir, dir);
48
49
  if (existsSync(target)) rmSync(target, { recursive: true });
49
50
  }
51
+ for (const file of ["Dockerfile.sandbox", "sandbox-entrypoint.sh"]) {
52
+ const target = join(pkgDir, file);
53
+ if (existsSync(target)) rmSync(target);
54
+ }
50
55
 
51
56
  // ── Client dist (Vite build output) ─────────────────────────
52
57
  // Copied to `client/` (not `dist/client/`) so the server's
@@ -89,5 +94,16 @@ cpSync(join(rootDir, "src"), join(pkgDir, "src"), {
89
94
  });
90
95
  console.log("✓ shared src/");
91
96
 
97
+ // ── Sandbox build context ───────────────────────────────────
98
+ // `server/system/docker.ts` builds the sandbox image via `docker build
99
+ // -f Dockerfile.sandbox .` with cwd = pkgDir. The Dockerfile in turn
100
+ // `COPY`s `sandbox-entrypoint.sh`, so both files must sit at pkgDir
101
+ // or sandbox mode silently falls back to unrestricted execution.
102
+
103
+ for (const file of ["Dockerfile.sandbox", "sandbox-entrypoint.sh"]) {
104
+ copyFileSync(join(rootDir, file), join(pkgDir, file));
105
+ }
106
+ console.log("✓ sandbox build context");
107
+
92
108
  console.log("\nReady to publish. Run:");
93
109
  console.log(" cd packages/mulmoclaude && npm publish --access public");