Skip to content

mkrep

Usage
mkrep [--cd | --no-cd] [--mkdir | --no-mkdir] [--git | --no-git]
[-c | --clean | --no-clean] [--strict] [-l | --local]
[-v | --verbose] [-s | --silent] [--template <path>]
[--branch <name>] [--remote <url>] [--new-remote [<cmd>]]
[--server <type>] [--check-existing] [-y | --yes]
[--name <name>] [-h | --help] <dir>

Creates a directory, cds into it, and git-inits it – mkcd plus a git repo in one step. All three actions are on by default and each has a --no-* flag to skip it, plus a same-named flag to force it back on. If both a flag and its --no- counterpart are given, --no- wins.

--clean removes an existing target directory before recreating it, for a guaranteed-fresh start; --strict instead refuses to proceed if the directory already exists. The two compose: --clean runs first, so --clean --strict together is not a contradiction – strict sees an empty slot because clean just emptied it.

-l/--local forces strictly local action: any flag or environment variable that would link to, create, or check a remote (--remote, --new-remote, --server, --check-existing, $GIT_SERVER, $GITEA_URL, $GITEA_HOST, $GITLAB_URL, $GITLAB_HOST, $MKREP_REMOTE_CMD) is overridden and ignored. Even when passed alongside conflicting remote flags like --server or --remote, -l/--local takes precedence and proceeds with local directory creation and git initialization without erroring or contacting any forge.

--remote links an already-existing remote (git remote add origin ) – it does not create anything. Linking is idempotent: an origin already pointing at that URL is reported and accepted, so rerunning mkrep against the same target, or pointing it at a checkout that is already linked, succeeds instead of failing on “remote origin already exists”. An origin pointing somewhere else is an error, not a silent repoint. --new-remote creates one first by running a shell command template in the new repo directory, then nothing further is needed since the template itself does the linking (e.g. gh repo create {name} --source=. --remote=origin --push). Three placeholders are substituted in a template: {name} (--name, or the target directory’s basename), {user} ($USER), and {server} (the resolved server base URL, gitea/gitlab only). Pass a command after --new-remote to use it for this call only; with no value it falls back to $MKREP_REMOTE_CMD. --remote and --new-remote are mutually exclusive, and either requires --git.

--server (gitea, gitlab, or github) picks a host without an explicit --remote/--new-remote: resolve its base URL from $GITEA_URL/$GITEA_HOST (gitea) or $GITLAB_URL/$GITLAB_HOST (gitlab), preferring the _URL form when both are set. _URL is used as-is and must include its scheme (https://git.example.com); _HOST is bare (git.example.com) and gets https:// prepended. Then run $MKREP_REMOTE_CMD or that type’s built-in default template. With no --server, --remote, or --new-remote, $GIT_SERVER picks the type the same way (invalid values are rejected the same as an invalid --server) – $GITEA_URL/$GITEA_HOST/$GITLAB_URL/$GITLAB_HOST only ever supply the base URL, never the type on their own, so setting one for an unrelated tool (an API token helper, say) can’t turn a plain mkrep call into a remote-creating one. This auto-detect path is silent (no error) under --no-git; --server itself still requires --git, and --server together with --remote or --new-remote is an error. Either way, before creating anything mkrep checks whether / already exists on that host: if so, it links to the existing repo instead of creating one; if not, it creates the repo and reports the new remote’s URL. --check-existing runs just that check and reports the result without creating or linking anything; it requires a resolved server and is mutually exclusive with --remote and --new-remote.

Creating a repository on a live forge is the only outward-facing thing mkrep does, and on the $GIT_SERVER path an exported variable is all it takes to reach it – so a plain mkrep call, which reads as purely local, would otherwise make a repo on a server without ever saying so. That case therefore asks for confirmation first, defaulting to no. Declining leaves the local repo in place with no remote and still exits 0. Linking an existing repo is not affected, and neither is an explicitly requested remote: --server, --remote and --new-remote all say outright what they are going to do, so none of them prompts. Pass --yes to skip the question. Where it cannot be asked – a script, a pipe, any non-interactive shell – creation is skipped rather than assumed, with a note on stderr naming the flags that would allow it.

<dir> Directory to create and enter
--cd, --no-cd Change into <dir> (default: --cd)
--mkdir, --no-mkdir Create <dir>, including missing parents (default: --mkdir)
--git, --no-git Run git init in <dir> (default: --git)
-c, --clean Remove <dir> first if it already exists
--no-clean Leave an existing <dir> alone (default)
--strict Fail if <dir> already exists (checked after --clean)
-l, --local Force local-only operation; overrides and ignores any remote flags (--remote, --new-remote, --server, --check-existing) and remote environment variables
-v, --verbose Print each step as it runs
-s, --silent Suppress all output; overrides --verbose
--template <path> Passed through as git init --template=<path>
--branch <name> Passed through as git init -b <name>
--remote <url> Link an existing remote: git remote add origin <url>
--new-remote [<cmd>] Create + link a remote by running <cmd> (or $MKREP_REMOTE_CMD) in the new repo directory
--server <type> Auto-create/link a remote on gitea, gitlab, or github
--check-existing Report whether the repo exists on the resolved server; creates or links nothing
-y, --yes Create the remote without confirming, on the $GIT_SERVER path that would otherwise ask
--name <name> {name} substitution for --new-remote/--server (default: <dir>'s basename)
-h, --help Show this help message
0 All requested steps completed, or a $GIT_SERVER remote-create was declined at the prompt (the local repo is still set up)
1 Bad arguments, or a step (mkdir, cd, git init, remote) failed
Terminal window
mkrep ~/projects/my-new-repo
mkrep --clean --strict ~/projects/scratch
mkrep -l ~/projects/my-local-repo
mkrep --remote [email protected]:me/foo.git ~/projects/foo
set -Ux MKREP_REMOTE_CMD 'gh repo create {name} --private --source=. --remote=origin --push'
mkrep --new-remote ~/projects/foo
set -gx GITEA_URL https://git.example.com
set -gx GIT_SERVER gitea
mkrep ~/projects/foo # asks before creating the remote
mkrep --yes ~/projects/foo # creates it without asking
mkrep --server gitlab --check-existing ~/projects/foo
Starting points for $MKREP_REMOTE_CMD, one per host CLI -- each assumes
that tool is already installed and authenticated, creates a private
repo under the caller's own account, and pushes it if there is
already a commit to push (mkrep itself only runs git init, so a
freshly created repo has none yet -- pushing an unborn HEAD is a
guaranteed error regardless of the remote, so the push is skipped
rather than attempted). These are also mkrep's built-in defaults for
--server/$GIT_SERVER when $MKREP_REMOTE_CMD is unset. gh supports a
one-shot --source/--remote/--push; glab and tea's create commands do
not, so they are chained with the git commands that do the linking:
GitHub (gh): gh repo create {name} --private --source=. --remote=origin --push
GitLab (glab): glab repo create {name} --private --skipGitInit && git remote add origin {server}/{user}/{name}.git && if git rev-parse --verify -q HEAD >/dev/null 2>&1; git push -u origin HEAD; end
Gitea (tea): tea repos create --name {name} --private && git remote add origin {server}/{user}/{name}.git && if git rev-parse --verify -q HEAD >/dev/null 2>&1; git push -u origin HEAD; end

Dependencies: _fish_mkdir_p, __fish_palette, _mkrep_say, _mkrep_verbose, _mkrep_add_origin, _mkrep_default_remote_cmd, _mkrep_remote_url, _mkrep_repo_exists, git

Classification: bypasses-shadow(cd), self-limiting(rm), destructive, network