feat: Set and Forget - Seamless Gas Town Integration (#255)

Adds shell integration for automatic Gas Town context detection.

Features:
- `gt enable` / `gt disable` - Global on/off switch
- `gt shell install|remove|status` - Shell integration management
- `gt rig quick-add [path]` - One-command project setup
- `gt uninstall` - Clean removal with options
- Shell hook auto-sets GT_TOWN_ROOT/GT_RIG on cd

Implementation:
- XDG-compliant state storage (~/.local/state/gastown/)
- Safe RC file manipulation with block markers
- Environment overrides (GASTOWN_DISABLED/ENABLED)
- Doctor check for global state validation

Co-authored-by: Sohail Mohammad <sohailm25@gmail.com>
This commit is contained in:
Sohail Mohammad
2026-01-08 22:25:01 -06:00
committed by GitHub
parent 41a758d6d8
commit 81bfe48ed3
21 changed files with 1751 additions and 11 deletions

View File

@@ -0,0 +1,18 @@
#!/bin/bash
# ABOUTME: Wrapper script that runs gt prime before launching codex.
# ABOUTME: Ensures Gas Town context is available in Codex sessions.
set -e
gastown_enabled() {
[[ -n "$GASTOWN_DISABLED" ]] && return 1
[[ -n "$GASTOWN_ENABLED" ]] && return 0
local state_file="$HOME/.local/state/gastown/state.json"
[[ -f "$state_file" ]] && grep -q '"enabled":\s*true' "$state_file" 2>/dev/null
}
if gastown_enabled && command -v gt &>/dev/null; then
gt prime 2>/dev/null || true
fi
exec codex "$@"

View File

@@ -0,0 +1,18 @@
#!/bin/bash
# ABOUTME: Wrapper script that runs gt prime before launching opencode.
# ABOUTME: Ensures Gas Town context is available in OpenCode sessions.
set -e
gastown_enabled() {
[[ -n "$GASTOWN_DISABLED" ]] && return 1
[[ -n "$GASTOWN_ENABLED" ]] && return 0
local state_file="$HOME/.local/state/gastown/state.json"
[[ -f "$state_file" ]] && grep -q '"enabled":\s*true' "$state_file" 2>/dev/null
}
if gastown_enabled && command -v gt &>/dev/null; then
gt prime 2>/dev/null || true
fi
exec opencode "$@"

View File

@@ -0,0 +1,68 @@
// ABOUTME: Manages wrapper scripts for non-Claude agentic coding tools.
// ABOUTME: Provides gt-codex and gt-opencode wrappers that run gt prime first.
package wrappers
import (
"embed"
"fmt"
"os"
"path/filepath"
)
//go:embed scripts/*
var scriptsFS embed.FS
func Install() error {
binDir, err := binPath()
if err != nil {
return fmt.Errorf("determining bin directory: %w", err)
}
if err := os.MkdirAll(binDir, 0755); err != nil {
return fmt.Errorf("creating bin directory: %w", err)
}
wrappers := []string{"gt-codex", "gt-opencode"}
for _, name := range wrappers {
content, err := scriptsFS.ReadFile("scripts/" + name)
if err != nil {
return fmt.Errorf("reading embedded %s: %w", name, err)
}
destPath := filepath.Join(binDir, name)
if err := os.WriteFile(destPath, content, 0755); err != nil {
return fmt.Errorf("writing %s: %w", name, err)
}
}
return nil
}
func Remove() error {
binDir, err := binPath()
if err != nil {
return err
}
wrappers := []string{"gt-codex", "gt-opencode"}
for _, name := range wrappers {
destPath := filepath.Join(binDir, name)
os.Remove(destPath)
}
return nil
}
func binPath() (string, error) {
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, "bin"), nil
}
func BinDir() string {
p, _ := binPath()
return p
}