{"id":34187724,"url":"https://github.com/ryclarke/batch-tool","last_synced_at":"2026-03-12T06:40:12.246Z","repository":{"id":54428383,"uuid":"292321369","full_name":"ryclarke/batch-tool","owner":"ryclarke","description":"This tool provides convenient features for working on multiple git repositories simultaneously.","archived":false,"fork":false,"pushed_at":"2026-02-12T18:37:57.000Z","size":341,"stargazers_count":0,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-02-13T00:33:16.918Z","etag":null,"topics":["automation","batch-processing","tooling"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ryclarke.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-09-02T15:27:04.000Z","updated_at":"2026-02-12T16:19:31.000Z","dependencies_parsed_at":"2024-01-08T18:51:01.903Z","dependency_job_id":"c48cdda3-583c-4889-8037-917bc11a9e8b","html_url":"https://github.com/ryclarke/batch-tool","commit_stats":{"total_commits":11,"total_committers":2,"mean_commits":5.5,"dds":0.2727272727272727,"last_synced_commit":"b1a2b9ec492ef78ecb6734d9d408dd507fdeb520"},"previous_names":["ryclarke/batch-tool"],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/ryclarke/batch-tool","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryclarke%2Fbatch-tool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryclarke%2Fbatch-tool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryclarke%2Fbatch-tool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryclarke%2Fbatch-tool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ryclarke","download_url":"https://codeload.github.com/ryclarke/batch-tool/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryclarke%2Fbatch-tool/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30417542,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-12T04:41:02.746Z","status":"ssl_error","status_checked_at":"2026-03-12T04:40:12.571Z","response_time":114,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","batch-processing","tooling"],"created_at":"2025-12-15T15:20:23.827Z","updated_at":"2026-03-12T06:40:12.240Z","avatar_url":"https://github.com/ryclarke.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Batch Tool\n\nThis tool provides a suite of functionality for performing common tasks across multiple git repositories, including branch management and pull request creation.\n\n## Features\n\n- **Git Operations**: Create and push branches and commits, and manage history\n- **Pull Request Management**: Create, edit, and merge pull requests (supports GitHub and Bitbucket)\n- **Repository Catalog**: Cache repository metadata for quick matching and topical grouping\n- **Make Target Execution**: Run make targets across multiple repositories\n- **Flexible Configuration**: YAML-based configuration with repository aliases and default reviewers\n\n## Getting Started\n\n**TL;DR for new users:**\n1. `make install` - Installs batch-tool to your system\n2. Create a `batch-tool.yaml` file with your git provider and repositories\n3. Run `batch-tool git status \u003crepo-names\u003e` to get started\n\nFor detailed setup instructions, see the sections below.\n\n## Installation\n\n### Pre-built Binaries\n\nDownload and unpack the binary for your platform from [the latest release](https://github.com/ryclarke/batch-tool/releases/latest).\n\n### Build and Install from Source\n\nFor the fastest setup, use Make to install directly to your Go bin directory:\n\n```bash\ngit clone git@github.com:ryclarke/batch-tool.git\ncd batch-tool\n\nmake install\n```\n\nYou'll need a Go environment set up with GOPATH set. See [the Go getting started docs](https://golang.org/doc/install) for more info.\n\nThis will automatically build the tool and install it to `$GOPATH/bin` (or `~/go/bin` if `GOPATH` is not set).\n\n## Quick Start\n\n### 1. Install\n\nIf building from source, install the tool to your system:\n\n```bash\nmake install\n```\n\nMake sure `$GOPATH/bin` (or `~/go/bin`) is in your `PATH`.\n\n### 2. Configuration\n\nCreate a configuration file `batch-tool.yaml` in your working directory or user config directory (`~/.config`), or specify a file path manually with `--config`:\n\n```yaml\ngit:\n  provider: github\n  host: github.com\n  project: your-username-or-org\n  default-branch: main # fallback for a repo with no default branch\n  stash-updates: false # if true, automatically stash/restore changes during git update\n\nchannels:\n  output-style: tui  # Modern TUI interface (default); use \"native\" for scripts\n\nrepos:\n  sort: true  # sort output alphabetically by repository name\n\n  # don't match repos containing the following topics unless explicitly added\n  skip-unwanted: true\n  unwanted-labels: deprecated,poc\n\n  # aliases act like custom topics for referencing and grouping repoistories\n  aliases:\n    myproject:\n      - repo1\n      - repo2\n      - repo3\n\n  # list of default reviewers to request for each repository\n  reviewers:\n    repo1:\n      - reviewer1\n      - reviewer2\n```\n\nThe only required field is `git.project`, the rest of the configuration has safe default values.\n\n### 3. Authentication\n\nFor repository discovery and pull request operations, you'll need to configure authentication:\n\n- **GitHub**: Set up a [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)\n- **Bitbucket**: Configure an [API token](https://support.atlassian.com/bitbucket-cloud/docs/using-api-tokens/)\n\nThe authentication token should be provided via the `AUTH_TOKEN` environment variable (recommended) or the `auth-token` field in the batch-tool config file.\n\n### 4. Basic Usage\n\nCheck the status of multiple repositories:\n```bash\nbatch-tool git status repo1 repo2 repo3\n```\n\nRepositories can also be referenced by Github [Topics](https://github.com/topics) or Bitbucket [Labels](https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-labels#api-group-labels):\n```bash\nbatch-tool git status '~libraries'\n```\n\nYou may also use the same syntax to refer to aliases defined locally in the config file.\n\n- To refer to an alias or topic, include `~` in the argument as seen above.\n- To invert a match to *exclude* a repository or alias/topic, include a `!`.\n- To force selection of a repository or alias/topic, include a `+`.\n  - This bypasses unwanted label filtering and ignores exclusions from other arguments.\n  - If applied to an alias/topic, _every_ member will be included regardless of other filters.\n- To operate on the current working directory only, pass `.` as the sole repository argument.\n  - In this mode, argument expansion (aliases/topics/labels) is skipped.\n  - No repository batching occurs; the command runs once against the current directory.\n\n-------------------------------\n\nℹ️ The `~all` alias is defined implicitly and refers to all discovered repositories for the configured namespace (user profile or organization).\n\n-------------------------------\n\nExample:\n```bash\n# repos.aliases:\n#   myservice: [repo1 repo2 repo3 repo4]\n#   deprecated: [repo4]\n# repos.unwanted_labels: [deprecated]\n#\nbatch-tool git status '~myservice' '!repo3' # matches repo1 and repo2 only\nbatch-tool git status '~myservice' '+repo4' # forces inclusion of repo4\nbatch-tool git status '+~myservice' '!~deprecated' # matches all 4 repos\nbatch-tool pr get . # run against current directory without alias/label expansion\n```\n\n⚠️ When using special characters for matching and exclusion, ensure that all arguments are quoted properly to avoid improper shell expansion.\n\n## Interactive Mode\n\nWhen the `--style=tui` flag is provided, batch-tool launches an interactive terminal user interface (TUI) for command selection and navigation.\n\n### Using Interactive Mode\n\n```bash\n# Launch the interactive command selector\nbatch-tool --style=tui\n```\n\nThe TUI provides:\n- **Visual command navigation**: Browse through available commands and subcommands\n- **Help information**: View command descriptions at each level\n- **Keyboard navigation**: Use arrow keys, vim-style (hjkl), or Enter to navigate\n- **Breadcrumb trail**: See your current location in the command hierarchy\n\n### Keyboard Controls\n\n- `↑/k` - Move cursor up\n- `↓/j` - Move cursor down\n- `←/h/backspace` - Go back to parent command\n- `→/l/enter` - Select command or enter subcommand\n- `q/ctrl+c` - Quit\n\n### Output Styles\n\nThe `--style` flag also controls how command output is displayed:\n\n- `tui` (default): Modern TUI with interactive progress display, real-time updates, and scrollable output\n- `native`: Traditional terminal output with streaming updates\n\nExample with output style:\n```bash\n# Use interactive TUI for output display\nbatch-tool git status repo1 repo2 --style=tui\n```\n\n## Commands\n\n### Git Operations\n\n```bash\n# Check status across repositories\nbatch-tool git status \u003crepos...\u003e\n\n# Create new branches for each repository\nbatch-tool git branch -b \"\u003cbranch-name\u003e\" \u003crepos...\u003e\n\n# Checkout the default branches and pull any upstream changes (destroys uncommitted changes)\nbatch-tool git update \u003crepos...\u003e\n\n# Show diff information in the working trees\nbatch-tool git diff \u003crepos...\u003e\n\n# Commit and push changes\nbatch-tool git commit -m \"commit message\" \u003crepos...\u003e\n```\n\n#### Git Update with Stash\n\nThe `git update` command can automatically save and restore uncommitted changes using `git stash`. This is useful when you have local modifications that you want to preserve while updating to the latest default branch.\n\n**Configuration:**\n```yaml\ngit:\n  stash-updates: true  # Enable automatic stash by default\n```\n\n**Usage:**\n```bash\n# Enable stash just for this command\nbatch-tool git update --stash \u003crepos...\u003e\n\n# Or use the inverted flag to disable stash if it's enabled in config\nbatch-tool git update --no-stash \u003crepos...\u003e\n```\n\n**Safety Features:**\n- Only works with stashes created by batch-tool (identified by `batch-tool YYYY-MM-DDTHH:MM:SSZ` message)\n- Safely handles clean working directories (no changes to stash)\n- Fails explicitly if stashed changes cannot be restored\n- Can be globally enabled in config, but can be disabled per-command with `--no-stash`\n\n### Pull Request Management\n\n**Note**: Requires authentication token configuration.\n\n```bash\n# Create new pull requests\nbatch-tool pr new -t \"PR Title\" -d \"Description\" \u003crepos...\u003e\n\n# Create PRs with user and team reviewers\nbatch-tool pr new -r reviewer1 -R my-org/platform-team \u003crepos...\u003e\n\n# Edit existing pull requests\nbatch-tool pr edit -t \"New Title\" -d \"New Description\" \u003crepos...\u003e\n\n# Add requested reviewers by username\nbatch-tool pr edit -r reviewer1 -r reviewer2 \u003crepos...\u003e\n\n# Add requested team reviewers by slug (GitHub provider)\nbatch-tool pr edit -R my-org/backend-team -R my-org/frontend-team \u003crepos...\u003e\n\n# Replace existing reviewers (users and teams) instead of appending\nbatch-tool pr edit -r reviewer1 -R my-org/platform-team --reset-reviewers \u003crepos...\u003e\n\n# Merge with explicit method and status check behavior\nbatch-tool pr merge -m squash --check \u003crepos...\u003e\nbatch-tool pr merge --force \u003crepos...\u003e\n\n# Merge all accepted pull requests\nbatch-tool pr merge \u003crepos...\u003e\n```\n\n### Miscellaneous\n\n```bash\n# Generate autocompletion script for the specified shell\nbatch-tool completion \u003cbash|fish|powershell|zsh\u003e\n\n# Execute make targets\nbatch-tool make -t \u003cmake target\u003e \u003crepos...\u003e\n\n# Execute arbitrary shell commands across repositories\n## (DANGEROUS - use with caution) ##\nbatch-tool sh -c \"command to execute\" \u003crepos...\u003e\n\n# Execute a script file or executable binary across repositories\n## (DANGEROUS - use with caution) ##\nbatch-tool sh -f /path/to/script.sh \u003crepos...\u003e\n\n# Pass arguments to the script using -a/--args flag (repeatable)\nbatch-tool sh -f /path/to/script.sh -a arg1 -a arg2 \u003crepos...\u003e\n\n# Skip confirmation prompt with -y flag\nbatch-tool sh -y -c \"echo 'safe command'\" \u003crepos...\u003e\n\n# Test repository filter rules against topics and local aliases\nbatch-tool labels \u003crepos...\u003e\n\n# View local repository metadata\nbatch-tool catalog\n\n# Run synchronously (useful for computationally-expensive operations)\nbatch-tool --sync \u003ccommand\u003e \u003crepos...\u003e\n```\n\n## Global Flags\n\n- `--config string`: Specify config file (default: `batch-tool.yaml`)\n- `--style string` / `-o`: Output style (`tui` or `native`, default: `tui`)\n- `--print` / `-p`: Print results to stdout after processing is complete\n- `--wait` / `--no-wait`: Wait for user input after processing (auto-disabled in non-interactive output)\n- `--env` / `-e` (repeatable): Environment variables to set for command execution (`KEY=VALUE`)\n- `--sync`: Execute commands synchronously (alias for `--max-concurrency=1`)\n- `--max-concurrency int`: Maximum number of concurrent operations (default: number of logical CPUs)\n- `--sort`: Sort repositories (default: true)\n- `--skip-unwanted`: Skip repositories with unwanted labels (default: true)\n\n## Configuration Reference\n\n### Git Provider Settings\n\n```yaml\ngit:\n  provider: github | bitbucket\n  host: github.com  # or your Bitbucket server\n  project: your-org-or-username\n  default-branch: main | develop\n  stash-updates: false          # Stash/restore local changes during git update by default\n  default-merge-method: squash  # PR merge method: merge | squash | rebase\n  directory: /path/to/git/repos  # Base directory for repository clones\n```\n\n#### Repository Directory Structure\n\nThe `git.directory` option configures the base directory where repositories will be cloned. When specified, repositories are automatically organized in subdirectories that mirror the git provider's structure:\n\n```\n$GIT_DIRECTORY/\n├── github.com/\n│   ├── myorg/\n│   │   ├── repo1/\n│   │   ├── repo2/\n│   │   └── repo3/\n│   └── anothorg/\n│       └── shared-repo/\n└── bitbucket.example.com/\n    └── myproject/\n        └── api-service/\n```\n\n**Default behavior**: If not specified, defaults to `$GOPATH/src` if `GOPATH` is set, otherwise uses the current working directory.\n\n### Repository Settings\n\n```yaml\nrepos:\n  sort: true                   # Sort repository output\n  skip-unwanted: true          # Skip repos with unwanted labels\n  unwanted-labels:             # Labels to skip when skip-unwanted is true\n    - deprecated\n    - poc\n    - archived\n\n  aliases:                     # Group repositories under aliases\n    frontend:\n      - web-app\n      - mobile-app\n    backend:\n      - api-server\n      - worker-service\n\n  reviewers:                   # Default reviewers per repository\n    web-app:\n      - frontend-team\n    api-server:\n      - backend-team\n```\n\n### Output Style and Concurrency Settings\n\n```yaml\nchannels:\n  output-style: tui          # Output style: \"tui\" (default) or \"native\" (fallback)\n  buffer-size: 100           # Channel buffer size for console output (default: 100)\n  max-concurrency: 8         # Maximum concurrent operations (default: number of logical CPUs)\n```\n\n#### Output Styles\n\nThe `output-style` setting controls how command output is displayed:\n\n- **`tui`** (default): Modern terminal UI with real-time updates, styled output, and progress indicators. Features include:\n  - Live progress tracking with completion status\n  - Styled repository names and status indicators\n  - Real-time output streaming with full scrolling support\n  - Color-coded errors and messages\n  - Elapsed time display\n  - Keyboard controls for navigation, including support for Vim keybinds!\n\n- **`native`**: Low-complexity fallback with traditional sequential output with repository headers. Suitable for legacy or non-interactive environments, scripts, and CI/CD pipelines.\n\n\u003e **Note**: The TUI style is recommended for interactive use and provides a better experience for operations across many repositories and/or using long-running commands.\n\n#### Concurrency Control\n\nThe `max-concurrency` setting controls how many repositories are processed simultaneously. This is useful for:\n\n- **Resource-intensive operations**: Reduce concurrency to avoid overwhelming the system\n- **Rate-limited APIs**: Prevent hitting API rate limits when working with pull requests\n- **Network-bound operations**: Balance between speed and stability\n\n**Examples:**\n- `max-concurrency: 1` - Process repositories one at a time (equivalent to `--sync`)\n- `max-concurrency: 5` - Conservative setting for API operations\n- `max-concurrency: 20` - Aggressive setting for local git operations\n\n**Tip**: The default concurrency is set to the number of logical CPUs on your system. Start with this default and adjust based on your specific use case and system capabilities.\n\n## Examples\n\n### Daily Workflow\n\n1. **Morning sync**: Update all repositories to latest\n```bash\nbatch-tool git update '~all'\n```\n\n2. **Create feature branch**: Start new work across multiple repos\n```bash\nbatch-tool git branch -b feature/new-feature '~frontend' '~backend'\n```\n\n3. **Check status**: See what's changed\n```bash\nbatch-tool git status '~frontend' '~backend'\n```\n\n4. **Create pull requests**: Submit your changes\n```bash\nbatch-tool pr new -t \"Add new feature\" -d \"Detailed description\" '~frontend' '~backend'\n```\n\n### Maintenance Tasks\n\n1. **Run tests across projects**:\n```bash\nbatch-tool make -t test '~myproject'\n```\n\n2. **Format code**:\n```bash\nbatch-tool make -t format '~myproject'\n```\n\n3. **Synchronous operations** (when needed):\n```bash\nbatch-tool --sync make -t build '~myproject'\n```\n\n4. **Execute custom commands** (use with caution):\n```bash\n# Example: Check Go version across repositories\nbatch-tool sh -c \"go version\" '~myproject'\n\n# Example: Clean up temporary files\nbatch-tool sh -c \"rm -f *.tmp\" '~myproject'\n```\n\n## Tips\n\n- Use repository aliases in your config to group related repositories\n- The `--sync` flag is useful for operations that must run sequentially\n- Repository labels help organize and filter your catalog\n- Default reviewers in config save time when creating pull requests\n- The tool works from any directory - it will find repositories based on your configuration\n- **⚠️ Shell Command Safety**: The `sh` command is powerful but dangerous. It will prompt for confirmation before executing any command across multiple repositories. Use with extreme caution, especially with destructive commands.\n\n## Troubleshooting\n\n- **Authentication errors**: Ensure your API token is properly configured\n- **Repository not found**: Check that repository names match your git provider\n- **Sync issues**: Use `--sync` flag for operations that need to run sequentially\n- **Config issues**: Verify your `batch-tool.yaml` syntax and paths\n\nFor more detailed help on any command, use:\n```bash\nbatch-tool [command] --help\n```\n## Development\n\n### Prerequisites\n\n- Go 1.25 or later\n- Make\n\n### Setup\n\n1. Clone the repository:\n```bash\ngit clone git@github.com:ryclarke/batch-tool.git\ncd batch-tool\n```\n\n2. Install development tools:\n```bash\nmake deps\n```\n\nThis installs:\n- `gotestsum` - Enhanced test output\n- `goreleaser` - Release automation\n- `golangci-lint` - Code quality and style enforcement\n\n### Building\n\nBuild for your current platform:\n```bash\nmake build\n```\n\n### Testing\n\nRun tests:\n```bash\nmake test\n```\n\nRun tests with coverage:\n```bash\nmake cover\n```\n\n### Linting\n\nRun linters to check code quality:\n```bash\nmake lint\n```\n\nAuto-fix linting issues where possible:\n```bash\nmake lint-fix\n```\n\n### Code Style\n\nThis project uses `golangci-lint` to enforce consistent code style. Key requirements:\n\n- **Import Grouping**: Imports must be grouped in order:\n  1. Standard library packages\n  2. Third-party dependencies\n  3. Internal project packages (github.com/ryclarke/batch-tool/*)\n\n- **Error Handling**: All errors must be checked (use `_ =` to explicitly ignore)\n- **Code Quality**: Follow standard Go idioms and best practices\n\nThe CI pipeline runs linting automatically on all pull requests.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryclarke%2Fbatch-tool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fryclarke%2Fbatch-tool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryclarke%2Fbatch-tool/lists"}