agentknock run
agentknock run requests selected secrets from the paired phone and runs a local command after approval. Environment secrets supply values to the command. An SSH-key secret supplies access to authentication and Git signing operations; its private key stays on the phone.
The client must have an active pairing. Use agentknock secret list to find available secret names and types.
agentknock run -s github -- gh repo viewYou can omit run: agentknock -s github -- gh repo view has the same behavior. At least one -s option and a command after -- are required.
Options
Section titled “Options”| Option | Behavior |
|---|---|
-s SECRET, --secret SECRET |
Request a secret by name. Repeat for multiple secrets; all are requested together for this command. Each name must be unique, nonempty, and contain no comma. You can combine environment secrets with at most one SSH-key secret. |
--only-env SECRET VARIABLE |
Request only the named variable from this environment secret. Repeat to include more variables from the same secret. Other selected secrets keep their own delivery settings. |
--omit-env SECRET VARIABLE |
Request all variables from this environment secret except the named variable. Repeat to omit more variables. |
--rename-env SECRET VARIABLE NEW_VARIABLE |
Deliver the stored variable under NEW_VARIABLE in the command’s environment. Repeat for other variables. The stored name and value on the phone stay unchanged. |
--stdin SECRET VARIABLE |
Send one variable’s exact value to the command’s standard input instead of adding it to the environment. Replaces inherited input; can be specified only once. |
--reason REASON |
Include an explanation with the request. Optional, but if supplied it must be nonempty. The text is sent unchanged to the phone. |
--no-ssh-passthrough |
When using an SSH-key secret, exclude other agent keys from Agentknock’s temporary agent and reject Git signing requests for another key. See SSH controls. |
--no-ssh-agent |
Remove SSH_AUTH_SOCK from the command’s environment, including an inherited or delivered value. Agentknock Git signing remains available. |
--no-git-sign |
Omit Agentknock’s Git signing integration. SSH authentication and existing Git signing configuration remain available. |
--quiet |
Suppress Agentknock’s progress, launch information, and runtime error messages. Argument errors are still printed. |
--verbose |
Show progress as each stage changes, then list the delivered environment names, standard-input source, selected SSH secret, and command being launched. Secret values and private keys are never displayed. |
--quiet and --verbose are mutually exclusive. Neither changes the command’s own output. All Agentknock options belong before --; arguments after it belong to the command.
Control environment variable delivery
Section titled “Control environment variable delivery”By default, an environment secret supplies all its variables under their stored names. Delivery options apply to the named secret for this invocation. They use the variable’s stored name, even when you also rename it.
For example, this selects one value and delivers it under the name expected by the command:
agentknock -s github --only-env github GH_TOKEN --rename-env github GH_TOKEN GITHUB_TOKEN -- ./release--only-env and --omit-env restrict which values the phone returns. --rename-env and --stdin control where a returned value goes; they don’t exclude the secret’s other values.
Standard input
Section titled “Standard input”--stdin supplies a pipe containing the exact stored value, including any existing newlines, without adding a newline. Agentknock closes the pipe after writing the value, so the command receives end-of-file. Terminal input or an incoming pipeline is replaced, not appended to the secret.
Combine --stdin with --only-env when the command needs just that value:
agentknock -s registry --only-env registry PASSWORD --stdin registry PASSWORD \ -- docker login --username example-user --password-stdin registry.example.comThe selected value is not added to the environment. Other variables from the secret are still delivered unless restricted with --only-env or --omit-env.
Valid combinations
Section titled “Valid combinations”Every secret named in a delivery option must also be selected with -s and must be an environment secret. Variable names in these options must start with an ASCII letter or underscore and contain only ASCII letters, digits, and underscores.
- Use either
--only-envor--omit-envfor a given secret. You can use different approaches for different secrets in the same command. - When using
--only-env, also select every stored variable you want to rename or send to standard input. - A variable cannot be both omitted and renamed, both omitted and sent to standard input, or both renamed and sent to standard input.
- Specify each selection, omission, or rename only once for a given stored variable. A command can receive only one value on standard input.
Agentknock rejects a response that contains missing or extra secrets, a different set of variables than --only-env requested, an omitted variable, or a missing value required by a rename or standard-input option. Invalid combinations and responses prevent the command from starting.
Combining values and inherited environment
Section titled “Combining values and inherited environment”Renaming and standard-input routing happen before values are combined. If two delivered variables have the same final environment name, their values must match; otherwise Agentknock refuses to start the command. This applies both within one secret and across selected secrets. Renaming can resolve a collision, and the order of -s options never decides which value wins.
The command inherits the client’s environment, with delivered values replacing existing values under their final names. Delivery options don’t clear inherited variables: omitting a value, renaming it, or sending it to standard input can leave an existing variable under the original name intact.
Environment values cannot contain a null byte. Standard-input delivery preserves the complete value, including null bytes. Agentknock doesn’t print returned values or store them in its configuration. The command and its descendants can read, copy, print, or store the values they receive.
SSH authentication
Section titled “SSH authentication”When an SSH-key secret is selected, Agentknock provides a temporary agent through SSH_AUTH_SOCK. SSH and tools that use it, including Git with an SSH remote, can authenticate with the selected key. The temporary agent supports Ed25519 and RSA authentication; RSA requires SHA-256 or SHA-512 signatures. Other key types, including ECDSA, aren’t offered for SSH authentication through Agentknock.
A supported selected key is listed first, followed by other keys from the existing SSH agent. A matching key from the existing agent is excluded. Each authentication operation using the selected key is sent to the phone for a separate decision. Operations using other agent keys are handled by that agent without a phone decision. After a denial, SSH can still try other available keys or authentication methods.
The existing agent is taken from a delivered SSH_AUTH_SOCK value when present, otherwise from the inherited value. If it is unavailable, the selected phone key remains available.
An SSH IdentityAgent setting can override SSH_AUTH_SOCK; set it to SSH_AUTH_SOCK for hosts that should use Agentknock. Arbitrary signing with the selected key through the agent is rejected; Git signing uses the integration described below. Adding and removing keys with ssh-add is not supported.
SSH controls
Section titled “SSH controls”--no-ssh-passthrough restricts Agentknock’s agent to the selected key and makes its Git signing helper reject requests for other keys. It doesn’t prevent the command from using private-key files or another agent explicitly selected in SSH configuration. When no SSH-key secret is selected, it has no effect on an inherited agent.
--no-ssh-agent removes SSH_AUTH_SOCK from the command’s environment. Git can still sign through Agentknock, and its signing helper can still use the existing agent for other signing keys unless --no-ssh-passthrough is also set.
--no-git-sign leaves the temporary SSH agent available but adds no Git signing integration. Combining it with --no-ssh-agent disables both forms of Agentknock access to the selected SSH key. The key is still included in the initial secret request.
When no SSH-key secret is selected, Agentknock adds neither an SSH agent nor Git signing configuration. An existing SSH_AUTH_SOCK remains available unless --no-ssh-agent removes it.
Git signing
Section titled “Git signing”With an SSH-key secret selected, Agentknock can request SSH signatures for Git commits and tags. Git signing is not limited to the SSH agent’s Ed25519 and RSA authentication keys: the CLI also accepts ECDSA signatures when supported by the phone. Git must use SSH signing and actually request a signature:
agentknock -s git-signing -- git -c gpg.format=ssh commit -S -m "Update documentation"Agentknock doesn’t enable signing, change gpg.format, or replace a configured user.signingKey. If Git has no signing key configured, Agentknock supplies the selected secret’s public key through Git’s default key command. If a signing key is configured, it must identify the selected public key for Agentknock to sign with it.
Use a public-key file or a key:: value containing the public key for user.signingKey. Key comments don’t affect matching. A path to a local private-key file uses the ssh-keygen fallback described below, even when that private key corresponds to the selected phone key.
For this command and its descendants, Agentknock sets gpg.ssh.program and gpg.ssh.defaultKeyCommand through environment-based Git configuration. These settings override existing values for those two entries without editing Git configuration files. Explicit git -c settings can override them. Use --no-git-sign to keep your existing signing program and default key command in effect.
Agentknock preserves any existing environment-based Git settings by adding its entries after them. If GIT_CONFIG_COUNT is set, its value must be a nonnegative integer or preparation of the signing integration fails.
If Git requests signing with another key, Agentknock delegates to ssh-keygen, which can use a local private key or a key from the existing agent. With --no-ssh-passthrough, that signing request fails instead. Non-signing operations, such as signature verification, continue through ssh-keygen.
Each signature using the selected key requires a separate phone decision. The request contains the exact commit or tag payload. When available, it also includes repository and branch information; commits include a changed-file count and a list of paths when there are at most 50. The list is omitted if paths cannot be represented safely as text. File contents and diffs aren’t included in that context. See Git signing for configuration and approval details.
Command selection and approval context
Section titled “Command selection and approval context”Agentknock treats the first argument after -- as an executable name or path and passes the remaining arguments unchanged. The command runs in the current working directory. An executable name without a slash is resolved through the inherited PATH, or the system default search path if PATH is unset. A name containing a slash is used as a path.
Agentknock selects the executable before requesting secrets. A missing command fails before the phone is contacted, and a returned PATH cannot change the selected executable. The returned environment can still affect programs that the command launches.
Agentknock doesn’t invoke a shell. Your calling shell performs its usual expansion before Agentknock starts, so a reference such as "$TOKEN" in the command line uses the shell’s existing value. To expand a delivered variable or run a pipeline inside the approved command, explicitly invoke a shell with sh -c '...'. In that case, the shell is the selected executable and receives the secrets.
The phone receives the secret selection, delivery options, reason, command and arguments, working directory, executable path and type, SHA-256 hash when readable, standard-stream connection types, and up to four executable paths from the process chain that launched Agentknock.
For a directly executed, readable shebang script no larger than 16 KiB, the request also includes its complete source. Larger scripts omit the source. Running ./script.py can include that file; running python script.py selects the interpreter and does not capture the script. Imported files and other runtime dependencies are not collected.
Before launch, Agentknock rechecks the executable’s hash when available; macOS also checks its file identity. A failed check prevents launch. See Command execution and trust for the platform differences and limits.
Output and errors
Section titled “Output and errors”Every line of Agentknock’s own runtime messages starts with AGENTKNOCK: followed by a space and is written to standard error. This includes progress, verbose details, and errors before launch, plus messages from SSH authentication and Git signing while the command is running. Multiline messages repeat the prefix on every line.
The command and its descendants retain their original output on standard output and standard error. The prefix helps you distinguish Agentknock’s messages when reading a terminal or combined log, even when the command also writes to standard error. A prefixed line can be routine progress; it doesn’t by itself indicate failure.
Redirecting or piping standard output alone keeps Agentknock’s messages out of the command’s data. Combining the streams with 2>&1 includes those messages. Apply redirection to the whole Agentknock invocation to capture its diagnostics; redirection only inside a launched shell may not capture Agentknock’s later SSH or Git messages.
To suppress Agentknock’s runtime messages while keeping the command’s own errors visible, use --quiet. This also suppresses Agentknock’s runtime errors, so check the exit status to determine whether the operation succeeded.
Help and command-line validation errors use ordinary CLI formatting without the prefix. Argument errors are still shown with --quiet.
The command inherits standard input unless --stdin replaces it. Waiting requests report progress and elapsed time every 30 seconds by default; --verbose also reports each stage as it changes. See Output and waiting for connection retries and response timing.
Denial, an invalid response, or failure to prepare secret delivery prevents the command from starting. An interrupt or termination signal before launch also cancels the run. Approval can already have reached the phone’s audit log even if a later interruption or launch failure prevents execution.
Once access is prepared, Agentknock replaces itself with the command. The command’s exit status and signal behavior therefore become those of the invocation. See Exit status for failures before launch.
The temporary SSH and Git signing service runs while the original command process is alive. It shuts down when that process exits; a background child that outlives it cannot keep using the service.
The service uses a private temporary directory for its sockets and signing helper. On Linux, it prefers a private, user-owned $XDG_RUNTIME_DIR and falls back to the system temporary directory if it cannot use that location. On macOS, it uses /tmp. The directory is removed when the service shuts down.