Install | Usage | Agent Skills
Stop risking token leaks - Use secure, short-lived GitHub tokens for local development
[!NOTE] If you are a coding agent and ghtkn is installed, run
ghtkn docs listto list the documentation andghtkn docs show <name>to read it before answering questions about ghtkn or troubleshooting its errors. The embedded documentation matches the installed version. If ghtkn isn't installed, read the documents listed in Documentation and skills.
Are you still using Personal Access Tokens (PATs) or GitHub CLI OAuth tokens stored on your local machine? These long-lived tokens pose significant security risks:
ghtkn (pronounced G-H Token) generates 8-hour User Access Tokens from GitHub Apps using Device Flow - a fundamentally more secure approach:
ghtkn allows you to manage multiple GitHub Apps through configuration files and securely store tokens using OS keyring (Windows Credential Manager, macOS Keychain, or GNOME Keyring) or another backend.
Only on this accountYou don't need to create secrets such as Client Secrets and Private Keys.
ghtkn init and modify itghtkn init
%APPDATA%\ghtkn\ghtkn.yaml${XDG_CONFIG_HOME:-${HOME}/.config}/ghtkn/ghtkn.yamlapps:
- name: suzuki-shunsuke/none
client_id: xxx # Mandatory. GitHub App Client ID
[!NOTE]
The GitHub App Client ID is not a secret, so there's generally no problem writing it in plain text in local configuration files.
ghtkn auth for authenticationghtkn auth
https://github.com/login/device will open in your browser, so enter the code displayed in the terminal and approve it.
With Device Flow, access tokens cannot be generated in non-interactive environments like CI. ghtkn is primarily intended for local development.
You can close the opened tab.
ghtkn get to get a user access tokenghtkn get
A user access token starting with ghu_ is outputted.
Day to day you shouldn't need to look at the token at all: ghtkn exec runs a command with the token in an environment variable, so it doesn't pass through your shell, your terminal output, or an agent's transcript. The step above is only here to show you what ghtkn issues.
gh issue create using the access tokenREPO=suzuki-shunsuke/ghtkn # Please change this to your public repository
ghtkn exec -e GH_TOKEN -- gh issue create -R "$REPO" --title "Hello, ghtkn" --body "This is created by ghtkn"
Then it fails due to the permission error even if you have the permission.
GraphQL: Resource not accessible by integration (createIssue)
Please grant the permission issues:write to the GitHub App and run again, then it still fails.
Please install the app to the repository and run again, then it succeeds.
At this time, the issue creator will be you, not the App.
The permissions (Permissions and Repositories) of a user access token are held by both the authorized user (i.e. you) and the GitHub App. Therefore, as shown above, the GitHub App cannot perform operations that it is not permitted to perform, and conversely, the user cannot perform operations that they are not authorized to perform.
ghtkn exec runs a command with the access token in its environment:
ghtkn exec -- gh pr view
ghtkn exec -e GH_TOKEN -- gh pr view
ghtkn exec -e PINACT_GITHUB_TOKEN:suzuki-shunsuke/read -e GH_TOKEN:suzuki-shunsuke/write -- bash foo.sh
The token goes to GITHUB_TOKEN by default, or to the variables given with -e, one per app. Unlike ghtkn get, ghtkn writes the token nowhere, so it can't land in your terminal output, a log, or a coding agent's transcript by accident. The command still receives it, so one that prints its own environment exposes it. The -- is required: everything after it belongs to the command, flags included.
You can wrap commands using shell functions or scripts.
Shell functions:
gh() {
ghtkn exec -e GH_TOKEN -- gh "$@" # No infinite loop: ghtkn runs the gh executable, which the shell function doesn't shadow
}
Shell scripts:
e.g. ~/.local/bin/gh:
#!/usr/bin/env bash
set -eu
# If GH_TOKEN or GITHUB_TOKEN is set, use it.
if [ -n "${GH_TOKEN:-}" ] || [ -n "${GITHUB_TOKEN:-}" ]; then
# echo "[WARN] skip ghtkn because GH_TOKEN or GITHUB_TOKEN is set" >&2
exec /opt/homebrew/bin/gh "$@" # Specify the absolute path to avoid infinite loop
fi
exec ghtkn exec -e GH_TOKEN -- /opt/homebrew/bin/gh "$@"
If the command is managed by aqua, aqua exec is useful:
exec aqua exec -- gh "$@"
chmod +x ~/.local/bin/gh
It's useful to wrap gh using shell script as gh always requires GitHub access tokens.
ghtkn ships a single skill. It holds no documentation of its own: it tells the coding agent to read the documentation embedded in the ghtkn binary with ghtkn docs list and ghtkn docs show <name>, so the agent always reads the documentation of the version it is actually running.
gh skill install suzuki-shunsuke/ghtkn ghtkn
[!NOTE] ghtkn used to ship one skill per topic (
ghtkn-backend,ghtkn-sandbox, and so on). The singleghtknskill replaces all of them, and installing it doesn't remove the old ones, so delete theghtkn-*directories from your skills directory (~/.claude/skills, for instance) after upgrading. Left in place, they keep serving the documentation of whichever version you installed them from.
Detailed documentation is split by topic under docs/. These documents are embedded in the ghtkn binary, so ghtkn docs list and ghtkn docs show <name> serve exactly what is listed below. They are the single source of truth, shared between this README, the embedded documentation, and the skill, so there's no duplicated maintenance.
ghtkn exec, without printing them.ghtkn auth, the device flow, and clipboard.keyring, text, agent); useful for containers and microVMs.Go
99.1%
Install | Usage | Agent Skills
Stop risking token leaks - Use secure, short-lived GitHub tokens for local development
[!NOTE] If you are a coding agent and ghtkn is installed, run
ghtkn docs listto list the documentation andghtkn docs show <name>to read it before answering questions about ghtkn or troubleshooting its errors. The embedded documentation matches the installed version. If ghtkn isn't installed, read the documents listed in Documentation and skills.
Are you still using Personal Access Tokens (PATs) or GitHub CLI OAuth tokens stored on your local machine? These long-lived tokens pose significant security risks:
ghtkn (pronounced G-H Token) generates 8-hour User Access Tokens from GitHub Apps using Device Flow - a fundamentally more secure approach:
ghtkn allows you to manage multiple GitHub Apps through configuration files and securely store tokens using OS keyring (Windows Credential Manager, macOS Keychain, or GNOME Keyring) or another backend.
Only on this accountYou don't need to create secrets such as Client Secrets and Private Keys.
ghtkn init and modify itghtkn init
%APPDATA%\ghtkn\ghtkn.yaml${XDG_CONFIG_HOME:-${HOME}/.config}/ghtkn/ghtkn.yamlapps:
- name: suzuki-shunsuke/none
client_id: xxx # Mandatory. GitHub App Client ID
[!NOTE]
The GitHub App Client ID is not a secret, so there's generally no problem writing it in plain text in local configuration files.
ghtkn auth for authenticationghtkn auth
https://github.com/login/device will open in your browser, so enter the code displayed in the terminal and approve it.
With Device Flow, access tokens cannot be generated in non-interactive environments like CI. ghtkn is primarily intended for local development.
You can close the opened tab.
ghtkn get to get a user access tokenghtkn get
A user access token starting with ghu_ is outputted.
Day to day you shouldn't need to look at the token at all: ghtkn exec runs a command with the token in an environment variable, so it doesn't pass through your shell, your terminal output, or an agent's transcript. The step above is only here to show you what ghtkn issues.
gh issue create using the access tokenREPO=suzuki-shunsuke/ghtkn # Please change this to your public repository
ghtkn exec -e GH_TOKEN -- gh issue create -R "$REPO" --title "Hello, ghtkn" --body "This is created by ghtkn"
Then it fails due to the permission error even if you have the permission.
GraphQL: Resource not accessible by integration (createIssue)
Please grant the permission issues:write to the GitHub App and run again, then it still fails.
Please install the app to the repository and run again, then it succeeds.
At this time, the issue creator will be you, not the App.
The permissions (Permissions and Repositories) of a user access token are held by both the authorized user (i.e. you) and the GitHub App. Therefore, as shown above, the GitHub App cannot perform operations that it is not permitted to perform, and conversely, the user cannot perform operations that they are not authorized to perform.
ghtkn exec runs a command with the access token in its environment:
ghtkn exec -- gh pr view
ghtkn exec -e GH_TOKEN -- gh pr view
ghtkn exec -e PINACT_GITHUB_TOKEN:suzuki-shunsuke/read -e GH_TOKEN:suzuki-shunsuke/write -- bash foo.sh
The token goes to GITHUB_TOKEN by default, or to the variables given with -e, one per app. Unlike ghtkn get, ghtkn writes the token nowhere, so it can't land in your terminal output, a log, or a coding agent's transcript by accident. The command still receives it, so one that prints its own environment exposes it. The -- is required: everything after it belongs to the command, flags included.
You can wrap commands using shell functions or scripts.
Shell functions:
gh() {
ghtkn exec -e GH_TOKEN -- gh "$@" # No infinite loop: ghtkn runs the gh executable, which the shell function doesn't shadow
}
Shell scripts:
e.g. ~/.local/bin/gh:
#!/usr/bin/env bash
set -eu
# If GH_TOKEN or GITHUB_TOKEN is set, use it.
if [ -n "${GH_TOKEN:-}" ] || [ -n "${GITHUB_TOKEN:-}" ]; then
# echo "[WARN] skip ghtkn because GH_TOKEN or GITHUB_TOKEN is set" >&2
exec /opt/homebrew/bin/gh "$@" # Specify the absolute path to avoid infinite loop
fi
exec ghtkn exec -e GH_TOKEN -- /opt/homebrew/bin/gh "$@"
If the command is managed by aqua, aqua exec is useful:
exec aqua exec -- gh "$@"
chmod +x ~/.local/bin/gh
It's useful to wrap gh using shell script as gh always requires GitHub access tokens.
ghtkn ships a single skill. It holds no documentation of its own: it tells the coding agent to read the documentation embedded in the ghtkn binary with ghtkn docs list and ghtkn docs show <name>, so the agent always reads the documentation of the version it is actually running.
gh skill install suzuki-shunsuke/ghtkn ghtkn
[!NOTE] ghtkn used to ship one skill per topic (
ghtkn-backend,ghtkn-sandbox, and so on). The singleghtknskill replaces all of them, and installing it doesn't remove the old ones, so delete theghtkn-*directories from your skills directory (~/.claude/skills, for instance) after upgrading. Left in place, they keep serving the documentation of whichever version you installed them from.
Detailed documentation is split by topic under docs/. These documents are embedded in the ghtkn binary, so ghtkn docs list and ghtkn docs show <name> serve exactly what is listed below. They are the single source of truth, shared between this README, the embedded documentation, and the skill, so there's no duplicated maintenance.
ghtkn exec, without printing them.ghtkn auth, the device flow, and clipboard.keyring, text, agent); useful for containers and microVMs.Go
99.1%