Set GIT_AUTHOR_NAME per agent session (gt-6r18e.1)
Export GIT_AUTHOR_NAME alongside BD_ACTOR in all agent session startup locations. This enables git log --author queries for agent work while keeping GIT_AUTHOR_EMAIL as the workspace owner. Files updated: - internal/session/manager.go (polecat sessions) - internal/daemon/daemon.go (deacon, witness, polecat via daemon) - internal/daemon/lifecycle.go (polecat lifecycle) - internal/cmd/*.go (crew, mayor, deacon, witness, refinery, up, handoff) - internal/session/manager_test.go (updated test expectations) - docs/federation.md (marked feature as implemented) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -151,7 +151,7 @@ func runCrewAt(cmd *cobra.Command, args []string) error {
|
||||
// Pass "gt prime" as initial prompt so Claude loads context immediately
|
||||
// Export GT_ROLE and BD_ACTOR since tmux SetEnvironment only affects new panes
|
||||
bdActor := fmt.Sprintf("%s/crew/%s", r.Name, name)
|
||||
claudeCmd := fmt.Sprintf(`export GT_ROLE=crew GT_RIG=%s GT_CREW=%s BD_ACTOR=%s && claude --dangerously-skip-permissions "gt prime"`, r.Name, name, bdActor)
|
||||
claudeCmd := fmt.Sprintf(`export GT_ROLE=crew GT_RIG=%s GT_CREW=%s BD_ACTOR=%s GIT_AUTHOR_NAME=%s && claude --dangerously-skip-permissions "gt prime"`, r.Name, name, bdActor, bdActor)
|
||||
if err := t.RespawnPane(paneID, claudeCmd); err != nil {
|
||||
return fmt.Errorf("starting claude: %w", err)
|
||||
}
|
||||
@@ -176,7 +176,7 @@ func runCrewAt(cmd *cobra.Command, args []string) error {
|
||||
// Pass "gt prime" as initial prompt so Claude loads context immediately
|
||||
// Export GT_ROLE and BD_ACTOR since tmux SetEnvironment only affects new panes
|
||||
bdActor := fmt.Sprintf("%s/crew/%s", r.Name, name)
|
||||
claudeCmd := fmt.Sprintf(`export GT_ROLE=crew GT_RIG=%s GT_CREW=%s BD_ACTOR=%s && claude --dangerously-skip-permissions "gt prime"`, r.Name, name, bdActor)
|
||||
claudeCmd := fmt.Sprintf(`export GT_ROLE=crew GT_RIG=%s GT_CREW=%s BD_ACTOR=%s GIT_AUTHOR_NAME=%s && claude --dangerously-skip-permissions "gt prime"`, r.Name, name, bdActor, bdActor)
|
||||
if err := t.RespawnPane(paneID, claudeCmd); err != nil {
|
||||
return fmt.Errorf("restarting claude: %w", err)
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ func runCrewRestart(cmd *cobra.Command, args []string) error {
|
||||
// Start claude with skip permissions (crew workers are trusted)
|
||||
// Export GT_ROLE and BD_ACTOR since tmux SetEnvironment only affects new panes
|
||||
bdActor := fmt.Sprintf("%s/crew/%s", r.Name, name)
|
||||
claudeCmd := fmt.Sprintf("export GT_ROLE=crew GT_RIG=%s GT_CREW=%s BD_ACTOR=%s && claude --dangerously-skip-permissions", r.Name, name, bdActor)
|
||||
claudeCmd := fmt.Sprintf("export GT_ROLE=crew GT_RIG=%s GT_CREW=%s BD_ACTOR=%s GIT_AUTHOR_NAME=%s && claude --dangerously-skip-permissions", r.Name, name, bdActor, bdActor)
|
||||
if err := t.SendKeys(sessionID, claudeCmd); err != nil {
|
||||
fmt.Printf("Error starting claude for %s: %v\n", arg, err)
|
||||
lastErr = err
|
||||
@@ -484,7 +484,7 @@ func restartCrewSession(rigName, crewName, clonePath string) error {
|
||||
|
||||
// Start claude with skip permissions
|
||||
bdActor := fmt.Sprintf("%s/crew/%s", rigName, crewName)
|
||||
claudeCmd := fmt.Sprintf("export GT_ROLE=crew GT_RIG=%s GT_CREW=%s BD_ACTOR=%s && claude --dangerously-skip-permissions", rigName, crewName, bdActor)
|
||||
claudeCmd := fmt.Sprintf("export GT_ROLE=crew GT_RIG=%s GT_CREW=%s BD_ACTOR=%s GIT_AUTHOR_NAME=%s && claude --dangerously-skip-permissions", rigName, crewName, bdActor, bdActor)
|
||||
if err := t.SendKeys(sessionID, claudeCmd); err != nil {
|
||||
return fmt.Errorf("starting claude: %w", err)
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ func startDeaconSession(t *tmux.Tmux) error {
|
||||
// Restarts are handled by daemon via ensureDeaconRunning on each heartbeat
|
||||
// The startup hook handles context loading automatically
|
||||
// Export GT_ROLE and BD_ACTOR in the command since tmux SetEnvironment only affects new panes
|
||||
if err := t.SendKeys(DeaconSessionName, "export GT_ROLE=deacon BD_ACTOR=deacon && claude --dangerously-skip-permissions"); err != nil {
|
||||
if err := t.SendKeys(DeaconSessionName, "export GT_ROLE=deacon BD_ACTOR=deacon GIT_AUTHOR_NAME=deacon && claude --dangerously-skip-permissions"); err != nil {
|
||||
return fmt.Errorf("sending command: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -326,7 +326,7 @@ func buildRestartCommand(sessionName string) (string, error) {
|
||||
// The SessionStart hook will run gt prime.
|
||||
// Use exec to ensure clean process replacement.
|
||||
if gtRole != "" {
|
||||
return fmt.Sprintf("cd %s && export GT_ROLE=%s BD_ACTOR=%s && exec claude --dangerously-skip-permissions", workDir, gtRole, gtRole), nil
|
||||
return fmt.Sprintf("cd %s && export GT_ROLE=%s BD_ACTOR=%s GIT_AUTHOR_NAME=%s && exec claude --dangerously-skip-permissions", workDir, gtRole, gtRole, gtRole), nil
|
||||
}
|
||||
return fmt.Sprintf("cd %s && exec claude --dangerously-skip-permissions", workDir), nil
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ func startMayorSession(t *tmux.Tmux) error {
|
||||
// Launch Claude - the startup hook handles 'gt prime' automatically
|
||||
// Use SendKeysDelayed to allow shell initialization after NewSession
|
||||
// Export GT_ROLE and BD_ACTOR in the command since tmux SetEnvironment only affects new panes
|
||||
claudeCmd := `export GT_ROLE=mayor BD_ACTOR=mayor && claude --dangerously-skip-permissions`
|
||||
claudeCmd := `export GT_ROLE=mayor BD_ACTOR=mayor GIT_AUTHOR_NAME=mayor && claude --dangerously-skip-permissions`
|
||||
if err := t.SendKeysDelayed(MayorSessionName, claudeCmd, 200); err != nil {
|
||||
return fmt.Errorf("sending command: %w", err)
|
||||
}
|
||||
|
||||
@@ -340,7 +340,7 @@ func ensureRefinerySession(rigName string, r *rig.Rig) (bool, error) {
|
||||
|
||||
// Launch Claude in a respawn loop
|
||||
// Export GT_ROLE and BD_ACTOR in the command since tmux SetEnvironment only affects new panes
|
||||
loopCmd := `export GT_ROLE=refinery BD_ACTOR=` + bdActor + ` && while true; do echo "🛢️ Starting Refinery for ` + rigName + `..."; claude --dangerously-skip-permissions; echo ""; echo "Refinery exited. Restarting in 2s... (Ctrl-C to stop)"; sleep 2; done`
|
||||
loopCmd := `export GT_ROLE=refinery BD_ACTOR=` + bdActor + ` GIT_AUTHOR_NAME=` + bdActor + ` && while true; do echo "🛢️ Starting Refinery for ` + rigName + `..."; claude --dangerously-skip-permissions; echo ""; echo "Refinery exited. Restarting in 2s... (Ctrl-C to stop)"; sleep 2; done`
|
||||
if err := t.SendKeysDelayed(sessionName, loopCmd, 200); err != nil {
|
||||
return false, fmt.Errorf("sending command: %w", err)
|
||||
}
|
||||
|
||||
@@ -262,9 +262,9 @@ func ensureSession(t *tmux.Tmux, sessionName, workDir, role string) error {
|
||||
var claudeCmd string
|
||||
if role == "deacon" {
|
||||
// Deacon uses respawn loop
|
||||
claudeCmd = `export GT_ROLE=deacon BD_ACTOR=deacon && while true; do echo "⛪ Starting Deacon session..."; claude --dangerously-skip-permissions; echo ""; echo "Deacon exited. Restarting in 2s... (Ctrl-C to stop)"; sleep 2; done`
|
||||
claudeCmd = `export GT_ROLE=deacon BD_ACTOR=deacon GIT_AUTHOR_NAME=deacon && while true; do echo "⛪ Starting Deacon session..."; claude --dangerously-skip-permissions; echo ""; echo "Deacon exited. Restarting in 2s... (Ctrl-C to stop)"; sleep 2; done`
|
||||
} else {
|
||||
claudeCmd = fmt.Sprintf(`export GT_ROLE=%s BD_ACTOR=%s && claude --dangerously-skip-permissions`, role, role)
|
||||
claudeCmd = fmt.Sprintf(`export GT_ROLE=%s BD_ACTOR=%s GIT_AUTHOR_NAME=%s && claude --dangerously-skip-permissions`, role, role, role)
|
||||
}
|
||||
|
||||
if err := t.SendKeysDelayed(sessionName, claudeCmd, 200); err != nil {
|
||||
@@ -301,7 +301,7 @@ func ensureWitness(t *tmux.Tmux, sessionName, rigPath, rigName string) error {
|
||||
|
||||
// Launch Claude
|
||||
// Export GT_ROLE and BD_ACTOR in the command since tmux SetEnvironment only affects new panes
|
||||
claudeCmd := fmt.Sprintf(`export GT_ROLE=witness BD_ACTOR=%s && claude --dangerously-skip-permissions`, bdActor)
|
||||
claudeCmd := fmt.Sprintf(`export GT_ROLE=witness BD_ACTOR=%s GIT_AUTHOR_NAME=%s && claude --dangerously-skip-permissions`, bdActor, bdActor)
|
||||
if err := t.SendKeysDelayed(sessionName, claudeCmd, 200); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -512,7 +512,7 @@ func ensureCrewSession(t *tmux.Tmux, sessionName, crewPath, rigName, crewName st
|
||||
_ = t.ConfigureGasTownSession(sessionName, theme, "", "Crew", crewName)
|
||||
|
||||
// Launch Claude
|
||||
claudeCmd := fmt.Sprintf(`export GT_ROLE=crew GT_RIG=%s GT_CREW=%s BD_ACTOR=%s && claude --dangerously-skip-permissions`, rigName, crewName, bdActor)
|
||||
claudeCmd := fmt.Sprintf(`export GT_ROLE=crew GT_RIG=%s GT_CREW=%s BD_ACTOR=%s GIT_AUTHOR_NAME=%s && claude --dangerously-skip-permissions`, rigName, crewName, bdActor, bdActor)
|
||||
if err := t.SendKeysDelayed(sessionName, claudeCmd, 200); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -600,7 +600,7 @@ func ensurePolecatSession(t *tmux.Tmux, sessionName, polecatPath, rigName, polec
|
||||
_ = t.ConfigureGasTownSession(sessionName, theme, "", "Polecat", polecatName)
|
||||
|
||||
// Launch Claude
|
||||
claudeCmd := fmt.Sprintf(`export GT_ROLE=polecat GT_RIG=%s GT_POLECAT=%s BD_ACTOR=%s && claude --dangerously-skip-permissions`, rigName, polecatName, bdActor)
|
||||
claudeCmd := fmt.Sprintf(`export GT_ROLE=polecat GT_RIG=%s GT_POLECAT=%s BD_ACTOR=%s GIT_AUTHOR_NAME=%s && claude --dangerously-skip-permissions`, rigName, polecatName, bdActor, bdActor)
|
||||
if err := t.SendKeysDelayed(sessionName, claudeCmd, 200); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -329,7 +329,7 @@ func ensureWitnessSession(rigName string, r *rig.Rig) (bool, error) {
|
||||
// Restarts are handled by daemon via LIFECYCLE mail or deacon health-scan
|
||||
// NOTE: No gt prime injection needed - SessionStart hook handles it automatically
|
||||
// Export GT_ROLE and BD_ACTOR in the command since tmux SetEnvironment only affects new panes
|
||||
if err := t.SendKeys(sessionName, fmt.Sprintf("export GT_ROLE=witness BD_ACTOR=%s && claude --dangerously-skip-permissions", bdActor)); err != nil {
|
||||
if err := t.SendKeys(sessionName, fmt.Sprintf("export GT_ROLE=witness BD_ACTOR=%s GIT_AUTHOR_NAME=%s && claude --dangerously-skip-permissions", bdActor, bdActor)); err != nil {
|
||||
return false, fmt.Errorf("sending command: %w", err)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user