CLI for querying the Tailscale API
Project description
query-ts
A command-line tool for querying the Tailscale API. List and filter devices, users, groups, services, and ACLs using a small, glob-friendly query language, and render the results as a table, JSON, YAML, or plain text.
Features
- Query devices (default), users, groups, services, and ACLs.
- A simple filter DSL with glob matching, tag matching,
AND/OR, parentheses, and negation. - Human-friendly coloured tables by default, plus
--json,--yaml, and--plainoutput for scripting. - Authenticates with either a Tailscale API key or OAuth2 client credentials (tokens fetched and cached automatically).
Installation
Install from PyPI with your tool of choice:
pip install query-ts
# or, to install as an isolated tool:
uv tool install query-ts
# or:
pipx install query-ts
This installs a query-ts command and requires Python 3.11+.
To run from a checkout instead (the project is managed with uv):
uv run query-ts --help
Authentication
Provide either an API key or OAuth2 client credentials, not both. One of the two is required; the CLI exits with an error if no credentials are given.
API key
export TAILSCALE_API_KEY="tskey-api-..."
# or pass it inline with -k/--api-key
OAuth2 client credentials
Both the ID and secret are required together:
export TAILSCALE_OAUTH_CLIENT_ID="..."
export TAILSCALE_OAUTH_CLIENT_SECRET="..."
# or pass --oauth-client-id and --oauth-client-secret
An access token is obtained via the client_credentials grant and cached for
its lifetime, refreshing automatically before it expires.
Tailnet
By default the authenticated user's own tailnet (-) is used. Override it with
-n/--tailnet or the TAILSCALE_TAILNET environment variable.
Usage
query-ts [QUERY] [OPTIONS]
QUERY is an optional filter expression. Without it, all resources of the
selected type are listed.
# All devices, as a table
query-ts
# Devices whose name starts with "web-"
query-ts 'web-*'
# Production-tagged devices that aren't deprecated
query-ts 'env:production -tag:deprecated'
# Users matching a pattern
query-ts --users 'admin*'
# JSON output for two name patterns
query-ts --json 'web-* OR api-*'
# Comma-separated device names (implies plain output)
query-ts --comma 'env:prod'
# List ACL groups
query-ts --type=groups
Query language
Patterns are glob-style (fnmatch)
and matched case-insensitively against resource names.
Name patterns
| Pattern | Matches |
|---|---|
web-* |
names starting with web- |
*.example.com |
FQDNs ending in .example.com |
Tag patterns
A word containing a colon is treated as a tag filter. The prefix:suffix form
expands to the tag prefix-suffix:
| Pattern | Matches tag |
|---|---|
tag:env-prod |
env-prod |
env:prod |
env-prod (same as above) |
env:prod* |
env-prod, env-production, etc. (glob on the suffix) |
Logical operators
| Expression | Meaning |
|---|---|
web AND env:prod |
both conditions (AND is the default) |
web env:prod |
implicit AND (same as above) |
web OR env:prod |
either condition |
(web OR api) env:prod |
parentheses for precedence |
AND and OR are case-insensitive.
Negation
A leading - negates a term:
query-ts '-web-*' # exclude names matching web-*
query-ts '-tag:env-prod' # exclude tagged resources
A query that begins with - (such as a negation) would otherwise be mistaken
for a command-line option. Use -- to stop option parsing and pass it as the
query:
query-ts -- -web-* # exclude names matching web-*
Options
Resource type
| Flag | Description |
|---|---|
--devices |
Query devices (default) |
--users |
Query users |
--groups |
Query ACL groups |
--services |
Query Tailscale Services |
--acl |
Query ACL rules |
-t, --type TYPE |
Resource type: devices, users, groups, services, acl |
Output format
| Flag | Description |
|---|---|
-j, --json |
Output as JSON |
-y, --yaml |
Output as YAML |
-p, --plain |
Output as plain text (newline-separated names) |
-f, --format FORMAT |
Output format: table, json, yaml, plain |
The default format is a coloured table.
Plain-text output
| Flag | Description |
|---|---|
-s, --separator SEP |
Field separator for plain output (default: newline) |
-c, --comma |
Use a comma separator; selects plain output unless a format is set explicitly |
--field FIELD |
Field to extract in plain output (e.g. name, id) |
These options only affect plain output. When --field is omitted, a default
is chosen per resource type (hostname for devices, login for users).
Connection & authentication
| Flag | Description |
|---|---|
-k, --api-key KEY |
Tailscale API key (env: TAILSCALE_API_KEY) |
--oauth-client-id ID |
OAuth2 client ID (env: TAILSCALE_OAUTH_CLIENT_ID) |
--oauth-client-secret SECRET |
OAuth2 client secret (env: TAILSCALE_OAUTH_CLIENT_SECRET) |
-n, --tailnet NET |
Tailnet name, or - for the authenticated user's tailnet (env: TAILSCALE_TAILNET) |
Display
| Flag | Description |
|---|---|
--color / --no-color |
Force or disable colour output (auto-detected by default) |
--version |
Show the version and exit |
-h, --help |
Show help and exit |
Development
# Install dependencies (including dev tools)
uv sync
# Run the test suite
uv run pytest tests/ -v
Tests use respx to mock the Tailscale
HTTP API, so no real credentials or network access are required.
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file query_ts-1.0.0.tar.gz.
File metadata
- Download URL: query_ts-1.0.0.tar.gz
- Upload date:
- Size: 50.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e3f0dba3c6d6e77ff3e754f946ee98bccc2fbd019a1b923a0edf0703f179869c
|
|
| MD5 |
6f8b5b8daa788890c94c36e1a32e5f02
|
|
| BLAKE2b-256 |
51913ae2eb58acb46c5c481f437b47b85d59335a597ab97ff269cf16e0d91976
|
Provenance
The following attestation bundles were made for query_ts-1.0.0.tar.gz:
Publisher:
release.yml on 1stvamp/query-ts
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
query_ts-1.0.0.tar.gz -
Subject digest:
e3f0dba3c6d6e77ff3e754f946ee98bccc2fbd019a1b923a0edf0703f179869c - Sigstore transparency entry: 1616917034
- Sigstore integration time:
-
Permalink:
1stvamp/query-ts@f4792a7e51c5a4f7b5e227b45106edc18ba14a91 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/1stvamp
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f4792a7e51c5a4f7b5e227b45106edc18ba14a91 -
Trigger Event:
push
-
Statement type:
File details
Details for the file query_ts-1.0.0-py3-none-any.whl.
File metadata
- Download URL: query_ts-1.0.0-py3-none-any.whl
- Upload date:
- Size: 17.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
12bdaf173260bd91ff6a9db605143ce80d352ab78395e3016d506cfde77d2d39
|
|
| MD5 |
6e2551cbc437aa785f6ffed12138f8ce
|
|
| BLAKE2b-256 |
624dbae0ad174c61e43072fdd5963c0c3a42041d830e3d640e3140d5a2d1b9d1
|
Provenance
The following attestation bundles were made for query_ts-1.0.0-py3-none-any.whl:
Publisher:
release.yml on 1stvamp/query-ts
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
query_ts-1.0.0-py3-none-any.whl -
Subject digest:
12bdaf173260bd91ff6a9db605143ce80d352ab78395e3016d506cfde77d2d39 - Sigstore transparency entry: 1616917132
- Sigstore integration time:
-
Permalink:
1stvamp/query-ts@f4792a7e51c5a4f7b5e227b45106edc18ba14a91 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/1stvamp
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f4792a7e51c5a4f7b5e227b45106edc18ba14a91 -
Trigger Event:
push
-
Statement type: