Skip to content

feat: unattended GPG signing for TUI agents - #25

Merged
aadil96 merged 5 commits into
mainfrom
feat/gpg-preset-signing
Aug 2, 2026
Merged

feat: unattended GPG signing for TUI agents#25
aadil96 merged 5 commits into
mainfrom
feat/gpg-preset-signing

Conversation

@aadil96

@aadil96 aadil96 commented Jul 19, 2026

Copy link
Copy Markdown
Owner

What

Makes git commit signing work non-interactively for opencode/codex TUI agents. Passphrase cached in gnome-keyring, presets into gpg-agent at login/shell-start.

Changes

  • Git hygiene: private_* added to .gitignore, untracked existing private-files from index
  • gpg-agent.conf: allow-preset-passphrase, pinentry-timeout 30, cache TTLs (1d/400d)
  • gpg-sign-preset script: Resolves keygrip at runtime, pulls passphrase from gnome-keyring via secret-tool, pipes to gpg-preset-passphrase. Silent exit on missing deps.
  • Shell hooks: zshrc + bashrc preset at interactive shell start
  • Systemd unit: gpg-sign-preset.service runs at login, WantedBy=default.target
  • Chezmoiscripts: run_onchange trigger tracks unit file for daemon-reload + enable
  • Install packages: Auto-installs gpg-agent + libsecret-tools via apt-get
  • Docs: troubleshooting entry (keyring locked/headless), AGENTS.md key-files table

One-time manual step after merge

secret-tool store --label="GPG signing passphrase" service gpg-signing key C8B994F19E7D34D9

(type passphrase on TTY prompt, no echo — then all future commits sign silently)

Verification

  • chezmoi apply — configs render correctly
  • gpg-agent.confallow-preset-passphrase present
  • Keygrip parsing correct for both primary keys and subkeys (stateful awk)
  • No secrets in tree or history (verified via read-only scan)
  • Secret-scan gate passes (pre-push diff)

aadil96 added 3 commits July 19, 2026 14:19
- Add private_* to .gitignore, untrack existing private files
- Create gpg-agent.conf with allow-preset-passphrase and long TTLs
- Create gpg-sign-preset script (presets passphrase from gnome-keyring)
- Hook into zshrc/bashrc to preset at interactive shell start
- Add systemd user unit + chezmoiscript to enable at graphical login
- Add troubleshooting entry and update AGENTS.md key-files table
- One-time manual step: secret-tool store --label=... service gpg-signing keygrip <grip>
- B2: Fix keygrip parser — stateful awk captures grp after matching fpr (subkey-safe)
- M2: Move gpg configs from private_dot_gnupg/ to dot_gnupg/ (tracked, no secrets)
- M3: Add pinentry-timeout 30 to gpg-agent.conf (fail fast on missed preset)
- M4: Convert run_once chezmoiscript to run_onchange tracking unit file
- m2: Store secret-tool entry by fingerprint instead of keygrip (survives rotation)
- m3: Add empty key guard to preset script
- m5: Drop After=graphical-session.target from unit (any-login)
- AGENTS.md: Update paths/doc for dot_gnupg/ move
@what-the-diff

what-the-diff Bot commented Jul 19, 2026

Copy link
Copy Markdown

PR Summary

  • New Script Addition
    The team added a new script to enable and start a GPG (a tool for secure communication) signing service using systemd, which is a system and service manager.

  • Package Installation Script Updated
    The package installation script was updated to install GPG-related tools if they are missing, ensuring smooth operation across different environments.

  • Modified Git Tracking
    Changes were made to the .gitignore file to avoid tracking 'private_*' files and 'SESSION_STATE.md', helping to improve privacy and version control management.

  • Documentation Enhancements
    Updates were made to the AGENTS.md documentation to provide more information about GPG agent config files and their purposes. The troubleshooting guide was also enhanced with new instructions related to handling GPG agent and resolving issues with commit prompts, improving user problem-solving capabilities.

  • Bash and Zsh Configuration Updated
    Changes were made to the Bash and Zsh configuration files so that the GPG signing passphrase is preset for non-interactive commits, thereby simplifying the commit process.

  • New System Service and Configurations
    A new systemd service was added to manage the GPG signing, providing a more sturdy architecture. Additionally, a new GPG agent configuration was created with parameters including the pinentry program and cache timeouts to optimize the tool's operation.

  • Path Update for GPG Configuration File
    The path to the GPG configuration file was updated, by renaming 'private_dot_gnupg/private_gpg.conf' to 'dot_gnupg/gpg.conf', to enhance path management.

  • GPG Signing Script
    A new executable script was added for presetting GPG passphrase into the GPG agent using a tool called 'secret-tool', making it easier to maintain secure communication.

  • Obsolete Configuration Removed
    Finally, to keep the codebase clean, an outdated configuration file labeled as 'dot_config/private_jj/config.toml' was removed.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 643e236044

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

set -euo pipefail

if command -v systemctl >/dev/null 2>&1; then
systemctl --user daemon-reload

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Guard systemd user calls when no user bus exists

In non-systemd user sessions such as devcontainers or headless SSH sessions where systemctl is installed but no user manager is running, this command fails (systemctl --user daemon-reload returns Failed to connect to bus: No medium found in the current container). Because the script has set -e, chezmoi apply aborts before completing; the binary check needs to also verify a usable user bus or tolerate this failure.

Useful? React with 👍 / 👎.

Comment thread dot_gnupg/gpg-agent.conf
@@ -0,0 +1,5 @@
pinentry-program /usr/bin/pinentry-curses

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid hard-coding a Linux pinentry path

For macOS installs supported by this dotfiles repo, applying this writes a Linux-specific /usr/bin/pinentry-curses into ~/.gnupg/gpg-agent.conf. When the signing cache is empty, gpg-agent will try that missing path instead of the platform's pinentry, so signed commits or decryption fail rather than prompting; this should be templated via lookPath/OS guards or left to GnuPG defaults.

Useful? React with 👍 / 👎.

key="{{ .gpg_signing_key }}"
[ -n "$key" ] || exit 0

command -v gpg-preset-passphrase >/dev/null 2>&1 || exit 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve gpg-preset-passphrase outside PATH

On Debian/Ubuntu the gpg-agent package installs this helper under GnuPG's libexec directory (for example gpgconf --list-dirs libexecdir reports /usr/lib/gnupg, containing gpg-preset-passphrase) rather than as a normal PATH command. In those standard shells this guard silently exits, so neither the systemd service nor the shell hook ever presets the passphrase cache and the original commit prompt hang remains.

Useful? React with 👍 / 👎.

@aadil96
aadil96 merged commit 45c24a1 into main Aug 2, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant