From ea5a2f6b4cd0d6b7a4bddbc8ce6cb48648810051 Mon Sep 17 00:00:00 2001 From: Michael Panchenko Date: Wed, 27 May 2026 13:37:45 +0200 Subject: [PATCH] :sparkles: Wire host git identity into the devenv container run-devenv-agentic now seeds the container's global git config from the host on every bring-up so commits made inside the devenv (typically by coding agents reached through start-coding-agent) carry a real author/committer instead of the bare `penpot@` fallback that makes review unworkable. New optional flags on run-devenv-agentic: --git-user-name NAME author/committer name --git-user-email EMAIL matching email When a flag is omitted the value is resolved from the host's effective `git config user.{name,email}` (plain `git config`, no --global) so a per-repo override in /.git/config wins over ~/.gitconfig -- matching what `git commit` on the host would actually record. If neither flag nor host config provides a value the script prints a warning and continues; in-container commits will fail until the user fixes it. start-instance applies the values via two `docker exec ... git config --global user.{name,email}` calls right after the container reaches Running, before start-tmux.sh is launched. Keeps the write logic next to the rest of the per-instance bring-up and out of the tmux script -- no env-var contract between manage.sh and the tmux entry point is needed. Docs updated in docs/technical-guide/developer/devenv.md (new "Git identity inside the container" section) and the agentic-devenv guide. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../developer/agentic-devenv.md | 13 +++++ docs/technical-guide/developer/devenv.md | 22 +++++++- manage.sh | 55 ++++++++++++++++++- 3 files changed, 86 insertions(+), 4 deletions(-) diff --git a/docs/technical-guide/developer/agentic-devenv.md b/docs/technical-guide/developer/agentic-devenv.md index 9cbc92d91c..c796f16f96 100644 --- a/docs/technical-guide/developer/agentic-devenv.md +++ b/docs/technical-guide/developer/agentic-devenv.md @@ -85,6 +85,19 @@ instance up, so you don't need to compute the offsets by hand. See the the workspace and lifecycle details (including the `--sync` flag and shutdown shape). +**Git identity for agent commits.** Coding agents typically need to commit +inside the devenv, so `run-devenv-agentic` wires a Git identity into the +container's global config on every bring-up. By default it propagates the +host's effective `git config user.{name,email}` (local repo override wins +over `~/.gitconfig`, matching what `git commit` on the host would record). +Override either with `--git-user-name "Full Name"` / +`--git-user-email you@example.com` — useful when you want agent commits to +carry an identity different from your normal one. Without either source the +script warns and proceeds; commits made by the agent will fail until you fix +it. See the +[Dev environment guide](./devenv.md#git-identity-inside-the-container) for +the full mechanics. + > **Note:** the MCP and Serena tmux windows are only added when the session is > first created. If you've already run `./manage.sh run-devenv` (non-agentic) > in an instance, `run-devenv-agentic` errors out because the instance is diff --git a/docs/technical-guide/developer/devenv.md b/docs/technical-guide/developer/devenv.md index f58fd47656..66a1d7c41b 100644 --- a/docs/technical-guide/developer/devenv.md +++ b/docs/technical-guide/developer/devenv.md @@ -106,7 +106,27 @@ Container-internal ports stay fixed. Target a specific instance with `start-coding-agent` (`--instance ws1` on `run-devenv-shell` / `run-devenv`). The `--ws` flag accepts a **non-negative integer only** — `--ws main` or `--ws ws1` is rejected, keeping the flag shape uniform across -commands. `run-devenv-agentic` also accepts `--serena-context CTX`. +commands. `run-devenv-agentic` also accepts `--serena-context CTX` and +`--git-user-name NAME` / `--git-user-email EMAIL` (see below). + +### Git identity inside the container + +`run-devenv-agentic` wires a Git author identity into the container's +**global** git config (`git config --global user.{name,email}`) so commits +made from inside the devenv carry a real author/committer. Without this, +the container would commit as the unconfigured `penpot@` +fallback — usable but useless for review. + +The values come from `--git-user-name NAME` / `--git-user-email EMAIL` +when passed, or from your host's effective `git config user.{name,email}` +otherwise. "Effective" here means the values plain `git config user.X` +returns at the working directory `manage.sh` is invoked from — local +(`/.git/config`) overrides global (`~/.gitconfig`), matching what +`git commit` on the host would record. If neither is available the script +prints a warning and continues — commits will fail inside the container +until you set an identity. The values are applied every time +`run-devenv-agentic` brings an instance up (idempotent), so re-running +with different flags is the way to change the in-container identity. ### Shared state and workers diff --git a/manage.sh b/manage.sh index 95db9389e6..ca23c2cc44 100755 --- a/manage.sh +++ b/manage.sh @@ -645,6 +645,8 @@ function parse-ws-integer { function start-instance { local instance="$1" local serena_context="$2" + local git_user_name="${3:-}" + local git_user_email="${4:-}" instance-compose "$instance" up -d --no-deps main redis @@ -660,6 +662,16 @@ function start-instance { sleep 1 done + # Seed the container's global git config from the values resolved on the + # host so commits made inside the devenv carry a real author/committer. Empty + # values are skipped — the host-identity warning is the caller's job. + if [[ -n "$git_user_name" ]]; then + docker exec "$container" sudo -u penpot git config --global user.name "$git_user_name" + fi + if [[ -n "$git_user_email" ]]; then + docker exec "$container" sudo -u penpot git config --global user.email "$git_user_email" + fi + # Detached tmux so callers don't block on attach. Agentic mode is the only # mode here, so MCP and Serena are always on. docker exec -d \ @@ -710,6 +722,14 @@ function print-instance-info { # ws1+ also sync implicitly the first time when their workspace # directory does not exist yet. # --serena-context CTX passed to Serena (default: desktop-app). +# --git-user-name NAME Git author/committer name to wire into the +# container's global git config (so commits made inside the +# devenv carry a real identity). Defaults to the host's +# effective `git config user.name` when omitted (resolved at +# the current working directory, so a per-repo local override +# in /.git/config takes precedence over ~/.gitconfig). +# --git-user-email EMAIL matching email; defaults to the host's effective +# `git config user.email` (same local-over-global precedence). # # ws0 is the worker-bearer and must be running whenever any ws1+ is up. When # starting ws1+, ws0 is brought up first automatically if it is not already @@ -718,6 +738,8 @@ function run-devenv-agentic { local target="ws0" local do_sync=false local serena_context="desktop-app" + local git_user_name="" + local git_user_email="" while [[ $# -gt 0 ]]; do case "$1" in @@ -727,6 +749,10 @@ function run-devenv-agentic { do_sync=true; shift;; --serena-context) serena_context="$2"; shift 2;; + --git-user-name) + git_user_name="$2"; shift 2;; + --git-user-email) + git_user_email="$2"; shift 2;; *) echo "run-devenv-agentic: unknown argument '$1'" >&2 return 1;; @@ -738,6 +764,26 @@ function run-devenv-agentic { return 1 fi + # Fall back to the host developer's effective git identity when the + # respective flag is not provided. Plain `git config user.X` (no --global) + # honours the local->global->system precedence, so a per-repo override in + # /.git/config takes precedence over ~/.gitconfig -- matching what + # `git commit` on the host would actually record. `|| true` swallows the + # non-zero exit for a missing entry; the empty result is propagated + # untouched and surfaces as a no-op inside the container (start-tmux.sh + # skips `git config --global` when the env var is empty). + if [[ -z "$git_user_name" ]]; then + git_user_name="$(git config user.name 2>/dev/null || true)" + fi + if [[ -z "$git_user_email" ]]; then + git_user_email="$(git config user.email 2>/dev/null || true)" + fi + if [[ -z "$git_user_name" || -z "$git_user_email" ]]; then + echo "[$target] warning: host git identity is incomplete (name='${git_user_name}', email='${git_user_email}')." >&2 + echo " Commits made inside the devenv will fail until you set it via --git-user-name / --git-user-email" >&2 + echo " or 'git config user.{name,email}' on the host." >&2 + fi + if devenv-main-running "$target"; then echo "run-devenv-agentic: instance '$target' is already running." >&2 return 1 @@ -753,7 +799,7 @@ function run-devenv-agentic { echo "[ws0] not running; starting it first (workers run only on ws0)." echo "Starting ws0..." write-instance-mcp-configs "ws0" - start-instance "ws0" "$serena_context" + start-instance "ws0" "$serena_context" "$git_user_name" "$git_user_email" print-instance-info "ws0" fi @@ -772,7 +818,7 @@ function run-devenv-agentic { echo "Starting $target..." write-instance-mcp-configs "$target" - start-instance "$target" "$serena_context" + start-instance "$target" "$serena_context" "$git_user_name" "$git_user_email" print-instance-info "$target" } @@ -1185,7 +1231,10 @@ function usage { echo " Auto-starts ws0 first when --ws N (N>=1) is requested (workers run only on ws0)." echo " Options: --ws N (default: 0; non-negative integer only)," echo " --sync (re-seed workspace from live repo; ws1+ only)," - echo " --serena-context CONTEXT (default: desktop-app)" + echo " --serena-context CONTEXT (default: desktop-app)," + echo " --git-user-name NAME / --git-user-email EMAIL" + echo " (default: host's effective 'git config user.{name,email}'," + echo " honouring per-repo local overrides)" echo "- attach-devenv Attaches to the tmux session inside a running instance." echo " Options: --ws N (default: 0; non-negative integer only)" echo "- start-coding-agent Launches an AI coding agent against one workspace with the right MCP config wired in."