Repository files navigation

gitte

license

Monorepo-like development across many git repositories — without the monorepo.

Gitte keeps all your repos in sync, runs startup checks to verify your local machine is ready, and executes ordered actions (build, up, down, …) across projects with dependency resolution and parallel execution.


Table of contents


Features

  • Startup checks — verify tools, versions, and credentials before doing anything
  • Git sync — clone and pull all configured repositories in parallel
  • Ordered actions — run commands across projects with needs-based dependency ordering and parallel execution
  • Project toggles — interactively enable/disable projects per machine
  • Template inheritance — share action definitions across similar projects
  • Feature gates — toggle environment-variable-based behaviours per machine
  • Auto-discovery — discover and sync repositories from GitLab groups or GitHub orgs
  • Clean operations — remove untracked files, reset local changes, or check out default branches across all repos
  • TTY-aware output — animated spinner TUI in a terminal, structured plain-text output in CI / non-TTY

Installation

APT (Debian and Ubuntu)

curl -fsSL https://gitte-apt.cego.dk/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/gitte.gpg
echo"deb [signed-by=/etc/apt/keyrings/gitte.gpg] https://gitte-apt.cego.dk ./"| sudo tee /etc/apt/sources.list.d/gitte.list
sudo apt update
sudo apt install gitte

Homebrew (macOS and Linux)

brew tap cego/gitte https://github.com/cego/gitte
brew install cego/gitte/gitte

Binary download

Download the latest binary from the releases page and place it on your PATH.

Go install

Requires Go 1.24 or later.

go install github.com/cego/gitte@latest

Quick start

1. Create a .gitte.yml in your workspace root:

startup:
git-present:
type: commandcmd: ["git", "--version"]hint: "git is not installed"projects:
myservice:
remote: git@github.com:example/myservice.gitdefault_branch: mainactions:
start:
groups:
local: ["docker", "compose", "up", "-d"]stop:
groups:
local: ["docker", "compose", "down"]

2. Run the full pipeline:

gitte run start local

Gitte will run startup checks, pull all repos, then execute the start action for group local across all enabled projects.


Commands

Overview

CommandDescription
gitte run [action] [group] [projects]Full pipeline: startup checks → git sync → actions
gitte actions [action] [group] [projects]Run actions only (skip startup and git sync)
gitte startupRun startup checks only
gitte gitops [--discover]Clone/pull all repos; --discover also fetches from configured sources
gitte listList all projects and their available actions
gitte toggleInteractive TUI to enable/disable projects per machine
gitte clean <subcommand>Clean up repos (see below)
gitte features list|enable|disableManage feature gates
gitte sourcesManage discovery sources (GitLab groups / GitHub orgs)
gitte token set|get|delete|listStore API tokens in the system keyring
gitte validateValidate config: schema, cycles, missing references

Argument syntax

Arguments to run and actions are positional: action [group] [projects].

gitte run start # start action, all groups, all enabled projects
gitte run start local# start action, group local, all enabled projects
gitte run start local myservice # start action, group local, project myservice only
gitte run start local frontend+backend # start action, group local, projects frontend and backend
gitte run start+test # run start then test, all groups, all enabled projects

Use * or all as a wildcard. Combine multiple values with +.

gitte clean

Destructive cleanup operations across all configured repositories. Each subcommand shows a live progress TUI while running.

gitte clean untracked # remove untracked files (git clean -fdx)
gitte clean local-changes # reset repos with local changes (prompts before acting)
gitte clean master # checkout the default branch in all repos
gitte clean all # run all three in sequence

gitte clean local-changes lists affected repos and prompts:

Reset [a]ll / [i]ndividually / [C]ancel?

Configuration

See docs/config.md for the full configuration reference.


Environment variables

VariableDefaultDescription
GITTE_CWDprocess cwdOverride the working directory
GITTE_NO_TTY0Set to 1 to force plain-text output (no TUI)
GITTE_NO_NEEDS0Set to 1 to ignore needs dependencies
GITTE_NO_REBASEfalseSet to true to skip auto-rebase onto default branch
GITTE_MAX_TASK_PARALLELIZATIONunlimitedCap the number of concurrent tasks

Telemetry

Gitte can export OpenTelemetry traces to an OTLP/HTTP endpoint (e.g. Elastic APM) to help debug failures. Traces capture per-repo git context (branch, commit SHA, dirty state) and per-task outcomes with errors. To identify which developer and machine hit a failure, the OS username (user.name) and hostname (host.name) are attached to every trace.

What is recorded: the gitte CLI arguments and each action's command line are exported as span attributes (this is intentional — knowing what ran is the point). Note that gitte's injected environment — a project's env, env_when, and feature-gate env — is also exported on task spans (the gitte.env attribute) and in the task logs; the inherited process environment (everything in os.Environ) is not. So keep secrets out of action command definitions, CLI arguments, and config env/feature-gate blocks — pass real secrets through the process environment instead. Full remote URLs are never collected either (repos are identified by name only).

Each gitte run produces a structured trace: a root span with child spans for each phase (startup, gitops, actions), a span per startup check, a span per action (e.g. build, up) parenting its task spans, and a span per repo sync. Action and startup command output is also shipped as OTEL logs, correlated to the span that produced each line (stdout → INFO, stderr → WARN).

Logs are enabled with tracing; set GITTE_TELEMETRY_LOGS to off, false, or 0 to keep traces but disable the (higher-volume) log export. Keep secrets out of command output — log lines are exported verbatim.

Enable it via the shared config:

telemetry:
endpoint: https://apm.example.com:8200headers:
Authorization: "Bearer <secret-token>"# or: "ApiKey <base64-key>"

Environment variables:

VariableEffect
GITTE_TELEMETRY=off, false, or 0Disable telemetry locally (case-insensitive; surrounding whitespace is ignored)
GITTE_TELEMETRY_URLOverride the endpoint; whitespace is trimmed and https:// is added when no scheme is present
GITTE_TELEMETRY_LOGS=off, false, or 0Disable OTEL log export (keep traces; case-insensitive with surrounding whitespace ignored)
OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_HEADERSStandard OTEL env vars; endpoint vars are used when no gitte endpoint is set, and headers can provide credentials for a GITTE_TELEMETRY_URL override

Precedence: GITTE_TELEMETRY=off|false|0 > GITTE_TELEMETRY_URL > config endpoint > OTEL_EXPORTER_OTLP_*. Telemetry is best-effort and never blocks or slows gitte; export failures are silently ignored. When GITTE_TELEMETRY_URL overrides the config endpoint, config headers are not used; set OTEL_EXPORTER_OTLP_HEADERS to provide override-endpoint credentials through the OTEL exporter.


Global flags

--config <path> Path to .gitte.yml (default: auto-detected by walking up)
--cwd <path> Override working directory
--no-tty Force plain-text output

State and override files

.gitte-state.yml — stores per-machine state: project toggles, feature gate overrides, and remote config cache. Gitte automatically adds this file to .gitignore. Do not commit it.

.gitte-override.yml — deep-merged on top of .gitte.yml when present. Use this for local machine-specific settings that should not be committed (e.g. sources added via gitte sources add).

About

Developer environment orchestration — monorepo-like development across many git repositories, without the monorepo

Resources

Stars

14 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

gitte

license

Monorepo-like development across many git repositories — without the monorepo.

Gitte keeps all your repos in sync, runs startup checks to verify your local machine is ready, and executes ordered actions (build, up, down, …) across projects with dependency resolution and parallel execution.


Table of contents


Features

  • Startup checks — verify tools, versions, and credentials before doing anything
  • Git sync — clone and pull all configured repositories in parallel
  • Ordered actions — run commands across projects with needs-based dependency ordering and parallel execution
  • Project toggles — interactively enable/disable projects per machine
  • Template inheritance — share action definitions across similar projects
  • Feature gates — toggle environment-variable-based behaviours per machine
  • Auto-discovery — discover and sync repositories from GitLab groups or GitHub orgs
  • Clean operations — remove untracked files, reset local changes, or check out default branches across all repos
  • TTY-aware output — animated spinner TUI in a terminal, structured plain-text output in CI / non-TTY

Installation

APT (Debian and Ubuntu)

curl -fsSL https://gitte-apt.cego.dk/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/gitte.gpg
echo"deb [signed-by=/etc/apt/keyrings/gitte.gpg] https://gitte-apt.cego.dk ./"| sudo tee /etc/apt/sources.list.d/gitte.list
sudo apt update
sudo apt install gitte

Homebrew (macOS and Linux)

brew tap cego/gitte https://github.com/cego/gitte
brew install cego/gitte/gitte

Binary download

Download the latest binary from the releases page and place it on your PATH.

Go install

Requires Go 1.24 or later.

go install github.com/cego/gitte@latest

Quick start

1. Create a .gitte.yml in your workspace root:

startup:
git-present:
type: commandcmd: ["git", "--version"]hint: "git is not installed"projects:
myservice:
remote: git@github.com:example/myservice.gitdefault_branch: mainactions:
start:
groups:
local: ["docker", "compose", "up", "-d"]stop:
groups:
local: ["docker", "compose", "down"]

2. Run the full pipeline:

gitte run start local

Gitte will run startup checks, pull all repos, then execute the start action for group local across all enabled projects.


Commands

Overview

CommandDescription
gitte run [action] [group] [projects]Full pipeline: startup checks → git sync → actions
gitte actions [action] [group] [projects]Run actions only (skip startup and git sync)
gitte startupRun startup checks only
gitte gitops [--discover]Clone/pull all repos; --discover also fetches from configured sources
gitte listList all projects and their available actions
gitte toggleInteractive TUI to enable/disable projects per machine
gitte clean <subcommand>Clean up repos (see below)
gitte features list|enable|disableManage feature gates
gitte sourcesManage discovery sources (GitLab groups / GitHub orgs)
gitte token set|get|delete|listStore API tokens in the system keyring
gitte validateValidate config: schema, cycles, missing references

Argument syntax

Arguments to run and actions are positional: action [group] [projects].

gitte run start # start action, all groups, all enabled projects
gitte run start local# start action, group local, all enabled projects
gitte run start local myservice # start action, group local, project myservice only
gitte run start local frontend+backend # start action, group local, projects frontend and backend
gitte run start+test # run start then test, all groups, all enabled projects

Use * or all as a wildcard. Combine multiple values with +.

gitte clean

Destructive cleanup operations across all configured repositories. Each subcommand shows a live progress TUI while running.

gitte clean untracked # remove untracked files (git clean -fdx)
gitte clean local-changes # reset repos with local changes (prompts before acting)
gitte clean master # checkout the default branch in all repos
gitte clean all # run all three in sequence

gitte clean local-changes lists affected repos and prompts:

Reset [a]ll / [i]ndividually / [C]ancel?

Configuration

See docs/config.md for the full configuration reference.


Environment variables

VariableDefaultDescription
GITTE_CWDprocess cwdOverride the working directory
GITTE_NO_TTY0Set to 1 to force plain-text output (no TUI)
GITTE_NO_NEEDS0Set to 1 to ignore needs dependencies
GITTE_NO_REBASEfalseSet to true to skip auto-rebase onto default branch
GITTE_MAX_TASK_PARALLELIZATIONunlimitedCap the number of concurrent tasks

Telemetry

Gitte can export OpenTelemetry traces to an OTLP/HTTP endpoint (e.g. Elastic APM) to help debug failures. Traces capture per-repo git context (branch, commit SHA, dirty state) and per-task outcomes with errors. To identify which developer and machine hit a failure, the OS username (user.name) and hostname (host.name) are attached to every trace.

What is recorded: the gitte CLI arguments and each action's command line are exported as span attributes (this is intentional — knowing what ran is the point). Note that gitte's injected environment — a project's env, env_when, and feature-gate env — is also exported on task spans (the gitte.env attribute) and in the task logs; the inherited process environment (everything in os.Environ) is not. So keep secrets out of action command definitions, CLI arguments, and config env/feature-gate blocks — pass real secrets through the process environment instead. Full remote URLs are never collected either (repos are identified by name only).

Each gitte run produces a structured trace: a root span with child spans for each phase (startup, gitops, actions), a span per startup check, a span per action (e.g. build, up) parenting its task spans, and a span per repo sync. Action and startup command output is also shipped as OTEL logs, correlated to the span that produced each line (stdout → INFO, stderr → WARN).

Logs are enabled with tracing; set GITTE_TELEMETRY_LOGS to off, false, or 0 to keep traces but disable the (higher-volume) log export. Keep secrets out of command output — log lines are exported verbatim.

Enable it via the shared config:

telemetry:
endpoint: https://apm.example.com:8200headers:
Authorization: "Bearer <secret-token>"# or: "ApiKey <base64-key>"

Environment variables:

VariableEffect
GITTE_TELEMETRY=off, false, or 0Disable telemetry locally (case-insensitive; surrounding whitespace is ignored)
GITTE_TELEMETRY_URLOverride the endpoint; whitespace is trimmed and https:// is added when no scheme is present
GITTE_TELEMETRY_LOGS=off, false, or 0Disable OTEL log export (keep traces; case-insensitive with surrounding whitespace ignored)
OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_HEADERSStandard OTEL env vars; endpoint vars are used when no gitte endpoint is set, and headers can provide credentials for a GITTE_TELEMETRY_URL override

Precedence: GITTE_TELEMETRY=off|false|0 > GITTE_TELEMETRY_URL > config endpoint > OTEL_EXPORTER_OTLP_*. Telemetry is best-effort and never blocks or slows gitte; export failures are silently ignored. When GITTE_TELEMETRY_URL overrides the config endpoint, config headers are not used; set OTEL_EXPORTER_OTLP_HEADERS to provide override-endpoint credentials through the OTEL exporter.


Global flags

--config <path> Path to .gitte.yml (default: auto-detected by walking up)
--cwd <path> Override working directory
--no-tty Force plain-text output

State and override files

.gitte-state.yml — stores per-machine state: project toggles, feature gate overrides, and remote config cache. Gitte automatically adds this file to .gitignore. Do not commit it.

.gitte-override.yml — deep-merged on top of .gitte.yml when present. Use this for local machine-specific settings that should not be committed (e.g. sources added via gitte sources add).

About

Developer environment orchestration — monorepo-like development across many git repositories, without the monorepo

Resources

Stars

14 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

gitte

license

Monorepo-like development across many git repositories — without the monorepo.

Gitte keeps all your repos in sync, runs startup checks to verify your local machine is ready, and executes ordered actions (build, up, down, …) across projects with dependency resolution and parallel execution.


Table of contents


Features

  • Startup checks — verify tools, versions, and credentials before doing anything
  • Git sync — clone and pull all configured repositories in parallel
  • Ordered actions — run commands across projects with needs-based dependency ordering and parallel execution
  • Project toggles — interactively enable/disable projects per machine
  • Template inheritance — share action definitions across similar projects
  • Feature gates — toggle environment-variable-based behaviours per machine
  • Auto-discovery — discover and sync repositories from GitLab groups or GitHub orgs
  • Clean operations — remove untracked files, reset local changes, or check out default branches across all repos
  • TTY-aware output — animated spinner TUI in a terminal, structured plain-text output in CI / non-TTY

Installation

APT (Debian and Ubuntu)

curl -fsSL https://gitte-apt.cego.dk/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/gitte.gpg
echo"deb [signed-by=/etc/apt/keyrings/gitte.gpg] https://gitte-apt.cego.dk ./"| sudo tee /etc/apt/sources.list.d/gitte.list
sudo apt update
sudo apt install gitte

Homebrew (macOS and Linux)

brew tap cego/gitte https://github.com/cego/gitte
brew install cego/gitte/gitte

Binary download

Download the latest binary from the releases page and place it on your PATH.

Go install

Requires Go 1.24 or later.

go install github.com/cego/gitte@latest

Quick start

1. Create a .gitte.yml in your workspace root:

startup:
git-present:
type: commandcmd: ["git", "--version"]hint: "git is not installed"projects:
myservice:
remote: git@github.com:example/myservice.gitdefault_branch: mainactions:
start:
groups:
local: ["docker", "compose", "up", "-d"]stop:
groups:
local: ["docker", "compose", "down"]

2. Run the full pipeline:

gitte run start local

Gitte will run startup checks, pull all repos, then execute the start action for group local across all enabled projects.


Commands

Overview

CommandDescription
gitte run [action] [group] [projects]Full pipeline: startup checks → git sync → actions
gitte actions [action] [group] [projects]Run actions only (skip startup and git sync)
gitte startupRun startup checks only
gitte gitops [--discover]Clone/pull all repos; --discover also fetches from configured sources
gitte listList all projects and their available actions
gitte toggleInteractive TUI to enable/disable projects per machine
gitte clean <subcommand>Clean up repos (see below)
gitte features list|enable|disableManage feature gates
gitte sourcesManage discovery sources (GitLab groups / GitHub orgs)
gitte token set|get|delete|listStore API tokens in the system keyring
gitte validateValidate config: schema, cycles, missing references

Argument syntax

Arguments to run and actions are positional: action [group] [projects].

gitte run start # start action, all groups, all enabled projects
gitte run start local# start action, group local, all enabled projects
gitte run start local myservice # start action, group local, project myservice only
gitte run start local frontend+backend # start action, group local, projects frontend and backend
gitte run start+test # run start then test, all groups, all enabled projects

Use * or all as a wildcard. Combine multiple values with +.

gitte clean

Destructive cleanup operations across all configured repositories. Each subcommand shows a live progress TUI while running.

gitte clean untracked # remove untracked files (git clean -fdx)
gitte clean local-changes # reset repos with local changes (prompts before acting)
gitte clean master # checkout the default branch in all repos
gitte clean all # run all three in sequence

gitte clean local-changes lists affected repos and prompts:

Reset [a]ll / [i]ndividually / [C]ancel?

Configuration

See docs/config.md for the full configuration reference.


Environment variables

VariableDefaultDescription
GITTE_CWDprocess cwdOverride the working directory
GITTE_NO_TTY0Set to 1 to force plain-text output (no TUI)
GITTE_NO_NEEDS0Set to 1 to ignore needs dependencies
GITTE_NO_REBASEfalseSet to true to skip auto-rebase onto default branch
GITTE_MAX_TASK_PARALLELIZATIONunlimitedCap the number of concurrent tasks

Telemetry

Gitte can export OpenTelemetry traces to an OTLP/HTTP endpoint (e.g. Elastic APM) to help debug failures. Traces capture per-repo git context (branch, commit SHA, dirty state) and per-task outcomes with errors. To identify which developer and machine hit a failure, the OS username (user.name) and hostname (host.name) are attached to every trace.

What is recorded: the gitte CLI arguments and each action's command line are exported as span attributes (this is intentional — knowing what ran is the point). Note that gitte's injected environment — a project's env, env_when, and feature-gate env — is also exported on task spans (the gitte.env attribute) and in the task logs; the inherited process environment (everything in os.Environ) is not. So keep secrets out of action command definitions, CLI arguments, and config env/feature-gate blocks — pass real secrets through the process environment instead. Full remote URLs are never collected either (repos are identified by name only).

Each gitte run produces a structured trace: a root span with child spans for each phase (startup, gitops, actions), a span per startup check, a span per action (e.g. build, up) parenting its task spans, and a span per repo sync. Action and startup command output is also shipped as OTEL logs, correlated to the span that produced each line (stdout → INFO, stderr → WARN).

Logs are enabled with tracing; set GITTE_TELEMETRY_LOGS to off, false, or 0 to keep traces but disable the (higher-volume) log export. Keep secrets out of command output — log lines are exported verbatim.

Enable it via the shared config:

telemetry:
endpoint: https://apm.example.com:8200headers:
Authorization: "Bearer <secret-token>"# or: "ApiKey <base64-key>"

Environment variables:

VariableEffect
GITTE_TELEMETRY=off, false, or 0Disable telemetry locally (case-insensitive; surrounding whitespace is ignored)
GITTE_TELEMETRY_URLOverride the endpoint; whitespace is trimmed and https:// is added when no scheme is present
GITTE_TELEMETRY_LOGS=off, false, or 0Disable OTEL log export (keep traces; case-insensitive with surrounding whitespace ignored)
OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_HEADERSStandard OTEL env vars; endpoint vars are used when no gitte endpoint is set, and headers can provide credentials for a GITTE_TELEMETRY_URL override

Precedence: GITTE_TELEMETRY=off|false|0 > GITTE_TELEMETRY_URL > config endpoint > OTEL_EXPORTER_OTLP_*. Telemetry is best-effort and never blocks or slows gitte; export failures are silently ignored. When GITTE_TELEMETRY_URL overrides the config endpoint, config headers are not used; set OTEL_EXPORTER_OTLP_HEADERS to provide override-endpoint credentials through the OTEL exporter.


Global flags

--config <path> Path to .gitte.yml (default: auto-detected by walking up)
--cwd <path> Override working directory
--no-tty Force plain-text output

State and override files

.gitte-state.yml — stores per-machine state: project toggles, feature gate overrides, and remote config cache. Gitte automatically adds this file to .gitignore. Do not commit it.

.gitte-override.yml — deep-merged on top of .gitte.yml when present. Use this for local machine-specific settings that should not be committed (e.g. sources added via gitte sources add).

About

Developer environment orchestration — monorepo-like development across many git repositories, without the monorepo

Resources

Stars

14 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

gitte

license

Monorepo-like development across many git repositories — without the monorepo.

Gitte keeps all your repos in sync, runs startup checks to verify your local machine is ready, and executes ordered actions (build, up, down, …) across projects with dependency resolution and parallel execution.


Table of contents


Features

  • Startup checks — verify tools, versions, and credentials before doing anything
  • Git sync — clone and pull all configured repositories in parallel
  • Ordered actions — run commands across projects with needs-based dependency ordering and parallel execution
  • Project toggles — interactively enable/disable projects per machine
  • Template inheritance — share action definitions across similar projects
  • Feature gates — toggle environment-variable-based behaviours per machine
  • Auto-discovery — discover and sync repositories from GitLab groups or GitHub orgs
  • Clean operations — remove untracked files, reset local changes, or check out default branches across all repos
  • TTY-aware output — animated spinner TUI in a terminal, structured plain-text output in CI / non-TTY

Installation

APT (Debian and Ubuntu)

curl -fsSL https://gitte-apt.cego.dk/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/gitte.gpg
echo"deb [signed-by=/etc/apt/keyrings/gitte.gpg] https://gitte-apt.cego.dk ./"| sudo tee /etc/apt/sources.list.d/gitte.list
sudo apt update
sudo apt install gitte

Homebrew (macOS and Linux)

brew tap cego/gitte https://github.com/cego/gitte
brew install cego/gitte/gitte

Binary download

Download the latest binary from the releases page and place it on your PATH.

Go install

Requires Go 1.24 or later.

go install github.com/cego/gitte@latest

Quick start

1. Create a .gitte.yml in your workspace root:

startup:
git-present:
type: commandcmd: ["git", "--version"]hint: "git is not installed"projects:
myservice:
remote: git@github.com:example/myservice.gitdefault_branch: mainactions:
start:
groups:
local: ["docker", "compose", "up", "-d"]stop:
groups:
local: ["docker", "compose", "down"]

2. Run the full pipeline:

gitte run start local

Gitte will run startup checks, pull all repos, then execute the start action for group local across all enabled projects.


Commands

Overview

CommandDescription
gitte run [action] [group] [projects]Full pipeline: startup checks → git sync → actions
gitte actions [action] [group] [projects]Run actions only (skip startup and git sync)
gitte startupRun startup checks only
gitte gitops [--discover]Clone/pull all repos; --discover also fetches from configured sources
gitte listList all projects and their available actions
gitte toggleInteractive TUI to enable/disable projects per machine
gitte clean <subcommand>Clean up repos (see below)
gitte features list|enable|disableManage feature gates
gitte sourcesManage discovery sources (GitLab groups / GitHub orgs)
gitte token set|get|delete|listStore API tokens in the system keyring
gitte validateValidate config: schema, cycles, missing references

Argument syntax

Arguments to run and actions are positional: action [group] [projects].

gitte run start # start action, all groups, all enabled projects
gitte run start local# start action, group local, all enabled projects
gitte run start local myservice # start action, group local, project myservice only
gitte run start local frontend+backend # start action, group local, projects frontend and backend
gitte run start+test # run start then test, all groups, all enabled projects

Use * or all as a wildcard. Combine multiple values with +.

gitte clean

Destructive cleanup operations across all configured repositories. Each subcommand shows a live progress TUI while running.

gitte clean untracked # remove untracked files (git clean -fdx)
gitte clean local-changes # reset repos with local changes (prompts before acting)
gitte clean master # checkout the default branch in all repos
gitte clean all # run all three in sequence

gitte clean local-changes lists affected repos and prompts:

Reset [a]ll / [i]ndividually / [C]ancel?

Configuration

See docs/config.md for the full configuration reference.


Environment variables

VariableDefaultDescription
GITTE_CWDprocess cwdOverride the working directory
GITTE_NO_TTY0Set to 1 to force plain-text output (no TUI)
GITTE_NO_NEEDS0Set to 1 to ignore needs dependencies
GITTE_NO_REBASEfalseSet to true to skip auto-rebase onto default branch
GITTE_MAX_TASK_PARALLELIZATIONunlimitedCap the number of concurrent tasks

Telemetry

Gitte can export OpenTelemetry traces to an OTLP/HTTP endpoint (e.g. Elastic APM) to help debug failures. Traces capture per-repo git context (branch, commit SHA, dirty state) and per-task outcomes with errors. To identify which developer and machine hit a failure, the OS username (user.name) and hostname (host.name) are attached to every trace.

What is recorded: the gitte CLI arguments and each action's command line are exported as span attributes (this is intentional — knowing what ran is the point). Note that gitte's injected environment — a project's env, env_when, and feature-gate env — is also exported on task spans (the gitte.env attribute) and in the task logs; the inherited process environment (everything in os.Environ) is not. So keep secrets out of action command definitions, CLI arguments, and config env/feature-gate blocks — pass real secrets through the process environment instead. Full remote URLs are never collected either (repos are identified by name only).

Each gitte run produces a structured trace: a root span with child spans for each phase (startup, gitops, actions), a span per startup check, a span per action (e.g. build, up) parenting its task spans, and a span per repo sync. Action and startup command output is also shipped as OTEL logs, correlated to the span that produced each line (stdout → INFO, stderr → WARN).

Logs are enabled with tracing; set GITTE_TELEMETRY_LOGS to off, false, or 0 to keep traces but disable the (higher-volume) log export. Keep secrets out of command output — log lines are exported verbatim.

Enable it via the shared config:

telemetry:
endpoint: https://apm.example.com:8200headers:
Authorization: "Bearer <secret-token>"# or: "ApiKey <base64-key>"

Environment variables:

VariableEffect
GITTE_TELEMETRY=off, false, or 0Disable telemetry locally (case-insensitive; surrounding whitespace is ignored)
GITTE_TELEMETRY_URLOverride the endpoint; whitespace is trimmed and https:// is added when no scheme is present
GITTE_TELEMETRY_LOGS=off, false, or 0Disable OTEL log export (keep traces; case-insensitive with surrounding whitespace ignored)
OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_HEADERSStandard OTEL env vars; endpoint vars are used when no gitte endpoint is set, and headers can provide credentials for a GITTE_TELEMETRY_URL override

Precedence: GITTE_TELEMETRY=off|false|0 > GITTE_TELEMETRY_URL > config endpoint > OTEL_EXPORTER_OTLP_*. Telemetry is best-effort and never blocks or slows gitte; export failures are silently ignored. When GITTE_TELEMETRY_URL overrides the config endpoint, config headers are not used; set OTEL_EXPORTER_OTLP_HEADERS to provide override-endpoint credentials through the OTEL exporter.


Global flags

--config <path> Path to .gitte.yml (default: auto-detected by walking up)
--cwd <path> Override working directory
--no-tty Force plain-text output

State and override files

.gitte-state.yml — stores per-machine state: project toggles, feature gate overrides, and remote config cache. Gitte automatically adds this file to .gitignore. Do not commit it.

.gitte-override.yml — deep-merged on top of .gitte.yml when present. Use this for local machine-specific settings that should not be committed (e.g. sources added via gitte sources add).

About

Developer environment orchestration — monorepo-like development across many git repositories, without the monorepo

Resources

Stars

14 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

gitte

license

Monorepo-like development across many git repositories — without the monorepo.

Gitte keeps all your repos in sync, runs startup checks to verify your local machine is ready, and executes ordered actions (build, up, down, …) across projects with dependency resolution and parallel execution.


Table of contents


Features

  • Startup checks — verify tools, versions, and credentials before doing anything
  • Git sync — clone and pull all configured repositories in parallel
  • Ordered actions — run commands across projects with needs-based dependency ordering and parallel execution
  • Project toggles — interactively enable/disable projects per machine
  • Template inheritance — share action definitions across similar projects
  • Feature gates — toggle environment-variable-based behaviours per machine
  • Auto-discovery — discover and sync repositories from GitLab groups or GitHub orgs
  • Clean operations — remove untracked files, reset local changes, or check out default branches across all repos
  • TTY-aware output — animated spinner TUI in a terminal, structured plain-text output in CI / non-TTY

Installation

APT (Debian and Ubuntu)

curl -fsSL https://gitte-apt.cego.dk/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/gitte.gpg
echo"deb [signed-by=/etc/apt/keyrings/gitte.gpg] https://gitte-apt.cego.dk ./"| sudo tee /etc/apt/sources.list.d/gitte.list
sudo apt update
sudo apt install gitte

Homebrew (macOS and Linux)

brew tap cego/gitte https://github.com/cego/gitte
brew install cego/gitte/gitte

Binary download

Download the latest binary from the releases page and place it on your PATH.

Go install

Requires Go 1.24 or later.

go install github.com/cego/gitte@latest

Quick start

1. Create a .gitte.yml in your workspace root:

startup:
git-present:
type: commandcmd: ["git", "--version"]hint: "git is not installed"projects:
myservice:
remote: git@github.com:example/myservice.gitdefault_branch: mainactions:
start:
groups:
local: ["docker", "compose", "up", "-d"]stop:
groups:
local: ["docker", "compose", "down"]

2. Run the full pipeline:

gitte run start local

Gitte will run startup checks, pull all repos, then execute the start action for group local across all enabled projects.


Commands

Overview

CommandDescription
gitte run [action] [group] [projects]Full pipeline: startup checks → git sync → actions
gitte actions [action] [group] [projects]Run actions only (skip startup and git sync)
gitte startupRun startup checks only
gitte gitops [--discover]Clone/pull all repos; --discover also fetches from configured sources
gitte listList all projects and their available actions
gitte toggleInteractive TUI to enable/disable projects per machine
gitte clean <subcommand>Clean up repos (see below)
gitte features list|enable|disableManage feature gates
gitte sourcesManage discovery sources (GitLab groups / GitHub orgs)
gitte token set|get|delete|listStore API tokens in the system keyring
gitte validateValidate config: schema, cycles, missing references

Argument syntax

Arguments to run and actions are positional: action [group] [projects].

gitte run start # start action, all groups, all enabled projects
gitte run start local# start action, group local, all enabled projects
gitte run start local myservice # start action, group local, project myservice only
gitte run start local frontend+backend # start action, group local, projects frontend and backend
gitte run start+test # run start then test, all groups, all enabled projects

Use * or all as a wildcard. Combine multiple values with +.

gitte clean

Destructive cleanup operations across all configured repositories. Each subcommand shows a live progress TUI while running.

gitte clean untracked # remove untracked files (git clean -fdx)
gitte clean local-changes # reset repos with local changes (prompts before acting)
gitte clean master # checkout the default branch in all repos
gitte clean all # run all three in sequence

gitte clean local-changes lists affected repos and prompts:

Reset [a]ll / [i]ndividually / [C]ancel?

Configuration

See docs/config.md for the full configuration reference.


Environment variables

VariableDefaultDescription
GITTE_CWDprocess cwdOverride the working directory
GITTE_NO_TTY0Set to 1 to force plain-text output (no TUI)
GITTE_NO_NEEDS0Set to 1 to ignore needs dependencies
GITTE_NO_REBASEfalseSet to true to skip auto-rebase onto default branch
GITTE_MAX_TASK_PARALLELIZATIONunlimitedCap the number of concurrent tasks

Telemetry

Gitte can export OpenTelemetry traces to an OTLP/HTTP endpoint (e.g. Elastic APM) to help debug failures. Traces capture per-repo git context (branch, commit SHA, dirty state) and per-task outcomes with errors. To identify which developer and machine hit a failure, the OS username (user.name) and hostname (host.name) are attached to every trace.

What is recorded: the gitte CLI arguments and each action's command line are exported as span attributes (this is intentional — knowing what ran is the point). Note that gitte's injected environment — a project's env, env_when, and feature-gate env — is also exported on task spans (the gitte.env attribute) and in the task logs; the inherited process environment (everything in os.Environ) is not. So keep secrets out of action command definitions, CLI arguments, and config env/feature-gate blocks — pass real secrets through the process environment instead. Full remote URLs are never collected either (repos are identified by name only).

Each gitte run produces a structured trace: a root span with child spans for each phase (startup, gitops, actions), a span per startup check, a span per action (e.g. build, up) parenting its task spans, and a span per repo sync. Action and startup command output is also shipped as OTEL logs, correlated to the span that produced each line (stdout → INFO, stderr → WARN).

Logs are enabled with tracing; set GITTE_TELEMETRY_LOGS to off, false, or 0 to keep traces but disable the (higher-volume) log export. Keep secrets out of command output — log lines are exported verbatim.

Enable it via the shared config:

telemetry:
endpoint: https://apm.example.com:8200headers:
Authorization: "Bearer <secret-token>"# or: "ApiKey <base64-key>"

Environment variables:

VariableEffect
GITTE_TELEMETRY=off, false, or 0Disable telemetry locally (case-insensitive; surrounding whitespace is ignored)
GITTE_TELEMETRY_URLOverride the endpoint; whitespace is trimmed and https:// is added when no scheme is present
GITTE_TELEMETRY_LOGS=off, false, or 0Disable OTEL log export (keep traces; case-insensitive with surrounding whitespace ignored)
OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_HEADERSStandard OTEL env vars; endpoint vars are used when no gitte endpoint is set, and headers can provide credentials for a GITTE_TELEMETRY_URL override

Precedence: GITTE_TELEMETRY=off|false|0 > GITTE_TELEMETRY_URL > config endpoint > OTEL_EXPORTER_OTLP_*. Telemetry is best-effort and never blocks or slows gitte; export failures are silently ignored. When GITTE_TELEMETRY_URL overrides the config endpoint, config headers are not used; set OTEL_EXPORTER_OTLP_HEADERS to provide override-endpoint credentials through the OTEL exporter.


Global flags

--config <path> Path to .gitte.yml (default: auto-detected by walking up)
--cwd <path> Override working directory
--no-tty Force plain-text output

State and override files

.gitte-state.yml — stores per-machine state: project toggles, feature gate overrides, and remote config cache. Gitte automatically adds this file to .gitignore. Do not commit it.

.gitte-override.yml — deep-merged on top of .gitte.yml when present. Use this for local machine-specific settings that should not be committed (e.g. sources added via gitte sources add).

About

Developer environment orchestration — monorepo-like development across many git repositories, without the monorepo

Resources

Stars

14 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

gitte

license

Monorepo-like development across many git repositories — without the monorepo.

Gitte keeps all your repos in sync, runs startup checks to verify your local machine is ready, and executes ordered actions (build, up, down, …) across projects with dependency resolution and parallel execution.


Table of contents


Features

  • Startup checks — verify tools, versions, and credentials before doing anything
  • Git sync — clone and pull all configured repositories in parallel
  • Ordered actions — run commands across projects with needs-based dependency ordering and parallel execution
  • Project toggles — interactively enable/disable projects per machine
  • Template inheritance — share action definitions across similar projects
  • Feature gates — toggle environment-variable-based behaviours per machine
  • Auto-discovery — discover and sync repositories from GitLab groups or GitHub orgs
  • Clean operations — remove untracked files, reset local changes, or check out default branches across all repos
  • TTY-aware output — animated spinner TUI in a terminal, structured plain-text output in CI / non-TTY

Installation

APT (Debian and Ubuntu)

curl -fsSL https://gitte-apt.cego.dk/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/gitte.gpg
echo"deb [signed-by=/etc/apt/keyrings/gitte.gpg] https://gitte-apt.cego.dk ./"| sudo tee /etc/apt/sources.list.d/gitte.list
sudo apt update
sudo apt install gitte

Homebrew (macOS and Linux)

brew tap cego/gitte https://github.com/cego/gitte
brew install cego/gitte/gitte

Binary download

Download the latest binary from the releases page and place it on your PATH.

Go install

Requires Go 1.24 or later.

go install github.com/cego/gitte@latest

Quick start

1. Create a .gitte.yml in your workspace root:

startup:
git-present:
type: commandcmd: ["git", "--version"]hint: "git is not installed"projects:
myservice:
remote: git@github.com:example/myservice.gitdefault_branch: mainactions:
start:
groups:
local: ["docker", "compose", "up", "-d"]stop:
groups:
local: ["docker", "compose", "down"]

2. Run the full pipeline:

gitte run start local

Gitte will run startup checks, pull all repos, then execute the start action for group local across all enabled projects.


Commands

Overview

CommandDescription
gitte run [action] [group] [projects]Full pipeline: startup checks → git sync → actions
gitte actions [action] [group] [projects]Run actions only (skip startup and git sync)
gitte startupRun startup checks only
gitte gitops [--discover]Clone/pull all repos; --discover also fetches from configured sources
gitte listList all projects and their available actions
gitte toggleInteractive TUI to enable/disable projects per machine
gitte clean <subcommand>Clean up repos (see below)
gitte features list|enable|disableManage feature gates
gitte sourcesManage discovery sources (GitLab groups / GitHub orgs)
gitte token set|get|delete|listStore API tokens in the system keyring
gitte validateValidate config: schema, cycles, missing references

Argument syntax

Arguments to run and actions are positional: action [group] [projects].

gitte run start # start action, all groups, all enabled projects
gitte run start local# start action, group local, all enabled projects
gitte run start local myservice # start action, group local, project myservice only
gitte run start local frontend+backend # start action, group local, projects frontend and backend
gitte run start+test # run start then test, all groups, all enabled projects

Use * or all as a wildcard. Combine multiple values with +.

gitte clean

Destructive cleanup operations across all configured repositories. Each subcommand shows a live progress TUI while running.

gitte clean untracked # remove untracked files (git clean -fdx)
gitte clean local-changes # reset repos with local changes (prompts before acting)
gitte clean master # checkout the default branch in all repos
gitte clean all # run all three in sequence

gitte clean local-changes lists affected repos and prompts:

Reset [a]ll / [i]ndividually / [C]ancel?

Configuration

See docs/config.md for the full configuration reference.


Environment variables

VariableDefaultDescription
GITTE_CWDprocess cwdOverride the working directory
GITTE_NO_TTY0Set to 1 to force plain-text output (no TUI)
GITTE_NO_NEEDS0Set to 1 to ignore needs dependencies
GITTE_NO_REBASEfalseSet to true to skip auto-rebase onto default branch
GITTE_MAX_TASK_PARALLELIZATIONunlimitedCap the number of concurrent tasks

Telemetry

Gitte can export OpenTelemetry traces to an OTLP/HTTP endpoint (e.g. Elastic APM) to help debug failures. Traces capture per-repo git context (branch, commit SHA, dirty state) and per-task outcomes with errors. To identify which developer and machine hit a failure, the OS username (user.name) and hostname (host.name) are attached to every trace.

What is recorded: the gitte CLI arguments and each action's command line are exported as span attributes (this is intentional — knowing what ran is the point). Note that gitte's injected environment — a project's env, env_when, and feature-gate env — is also exported on task spans (the gitte.env attribute) and in the task logs; the inherited process environment (everything in os.Environ) is not. So keep secrets out of action command definitions, CLI arguments, and config env/feature-gate blocks — pass real secrets through the process environment instead. Full remote URLs are never collected either (repos are identified by name only).

Each gitte run produces a structured trace: a root span with child spans for each phase (startup, gitops, actions), a span per startup check, a span per action (e.g. build, up) parenting its task spans, and a span per repo sync. Action and startup command output is also shipped as OTEL logs, correlated to the span that produced each line (stdout → INFO, stderr → WARN).

Logs are enabled with tracing; set GITTE_TELEMETRY_LOGS to off, false, or 0 to keep traces but disable the (higher-volume) log export. Keep secrets out of command output — log lines are exported verbatim.

Enable it via the shared config:

telemetry:
endpoint: https://apm.example.com:8200headers:
Authorization: "Bearer <secret-token>"# or: "ApiKey <base64-key>"

Environment variables:

VariableEffect
GITTE_TELEMETRY=off, false, or 0Disable telemetry locally (case-insensitive; surrounding whitespace is ignored)
GITTE_TELEMETRY_URLOverride the endpoint; whitespace is trimmed and https:// is added when no scheme is present
GITTE_TELEMETRY_LOGS=off, false, or 0Disable OTEL log export (keep traces; case-insensitive with surrounding whitespace ignored)
OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_HEADERSStandard OTEL env vars; endpoint vars are used when no gitte endpoint is set, and headers can provide credentials for a GITTE_TELEMETRY_URL override

Precedence: GITTE_TELEMETRY=off|false|0 > GITTE_TELEMETRY_URL > config endpoint > OTEL_EXPORTER_OTLP_*. Telemetry is best-effort and never blocks or slows gitte; export failures are silently ignored. When GITTE_TELEMETRY_URL overrides the config endpoint, config headers are not used; set OTEL_EXPORTER_OTLP_HEADERS to provide override-endpoint credentials through the OTEL exporter.


Global flags

--config <path> Path to .gitte.yml (default: auto-detected by walking up)
--cwd <path> Override working directory
--no-tty Force plain-text output

State and override files

.gitte-state.yml — stores per-machine state: project toggles, feature gate overrides, and remote config cache. Gitte automatically adds this file to .gitignore. Do not commit it.

.gitte-override.yml — deep-merged on top of .gitte.yml when present. Use this for local machine-specific settings that should not be committed (e.g. sources added via gitte sources add).

About

Developer environment orchestration — monorepo-like development across many git repositories, without the monorepo

Resources

Stars

14 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

gitte

license

Monorepo-like development across many git repositories — without the monorepo.

Gitte keeps all your repos in sync, runs startup checks to verify your local machine is ready, and executes ordered actions (build, up, down, …) across projects with dependency resolution and parallel execution.


Table of contents


Features

  • Startup checks — verify tools, versions, and credentials before doing anything
  • Git sync — clone and pull all configured repositories in parallel
  • Ordered actions — run commands across projects with needs-based dependency ordering and parallel execution
  • Project toggles — interactively enable/disable projects per machine
  • Template inheritance — share action definitions across similar projects
  • Feature gates — toggle environment-variable-based behaviours per machine
  • Auto-discovery — discover and sync repositories from GitLab groups or GitHub orgs
  • Clean operations — remove untracked files, reset local changes, or check out default branches across all repos
  • TTY-aware output — animated spinner TUI in a terminal, structured plain-text output in CI / non-TTY

Installation

APT (Debian and Ubuntu)

curl -fsSL https://gitte-apt.cego.dk/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/gitte.gpg
echo"deb [signed-by=/etc/apt/keyrings/gitte.gpg] https://gitte-apt.cego.dk ./"| sudo tee /etc/apt/sources.list.d/gitte.list
sudo apt update
sudo apt install gitte

Homebrew (macOS and Linux)

brew tap cego/gitte https://github.com/cego/gitte
brew install cego/gitte/gitte

Binary download

Download the latest binary from the releases page and place it on your PATH.

Go install

Requires Go 1.24 or later.

go install github.com/cego/gitte@latest

Quick start

1. Create a .gitte.yml in your workspace root:

startup:
git-present:
type: commandcmd: ["git", "--version"]hint: "git is not installed"projects:
myservice:
remote: git@github.com:example/myservice.gitdefault_branch: mainactions:
start:
groups:
local: ["docker", "compose", "up", "-d"]stop:
groups:
local: ["docker", "compose", "down"]

2. Run the full pipeline:

gitte run start local

Gitte will run startup checks, pull all repos, then execute the start action for group local across all enabled projects.


Commands

Overview

CommandDescription
gitte run [action] [group] [projects]Full pipeline: startup checks → git sync → actions
gitte actions [action] [group] [projects]Run actions only (skip startup and git sync)
gitte startupRun startup checks only
gitte gitops [--discover]Clone/pull all repos; --discover also fetches from configured sources
gitte listList all projects and their available actions
gitte toggleInteractive TUI to enable/disable projects per machine
gitte clean <subcommand>Clean up repos (see below)
gitte features list|enable|disableManage feature gates
gitte sourcesManage discovery sources (GitLab groups / GitHub orgs)
gitte token set|get|delete|listStore API tokens in the system keyring
gitte validateValidate config: schema, cycles, missing references

Argument syntax

Arguments to run and actions are positional: action [group] [projects].

gitte run start # start action, all groups, all enabled projects
gitte run start local# start action, group local, all enabled projects
gitte run start local myservice # start action, group local, project myservice only
gitte run start local frontend+backend # start action, group local, projects frontend and backend
gitte run start+test # run start then test, all groups, all enabled projects

Use * or all as a wildcard. Combine multiple values with +.

gitte clean

Destructive cleanup operations across all configured repositories. Each subcommand shows a live progress TUI while running.

gitte clean untracked # remove untracked files (git clean -fdx)
gitte clean local-changes # reset repos with local changes (prompts before acting)
gitte clean master # checkout the default branch in all repos
gitte clean all # run all three in sequence

gitte clean local-changes lists affected repos and prompts:

Reset [a]ll / [i]ndividually / [C]ancel?

Configuration

See docs/config.md for the full configuration reference.


Environment variables

VariableDefaultDescription
GITTE_CWDprocess cwdOverride the working directory
GITTE_NO_TTY0Set to 1 to force plain-text output (no TUI)
GITTE_NO_NEEDS0Set to 1 to ignore needs dependencies
GITTE_NO_REBASEfalseSet to true to skip auto-rebase onto default branch
GITTE_MAX_TASK_PARALLELIZATIONunlimitedCap the number of concurrent tasks

Telemetry

Gitte can export OpenTelemetry traces to an OTLP/HTTP endpoint (e.g. Elastic APM) to help debug failures. Traces capture per-repo git context (branch, commit SHA, dirty state) and per-task outcomes with errors. To identify which developer and machine hit a failure, the OS username (user.name) and hostname (host.name) are attached to every trace.

What is recorded: the gitte CLI arguments and each action's command line are exported as span attributes (this is intentional — knowing what ran is the point). Note that gitte's injected environment — a project's env, env_when, and feature-gate env — is also exported on task spans (the gitte.env attribute) and in the task logs; the inherited process environment (everything in os.Environ) is not. So keep secrets out of action command definitions, CLI arguments, and config env/feature-gate blocks — pass real secrets through the process environment instead. Full remote URLs are never collected either (repos are identified by name only).

Each gitte run produces a structured trace: a root span with child spans for each phase (startup, gitops, actions), a span per startup check, a span per action (e.g. build, up) parenting its task spans, and a span per repo sync. Action and startup command output is also shipped as OTEL logs, correlated to the span that produced each line (stdout → INFO, stderr → WARN).

Logs are enabled with tracing; set GITTE_TELEMETRY_LOGS to off, false, or 0 to keep traces but disable the (higher-volume) log export. Keep secrets out of command output — log lines are exported verbatim.

Enable it via the shared config:

telemetry:
endpoint: https://apm.example.com:8200headers:
Authorization: "Bearer <secret-token>"# or: "ApiKey <base64-key>"

Environment variables:

VariableEffect
GITTE_TELEMETRY=off, false, or 0Disable telemetry locally (case-insensitive; surrounding whitespace is ignored)
GITTE_TELEMETRY_URLOverride the endpoint; whitespace is trimmed and https:// is added when no scheme is present
GITTE_TELEMETRY_LOGS=off, false, or 0Disable OTEL log export (keep traces; case-insensitive with surrounding whitespace ignored)
OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_HEADERSStandard OTEL env vars; endpoint vars are used when no gitte endpoint is set, and headers can provide credentials for a GITTE_TELEMETRY_URL override

Precedence: GITTE_TELEMETRY=off|false|0 > GITTE_TELEMETRY_URL > config endpoint > OTEL_EXPORTER_OTLP_*. Telemetry is best-effort and never blocks or slows gitte; export failures are silently ignored. When GITTE_TELEMETRY_URL overrides the config endpoint, config headers are not used; set OTEL_EXPORTER_OTLP_HEADERS to provide override-endpoint credentials through the OTEL exporter.


Global flags

--config <path> Path to .gitte.yml (default: auto-detected by walking up)
--cwd <path> Override working directory
--no-tty Force plain-text output

State and override files

.gitte-state.yml — stores per-machine state: project toggles, feature gate overrides, and remote config cache. Gitte automatically adds this file to .gitignore. Do not commit it.

.gitte-override.yml — deep-merged on top of .gitte.yml when present. Use this for local machine-specific settings that should not be committed (e.g. sources added via gitte sources add).

About

Developer environment orchestration — monorepo-like development across many git repositories, without the monorepo

Resources

Stars

14 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

gitte

license

Monorepo-like development across many git repositories — without the monorepo.

Gitte keeps all your repos in sync, runs startup checks to verify your local machine is ready, and executes ordered actions (build, up, down, …) across projects with dependency resolution and parallel execution.


Table of contents


Features

  • Startup checks — verify tools, versions, and credentials before doing anything
  • Git sync — clone and pull all configured repositories in parallel
  • Ordered actions — run commands across projects with needs-based dependency ordering and parallel execution
  • Project toggles — interactively enable/disable projects per machine
  • Template inheritance — share action definitions across similar projects
  • Feature gates — toggle environment-variable-based behaviours per machine
  • Auto-discovery — discover and sync repositories from GitLab groups or GitHub orgs
  • Clean operations — remove untracked files, reset local changes, or check out default branches across all repos
  • TTY-aware output — animated spinner TUI in a terminal, structured plain-text output in CI / non-TTY

Installation

APT (Debian and Ubuntu)

curl -fsSL https://gitte-apt.cego.dk/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/gitte.gpg
echo"deb [signed-by=/etc/apt/keyrings/gitte.gpg] https://gitte-apt.cego.dk ./"| sudo tee /etc/apt/sources.list.d/gitte.list
sudo apt update
sudo apt install gitte

Homebrew (macOS and Linux)

brew tap cego/gitte https://github.com/cego/gitte
brew install cego/gitte/gitte

Binary download

Download the latest binary from the releases page and place it on your PATH.

Go install

Requires Go 1.24 or later.

go install github.com/cego/gitte@latest

Quick start

1. Create a .gitte.yml in your workspace root:

startup:
git-present:
type: commandcmd: ["git", "--version"]hint: "git is not installed"projects:
myservice:
remote: git@github.com:example/myservice.gitdefault_branch: mainactions:
start:
groups:
local: ["docker", "compose", "up", "-d"]stop:
groups:
local: ["docker", "compose", "down"]

2. Run the full pipeline:

gitte run start local

Gitte will run startup checks, pull all repos, then execute the start action for group local across all enabled projects.


Commands

Overview

CommandDescription
gitte run [action] [group] [projects]Full pipeline: startup checks → git sync → actions
gitte actions [action] [group] [projects]Run actions only (skip startup and git sync)
gitte startupRun startup checks only
gitte gitops [--discover]Clone/pull all repos; --discover also fetches from configured sources
gitte listList all projects and their available actions
gitte toggleInteractive TUI to enable/disable projects per machine
gitte clean <subcommand>Clean up repos (see below)
gitte features list|enable|disableManage feature gates
gitte sourcesManage discovery sources (GitLab groups / GitHub orgs)
gitte token set|get|delete|listStore API tokens in the system keyring
gitte validateValidate config: schema, cycles, missing references

Argument syntax

Arguments to run and actions are positional: action [group] [projects].

gitte run start # start action, all groups, all enabled projects
gitte run start local# start action, group local, all enabled projects
gitte run start local myservice # start action, group local, project myservice only
gitte run start local frontend+backend # start action, group local, projects frontend and backend
gitte run start+test # run start then test, all groups, all enabled projects

Use * or all as a wildcard. Combine multiple values with +.

gitte clean

Destructive cleanup operations across all configured repositories. Each subcommand shows a live progress TUI while running.

gitte clean untracked # remove untracked files (git clean -fdx)
gitte clean local-changes # reset repos with local changes (prompts before acting)
gitte clean master # checkout the default branch in all repos
gitte clean all # run all three in sequence

gitte clean local-changes lists affected repos and prompts:

Reset [a]ll / [i]ndividually / [C]ancel?

Configuration

See docs/config.md for the full configuration reference.


Environment variables

VariableDefaultDescription
GITTE_CWDprocess cwdOverride the working directory
GITTE_NO_TTY0Set to 1 to force plain-text output (no TUI)
GITTE_NO_NEEDS0Set to 1 to ignore needs dependencies
GITTE_NO_REBASEfalseSet to true to skip auto-rebase onto default branch
GITTE_MAX_TASK_PARALLELIZATIONunlimitedCap the number of concurrent tasks

Telemetry

Gitte can export OpenTelemetry traces to an OTLP/HTTP endpoint (e.g. Elastic APM) to help debug failures. Traces capture per-repo git context (branch, commit SHA, dirty state) and per-task outcomes with errors. To identify which developer and machine hit a failure, the OS username (user.name) and hostname (host.name) are attached to every trace.

What is recorded: the gitte CLI arguments and each action's command line are exported as span attributes (this is intentional — knowing what ran is the point). Note that gitte's injected environment — a project's env, env_when, and feature-gate env — is also exported on task spans (the gitte.env attribute) and in the task logs; the inherited process environment (everything in os.Environ) is not. So keep secrets out of action command definitions, CLI arguments, and config env/feature-gate blocks — pass real secrets through the process environment instead. Full remote URLs are never collected either (repos are identified by name only).

Each gitte run produces a structured trace: a root span with child spans for each phase (startup, gitops, actions), a span per startup check, a span per action (e.g. build, up) parenting its task spans, and a span per repo sync. Action and startup command output is also shipped as OTEL logs, correlated to the span that produced each line (stdout → INFO, stderr → WARN).

Logs are enabled with tracing; set GITTE_TELEMETRY_LOGS to off, false, or 0 to keep traces but disable the (higher-volume) log export. Keep secrets out of command output — log lines are exported verbatim.

Enable it via the shared config:

telemetry:
endpoint: https://apm.example.com:8200headers:
Authorization: "Bearer <secret-token>"# or: "ApiKey <base64-key>"

Environment variables:

VariableEffect
GITTE_TELEMETRY=off, false, or 0Disable telemetry locally (case-insensitive; surrounding whitespace is ignored)
GITTE_TELEMETRY_URLOverride the endpoint; whitespace is trimmed and https:// is added when no scheme is present
GITTE_TELEMETRY_LOGS=off, false, or 0Disable OTEL log export (keep traces; case-insensitive with surrounding whitespace ignored)
OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_HEADERSStandard OTEL env vars; endpoint vars are used when no gitte endpoint is set, and headers can provide credentials for a GITTE_TELEMETRY_URL override

Precedence: GITTE_TELEMETRY=off|false|0 > GITTE_TELEMETRY_URL > config endpoint > OTEL_EXPORTER_OTLP_*. Telemetry is best-effort and never blocks or slows gitte; export failures are silently ignored. When GITTE_TELEMETRY_URL overrides the config endpoint, config headers are not used; set OTEL_EXPORTER_OTLP_HEADERS to provide override-endpoint credentials through the OTEL exporter.


Global flags

--config <path> Path to .gitte.yml (default: auto-detected by walking up)
--cwd <path> Override working directory
--no-tty Force plain-text output

State and override files

.gitte-state.yml — stores per-machine state: project toggles, feature gate overrides, and remote config cache. Gitte automatically adds this file to .gitignore. Do not commit it.

.gitte-override.yml — deep-merged on top of .gitte.yml when present. Use this for local machine-specific settings that should not be committed (e.g. sources added via gitte sources add).

About

Developer environment orchestration — monorepo-like development across many git repositories, without the monorepo

Resources

Stars

14 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages