devflow

package module
v0.2.22 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 26, 2026 License: MIT Imports: 25 Imported by: 2

README

DevFlow

Project Badges

Complete Go development automation: project init, testing, versioning, updates, and backups. Single-line output optimized for AI agents and terminals.

Commands

  • gonew - Initialize new Go projects
  • gotest - Run tests, vet, race detection, coverage and badges
  • push - Git add, commit, tag, and push
  • gopush - Complete workflow: test + push + update dependents
  • devbackup - Configure and execute automated backups
  • badges - Generate SVG badges for README (test status, coverage, etc.)
  • devllm - Sync LLM configuration files from master template
  • goinstall - Install all devflow commands at once
  • codejob - Send coding tasks to AI agents (Jules, etc.)

Configuration

  • GitHub Auth - Configure GitHub authentication (OAuth, tokens, multi-account)

Installation

# Install all commands at once (includes codejob and all other tools)
go install github.com/tinywasm/devflow/cmd/goinstall@latest && goinstall

Or install a single command — see each tool's doc linked above.

Features

  • Intelligent push - Auto-pulls with --rebase on non-fast-forward rejection
  • Zero config - Auto-detects tests, project structure, WASM environments
  • Minimal output - Single-line summaries for terminals and LLMs
  • Smart versioning - Auto-increments tags, skips duplicates
  • Multi-account - Switch GitHub orgs easily (cdvelop, veltylabs, tinywasm)
  • Dependency updates - Auto-updates dependent modules in workspace
  • Full testing - Combines vet, tests, race detection, and exact weighted coverage across all packages

License

MIT

Documentation

Index

Constants

View Source
const (
	ColorRed    = "\033[0;31m"
	ColorGreen  = "\033[0;32m"
	ColorYellow = "\033[0;33m"
	ColorCyan   = "\033[0;36m"
	ColorNone   = "\033[0m"
)
View Source
const DefaultIssuePromptPath = "docs/PLAN.md"

DefaultIssuePromptPath is the conventional location for the task description file.

View Source
const DevFlowRepository = "github.com/tinywasm/devflow"
View Source
const DevflowOAuthClientID = "Ov23lijHU2vxBCpShn1Q"

DevflowOAuthClientID is the OAuth App Client ID for devflow.

IMPORTANT: This Client ID is intentionally hardcoded and is NOT a secret. OAuth Client IDs are public identifiers (like a username, not a password). The Client Secret is NEVER included in the code - Device Flow doesn't need it. This is the standard approach used by CLI tools like gh, goreleaser, hub, etc.

The OAuth App is registered under a personal GitHub account (not organization). Manage the app at: https://github.com/settings/developers -> OAuth Apps -> devflow

Variables

View Source
var ExecCommand = exec.Command

ExecCommand is a variable to allow mocking in tests

Functions

func CompareVersions added in v0.0.49

func CompareVersions(v1, v2 string) int

CompareVersions compares two semantic version strings (e.g., "v1.2.3"). It returns -1 if v1 < v2, 0 if v1 == v2, 1 if v1 > v2. It handles "v" prefix gracefully.

func CopyFile added in v0.2.4

func CopyFile(src, dst string) error

CopyFile copia un archivo (helper para backup)

func DispatchCodeJob added in v0.2.12

func DispatchCodeJob(sync RepoSync, drivers ...CodeJobDriver) (string, error)

DispatchCodeJob dispatches CodeJob if PLAN.md exists and no active session is in .env. Returns ("", nil) when there is nothing to dispatch (active session or missing PLAN.md). Returns ("", error) when dispatch was attempted but failed. Returns (result, nil) on successful dispatch. If no drivers are provided, defaults to NewJulesDriver(JulesConfig{}).

func EvaluateTestResults added in v0.2.4

func EvaluateTestResults(err error, output, moduleName string, msgs []string, skipRace bool) (testStatus, raceStatus string, stdTestsRan bool, newMsgs []string)

EvaluateTestResults analyzes the output of go test and decides the outcome This function is pure and can be easily tested.

func ExtractSections added in v0.2.4

func ExtractSections(content string) map[string]string

ExtractSections extrae secciones marcadas del contenido

func FindProjectRoot added in v0.0.72

func FindProjectRoot(startDir string) (string, error)

FindProjectRoot looks for go.mod in startDir or its immediate parent. Returns the absolute path to the directory containing go.mod, or an empty string and error if not found.

func FindSlowestTest added in v0.2.4

func FindSlowestTest(output string, threshold float64) (string, float64)

FindSlowestTest parses -v test output and returns the name and duration of the slowest individual test across all packages if it exceeds the specified threshold.

func FindTimedOutTests added in v0.2.4

func FindTimedOutTests(output string) []string

FindTimedOutTests parses go test output and extracts test names that timed out. Handles two scenarios: 1. Go's native timeout: "panic: test timed out after Ns\n running tests:\n TestName (Ns)" 2. Process killed externally (context.WithTimeout): finds the last "=== RUN" without a matching "--- PASS/FAIL"

func FormatCommitMessage added in v0.0.34

func FormatCommitMessage(message string) string

FormatCommitMessage ensures the message is trimmed.

func GenerateGitignore added in v0.0.13

func GenerateGitignore(targetDir string) error

GenerateGitignore generates .gitignore for Go

func GenerateHandlerFile added in v0.0.13

func GenerateHandlerFile(repoName, targetDir string) error

GenerateHandlerFile generates the main handler file

func GenerateLicense added in v0.0.13

func GenerateLicense(ownerName, targetDir string) error

GenerateLicense generates LICENSE (MIT)

func GenerateREADME added in v0.0.13

func GenerateREADME(repoName, description, targetDir string) error

GenerateREADME generates README.md

func GetBadgeColor added in v0.2.4

func GetBadgeColor(typ, value string) string

func GetGoVersion added in v0.2.4

func GetGoVersion() string

func HandleDone added in v0.2.12

func HandleDone(env *DotEnv, git *Git, prURL string) error

HandleDone executes cleanup when Jules completes: 1. git fetch --all 2. git checkout <jules-branch> for local review 3. os.Rename("docs/PLAN.md", "docs/CHECK_PLAN.md") 4. env.Delete("CODEJOB") 5. env.Set("CODEJOB_PR", prURL) 6. Update .gitignore

func HasTimeoutFlag added in v0.2.4

func HasTimeoutFlag(args []string) bool

HasTimeoutFlag checks if -timeout is already present in the args

func JulesSessionState added in v0.2.12

func JulesSessionState(sessionID, apiKey string, client HTTPClient) (msg, prURL string, done bool, err error)

JulesSessionState polls the Jules API for session status. Returns (message, prURL, isDone, error).

func KebabToCamel added in v0.2.4

func KebabToCamel(s string) string

KebabToCamel converts kebab-case or snake_case to CamelCase

func MergePR added in v0.2.14

func MergePR() error

MergePR merges the Jules PR persisted in .env as CODEJOB_PR, deletes docs/CHECK_PLAN.md, and cleans up state. Called by 'codejob done'.

func PrintError added in v0.0.13

func PrintError(msg string)

PrintError prints an error message in red.

func PrintInfo added in v0.0.13

func PrintInfo(msg string)

PrintInfo prints an informational message in cyan.

func PrintSuccess added in v0.0.13

func PrintSuccess(msg string)

PrintSuccess prints a success message in green.

func PrintWarning added in v0.0.13

func PrintWarning(msg string)

PrintWarning prints a warning message in yellow.

func RunCommand

func RunCommand(name string, args ...string) (string, error)

RunCommand executes a shell command It returns the output (trimmed) and an error if the command fails

func RunCommandInDir added in v0.0.51

func RunCommandInDir(dir, name string, args ...string) (string, error)

RunCommandInDir executes a command in a specific directory

func RunCommandSilent

func RunCommandSilent(name string, args ...string) (string, error)

RunCommandSilent executes a command (alias for RunCommand now, as RunCommand is also silent on success) kept for backward compatibility if needed, or we can remove it. The previous implementation was identical except for logging.

func RunCommandWithRetryInDir added in v0.0.51

func RunCommandWithRetryInDir(dir, name string, args []string, maxRetries int, delay time.Duration) (string, error)

RunCommandWithRetryInDir executes a command in a specific directory with retries

func RunCommandWithStdin added in v0.2.12

func RunCommandWithStdin(input, name string, args ...string) (string, error)

RunCommandWithStdin executes a command with the given string piped to stdin. Use this instead of passing secrets as CLI args to avoid leaking them in error messages.

func RunShellCommand added in v0.0.10

func RunShellCommand(command string) (string, error)

RunShellCommand executes a shell command in a cross-platform way On Windows: uses cmd.exe /C On Unix (Linux/macOS): uses sh -c

func RunShellCommandAsync added in v0.0.13

func RunShellCommandAsync(command string) error

RunShellCommandAsync starts a shell command asynchronously (non-blocking) Returns immediately after starting, does not wait for completion

func ShouldEnableWasm added in v0.2.4

func ShouldEnableWasm(nativeOut, wasmOut string) bool

ShouldEnableWasm decides if WASM tests should be run based on go list output differences

func ValidateCommitMessage added in v0.0.34

func ValidateCommitMessage(message string) error

ValidateCommitMessage ensures that a commit message is provided and is valid. It trims whitespace and returns an error if the message is empty.

func ValidateDescription added in v0.0.13

func ValidateDescription(desc string) error

ValidateDescription validates the repository description

func ValidateRepoName added in v0.0.13

func ValidateRepoName(name string) error

ValidateRepoName validates the repository name Only alphanumeric, dash, and underscore allowed

func ValidateShellSafeMessage added in v0.0.34

func ValidateShellSafeMessage(message string) string

ValidateShellSafeMessage provides a warning if the message contains characters that might need escaping in certain shells (like backticks, dollar signs, or single quotes) if it were to be used in a shell script, even though exec.Command is safe.

Types

type Badge added in v0.0.13

type Badge struct {
	Label string // The text displayed on the left side of the badge.
	Value string // The text displayed on the right side of the badge.
	Color string // The background color for the value part of the badge (e.g., "#4c1" or "green").
}

Badge represents a single badge with a label, value, and color. This is the primary struct used to define a badge's appearance and content.

For example, to create a "Go version" badge, you might use:

b := Badge{
  Label: "Go",
  Value: "1.18",
  Color: "#007d9c",
}

type Badges added in v0.0.13

type Badges struct {
	// contains filtered or unexported fields
}

Badges is responsible for creating and managing a collection of badges. It handles parsing input arguments, generating the SVG image, and preparing the necessary markdown to embed the badges in a file.

func NewBadges added in v0.0.13

func NewBadges(args ...string) *Badges

NewBadges creates and initializes a new Badges handler.

func (*Badges) BadgeMarkdown added in v0.0.13

func (h *Badges) BadgeMarkdown() string

BadgeMarkdown generates the markdown snippet for embedding the badge image.

func (*Badges) BuildBadges added in v0.0.13

func (h *Badges) BuildBadges() ([]string, error)

BuildBadges generates the SVG image, writes it to the specified output file, and returns a slice of strings intended for updating a markdown file.

func (*Badges) Err added in v0.0.13

func (h *Badges) Err() error

Err returns any error that occurred during the initialization or processing

func (*Badges) GenerateSVG added in v0.0.13

func (h *Badges) GenerateSVG() ([]byte, int, error)

GenerateSVG creates an SVG image from the configured badges.

It returns the SVG content as a byte slice, the number of badges included, and an error if the generation fails. This method is typically called by BuildBadges, but it can be used directly if you only need the SVG data.

Example of a generated SVG for two badges ("License:MIT:blue" and "Go:1.22:blue"):

<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" width="168" height="20" viewBox="0 0 168 20">

<!-- Badge: License -->
<g transform="translate(0, 0)">
  <rect x="0" y="0" width="58" height="20" fill="#6c757d"/>
  <rect x="58" y="0" width="46" height="20" fill="blue"/>
  <text x="29" y="14" text-anchor="middle" font-family="sans-serif" font-size="11" fill="white">License</text>
  <text x="81" y="14" text-anchor="middle" font-family="sans-serif" font-size="11" fill="white">MIT</text>
</g>
<!-- Badge: Go -->
<g transform="translate(109, 0)">
  <rect x="0" y="0" width="34" height="20" fill="#6c757d"/>
  <rect x="34" y="0" width="25" height="20" fill="blue"/>
  <text x="17" y="14" text-anchor="middle" font-family="sans-serif" font-size="11" fill="white">Go</text>
  <text x="46" y="14" text-anchor="middle" font-family="sans-serif" font-size="11" fill="white">1.22</text>
</g>

</svg>

func (*Badges) GoHandler added in v0.0.13

func (h *Badges) GoHandler() *Go

GoHandler returns the internal Go handler

func (*Badges) OutputFile added in v0.0.13

func (h *Badges) OutputFile() string

OutputFile returns the configured path for the output SVG file.

func (*Badges) ReadmeFile added in v0.0.13

func (h *Badges) ReadmeFile() string

ReadmeFile returns the configured path for the markdown file to be updated.

func (*Badges) SetLog added in v0.0.23

func (h *Badges) SetLog(fn func(...any))

SetLog sets the logger function

type Bashrc added in v0.0.10

type Bashrc struct {
	FilePath string
}

Bashrc handles updates to .bashrc file using markers

func NewBashrc added in v0.0.10

func NewBashrc() *Bashrc

NewBashrc creates a new Bashrc handler for ~/.bashrc

func (*Bashrc) ExtractValue added in v0.2.4

func (b *Bashrc) ExtractValue(exportLine, key string) (string, error)

ExtractValue extracts value from export statement Input: export KEY="value" or export KEY=value Output: value

func (*Bashrc) Get added in v0.0.10

func (b *Bashrc) Get(key string) (string, error)

Get reads a variable value from .bashrc file

func (*Bashrc) Set added in v0.0.10

func (b *Bashrc) Set(key, value string) error

Set updates or creates a variable in .bashrc If value is empty, removes the variable

type CodeJob added in v0.2.12

type CodeJob struct {
	// contains filtered or unexported fields
}

CodeJob orchestrates sending a coding task to a chain of AI agent drivers. It validates the prompt file, then tries each driver in priority order, falling back to the next on failure.

func NewCodeJob added in v0.2.12

func NewCodeJob(drivers ...CodeJobDriver) *CodeJob

NewCodeJob creates a CodeJob with the given ordered drivers.

func (*CodeJob) Send added in v0.2.12

func (c *CodeJob) Send(issuePromptPath string) (string, error)

Send validates issuePromptPath, checks repo sync, then tries each driver in order until one succeeds. Returns an error if the file is missing, empty, the repo is out of sync, or all drivers fail.

func (*CodeJob) SetLog added in v0.2.12

func (c *CodeJob) SetLog(fn func(...any))

SetLog sets the logging function for the orchestrator.

func (*CodeJob) SetRepoSync added in v0.2.12

func (c *CodeJob) SetRepoSync(s RepoSync)

SetRepoSync injects a RepoSync for pre-flight synchronization check. When set, Send() will refuse to dispatch if the local repo is not in sync with the remote.

type CodeJobDriver added in v0.2.12

type CodeJobDriver interface {
	Name() string
	SetLog(fn func(...any))
	Send(prompt, title string) (string, error)
}

CodeJobDriver defines the contract for an external AI coding agent. Implementations: JulesDriver, (future: OllamaDriver, etc.) title is the human-readable job name (e.g. "owner/repo"), derived by CodeJob.

type CodeJobInitWizard added in v0.2.12

type CodeJobInitWizard struct {
	// contains filtered or unexported fields
}

CodeJobInitWizard implements the one-time setup wizard for codejob. It follows the same wizard.Step pattern as gonew_wizard.go.

func NewCodeJobInitWizard added in v0.2.12

func NewCodeJobInitWizard() *CodeJobInitWizard

NewCodeJobInitWizard creates a CodeJobInitWizard.

func (*CodeJobInitWizard) GetSteps added in v0.2.12

func (c *CodeJobInitWizard) GetSteps() []*wizard.Step

GetSteps returns the single onboarding step: save the Jules API key to keyring.

func (*CodeJobInitWizard) Run added in v0.2.12

func (c *CodeJobInitWizard) Run() error

Run drives the init wizard from a CLI context. It handles masked input for the API key step.

func (*CodeJobInitWizard) SetLog added in v0.2.12

func (c *CodeJobInitWizard) SetLog(fn func(...any))

SetLog sets the logging function.

type ConsoleFilter

type ConsoleFilter struct {
	// contains filtered or unexported fields
}

func NewConsoleFilter

func NewConsoleFilter(output func(string)) *ConsoleFilter

func (*ConsoleFilter) Add

func (cf *ConsoleFilter) Add(input string)

func (*ConsoleFilter) Flush

func (cf *ConsoleFilter) Flush()

type DevBackup added in v0.0.10

type DevBackup struct {
	// contains filtered or unexported fields
}

DevBackup handles backup operations

func NewDevBackup added in v0.0.10

func NewDevBackup() *DevBackup

NewDevBackup creates a new DevBackup instance

func (*DevBackup) GetCommand added in v0.0.10

func (d *DevBackup) GetCommand() (string, error)

GetCommand retrieves the backup command First checks environment variable, then falls back to .bashrc

func (*DevBackup) Run added in v0.0.10

func (d *DevBackup) Run() (string, error)

Run executes the backup command asynchronously Returns a message for the summary or empty string if not configured

func (*DevBackup) SetCommand added in v0.0.10

func (d *DevBackup) SetCommand(command string) error

SetCommand sets the backup command in .bashrc and current environment

func (*DevBackup) SetLog added in v0.0.23

func (d *DevBackup) SetLog(fn func(...any))

SetLog sets the logger function

type DotEnv added in v0.2.12

type DotEnv struct {
	// contains filtered or unexported fields
}

DotEnv handles .env files while trying to preserve non-key=value lines (comments, empty lines).

func NewDotEnv added in v0.2.12

func NewDotEnv(path string) *DotEnv

NewDotEnv creates a new .env handler.

func (*DotEnv) Delete added in v0.2.12

func (e *DotEnv) Delete(key string) error

Delete removes a key from the .env file.

func (*DotEnv) Get added in v0.2.12

func (e *DotEnv) Get(key string) (string, bool)

Get retrieves a value from the .env file.

func (*DotEnv) Set added in v0.2.12

func (e *DotEnv) Set(key, value string) error

Set sets or updates a value in the .env file, preserving other lines.

type FolderWatcher added in v0.0.74

type FolderWatcher interface {
	AddDirectoriesToWatch(paths ...string) error
	RemoveDirectoriesFromWatcher(paths ...string) error
}

FolderWatcher defines interface for adding/removing directories to watch

type Future added in v0.0.36

type Future struct {
	// contains filtered or unexported fields
}

Future holds the async result of any initialization. It uses any (interface{}) for flexibility without generic syntax.

func NewFuture added in v0.0.36

func NewFuture(initFn func() (any, error)) *Future

NewFuture starts async initialization with the given function.

func NewResolvedFuture added in v0.0.41

func NewResolvedFuture(value any) *Future

NewResolvedFuture creates a Future that is already resolved with the given value. Useful for tests or when the value is already available synchronously.

func (*Future) Get added in v0.0.36

func (f *Future) Get() (any, error)

Get blocks until initialization completes and returns the result.

func (*Future) Ready added in v0.0.36

func (f *Future) Ready() <-chan bool

Ready returns a channel that signals completion.

type Git

type Git struct {
	// contains filtered or unexported fields
}

Git handler for Git operations

func NewGit

func NewGit() (*Git, error)

NewGit creates a new Git handler and verifies git is available

func (*Git) Add added in v0.0.73

func (g *Git) Add() error

Add adds all changes to staging

func (*Git) CheckRemoteAccess added in v0.0.69

func (g *Git) CheckRemoteAccess() error

CheckRemoteAccess verifies connectivity to the remote repository. If an auth error is detected and an authRetrier is configured, it triggers the Device Flow auth automatically and retries once.

func (*Git) Commit added in v0.0.73

func (g *Git) Commit(message string) (bool, error)

Commit creates a commit with the given message Returns true if a commit was created

func (*Git) CreateTag added in v0.0.73

func (g *Git) CreateTag(tag string) (bool, error)

CreateTag creates a new tag

func (*Git) GenerateNextTag

func (g *Git) GenerateNextTag() (string, error)

GenerateNextTag calculates the next semantic version

func (*Git) GetConfigUserEmail added in v0.0.13

func (g *Git) GetConfigUserEmail() (string, error)

GetConfigUserEmail gets the git user.email

func (*Git) GetConfigUserName added in v0.0.13

func (g *Git) GetConfigUserName() (string, error)

GetConfigUserName gets the git user.name

func (*Git) GetLatestTag

func (g *Git) GetLatestTag() (string, error)

GetLatestTag gets the latest tag

func (*Git) GitIgnoreAdd added in v0.0.32

func (g *Git) GitIgnoreAdd(entry string) error

GitIgnoreAdd adds entry to .gitignore if shouldWrite allows and entry not present. Creates .gitignore if it doesn't exist.

func (*Git) HasChanges added in v0.2.4

func (g *Git) HasChanges() (bool, error)

HasChanges checks if there are staged changes

func (*Git) HasPendingChanges added in v0.2.12

func (g *Git) HasPendingChanges() (bool, error)

HasPendingChanges returns true if there are uncommitted or unpushed changes. Used by CodeJob to ensure the file is visible to Jules before dispatching. It ignores changes to .env and .gitignore files.

func (*Git) HasUpstream added in v0.2.4

func (g *Git) HasUpstream() (bool, error)

HasUpstream checks if the branch has upstream

func (*Git) IncrementTag added in v0.0.73

func (g *Git) IncrementTag(tag string) (string, error)

IncrementTag increments a specific tag (e.g., v0.0.12 -> v0.0.13)

func (*Git) InitRepo added in v0.0.13

func (g *Git) InitRepo(dir string) error

InitRepo initializes a new git repository

func (*Git) IsAheadOfRemote added in v0.0.82

func (g *Git) IsAheadOfRemote() (bool, error)

IsAheadOfRemote checks if local branch is ahead of remote

func (*Git) Push

func (g *Git) Push(message, tag string) (PushResult, error)

Push executes the complete push workflow (add, commit, tag, push) Returns a PushResult and error if any.

func (*Git) PushWithTags added in v0.0.73

func (g *Git) PushWithTags(tag string) (bool, error)

PushWithTags pushes commits and tag

func (*Git) PushWithoutTags added in v0.0.82

func (g *Git) PushWithoutTags() (bool, error)

PushWithoutTags pushes commits without pushing tags

func (*Git) SetAuthRetrier added in v0.2.12

func (g *Git) SetAuthRetrier(a GitHubAuthenticator)

SetAuthRetrier injects an authenticator to use for auto-recovery on access errors

func (*Git) SetCodeJobDrivers added in v0.2.13

func (g *Git) SetCodeJobDrivers(drivers ...CodeJobDriver)

SetCodeJobDrivers injects AI agent drivers for CodeJob dispatch. If not set, Push() defaults to NewJulesDriver(JulesConfig{}).

func (*Git) SetLog

func (g *Git) SetLog(fn func(...any))

SetLog sets the logger function

func (*Git) SetRootDir added in v0.0.32

func (g *Git) SetRootDir(path string)

SetRootDir sets the root directory for git operations

func (*Git) SetShouldWrite added in v0.0.32

func (g *Git) SetShouldWrite(f func() bool)

SetShouldWrite sets a function that determines if Git write operations (like updating .gitignore) should be allowed.

func (*Git) SetUserConfig added in v0.0.13

func (g *Git) SetUserConfig(name, email string) error

SetUserConfig sets git user name and email

func (*Git) TagExists added in v0.0.73

func (g *Git) TagExists(tag string) (bool, error)

TagExists checks if a tag exists

type GitClient added in v0.0.69

type GitClient interface {
	CheckRemoteAccess() error
	Push(message, tag string) (PushResult, error)
	GetLatestTag() (string, error)
	SetLog(fn func(...any))
	SetShouldWrite(fn func() bool)
	SetRootDir(path string)
	GitIgnoreAdd(entry string) error
	GetConfigUserName() (string, error)
	GetConfigUserEmail() (string, error)
	InitRepo(dir string) error
	Add() error
	Commit(message string) (bool, error)
	CreateTag(tag string) (bool, error)
	PushWithTags(tag string) (bool, error)
	HasPendingChanges() (bool, error)
}

GitClient defines the interface for Git operations.

type GitHub added in v0.0.13

type GitHub struct {
	// contains filtered or unexported fields
}

GitHub handler for GitHub operations

func NewGitHub added in v0.0.13

func NewGitHub(logFn func(...any), auth ...GitHubAuthenticator) (*GitHub, error)

NewGitHub creates handler and verifies gh CLI availability. logFn is used to display authentication messages during Device Flow. If not authenticated, it initiates OAuth Device Flow automatically.

func (*GitHub) CreateRepo added in v0.0.13

func (gh *GitHub) CreateRepo(owner, name, description, visibility string) error

CreateRepo creates a new empty repository on GitHub If owner is provided, creates repo under that organization

func (*GitHub) DeleteRepo added in v0.0.39

func (gh *GitHub) DeleteRepo(owner, name string) error

DeleteRepo deletes a repository on GitHub. WARNING: This permanently deletes the repository and cannot be undone. Use with caution, primarily for test cleanup.

func (*GitHub) GetCurrentUser added in v0.0.13

func (gh *GitHub) GetCurrentUser() (string, error)

GetCurrentUser gets the current authenticated user

func (*GitHub) GetHelpfulErrorMessage added in v0.0.13

func (gh *GitHub) GetHelpfulErrorMessage(err error) string

GetHelpfulErrorMessage returns a helpful message for common errors

func (*GitHub) IsNetworkError added in v0.0.13

func (gh *GitHub) IsNetworkError(err error) bool

IsNetworkError checks if an error is likely a network error

func (*GitHub) RepoExists added in v0.0.13

func (gh *GitHub) RepoExists(owner, name string) (bool, error)

RepoExists checks if a repository exists

func (*GitHub) SetLog added in v0.0.13

func (gh *GitHub) SetLog(fn func(...any))

SetLog sets the logger function

type GitHubAuth added in v0.0.23

type GitHubAuth struct {
	// contains filtered or unexported fields
}

GitHubAuth handles GitHub authentication and token management

func NewGitHubAuth added in v0.0.23

func NewGitHubAuth() *GitHubAuth

NewGitHubAuth creates a new GitHub authentication handler

func (*GitHubAuth) DeviceFlowAuth added in v0.0.23

func (a *GitHubAuth) DeviceFlowAuth(kr *Keyring) (string, error)

DeviceFlowAuth initiates GitHub OAuth Device Flow and returns an access token

func (*GitHubAuth) EnsureGitHubAuth added in v0.0.23

func (a *GitHubAuth) EnsureGitHubAuth() error

EnsureGitHubAuth checks if GitHub is authenticated via keyring, and if not, initiates Device Flow

func (*GitHubAuth) Name added in v0.0.70

func (a *GitHubAuth) Name() string

Name returns the handler name for TUI display.

func (*GitHubAuth) SetLog added in v0.0.23

func (a *GitHubAuth) SetLog(fn func(...any))

SetLog sets the logger function

type GitHubAuthHandler added in v0.0.70

type GitHubAuthHandler interface {
	GitHubAuthenticator
	Name() string
}

GitHubAuthHandler defines the interface for GitHub auth as a TUI handler.

type GitHubAuthenticator added in v0.0.70

type GitHubAuthenticator interface {
	EnsureGitHubAuth() error
	SetLog(fn func(...any))
}

GitHubAuthenticator defines the interface for GitHub authentication. This allows mocking authentication in tests.

type GitHubClient added in v0.0.66

type GitHubClient interface {
	SetLog(fn func(...any))
	GetCurrentUser() (string, error)
	RepoExists(owner, name string) (bool, error)
	CreateRepo(owner, name, description, visibility string) error
	DeleteRepo(owner, name string) error
	IsNetworkError(err error) bool
	GetHelpfulErrorMessage(err error) string
}

GitHubClient defines the interface for GitHub operations. This allows mocking the GitHub dependency in tests.

type Go

type Go struct {
	// contains filtered or unexported fields
}

Go handler for Go operations

func NewGo

func NewGo(gitHandler GitClient) (*Go, error)

NewGo creates a new Go handler and verifies Go installation

func (*Go) DetectGoExecutable added in v0.0.13

func (g *Go) DetectGoExecutable() (string, error)

DetectGoExecutable returns the path to the go executable

func (*Go) FindDependentModules added in v0.2.4

func (g *Go) FindDependentModules(modulePath, searchPath string) ([]string, error)

FindDependentModules searches for modules that have modulePath as dependency

func (*Go) GetCurrentVersion added in v0.0.49

func (g *Go) GetCurrentVersion(moduleDir, dependencyPath string) (string, error)

GetCurrentVersion returns the current version of a dependency in a module

func (*Go) GetGit added in v0.2.4

func (g *Go) GetGit() GitClient

GetGit returns the git client

func (*Go) GetLog added in v0.2.4

func (g *Go) GetLog() func(...any)

GetLog returns the logger function

func (*Go) GetModulePath added in v0.2.4

func (g *Go) GetModulePath() (string, error)

GetModulePath gets full module path

func (*Go) GoVersion added in v0.0.13

func (g *Go) GoVersion() (string, error)

GoVersion reads the Go version from the go.mod file in the current directory. It returns the version string (e.g., "1.18") or an empty string if not found.

func (*Go) HasDependency added in v0.2.4

func (g *Go) HasDependency(gomodPath, modulePath string) bool

HasDependency checks if a go.mod contains a specific dependency

func (*Go) Install added in v0.1.51

func (g *Go) Install(version string) (string, error)

Install builds and installs all commands in the cmd/ directory It injects the version using ldflags if provided

func (*Go) ModExists added in v0.2.4

func (g *Go) ModExists() bool

ModExists checks if go.mod exists

func (*Go) ModExistsInCurrentOrParent added in v0.0.33

func (g *Go) ModExistsInCurrentOrParent() bool

ModExistsInCurrentOrParent checks if go.mod exists in the rootDir or one directory up.

func (*Go) ModInit added in v0.0.13

func (g *Go) ModInit(modulePath, targetDir string) error

ModInit initializes a new go module

func (*Go) Push

func (g *Go) Push(message, tag string, skipTests, skipRace, skipDependents, skipBackup bool, searchPath string) (string, error)

Push executes the complete workflow for Go projects Parameters:

message: Commit message
tag: Optional tag
skipTests: If true, skips tests
skipRace: If true, skips race tests
skipDependents: If true, skips updating dependent modules
skipBackup: If true, skips backup
searchPath: Path to search for dependent modules (default: "..")

func (*Go) SetConsoleOutput added in v0.2.4

func (g *Go) SetConsoleOutput(fn func(string))

SetConsoleOutput sets the function for console output (used by ConsoleFilter)

func (*Go) SetLog

func (g *Go) SetLog(fn func(...any))

SetLog sets the logger function

func (*Go) SetRetryConfig added in v0.0.69

func (g *Go) SetRetryConfig(delay time.Duration, attempts int)

SetRetryConfig sets the retry configuration for network operations

func (*Go) SetRootDir added in v0.0.33

func (g *Go) SetRootDir(path string)

SetRootDir sets the root directory for Go operations

func (*Go) Test

func (g *Go) Test(customArgs []string, skipRace bool, timeoutSec int, noCache bool, runAll bool) (string, error)

Test executes the test suite for the project. timeoutSec sets the per-package timeout in seconds (0 = default 30s).

func (*Go) UpdateDependentModule added in v0.0.45

func (g *Go) UpdateDependentModule(depDir, modulePath, version string) (string, error)

UpdateDependentModule updates a dependent module and optionally pushes it This is called for each module that depends on the one we just published UpdateDependentModule updates a specific dependent module It modifies go.mod to require the new version and runs go mod tidy

func (*Go) UpdateDependents added in v0.2.4

func (g *Go) UpdateDependents(modulePath, version, searchPath string) ([]string, error)

UpdateDependents updates modules that depend on the current one

func (*Go) UpdateModule added in v0.2.4

func (g *Go) UpdateModule(moduleDir, dependency, version string) error

UpdateModule updates a specific module to a new version

func (*Go) Verify added in v0.2.4

func (g *Go) Verify() error

Verify verifies go.mod integrity

func (*Go) WaitForVersionAvailable added in v0.0.69

func (g *Go) WaitForVersionAvailable(modulePath, version string) error

WaitForVersionAvailable waits for a module version to be available on Go proxy

type GoModHandler added in v0.0.74

type GoModHandler struct {
	Lines    []string // all lines of the file
	Modified bool     // track if changes were made
	// contains filtered or unexported fields
}

GoModHandler represents a parsed go.mod file and handles file events

func NewGoModHandler added in v0.0.74

func NewGoModHandler() *GoModHandler

NewGoModHandler reads and parses a go.mod file or returns an empty handler if path is empty

func (*GoModHandler) GetReplacePaths added in v0.0.76

func (m *GoModHandler) GetReplacePaths() ([]ReplaceEntry, error)

GetReplacePaths returns absolute paths from local replace directives. Relative paths are resolved starting from the directory containing go.mod.

func (*GoModHandler) HasOtherReplaces added in v0.0.74

func (m *GoModHandler) HasOtherReplaces(exceptModule string) bool

HasOtherReplaces returns true if there are replace directives other than the specified module

func (*GoModHandler) MainInputFileRelativePath added in v0.0.74

func (g *GoModHandler) MainInputFileRelativePath() string

func (*GoModHandler) Name added in v0.0.74

func (g *GoModHandler) Name() string

func (*GoModHandler) NewFileEvent added in v0.0.74

func (g *GoModHandler) NewFileEvent(fileName, extension, filePath, event string) error

NewFileEvent handles changes to go.mod

func (*GoModHandler) RemoveReplace added in v0.0.74

func (m *GoModHandler) RemoveReplace(modulePath string) bool

RemoveReplace removes a replace directive for the given module Returns true if a replace was found and removed

func (*GoModHandler) RunTidy added in v0.0.74

func (m *GoModHandler) RunTidy() error

RunTidy executes 'go mod tidy' in the directory of the go.mod file

func (*GoModHandler) Save added in v0.0.74

func (m *GoModHandler) Save() error

Save writes changes back to the file if modified

func (*GoModHandler) SetFolderWatcher added in v0.0.74

func (g *GoModHandler) SetFolderWatcher(watcher FolderWatcher)

func (*GoModHandler) SetLog added in v0.0.74

func (g *GoModHandler) SetLog(fn func(messages ...any))

func (*GoModHandler) SetRootDir added in v0.0.74

func (g *GoModHandler) SetRootDir(path string)

func (*GoModHandler) SupportedExtensions added in v0.0.74

func (g *GoModHandler) SupportedExtensions() []string

func (*GoModHandler) UnobservedFiles added in v0.0.74

func (g *GoModHandler) UnobservedFiles() []string

type GoModInterface added in v0.0.74

type GoModInterface interface {
	NewFileEvent(fileName, extension, filePath, event string) error
	SetFolderWatcher(watcher FolderWatcher)
	Name() string
	SupportedExtensions() []string
	MainInputFileRelativePath() string
	UnobservedFiles() []string
	SetLog(fn func(...any))
	SetRootDir(path string)
	GetReplacePaths() ([]ReplaceEntry, error)
}

GoModInterface defines interface for go.mod handling

type GoNew added in v0.0.13

type GoNew struct {
	// contains filtered or unexported fields
}

GoNew orchestrator

func NewGoNew added in v0.0.13

func NewGoNew(git GitClient, github *Future, goHandler *Go) *GoNew

NewGoNew creates orchestrator (all handlers must be initialized)

func (*GoNew) AddRemote added in v0.0.13

func (gn *GoNew) AddRemote(projectPath, visibility, owner string) (string, error)

AddRemote adds GitHub remote to existing local project

func (*GoNew) Create added in v0.0.13

func (gn *GoNew) Create(opts NewProjectOptions) (string, error)

Create executes full workflow with remote (or local-only fallback)

func (*GoNew) GetSteps added in v0.0.36

func (gn *GoNew) GetSteps() []*wizard.Step

GetSteps returns the sequence of steps to create a new Go project

func (*GoNew) SetLog added in v0.0.13

func (gn *GoNew) SetLog(fn func(...any))

SetLog sets the logger function

type HTTPClient added in v0.2.12

type HTTPClient interface {
	Do(req *http.Request) (*http.Response, error)
}

HTTPClient defines the interface for HTTP operations (injectable for tests).

type JulesAuth added in v0.2.12

type JulesAuth struct {
	// contains filtered or unexported fields
}

JulesAuth manages the Jules API key via the system keyring. On first use it prompts the user to enter the key and stores it securely.

func NewJulesAuth added in v0.2.12

func NewJulesAuth() (*JulesAuth, error)

NewJulesAuth creates a JulesAuth with an initialized keyring.

func (*JulesAuth) EnsureAPIKey added in v0.2.12

func (a *JulesAuth) EnsureAPIKey() (string, error)

EnsureAPIKey returns the Jules API key from the keyring. If absent, prompts the user for it once and persists it.

func (*JulesAuth) HasKey added in v0.2.12

func (a *JulesAuth) HasKey() bool

HasKey returns true if the Jules API key is already stored in the keyring.

func (*JulesAuth) SetLog added in v0.2.12

func (a *JulesAuth) SetLog(fn func(...any))

SetLog sets the logging function.

type JulesConfig added in v0.2.12

type JulesConfig struct {
	APIKey              string        // optional: loaded from keyring if empty
	SourceID            string        // optional: auto-detected via gh CLI if empty
	StartBranch         string        // optional: auto-detected via git if empty
	SessionTitle        string        // optional: defaults to prompt filename
	SourceIndexTimeout  time.Duration // optional: max wait for source to appear (default 2m)
	SourceIndexInterval time.Duration // optional: polling interval for source check (default 10s)
}

JulesConfig holds the configuration for the Jules driver. All fields are optional: APIKey is loaded from keyring if empty, SourceID and StartBranch are auto-detected via gh/git if empty.

type JulesDriver added in v0.2.12

type JulesDriver struct {
	// contains filtered or unexported fields
}

JulesDriver implements CodeJobDriver for the Jules AI agent.

func NewJulesDriver added in v0.2.12

func NewJulesDriver(config JulesConfig) *JulesDriver

NewJulesDriver creates a JulesDriver. All JulesConfig fields are optional.

func (*JulesDriver) Name added in v0.2.12

func (d *JulesDriver) Name() string

Name returns the driver name.

func (*JulesDriver) Send added in v0.2.12

func (d *JulesDriver) Send(prompt, title string) (string, error)

Send creates a Jules session using the prompt and title resolved by CodeJob. Jules accesses the referenced file directly from the repository via its GitHub App access. If the source is not yet indexed in Jules (404 on new repos), it polls GET /sources until the source appears or the timeout is exceeded.

func (*JulesDriver) SessionID added in v0.2.12

func (d *JulesDriver) SessionID() string

SessionID returns the last session ID created.

func (*JulesDriver) SetHTTPClient added in v0.2.12

func (d *JulesDriver) SetHTTPClient(client HTTPClient)

SetHTTPClient replaces the HTTP client (for testing).

func (*JulesDriver) SetLog added in v0.2.12

func (d *JulesDriver) SetLog(fn func(...any))

SetLog sets the logging function.

type Keyring added in v0.0.23

type Keyring struct {
	// contains filtered or unexported fields
}

Keyring provides secure credential storage using the system keyring

func NewKeyring added in v0.0.23

func NewKeyring() (*Keyring, error)

NewKeyring creates a keyring handler and ensures dependencies are installed

func (*Keyring) Delete added in v0.0.23

func (k *Keyring) Delete(key string) error

Delete removes a secret from the keyring

func (*Keyring) Get added in v0.0.23

func (k *Keyring) Get(key string) (string, error)

Get retrieves a secret from the keyring

func (*Keyring) Set added in v0.0.23

func (k *Keyring) Set(key, value string) error

Set stores a secret in the keyring

func (*Keyring) SetLog added in v0.0.23

func (k *Keyring) SetLog(fn func(...any))

SetLog sets the logging function for the keyring handler

type LLM added in v0.0.79

type LLM struct {
	// contains filtered or unexported fields
}

LLM handles synchronization of LLM configuration files

func NewLLM added in v0.0.79

func NewLLM() *LLM

NewLLM creates a new LLM handler

func (*LLM) DetectInstalledLLMs added in v0.0.79

func (l *LLM) DetectInstalledLLMs() []LLMConfig

DetectInstalledLLMs detecta qué LLMs están instalados Returns: lista de LLMConfig para los LLMs instalados

func (*LLM) ForceUpdate added in v0.2.4

func (l *LLM) ForceUpdate(configPath, masterContent string) error

ForceUpdate sobrescribe completamente el archivo (con backup)

func (*LLM) GetMasterContent added in v0.0.79

func (l *LLM) GetMasterContent() (string, error)

GetMasterContent lee el contenido del archivo maestro embebido

func (*LLM) GetSupportedLLMs added in v0.0.79

func (l *LLM) GetSupportedLLMs() []LLMConfig

GetSupportedLLMs retorna la lista de LLMs soportados

func (*LLM) SetLog added in v0.0.79

func (l *LLM) SetLog(fn func(...any))

SetLog sets the logger function

func (*LLM) SmartSync added in v0.2.4

func (l *LLM) SmartSync(configPath, masterContent string) (bool, error)

SmartSync realiza sincronización inteligente con merge de marcadores

func (*LLM) Sync added in v0.0.79

func (l *LLM) Sync(specificLLM string, force bool) (string, error)

Sync sincroniza todos los LLMs instalados Returns: resumen de operaciones realizadas

type LLMConfig added in v0.0.79

type LLMConfig struct {
	Name       string // "claude", "gemini"
	Dir        string // "~/.claude", "~/.gemini"
	ConfigFile string // "CLAUDE.md", "GEMINI.md"
}

LLMConfig representa la configuración de un LLM específico

type MarkDown added in v0.0.13

type MarkDown struct {
	// contains filtered or unexported fields
}

func NewMarkDown added in v0.0.13

func NewMarkDown(rootDir, destination string, writerFile func(name string, data []byte) error) *MarkDown

NewMarkDown creates a new MarkDown instance with the root directory. Destination (output directory) and input must be set via methods.

func (*MarkDown) Extract added in v0.0.13

func (m *MarkDown) Extract(outputFile string) error

Extract extracts code blocks from the configured input and writes to outputFile The output file extension determines which code type to extract (.go, .js, .css)

func (*MarkDown) InputByte added in v0.0.13

func (m *MarkDown) InputByte(content []byte) *MarkDown

InputByte sets the input as a byte slice (markdown content)

func (*MarkDown) InputEmbed added in v0.0.13

func (m *MarkDown) InputEmbed(path string, readerFile func(name string) ([]byte, error)) *MarkDown

InputEmbed sets the input as any ReaderFile implementation and a relative path inside it

func (*MarkDown) InputPath added in v0.0.13

func (m *MarkDown) InputPath(pathFile string, readerFile func(name string) ([]byte, error)) *MarkDown

InputPath sets the input as a file path (relative to rootDir)

func (*MarkDown) SetLog added in v0.0.23

func (m *MarkDown) SetLog(fn func(...any))

SetLog sets a custom logger function

func (*MarkDown) UpdateSection added in v0.0.13

func (m *MarkDown) UpdateSection(sectionID, content string, afterLine ...string) error

UpdateSection updates or creates a section in the input file based on identifier. sectionID: The identifier for the section (e.g., "BADGES"). content: The new content to insert. afterLine: Optional. Implementation tries to insert after this line number if section doesn't exist.

type MockGitHubAuth added in v0.0.70

type MockGitHubAuth struct {
	EnsureAuthError error // Set this to simulate auth failure
	// contains filtered or unexported fields
}

MockGitHubAuth is a mock implementation of GitHubAuthenticator for testing.

func NewMockGitHubAuth added in v0.0.70

func NewMockGitHubAuth() *MockGitHubAuth

NewMockGitHubAuth creates a new mock authenticator.

func (*MockGitHubAuth) EnsureGitHubAuth added in v0.0.70

func (m *MockGitHubAuth) EnsureGitHubAuth() error

EnsureGitHubAuth simulates the authentication process.

func (*MockGitHubAuth) Name added in v0.0.70

func (m *MockGitHubAuth) Name() string

Name returns the handler name for TUI display.

func (*MockGitHubAuth) SetLog added in v0.0.70

func (m *MockGitHubAuth) SetLog(fn func(...any))

SetLog sets the logger function.

type NewProjectOptions added in v0.0.13

type NewProjectOptions struct {
	Name        string // Required, must be valid (alphanumeric, dash, underscore only)
	Description string // Required, max 350 chars
	Owner       string // GitHub owner/organization (default: detected from gh or git config)
	Visibility  string // "public" or "private" (default: "public")
	Directory   string // Supports ~/path, ./path, /abs/path (default: ./{Name})
	LocalOnly   bool   // If true, skip remote creation
	License     string // Default "MIT"
}

NewProjectOptions options for creating a new project

type PushResult added in v0.0.80

type PushResult struct {
	Summary string // Human-readable summary of operations performed
	Tag     string // The tag that was created and pushed
}

PushResult contains the results of a Git push operation

func MergeAndPublish added in v0.2.16

func MergeAndPublish(git *Git) (PushResult, error)

MergeAndPublish merges the Jules PR, pulls the merged commit, commits any cleanup files (e.g. .gitignore updated by HandleDone), creates a new semver tag, and pushes it. This is the "close the loop" step that leaves the repo tagged and published, mirroring what 'push' does for regular commits.

type ReplaceEntry added in v0.0.74

type ReplaceEntry struct {
	ModulePath string // The module being replaced
	LocalPath  string // The local path replacement
}

ReplaceEntry represents a local replace directive found in go.mod

type RepoSync added in v0.2.12

type RepoSync interface {
	HasPendingChanges() (bool, error)
}

RepoSync checks whether the local repository is in sync with the remote. CodeJob uses this to refuse dispatch when local changes haven't been pushed yet.

type SessionProvider added in v0.2.12

type SessionProvider interface {
	SessionID() string
}

SessionProvider is implemented by CodeJobDrivers that return a session ID after a successful Send(). CodeJob uses this to persist to .env.

type TestCache added in v0.0.63

type TestCache struct {
	CacheDir string
}

TestCache provides git-based test caching to avoid re-running tests when the code hasn't changed since the last successful test run.

func NewTestCache added in v0.0.63

func NewTestCache() *TestCache

NewTestCache creates a new TestCache instance

func (*TestCache) GetCacheKey added in v0.2.4

func (tc *TestCache) GetCacheKey() (string, error)

GetCacheKey returns a unique key for the current module based on its path

func (*TestCache) GetCachePath added in v0.2.4

func (tc *TestCache) GetCachePath() (string, error)

GetCachePath returns the full path to the cache file

func (*TestCache) GetCachedMessage added in v0.0.63

func (tc *TestCache) GetCachedMessage() string

GetCachedMessage returns the cached test output message

func (*TestCache) GetGitState added in v0.2.4

func (tc *TestCache) GetGitState() (string, error)

GetGitState returns current git state: commit hash + diff hash This uniquely identifies the exact state of the code

func (*TestCache) InvalidateCache added in v0.0.63

func (tc *TestCache) InvalidateCache() error

InvalidateCache removes the cache file

func (*TestCache) IsCacheValid added in v0.0.63

func (tc *TestCache) IsCacheValid() bool

IsCacheValid checks if tests were already run successfully with the current code

func (*TestCache) SaveCache added in v0.0.63

func (tc *TestCache) SaveCache(message string) error

SaveCache saves the current git state and test message

Directories

Path Synopsis
cmd
badges command
codejob command
devbackup command
goinstall command
gonew command
gopush command
gotest command
llmskill command
push command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL