This file explains the main names the code keeps using. Read this before following the flow examples.
The app is split into four simple responsibilities:
main.go: starts the app.internal/config: reads user settings.internal/git: runsgitandgh.internal/tui: handles keys, state, and drawing.
The important rule is:
TUI code asks for an app action.
Git code decides the exact git command.
View code draws whatever is currently in Model.
Defined in internal/config/config.go.
Config is the user settings object. It is loaded once in main.go, then
stored on tui.Model.
It answers questions like:
- What theme should the UI use?
- Should gitm8 fetch on startup?
- Should commit logs show graph lines?
- Which Git identity profiles are available?
- Which AI provider/model should generate commit and PR text?
Important functions:
config.Load(): builds the final config.defaults(): sets fallback values.loadFile(): reads~/.gitm8/.gitm8rc,~/.gitm8/gitm8rc, legacy~/.gitm8rc, and~/.gitm8/credentials.applyEnv(): appliesGITM8_*environment variables.loadProfiles(): reads~/.gitm8/profiles.
Defined in internal/config/config.go.
Profile is one selectable Git identity:
Label: "Work"
Name: "Ada Lovelace"
Email: "ada@work.example"
The TUI uses profiles on the identity screen opened with i.
Defined in internal/git/git.go.
Runner is the app's doorway to Git. It has one optional field:
Dir: where Git commands should run. Empty means "use the current directory".
The TUI should call Runner methods instead of building commands directly.
Examples:
m.runner.StageOutput(ctx, path)
m.runner.Branches(ctx)
The actual process call is handled in internal/git/exec.go.
Defined in internal/git/git.go.
FileStatus is one row from git status --porcelain.
Fields:
Path: file path Git should operate on, or the new path for a rename.OldPath: old path for a rename or copy, otherwise empty.Index: staged status column from Git.Worktree: unstaged status column from Git.
Helpers:
Staged(): true when the file has staged changes.Unstaged(): true when the file has unstaged or untracked changes.Label(): returns Git's short status label, such asMor??.DisplayPath(): returns the user-facing label, includingold -> newfor renames.GitPaths(): returns the path arguments Git commands need for the row.Deleted(): true for removed tracked paths.Renamed(): true for rename/copy rows.
The TUI uses this for the changed-files panel.
Defined in internal/git/git.go.
RepoInfo is the small snapshot shown in the top status bar.
It contains:
- repo name
- current branch
- upstream branch
- configured Git user
- ahead/behind counts
- staged/unstaged counts
- last fetch time
It is built by Runner.RepoInfo() in internal/git/repo.go.
Defined in internal/tui/model.go.
Model is the full UI state. Bubble Tea passes it around constantly:
Model.Update(...)
-> returns changed Model
-> Model.View() draws that changed Model
Important fields:
runner: thegit.Runnerused for Git commands.config: loaded app settings.review: scrollable viewport for preview/review/log/help text.commit: text input for commit messages.branchInput: text input for new branch names.spinner: loading indicator while Git work runs.info: currentgit.RepoInfo.files: changed files from Git status.branches: branch list for branch and rebase screens.fileCursor,branchCursor,profileCursor: selected row indexes.target: currently selected file path orrepo.mode: current screen, such asreview,preview,branches, orcommit.gitOutput: latest command output shown in the header.
The TUI currently stores screen mode as a string in Model.mode.
Common modes:
review: repo or file diff view.preview: file content preview.logs: commit log view.branches: branch picker.rebase: rebase target picker.conflicts: unmerged-file picker with resolve/rebase actions.stashes: stash picker with apply/pop/drop actions.profiles: Git identity picker.commit: commit message input.new-branch: new branch name input.delete-branch: branch delete prompt.discard-file: file discard confirmation prompt.help: help screen.
Keys first go through updateKey() in internal/tui/update.go.
That function sends keys to:
updateDashboardKey()for normal dashboard keys.updateFocusedMode()for screens that take over input.
Defined in internal/tui/model.go.
Bubble Tea commands return messages. gitm8 uses three custom message types:
Means repo data finished loading.
Carries:
git.RepoInfo- changed files
- viewer text
- current target
- current mode
- error, if loading failed
Handled by handleRepoLoaded().
Means branch data finished loading.
Carries:
git.RepoInfo- changed files
- branch names
- mode, either
branchesorrebase - error, if loading failed
Handled by handleBranchesLoaded().
Means a Git command finished.
Carries:
- command output
- whether the screen should refresh
- error, if the command failed
Handled by handleGitActionFinished().
These come from Charm's Bubbles library:
viewport.Model: scrollable text area for review, preview, logs, and help.textinput.Model: input field for commit messages and new branch names.spinner.Model: small loading indicator while Git work runs.
Docs:
Defined in internal/tui/theme.go.
palette is the internal color set for one theme. applyTheme() copies a
palette into the shared Lip Gloss styles used by the whole TUI.
The shared styles are:
titleStyleerrorStylemutedStylekeyStylepanelStyleactiveStyle- syntax highlight styles
Docs:
Defined in internal/tui/view.go.
splashTickMsg is a tiny message sent by tea.Tick() while the splash screen
is animating. Each tick advances the splash frame. When the splash finishes,
the app loads the first repo view.
Docs: