SkillAgentSearch skills...

Submod

Manage git submodules without the fuss

Install / Use

/learn @bashandbone/Submod
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<!-- SPDX-FileCopyrightText: 2025 Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> SPDX-License-Identifier: LicenseRef-PlainMIT OR MIT -->

submod

Crates.io Documentation Static Badge Rust codecov Crates.io Downloads (latest version)

Git submodules solve a real problem. Managing submodules is a pain. You use them infrequently enough that you always forget which command does what — and when something breaks, the recovery steps are a small nightmare. New contributors hit this especially hard: onboarding onto a project that uses submodules is its own obstacle course.

submod wraps the whole lifecycle in one consistent CLI. Sixteen commands, including nuke-it-from-orbit for when you're done being reasonable. Built on gitoxide and git2, with automatic fallback so operations don't fail silently.[^1] It's actively used across @knitli and @plainlicense, where submodules handle shared functionality between repos.

:rocket: Features

  • TOML config — define submodules, sparse-checkout paths, and defaults in one file
  • Sparse checkout — clone only the parts of a submodule you actually need
  • Global defaults with per-submodule overrides — set it once, customize where it matters
  • Fallback chain — tries gitoxide first, falls back to git2, then CLI
  • Clear status and errors — you'll know what broke and why

[^1]: The fallback architecture is more a reflection of the status of gitoxide and git2 submodule support than a stability concern. Their features do not consistently provide the full lifecycle of submodule operations. Together they cover >90%, but sometimes immaturely. The fallbacks architecture handles that gracefully and lets native operations grow with those libraries.

📋 Table of Contents

🔧 Installation

Using Cargo

cargo install submod

Using Mise

Mise is a project management tool and package manager that can manage your development environment.

# Global installation
mise use -g cargo:submod@latest

# Project-specific installation
mise use cargo:submod@latest

From Source

git clone https://github.com/yourusername/submod.git
cd submod
cargo install --path .

🚀 Quick Start

  1. Initialize a config file in your git repository:

    # Create a basic submod.toml configuration
    cat > submod.toml << EOF
    [defaults]
    ignore = "dirty"
    
    [my-submodule]
    path = "vendor/my-lib"
    url = "https://github.com/example/my-lib.git"
    sparse_paths = ["src/", "include/", "*.md"]
    EOF
    
  2. Initialize your submodules:

    submod init
    
  3. Check status:

    submod check
    

⚙️ Configuration

Create a submod.toml file in your repository root:

# Global defaults applied to all submodules
[defaults]
ignore = "dirty"          # ignore dirty state in status
update = "checkout"       # update method
branch = "main"          # default branch to track

# Individual submodule configuration
[vendor-utils]
path = "vendor/utils"
url = "https://github.com/example/utils.git"
sparse_paths = ["src/", "include/", "*.md"]
ignore = "all"           # override default ignore setting
active = true            # whether submodule is active

[my-submodule]
path = "libs/my-submodule"
url = "https://github.com/example/my-submodule.git"
sparse_paths = ["src/core/", "docs/"]
branch = "develop"       # track specific branch

Configuration Options

Global Defaults

  • ignore: How to handle dirty submodules (all, dirty, untracked, none)
  • update: Update strategy (checkout, rebase, merge, none, !command)
  • branch: Default branch to track (. for current superproject branch)
  • fetchRecurse: Fetch recursion (always, on-demand, never)

Per-Submodule Settings

  • path: Local path where submodule should be placed
  • url: Git repository URL
  • sparse_paths: Array of paths to include in sparse checkout
  • active: Whether the submodule is active (default: true)
  • All global defaults can be overridden per submodule

📖 Commands

submod add

Add a new submodule to your configuration and repository:

# Basic add
submod add https://github.com/example/my-lib.git --name my-lib --path libs/my-lib

# With sparse checkout paths and extra options
submod add https://github.com/example/my-lib.git \
  --name my-lib \
  --path libs/my-lib \
  --sparse-paths "src/,include/" \
  --branch main \
  --ignore all \
  --fetch on-demand

Options:

| Flag | Short | Description | |------|-------|-------------| | <URL> | | (required) URL or local path of the submodule repository | | --name | -n | Nickname for the submodule used in your config and commands | | --path | -p | Local directory path where the submodule should be placed | | --branch | -b | Branch to track | | --ignore | -i | Dirty-state ignore level (all, dirty, untracked, none) | | --sparse-paths | -x | Comma-separated sparse checkout paths or globs | | --fetch | -f | Recursive fetch behavior (always, on-demand, never) | | --update | -u | Update strategy (checkout, rebase, merge, none) | | --shallow | -s | Shallow clone (last commit only) | | --no-init | | Add to config only; do not clone/initialize |

submod check

Check the status of all configured submodules:

submod check

alias: submod c

submod init

Initialize all missing submodules:

submod init

alias: submid i

submod update

Update all submodules to their latest commits:

submod update

alias: submod u

submod reset

Hard reset submodules (stash changes, reset --hard, clean):

# Reset all submodules
submod reset --all

# Reset specific submodules (comma-separated)
submod reset my-lib,vendor-utils

alias: submod r

submod sync

Run a complete sync (check + init + update):

submod sync

alias: submod s

submod change

Change the configuration of an existing submodule:

submod change my-lib --branch main --sparse-paths "src/,include/" --fetch always

submod change-global

Change global defaults for all submodules:

submod change-global --ignore dirty --update checkout

aliases: submod cg, submod chgl, submod global

submod list

List all configured submodules:

submod list
submod list --recursive

aliases: submod ls, submod l

submod delete

Delete a submodule from configuration and filesystem:

submod delete my-lib

alias: submod del

submod disable

Disable a submodule without deleting files (sets active = false):

submod disable my-lib

alias: submod del

submod nuke-it-from-orbit

Delete all or specific submodules from config and filesystem, with optional reinit:

# Nuke all submodules (re-initializes by default)
submod nuke-it-from-orbit --all

# Nuke specific submodules permanently
submod nuke-it-from-orbit --kill my-lib,old-dep

aliases: submod nuke-em, submod nuke-it, submod nuke-them

Use nuke-it-from-orbit was created because sometimes submodule just... don't cooperate. You're done being nice and just want to get back to work. Nuke it.

submod generate-config

Generate a new configuration file:

# From current git submodule setup
submod generate-config --from-setup .

# As a template with defaults
submod generate-config --template --output my-config.toml

aliases: submod gc, submod genconf

submod completeme

Generate shell completion scripts:

bash

mkdir -p ~/.bash_completion.d
submod completeme bash > ~/.bash_completion.d/submod

aliases: submod comp, submod complete, submod comp-me, submod complete-me

<details> <summary>Add completions to other shells</summary>

zsh

# zsh has an fpath array with possible function directories. You can
# put your competions in any of these; we use the first one here:
ZSH_DEFAULT="${XDG_DATA_HOME:-~/.local/share}/zsh/site-functions"
ZFUNCDIR=""${fpath[1]:-$ZSH_DEFAULT}"
mkdir -p "$ZFUNCDIR"
submod completeme zsh > "${ZFUNCDIR}/_submod"

fish

mkdir -p "${XDG_CONFIG_HOME:-~/.config}/fish/completions"
submod completeme fish > "{XDG_CONFIG_HOME:-~/.config}/fish/completions/submod.fish

powershell

mkdir -p $Home\Documents\PowerShell\completions
submod completeme powershell > $Home\Documents\PowerShell\completions\submod.completion.ps1

elvish

mkdir -p ~/.config/elvish/completions
submod completeme elvish > ~/.config/elvish/completions/submod.elv

nushell

submod completeme nu > "$NUSHELL_CONFIG_DIR/scripts/completions/submod.nu"
echo 'use completions/submod.nu' >> "$NU_CONFIG_PATH"
</details>

💻 Usage Examples

Basic Workflow

# Start with checking current state
submod check

# Initialize any missing submodules
submod init

# Update everything to latest
submod update

# Or 

Related Skills

View on GitHub
GitHub Stars9
CategoryDevelopment
Updated7d ago
Forks1

Languages

Rust

Security Score

75/100

Audited on Mar 22, 2026

No findings