Skip to content
Merged
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
6 changes: 4 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ Default guidance for coding-agent runs in this repository.
- Use Clap field types, defaults, value parsers, argument groups, and conflicts
to enforce CLI invariants during parsing instead of recreating the same
validation in command execution.
- Each flag has one spelling; do not add aliases.
- Keep fields on Clap `Args` structs private unless another construction path is
intentional. Downstream functions should accept validated domain inputs, not
a publicly constructible bag of CLI options.
Expand Down Expand Up @@ -295,6 +296,7 @@ Default guidance for coding-agent runs in this repository.
describes, not again on the command.
- Statuses, error codes, record fields, and other commands appear in
backticks; literal examples stay literal. Value names are `UPPER_SNAKE`.
- The root help states prompting, JSON output, and exit codes, and points at
the `cli-convention` reference for record shapes and error codes. A test
- The root help states prompting, JSON output, and exit codes, points at
the embedded skills for multi-step tasks, and points at the
`cli-convention` reference for record shapes and error codes. A test
binds the error-code table in that reference to the `ErrorCode` enum.
3 changes: 3 additions & 0 deletions docs/activities.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ tk activity list --since 24h --limit 100
tk activity get --id ACTIVITY_ID
```

Activity records list votes under `data.activity.votes` with each voter's
`userId` and `selection`.

Consensus:

```bash
Expand Down
2 changes: 2 additions & 0 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ TK_NON_INTERACTIVE=true to fail fast instead.
--message-format json prints one JSON record per line, each with a `reason`
field; error records also carry a `code`. JSON output never prompts.

Before a multi-step task, read its workflow: `tk skills list`, then
`tk skills show --name NAME`.
Record shapes and error codes: `tk skills show --name references/cli-convention`.
Exit codes: 0 success, 1 runtime error, 2 usage error.
```
Expand Down
24 changes: 22 additions & 2 deletions docs/gpg-signing.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,28 @@ echo hello | tk gpg sign
```

To sign commits with this key, see [Git signing](./git-signing.md#gpg-signing).
To add the key to GitHub, paste the output of `tk gpg keys export` into
Settings, SSH and GPG keys, New GPG key.

## GitHub

```bash
# Let the GitHub CLI add GPG keys and read your account's emails.
gh auth refresh -s write:gpg_key,user:email

# Show each key's user ID.
tk gpg keys list
# List the emails GitHub has verified on your account.
gh api user/emails --jq '.[] | select(.verified) | .email'

# Upload the public key.
tk gpg keys export --key FINGERPRINT > ./signing-key.asc
gh gpg-key add ./signing-key.asc --title tk-signing
```

GitHub marks a commit Verified only when its committer email appears in the
key's user ID and is a verified email on the GitHub account. Add a missing
email under GitHub Settings, Emails, and open the confirmation link GitHub
sends; a key whose user ID lacks the email needs a new key created with that
email in its `--user-id`.

## Key management

Expand Down
8 changes: 5 additions & 3 deletions skills/bootstrapping-organization/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,14 @@ which human approves. The organization id comes from step 1.

## Troubleshooting

- `login` fails with `unauthorized` (401 or 403): the profile's public key is not
registered on a user in that organization. Add it to the root user at
https://app.turnkey.com, then rerun the same `login`.
- `login` fails with `unauthorized` (401 or 403): the profile's public key,
`details.publicKey`, is not registered on a user in that organization. Add
it to the root user at https://app.turnkey.com, then rerun the same `login`.
- `login` fails with `invalid_input` naming `profile set`: the profile was
saved with a different organization or endpoint. Run the `tk profile set`
command the message names, then `login` again.
- `login` fails with any other error: see
[managing-identities](../managing-identities/SKILL.md).
- `user tag create` fails with `api_error` and a 400: a tag with that name
already exists. Read the id from `tk --profile admin --message-format json user tag list`.
- `user update` returns `status: "pending"`: an existing policy gates user
Expand Down
7 changes: 7 additions & 0 deletions skills/managing-identities/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ intended user and the user is not a root quorum member. Deletion is final.

## Troubleshooting

- `login` fails: follow `details.nextStep` when present, checking its
condition first. A missing profile is `not_found`. A key Turnkey does not
accept is `unauthorized`; register `details.publicKey` on a user, then log
in again.
A missing credential file is `not_found` and a malformed one
`invalid_input`; neither carries `nextStep`. See
[cli-convention](../references/cli-convention.md) for the full `details`.
- `user create` fails with `not_found` for `--tag-name`: the tag does not
exist in this organization. Create it with
`tk --profile admin --message-format json user tag create --name agent` or
Expand Down
3 changes: 1 addition & 2 deletions skills/monitoring-activities/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ Inputs: the activity id from the pending record, and the approver's profile

`status` is the record status; `data.activity.status` the raw value
(`ACTIVITY_STATUS_CONSENSUS_NEEDED` while approvals are outstanding).
`data.activity.type` and `data.activity.intent` describe the request;
`data.activity.votes[]` lists votes with `userId` and `selection`.
`data.activity.type` and `data.activity.intent` describe the request.

Without an id, page through recent activities:

Expand Down
2 changes: 1 addition & 1 deletion skills/provisioning-agent-identity/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ no minting row here: the one key never expires.
- `login` fails with `unauthorized` 401 or 403: the create activity is pending or
rejected, or `PUBLIC_KEY` was mistyped. Compare
`tk --profile admin --message-format json api-key list --user-id AGENT_USER_ID`
with `data.publicKey` from step 2.
with the error's `details.publicKey`.
- The self-registration in step 6 returns `completed` or `pending`: the DENY
is missing or names the wrong tag, such as the `''` an unset `AGENT_TAG`
leaves. First create `agents-no-credentials` and
Expand Down
4 changes: 2 additions & 2 deletions skills/references/cli-convention.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ this shape:
| `reason` | `command_result` |
| `command` | dotted command name, for example `user.create`, `secret.env`, `auth.whoami` |
| `status` | `completed`, `pending`, `rejected`, `failed`, or `unknown`; a record without an activity is `completed` |
| `data` | the command's payload; for API-backed commands it preserves the API response shape |
| `data` | the command's payload; for API-backed commands it preserves the API response shape, except that activity records omit each vote's nested `user`; `request` prints the response unchanged |
| `activity` | present when the command submitted or observed an activity: `{"id", "status"}` with the raw `ACTIVITY_STATUS_*` value |

Created resource ids live under `data.activity.result`, for example
Expand Down Expand Up @@ -75,7 +75,7 @@ Any command can print an error record instead, with exit code `1` or `2`:
| `reason` | `command_error`, or `missing_required_input` when a value was absent in non-interactive mode |
| `code` | the stable classification below |
| `httpStatus` | present for HTTP failures |
| `details` | recovery data: the last observed `activity` `{id, status}`, `pending` exports, or session expiry fields |
| `details` | recovery data: the last observed `activity` `{id, status}`, `pending` exports, session expiry fields, or, for profile and credential failures, the `profile`, saved `profiles`, credential `path`, or rejected `publicKey` and `organizationId`, plus `nextStep` suggesting a fix and the condition it assumes when no profile is selected, the named profile does not exist, or Turnkey rejects the key in `login` or `whoami` |
| `message` | the full error chain, for humans |

Error records carry no `schemaVersion`, `data`, or `activity`.
Expand Down
5 changes: 3 additions & 2 deletions skills/signing-git-commits/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ Result: commits and tags signed by a key that never leaves Turnkey, which
- Signing waits synchronously, so the policy is allow-always for the agent
user, scoped to the exact resource: `wallet.id` for GPG, `private_key.id`
for SSH. See [policy-patterns.md](../references/policy-patterns.md#signing-key-policies).
- Local verification is the success criterion. A hosting provider's "Verified"
badge needs the public key and committer email there; this makes no claim.
- Local verification is the success criterion. A hosting provider's
"Verified" badge is an external step this workflow makes no claim about;
for a GPG key on GitHub, see [gpg-signing](../../docs/gpg-signing.md#github).
- SSH signing has two paths. Direct: `gpg.ssh.program` runs `tk` (step 6),
so git's process runs `tk` and git's boundary holds the Turnkey credential.
Agent: `gpg.ssh.program` is `ssh-keygen` with `SSH_AUTH_SOCK` on the
Expand Down
Loading
Loading