Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/cli-windows-arm64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ jobs:
# holding the target path.
cp secretspec/README.md staging/README.md
cp CHANGELOG.md LICENSE staging/
cp target/aarch64-pc-windows-msvc/dist/secretspec.exe staging/
cp target/aarch64-pc-windows-msvc/dist/{secretspec,git-credential-secretspec}.exe staging/

- name: Create the archive
shell: pwsh
Expand All @@ -88,7 +88,7 @@ jobs:
$names = $zip.Entries.FullName
$zip.Dispose()
# Every file dist puts in a Windows archive, at the archive root.
foreach ($entry in 'secretspec.exe', 'README.md', 'LICENSE', 'CHANGELOG.md') {
foreach ($entry in 'secretspec.exe', 'git-credential-secretspec.exe', 'README.md', 'LICENSE', 'CHANGELOG.md') {
if ($names -notcontains $entry) {
throw "the archive is missing $entry"
}
Expand Down
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- A read-only `git-credential-secretspec` helper lets Git retrieve HTTPS
usernames and tokens through SecretSpec providers without duplicating them in
Git's credential store. Its built-in manifest keeps the default independent
of the current directory and isolates values by protocol, host, and configured
path; `secretspec git login` and `logout` manage those values explicitly.
SMTP credential contexts support `git send-email` without writing
`sendemail.smtpPass`, with passwords isolated by server, port, and username.
`configure` and `unconfigure` safely manage repository or global Git
configuration without replacing existing helpers, while `--file` retains the
custom-manifest workflow (0.20+).

## [0.19.1] - 2026-08-11

Republishes 0.19.0's command-line artifacts. The library and CLI behave exactly
Expand All @@ -23,7 +38,6 @@ as in 0.19.0.
checksum. The static installer keeps selecting the x86_64 build on Windows
ARM64, which runs under emulation, so download the archive directly for a
native binary.

### Fixed

- The 0.19.0 GitHub Release shipped without its CLI archives, its installer,
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ thiserror = "2.0"
etcetera = "0.11"
colored = "3.0"
dotenvy = "0.15"
dunce = "1.0"
inquire = { version = "0.9.4", features = ["experimental-multiline-input"] }
miette = { version = "7.6", features = ["fancy"] }
serde_json = "1.0"
Expand Down Expand Up @@ -59,6 +60,7 @@ rand = "0.9"
rsa = { version = "0.9", features = ["pem"] }
uuid = { version = "1", features = ["serde", "v4"] }
data-encoding = "2"
sha2 = "0.10"
detect-coding-agent = "0.1"
age = { version = "0.12", features = ["armor", "plugin", "ssh"] }

Expand Down
10 changes: 10 additions & 0 deletions docs/astro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,16 @@ Values can be resolved from: keyring (default), KeePass KDBX (0.17+), dotenv fil
},
],
},
{
label: "Integrations",
items: [
{
label: "Git credentials",
slug: "integrations/git",
badge: { text: "0.20+", variant: "note" },
},
],
},
{
label: "SDK",
items: [
Expand Down
270 changes: 270 additions & 0 deletions docs/src/content/docs/integrations/git.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
---
title: Git credentials
description: Let Git retrieve HTTPS and SMTP credentials through SecretSpec providers
---

The Git credential helper is available in SecretSpec 0.20+. It lets ordinary
`git clone`, `git fetch`, `git pull`, and `git push` commands retrieve HTTPS
credentials from any SecretSpec provider. It also supports SMTP authentication
for `git send-email`.

Use it when your Git token already lives in a provider such as 1Password,
Bitwarden, or Vault and you do not want to copy it into a separate Git
credential store. The integration does not manage SSH keys or inject secrets
into repositories.

## Prerequisites

- Git
- SecretSpec 0.20 or newer, including `git-credential-secretspec` on `PATH`

## Configure Git

These commands are available in SecretSpec 0.20+.

Register the helper, keeping the non-secret username in Git:

```bash
$ secretspec git configure \
--url https://github.com \
--username YOUR_USERNAME
```

Then store the password or token through your configured default provider:

```bash
$ secretspec git login https://github.com
? Enter value for PASSWORD (profile: default):
```

The built-in manifest declares a required `PASSWORD` and optional `USERNAME`.
It is embedded in the binary: the helper never searches the current directory
for `secretspec.toml`, so clone, fetch, and push resolve the same declarations
inside or outside a repository. Git configuration records no manifest path.

Each canonical credential target has a separate provider namespace. The
identity includes the protocol and host, plus the configured path when
`useHttpPath` is enabled, so credentials for different hosts or path scopes
cannot share a value accidentally.

To keep the username in the provider too, omit `--username` from `configure`
and supply it when logging in:

```bash
$ secretspec git configure --url https://github.com
$ secretspec git login https://github.com --username YOUR_USERNAME
```

`login` prompts securely on a terminal and reads the password or token from
standard input when piped. Use the same `--provider` override on `configure`
and `login` when the credential should not use your default provider.

The helper checks the URL independently before loading the provider. A token
configured for `https://github.com` is not returned for another host or for an
HTTP remote.

::::danger[Use HTTPS for credentials]
Although the helper accepts `http://` URLs for trusted local or test systems,
HTTP does not encrypt the credential in transit. Use `https://` for remote
services.
::::

To limit a credential to part of a host, include the path in the URL:

```bash
$ secretspec git configure \
--url https://github.com/cachix \
--username YOUR_USERNAME
$ secretspec git login https://github.com/cachix
```

SecretSpec also enables Git's `useHttpPath` setting for that URL. This example
answers for repositories below `https://github.com/cachix/`, but not for
another GitHub organization. The path-scoped credential is stored separately
from one configured for all of `https://github.com`.

## Send patches with SMTP

SMTP credential support is available in SecretSpec 0.20+. Git queries
credential helpers when `sendemail.smtpUser` is set and
`sendemail.smtpPass` is omitted:

```bash
$ git config --global sendemail.smtpServer smtp.example.com
$ git config --global sendemail.smtpServerPort 587
$ git config --global sendemail.smtpEncryption tls
$ git config --global sendemail.smtpUser user@example.com
$ secretspec git configure \
--url smtp://smtp.example.com:587 \
--username user@example.com \
--global
$ secretspec git login smtp://smtp.example.com:587
```

The username on `configure` must match `sendemail.smtpUser`. `login` and
`logout` read it back from Git configuration; pass `--username` explicitly if
the helper has already been unconfigured or another account is being managed.
Protocol, server, port, and username form the embedded storage identity, so two
accounts on the same SMTP server never share a password.

The `smtp` URL is Git's credential-context name, not a transport-security
setting. Encryption remains controlled by
`sendemail.smtpEncryption=tls|ssl`. SecretSpec never writes
`sendemail.smtpPass` or any other `sendemail.*` setting, and the helper rejects
HTTP(S), a different port, or another username when answering an SMTP request.

## Clone private repositories

Configure the embedded credential globally before the destination repository
exists:

::::danger[This changes your global Git configuration]
Using `--global` enables this credential helper for matching URLs in every Git
repository owned by your user. Review the URL before confirming. To roll back
the example below, run
`secretspec git unconfigure --url https://github.com --global`; see
[Remove the configuration](#remove-the-configuration) for all removal options.
::::

```bash
$ secretspec git configure \
--url https://github.com \
--username YOUR_USERNAME \
--global
$ secretspec git login https://github.com
```

Then clone normally:

```bash
$ git clone https://github.com/OWNER/REPOSITORY.git
```

Git invokes the SecretSpec credential helper automatically. The token does not
need to appear in the clone URL or your shell history.

Global changes require a confirmation that defaults to **No**. Pass `--yes`
only for non-interactive setup. A `--provider` override and the corresponding
SecretSpec environment variable are supported.

## Use a custom manifest

Custom Git helper configuration is available in SecretSpec 0.20+.

Pass `--file` when the credential should use declarations from a project or
company manifest. In this mode, `--token-secret` is required and
`--username-secret` and `--profile` are available:

```toml
[project]
name = "company-git"
revision = "1.0"

[profiles.default]
GITHUB_TOKEN = { description = "GitHub token for HTTPS authentication" }
```

```bash
$ secretspec set GITHUB_TOKEN --file company-git.toml
$ secretspec --file company-git.toml git configure \
--url https://github.com \
--token-secret GITHUB_TOKEN \
--username YOUR_USERNAME
```

The managed helper records the custom manifest's absolute path and resolved
profile. Explicit `--file` always takes precedence over the embedded manifest.
Use ordinary `secretspec set` and `delete` commands with the same file to manage
custom credential values; `git login` and `logout` intentionally operate only
on the embedded store.

## Remove stored values

`secretspec git logout` is available in SecretSpec 0.20+.

Remove the embedded username and password or token for one exact target:

```bash
$ secretspec git logout https://github.com
```

This leaves the Git helper configured. Repeat `login` to replace the credential,
or use `unconfigure` when Git should stop invoking SecretSpec for that target.
If `login` used a provider override, pass the same override to `logout`.

## Remove the configuration

`secretspec git unconfigure` is available in SecretSpec 0.20+.

Remove one credential helper from the current repository:

```bash
$ secretspec git unconfigure --url https://github.com
```

Remove every Git credential helper that SecretSpec configured in the current
repository:

```bash
$ secretspec git unconfigure --all
```

Add `--global` to operate on global configuration. Global removal also defaults
to **No** and accepts `--yes` for non-interactive use:

```bash
$ secretspec git unconfigure --all --global
```

SecretSpec stores generated entries in its own included Git configuration
file. Configure and unconfigure never replace existing credential helpers,
usernames, or unrelated includes. Removing the final managed credential removes
the SecretSpec include and its file. If that file contains anything SecretSpec
does not recognize, the command refuses to modify it and asks you to inspect it
manually.

## Manual configuration

The Git credential helper is available in SecretSpec 0.20+.

The default convenience command is equivalent to registering the embedded
helper yourself. For example:

```bash
$ git config --local credential.https://github.com.username YOUR_USERNAME
$ git config --local credential.https://github.com.helper \
'secretspec --url https://github.com --password-secret PASSWORD --username-secret USERNAME'
```

When configuring a path manually, set `useHttpPath` and use the same URL in the
helper:

```bash
$ git config --local credential.https://github.com/cachix.useHttpPath true
$ git config --local credential.https://github.com/cachix.helper \
'secretspec --url https://github.com/cachix --password-secret PASSWORD --username-secret USERNAME'
```

These entries are not recorded in SecretSpec's managed file, so
`secretspec git unconfigure` does not remove them. Remove manually configured
entries with `git config` as well.

For SMTP, include the expected username in the helper command and keep
transport settings under `sendemail.*`:

```bash
$ git config --global credential.smtp://smtp.example.com:587.helper \
"secretspec --url smtp://smtp.example.com:587 --username user@example.com \
--password-secret PASSWORD --username-secret USERNAME"
```

## Read-only behavior

In SecretSpec 0.20+, the helper only answers Git's `get` operation. It safely
ignores automatic `store` and `erase` requests, so a rejected credential cannot
delete or overwrite a value in a shared provider. Manage embedded values
explicitly with `secretspec git login` and `logout`, or custom-manifest values
with `secretspec set` and `delete`.

Git can continue to try another configured helper or prompt when SecretSpec has
no stored value for the selected target.
Loading
Loading