mkrep
Synopsis
Section titled “Synopsis”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>Description
Section titled “Description”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 <url>) – 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). Since --server cannot be combined with --new-remote, {server} there comes from $GIT_SERVER plus its _URL/_HOST variable; a template using {server} with no base URL resolved is an error rather than a literal {server}. Each value is shell-escaped as it is inserted, so a directory named a;touch X reaches the command as the literal text a;touch X and runs nothing extra; for the same reason a template must not put quotes around a placeholder. Pass a command after --new-remote (--new-remote <cmd> or --new-remote=<cmd>) to use it for this call only; with no command it falls back to $MKREP_REMOTE_CMD. The space form is recognized when exactly two operands follow, the first being the command; a bare --new-remote followed by a single operand treats that operand as <dir>. --remote and --new-remote are mutually exclusive, and either requires --git.
--server <type> (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 <user>/<name> 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.
Arguments
Section titled “Arguments”<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 |
Exit Status
Section titled “Exit Status”0 |
All requested steps completed, or a $GIT_SERVER remote-create was declined at the prompt (the local repo is still set up) |
1 |
A step (mkdir, cd, git init, remote) failed |
2 |
Bad arguments: unknown option, not exactly one directory, conflicting flags, or an unknown --server type |
Example
Section titled “Example”mkrep ~/projects/my-new-repomkrep --clean --strict ~/projects/scratchmkrep -l ~/projects/my-local-repomkrep --remote [email protected]:me/foo.git ~/projects/fooset -Ux MKREP_REMOTE_CMD 'gh repo create {name} --private --source=. --remote=origin --push'mkrep --new-remote ~/projects/foomkrep --new-remote 'gh repo create {name} --public --source=. --remote=origin' ~/projects/foomkrep --new-remote='gh repo create {name} --public --source=. --remote=origin' ~/projects/fooset -gx GITEA_URL https://git.example.comset -gx GIT_SERVER giteamkrep ~/projects/foo # asks before creating the remotemkrep --yes ~/projects/foo # creates it without askingmkrep --server gitlab --check-existing ~/projects/foo
Starting points for $MKREP_REMOTE_CMD, one per host CLI -- each assumesthat tool is already installed and authenticated, creates a privaterepo under the caller's own account, and pushes it if there isalready a commit to push (mkrep itself only runs git init, so afreshly created repo has none yet -- pushing an unborn HEAD is aguaranteed error regardless of the remote, so the push is skippedrather than attempted). These are also mkrep's built-in defaults for--server/$GIT_SERVER when $MKREP_REMOTE_CMD is unset. gh supports aone-shot --source/--remote/--push; glab and tea's create commands donot, 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; endDependencies: _fish_mkdir_p, __fish_palette, __fish_mark, _mkrep_say, _mkrep_add_origin, _mkrep_default_remote_cmd, _mkrep_expand_template, _mkrep_remote_url, _mkrep_repo_exists, git
Classification: bypasses-shadow(cd), self-limiting(rm), destructive, network