maesttro 0.4.4 → 0.6.0
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.
- package/README.md +15 -9
- package/dist/maesttro.js +3292 -614
- package/docker/Dockerfile +65 -10
- package/docker/entrypoint.sh +9 -3
- package/package.json +5 -2
package/docker/Dockerfile
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# git is built from source: Debian ships 2.47 and the runner wants a recent
|
|
2
|
-
# git. Builder matches node:
|
|
2
|
+
# git. Builder matches node:24-slim's Debian so the runtime libs line up.
|
|
3
3
|
FROM debian:bookworm-slim AS git-build
|
|
4
4
|
ARG GIT_VERSION=2.55.0
|
|
5
5
|
ARG GIT_SHA256=457fdb04dc8728e007d4688695e6912e6f680727920f2a40bf11eacc17505357
|
|
@@ -14,9 +14,18 @@ RUN apt-get update \
|
|
|
14
14
|
&& make -j"$(nproc)" prefix=/usr/local sysconfdir=/etc NO_TCLTK=1 NO_PERL=1 NO_PYTHON=1 NO_GETTEXT=1 NO_RUST=1 \
|
|
15
15
|
DESTDIR=/out all install
|
|
16
16
|
|
|
17
|
-
FROM
|
|
17
|
+
FROM oven/bun:1.4.2-slim AS bun
|
|
18
|
+
FROM ghcr.io/astral-sh/uv:0.12.19 AS uv
|
|
19
|
+
|
|
20
|
+
FROM node:24-slim
|
|
21
|
+
|
|
22
|
+
# Lets `maesttro update` find and remove older runner images once they lose their tag
|
|
23
|
+
LABEL org.maesttro.runner="1"
|
|
18
24
|
|
|
19
25
|
COPY --from=git-build /out/usr/local /usr/local
|
|
26
|
+
COPY --from=bun /usr/local/bin/bun /usr/local/bin/bun
|
|
27
|
+
COPY --from=uv /uv /uvx /usr/local/bin/
|
|
28
|
+
RUN ln -s /usr/local/bin/bun /usr/local/bin/bunx
|
|
20
29
|
|
|
21
30
|
# gh comes from GitHub's apt repo: Debian's lags by years and predates the
|
|
22
31
|
# hosts.yml / config.yml behaviour the CLI's read-only session mount relies on
|
|
@@ -30,28 +39,74 @@ RUN apt-get update \
|
|
|
30
39
|
> /etc/apt/sources.list.d/github-cli.list \
|
|
31
40
|
&& apt-get update \
|
|
32
41
|
&& apt-get install -y --no-install-recommends gh \
|
|
42
|
+
build-essential pkg-config \
|
|
43
|
+
unzip zip xz-utils bzip2 wget jq ripgrep fd-find tree file procps rsync patch sqlite3 \
|
|
44
|
+
libicu72 libssl3 zlib1g libgssapi-krb5-2 \
|
|
45
|
+
&& ln -s /usr/bin/fdfind /usr/local/bin/fd \
|
|
33
46
|
&& rm -rf /var/lib/apt/lists/*
|
|
34
47
|
|
|
35
|
-
|
|
36
|
-
|
|
48
|
+
ARG DOTNET_SDK_CHANNEL=10.0
|
|
49
|
+
ENV DOTNET_ROOT=/usr/share/dotnet \
|
|
50
|
+
DOTNET_CLI_TELEMETRY_OPTOUT=1 \
|
|
51
|
+
DOTNET_NOLOGO=1 \
|
|
52
|
+
DOTNET_GENERATE_ASPNET_CERTIFICATE=false \
|
|
53
|
+
DOTNET_SKIP_WORKLOAD_INTEGRITY_CHECK=true \
|
|
54
|
+
NUGET_XMLDOC_MODE=skip
|
|
55
|
+
RUN curl -fsSL https://dot.net/v1/dotnet-install.sh -o /tmp/dotnet-install.sh \
|
|
56
|
+
&& bash /tmp/dotnet-install.sh --channel "${DOTNET_SDK_CHANNEL}" --install-dir "${DOTNET_ROOT}" \
|
|
57
|
+
&& ln -s "${DOTNET_ROOT}/dotnet" /usr/local/bin/dotnet \
|
|
58
|
+
&& rm /tmp/dotnet-install.sh
|
|
59
|
+
|
|
60
|
+
# Python comes from uv (python-build-standalone), not Debian: one toolchain for
|
|
61
|
+
# interpreters, venvs and tools; python/python3/pip stay on PATH for node-gyp and habit
|
|
62
|
+
ARG PYTHON_VERSION=3.14
|
|
63
|
+
RUN UV_PYTHON_INSTALL_DIR=/usr/local/share/uv/python UV_PYTHON_BIN_DIR=/usr/local/bin \
|
|
64
|
+
uv python install "${PYTHON_VERSION}" --default \
|
|
65
|
+
&& ln -s "$(dirname "$(readlink -f /usr/local/bin/python3)")/pip3" /usr/local/bin/pip3 \
|
|
66
|
+
&& ln -s pip3 /usr/local/bin/pip
|
|
67
|
+
|
|
68
|
+
# System-level, not ~/.gitconfig: the per-session home mounted at /home/agent
|
|
69
|
+
# shadows anything baked into the image's home
|
|
37
70
|
COPY gitconfig /etc/gitconfig
|
|
38
71
|
COPY runner-marker /etc/maesttro/runner
|
|
39
72
|
|
|
40
73
|
# Curated client CLIs — keep in sync with src/clients.ts
|
|
41
74
|
RUN npm install -g \
|
|
42
75
|
@anthropic-ai/claude-code \
|
|
43
|
-
opencode-ai
|
|
76
|
+
opencode-ai \
|
|
77
|
+
typescript \
|
|
78
|
+
&& corepack enable
|
|
79
|
+
# The image pins the client version; an in-container update would only land on
|
|
80
|
+
# the ephemeral layer and be re-downloaded every session
|
|
81
|
+
ENV DISABLE_AUTOUPDATER=1
|
|
44
82
|
|
|
45
83
|
RUN useradd -m -s /bin/bash agent
|
|
46
84
|
USER agent
|
|
47
|
-
# Created as agent so a fresh volume inherits them; otherwise Docker creates
|
|
48
|
-
# ~/.config and ~/.claude as root when it sets up the nested read-only mounts
|
|
49
|
-
RUN mkdir -p /home/agent/.config/opencode /home/agent/.claude
|
|
50
85
|
WORKDIR /workspace
|
|
51
86
|
|
|
87
|
+
# Everything the agent installs lands on the container's writable layer, never
|
|
88
|
+
# the session's home, so it is gone when the session's container exits
|
|
89
|
+
ENV AGENT_TOOLS=/opt/agent-tools
|
|
90
|
+
ENV NPM_CONFIG_PREFIX=${AGENT_TOOLS} \
|
|
91
|
+
NPM_CONFIG_CACHE=${AGENT_TOOLS}/cache/npm \
|
|
92
|
+
COREPACK_HOME=${AGENT_TOOLS}/corepack \
|
|
93
|
+
COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \
|
|
94
|
+
BUN_INSTALL=${AGENT_TOOLS}/bun \
|
|
95
|
+
PYTHONUSERBASE=${AGENT_TOOLS} \
|
|
96
|
+
PIP_BREAK_SYSTEM_PACKAGES=1 \
|
|
97
|
+
PIP_CACHE_DIR=${AGENT_TOOLS}/cache/pip \
|
|
98
|
+
UV_CACHE_DIR=${AGENT_TOOLS}/cache/uv \
|
|
99
|
+
UV_TOOL_DIR=${AGENT_TOOLS}/uv/tools \
|
|
100
|
+
UV_TOOL_BIN_DIR=${AGENT_TOOLS}/bin \
|
|
101
|
+
UV_PYTHON_INSTALL_DIR=${AGENT_TOOLS}/uv/python \
|
|
102
|
+
UV_PYTHON_BIN_DIR=${AGENT_TOOLS}/bin \
|
|
103
|
+
DOTNET_CLI_HOME=${AGENT_TOOLS}/dotnet \
|
|
104
|
+
NUGET_PACKAGES=${AGENT_TOOLS}/cache/nuget \
|
|
105
|
+
NUGET_HTTP_CACHE_PATH=${AGENT_TOOLS}/cache/nuget-http
|
|
106
|
+
ENV PATH=${AGENT_TOOLS}/bin:${AGENT_TOOLS}/bun/bin:${AGENT_TOOLS}/dotnet/.dotnet/tools:${PATH}
|
|
107
|
+
|
|
52
108
|
# Client configs are applied at container start by `maesttro configure`
|
|
53
|
-
# (mounted from the host's install): /home/agent
|
|
54
|
-
# anything baked here would only ever reach brand-new volumes.
|
|
109
|
+
# (mounted from the host's install): the session home shadows /home/agent
|
|
55
110
|
|
|
56
111
|
# Starts as root only to remap agent to the host user's uid/gid (bind mounts
|
|
57
112
|
# keep host ownership on Linux), then drops to agent before running anything
|
package/docker/entrypoint.sh
CHANGED
|
@@ -9,10 +9,16 @@ if [ -n "$uid" ] && [ "$uid" != "$(id -u agent)" ]; then
|
|
|
9
9
|
usermod --non-unique --uid "$uid" --gid "$gid" agent
|
|
10
10
|
fi
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
if [
|
|
14
|
-
find /
|
|
12
|
+
# cp -a onto the directory itself would copy /etc/skel's own mode, clobbering the 0700 the host set
|
|
13
|
+
if [ ! -e /home/agent/.profile ]; then
|
|
14
|
+
find /etc/skel -mindepth 1 -maxdepth 1 -exec cp -a {} /home/agent/ \;
|
|
15
15
|
fi
|
|
16
16
|
|
|
17
|
+
owner="$(id -u agent):$(id -g agent)"
|
|
18
|
+
find /home/agent /home/agent/.claude -xdev \! -user agent -exec chown -h "$owner" {} + 2>/dev/null || true
|
|
19
|
+
|
|
20
|
+
mkdir -p "$AGENT_TOOLS"
|
|
21
|
+
chown "$owner" "$AGENT_TOOLS"
|
|
22
|
+
|
|
17
23
|
export HOME=/home/agent USER=agent LOGNAME=agent
|
|
18
24
|
exec setpriv --reuid=agent --regid=agent --init-groups /bin/bash -c "$*"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "maesttro",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Isolated Docker runner for local coding agents (opencode, claude, ...) under a dedicated bot GitHub identity, with curated configs baked in per client.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -26,5 +26,8 @@
|
|
|
26
26
|
"node": ">=18"
|
|
27
27
|
},
|
|
28
28
|
"license": "UNLICENSED",
|
|
29
|
-
"private": false
|
|
29
|
+
"private": false,
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@clack/prompts": "1.8.1"
|
|
32
|
+
}
|
|
30
33
|
}
|