takopi-ghauth adds a /ghauth command to Takopi for GitHub App token operations.
It is designed with a strict split:
- Background refresh runs outside Takopi (user
systemdtimer + refresh script). - Takopi plugin provides visibility and manual control (
/ghauth status|refresh|flow).
This keeps token rotation hands-off and reproducible, while still giving operators chat-based diagnostics.
This setup intentionally uses GitHub access through gh CLI, without requiring Takopi restarts on hourly token rotation.
- Adds
/ghauthcommand backend to Takopi viatakopi.command_backendsentrypoint. - Reads plugin config from
[plugins.ghauth]in Takopi config. - Reports token file freshness and token prefix (never prints full token).
- Optionally triggers the refresh script and returns success/failure with output tail.
- It does not run a scheduler inside Takopi.
- It does not store long-lived credentials in plugin code.
- It does not replace your refresh timer/service.
- GitHub App private key + metadata are stored locally.
- Refresh script mints installation token from GitHub App API.
- Script writes token to
~/.config/takopi/github-token.env. - Script updates
ghCLI auth with the new token. - User
systemdtimer runs script every ~45 minutes. - Engine tasks use
gh/gh apifor GitHub access. /ghauthlets you inspect health or trigger a manual refresh.
/ghauth help: command usage/ghauth flow: architecture/flow summary/ghauth status: token file presence, age, and prefix/ghauth refresh: executes refresh script once and reports result
Set under [plugins.ghauth] in ~/.takopi/takopi.toml:
[plugins.ghauth]
token_env_file = "~/.config/takopi/github-token.env"
refresh_script = "~/.local/bin/takopi-refresh-github-token"
run_refresh_with = [] # example: ["sudo", "-n"]
max_token_age_minutes = 55
refresh_timeout_seconds = 30Config meanings:
token_env_file: env file written by refresh script.refresh_script: script invoked by/ghauth refresh.run_refresh_with: optional command prefix (for privileged wrappers).max_token_age_minutes: threshold for stale warning in/ghauth status.refresh_timeout_seconds: timeout for manual refresh command.
Prereqs:
- GitHub App already created and installed on target repo(s).
- You know
GITHUB_APP_IDandGITHUB_APP_INSTALLATION_ID. - Private key
.pemexists on your local machine. - Host has
curl,jq,openssl,gh,systemd --user,uv, andtakopi.
Prefer copying directly to the final location:
ssh takopi@<server> 'mkdir -p ~/.config/takopi && chmod 700 ~/.config/takopi'
scp <local-key>.pem takopi@<server>:~/.config/takopi/github-app.pem
ssh takopi@<server> 'chmod 600 ~/.config/takopi/github-app.pem'If you must use /tmp, do so only temporarily and clean it up immediately after bootstrap:
scp <local-key>.pem takopi@<server>:/tmp/github-app.pemcd /home/takopi/takopi-ghauth
GITHUB_APP_ID=123456 \
GITHUB_APP_INSTALLATION_ID=987654 \
GITHUB_APP_PRIVATE_KEY_PATH=~/.config/takopi/github-app.pem \
./scripts/bootstrap_user_refresh.shThis script:
- Installs key to
~/.config/takopi/github-app.pemwith0600. - Writes app metadata to
~/.config/takopi/github-app.env. - Creates refresh script at
~/.local/bin/takopi-refresh-github-token. - Refreshes
ghCLI auth on each token rotation. - Creates timer/service units:
~/.config/systemd/user/takopi-github-token-refresh.service~/.config/systemd/user/takopi-github-token-refresh.timer- Enables timer and runs an immediate refresh.
If you staged the key in /tmp, clean it up now:
rm -f /tmp/github-app.pem /tmp/gitub-app.pemcd /home/takopi/takopi-ghauth
./scripts/install_local.shNotes:
- Script installs
takopi-ghauthinto the Takopi uv tool env. - If Takopi transport is Discord, it preserves
takopi-discord. - Add extra tool deps if needed:
TAKOPI_INSTALL_WITH="some-package another-package" ./scripts/install_local.shtakopi plugins
takopi plugins --loadExpected output includes:
command backends:ghauth (takopi-ghauth)
systemctl --user restart takopi
journalctl --user -u takopi -n 50 --no-pagerLook for plugin registration logs.
No recurring restart is needed for token rotation with the gh-auth flow.
If you previously added a Takopi service EnvironmentFile for token env vars, remove it to avoid stale in-process tokens.
After Takopi is online in Discord/Telegram:
/ghauth status/ghauth refresh/ghauth flow
If refresh fails, /ghauth refresh returns output tail for debugging.
For GitHub reads/writes in agent tasks, prefer gh and gh api commands. Example:
gh issue view 651 -R dClimate/aegis-monorepo --json number,title,url
gh api repos/dClimate/aegis-monorepo/issues/651- Keep only one key copy on host:
~/.config/takopi/github-app.pem. - Remove temporary key copies (especially
/tmp) right after bootstrap. - Keep
.pemand env files mode0600and config dir mode0700. - Never print full token; this plugin only reports prefix.
- Prefer GitHub App installation tokens over static PATs.
- Restrict GitHub App repository access to selected repos.
Stronger security option:
- Use an external secret manager/token broker (for example Vault or a dedicated token-mint service) so the GitHub App private key does not live on the Takopi host.
- In that model, Takopi receives short-lived installation tokens only.
script not foundfrom/ghauth refresh:- Fix
plugins.ghauth.refresh_scriptpath.
- Fix
token missingin/ghauth status:- Run refresh script manually and check API credentials.
ghsays not authenticated:- Run
~/.local/bin/takopi-refresh-github-tokenmanually once. - Check
gh auth status.
- Run
- Plugin not listed in
takopi plugins:- Re-run
./scripts/install_local.sh. - Restart Takopi service.
- Re-run
- Timer not running:
systemctl --user status takopi-github-token-refresh.timer