Files
mgsh/mgshrc.example
T
mikeandClaude Opus 5 59da8f376c Check the staged diff for credentials before push commits
`push` runs `git add --all .`, so anything lying in the project gets
committed, and with `mirror = true` it reaches a public server in the
same breath. It is the one action in mgsh that cannot be undone: a
deleted server repository comes back from an archive, a published
credential does not.

The staged diff is now scanned before the commit is made -- private keys,
GitHub/GitLab/Slack/AWS/PyPI tokens, and credential-shaped assignments --
and a hit is shown with file and line before asking whether to continue.
Declining leaves the changes staged but uncommitted, so removing the file
and adding a .gitignore entry is all it takes.

The hard part is not detection but silence. A scanner that cries wolf
gets answered with a reflexive "y" and stops being a safety net, so
values that are plainly environment references, dotted identifiers,
constant names, template slots or masked stand-ins are filtered out. A
test scans mgsh's own README and mgshrc.example -- both full of
credential-shaped text -- and fails if either would trip the check. It
caught the documentation for this very feature, which is why the README
describes the sample output instead of reproducing it.

For a line that legitimately looks like a credential there is
`mgsh:allow`, which suppresses that one line; `secretscan = off` turns
the check off entirely. Only an explicit "off" does that -- a typo in the
setting leaves the safety net in place, which is what the new falsy()
is for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-26 16:17:30 +02:00

66 lines
2.6 KiB
Plaintext

# Example mgsh configuration. mgsh writes a blank ~/.mgshrc on first run; fill
# in the required settings (mgsh refuses to start until they are set). This file
# is just an annotated reference.
#
# Simple "key = value" (or "key: value") lines; a '#' after whitespace starts a
# comment. There are no built-in defaults. Settings are resolved in this order,
# each step overriding the one before:
#
# ~/.mgshrc -> <project>/.mgshrc -> MGSH_* environment variables
# --- required ---
base = /Users/me/src
githost = git.example.com
gitport = 22
gituser = git
gitpath = /home/git
# --- optional ---
# gitkey = mgit_rsa
# gitname = Your Name
# gitemail = you@example.com
# pushdefault = matching
# editor = code
# --- pushremote: mirror to public servers (gitea/github/gitlab) via their API ---
# A single server, the flat form (this target is named "public"):
# remoteurl = https://git.example.com
# remotekey = <personal-access-token>
# remotetype = gitea # optional; auto-detected from remoteurl
# remotevisibility = private # visibility of created repos (default private)
#
# Or any number of named servers. `pushremote` pushes to all of them in the
# order given, `pushremote @hub` to a single one. Each target gets a git remote
# of the same name in the repository.
# remote.gitea.url = https://git.example.com
# remote.gitea.key = <personal-access-token>
# remote.hub.url = https://github.com
# remote.hub.key = <personal-access-token>
# remote.hub.type = github # optional; auto-detected from the url
# remote.hub.visibility = public # default private
# remotes = gitea, hub # optional: restrict and order the set
#
# mirror = true # `push` also mirrors via pushremote
# --- safety ---
# `push` checks the staged diff for private keys and API tokens before it
# commits, and asks before continuing. Only an explicit "off" disables it.
# secretscan = off
# --- per-project overrides ---
# A <project>/.mgshrc overrides all of the above for that project only, except
# base, gitname, gitemail and pushdefault, which stay global. Typical use:
#
# # ~/src/myproject/.mgshrc
# remotes = hub # this project is mirrored to github only
# mirror = true
#
# Keep tokens out of a project .mgshrc unless it is git-ignored — mgsh warns
# when it is not.
# Aliases live in the same file (managed by the `alias` command). The expansion
# is a mgsh command line; $1..$N and $*/$@ expand arguments, and a shell command
# needs a leading '!'.
alias co 'checkout $1'
alias ec '!echo $1'