Repository navigation
fix(core): install deepgram-skills-v1.8.0 by default - #154
Merged
Merged
Conversation
Pins the default skills bundle to deepgram/skills v1.8.0 (02bc27c): Voice Agent Think Live, multilingual Flux TTS, Nova-3 Configure and language_hint, and the CLI skill tracking deepctl 0.4.0.
dg-coreylweathers
requested review from
GregHolmes and
deepgram-kiley
as code owners
October 29, 2026 13:00
GregHolmes
approved these changes
Oct 29, 2026
Merged
dg-coreylweathers
added a commit
that referenced
this pull request
Nov 12, 2026
…#159) ## deepctl 0.4.1 This release prevents potential logging of API keys, and fixes how dg handles credentials, configuration, plugins and local servers. - 0.4.1 sends no telemetry. The error-report key that 0.2.21 to 0.4.0 shipped is removed. - dg sends your API key only to the host you chose: a regional Deepgram API host, a host you listed in your own config, or `DEEPGRAM_BASE_URL`. - Crash output no longer prints local variables, which could include an API key. - A project `deepgram.yaml` can no longer set credentials, trusted hosts or the programs dg runs. If you used 0.2.21 to 0.4.0, we recommend upgrading to 0.4.1 and rotating any API key you used with it. If you logged in through your browser, log in again after upgrading. ### What's fixed **Credentials and network (deepctl-core, api, login, listen, speak, mcp, debug-probe)** - dg sends the API key only to a regional Deepgram API host (`api.deepgram.com`, `api.eu.deepgram.com`, `api.au.deepgram.com` or `api.in.deepgram.com`, and only over https on the default port), a host listed in `api.allowed_hosts` in the user's own config, or `DEEPGRAM_BASE_URL`. A `DEEPGRAM_BASE_URL` set in an AI agent session doesn't count. `dg mcp` sends the key to `api.dx.deepgram.com`, or to a `--base-url` host listed in `api.allowed_hosts`. Device login (`dg login` without `--api-key`) uses `id.dx.deepgram.com` under the same rule. Any other host is refused before a request is made. - REST calls, WebSocket connections (live `dg listen`, `dg speak` with Flux, `dg debug probe`) and `dg api` no longer follow redirects. Without this change, a 3xx response could pass the key, audio or text on to another host. - `DEEPGRAM_CLI_INSECURE` turns off TLS verification only when it is set to `1`/`true`, only for localhost, 127.0.0.1 and ::1, and never in an AI agent session. **Configuration (deepctl-core)** - A project `deepgram.yaml` can no longer set credentials, trust settings or the programs dg runs. Any `--config` file other than the default `config.yaml` can no longer set trust settings or the programs dg runs. - The config file is written owner-only and atomically. It's locked against concurrent saves. A config that couldn't be read is never overwritten. Oversized or deeply nested YAML is refused. - In an AI agent session, dg uses the trust settings in the user config only from the file at its standard location under the real home directory, reached without a symlink, with one hard link, owned by the user and not writable by the group or others. It also doesn't use the API key from a user config that another user owns or the group or others can write. **Plugins (deepctl-core, plugin)** - A plugin can't replace a built-in command unless the user names it in `plugins.allow_override`. Plugin command names have to match a strict pattern. - `dg plugin search` lists only plugins that Deepgram publishes. - The plugin folders are created private (0700). In an AI agent session, dg uses the plugin environment that `dg plugin install` manages only from the real home directory, reached without a symlink, and skips it if another user owns its folders or the group or others can write to them. Plugins installed in dg's own Python environment still load. - In an AI agent session, dg refuses `dg plugin install`/`update`/`remove` and `dg ffprobe --path`. **Local servers and tools (mcp, debug-probe, debug-audio, shared-utils, ffprobe, init, install scripts)** - `dg mcp` runs over stdio only. The SSE mode, which had no authentication, is removed. Streamable HTTP was never supported. The docs proxy now ships inside `deepctl-cmd-mcp` (vendored from deepgram-mcp 0.1.1, MIT). It forwards only `search_deepgram_knowledge_sources` and makes no network connection until a tool is called. - `dg debug probe` accepts connections only from native clients and pages on localhost, 127.0.0.1 or [::1]. Requests from any other origin get a 403 before the upstream connection opens. - ffprobe gets its input as `file:<absolute path>`, so a file name that starts with `-` is never read as an option. ffprobe itself is looked up from an absolute configured path or from `PATH`, skipping relative entries. - `dg init` writes `.env` owner-only, adds it to `.gitignore`, and clones with `--`. - When `install.sh` or `install.ps1` has to install uv (no uv, pipx or pip found), it installs a pinned uv release and checks its installer against its sha256 before running it. **Telemetry and crash output (telemetry, root)** - 0.4.1 sends no telemetry. The Sentry key that 0.2.21 to 0.4.0 shipped is removed, and there is no built-in destination, so dg sends no error reports whatever the settings, and doesn't load the Sentry SDK. The error-report code stays for a later opt-in, rebuilt to send only allowlisted fields (command path, flag names, versions, OS, frame locations) with no values; in 0.4.1 it can reach only a loopback `DEEPCTL_TELEMETRY_DSN`, which exists for tests. - `dg --help` ends with "This version of dg sends no telemetry." The README says the same: no error reports, usage data or other telemetry. dg still contacts the Deepgram API for the commands you run, and pypi.org to check for updates. - Crash tracebacks no longer print local variables, which could include an API key. - In 0.4.0, `dg login`, `dg projects` and `dg update` could erase a `telemetry.enabled: false` opt-out, because every config save dropped the `telemetry` section. 0.4.1 keeps it, so it is still in place if reporting comes back. **Other** - Upgrade hints and `dg update` name the `deepgram` Homebrew formula. The old hint, `brew upgrade deepctl`, failed. - dg no longer splits a hyphenated file name into a command: `dg listen debug-call.wav` used to read the file as `debug call.wav`. Only the command name itself is expanded (`dg debug-audio` still works). - `dg --help` and other output no longer crash when stdout or stderr can't encode a character, as with a redirected or piped Windows console (cp1252). Characters the stream can't write are escaped instead. - A config file that can't be looked up (for example a symlink being replaced, or a folder that can't be searched) is reported as unreadable instead of crashing dg. It is never trusted or saved over. ### Upgrade notes | Change | What to do | |---|---| | `dg mcp --transport sse` now exits with an error. `--transport streamable-http` was never supported and still exits with an error. Only stdio is supported. `--port` and `--host` are still accepted, and ignored. | Remove `--transport`, `--port` and `--host` from your editor's MCP config, or set `--transport` to `stdio`. | | `dg mcp` exposes only `search_deepgram_knowledge_sources` and reads the API key on each call rather than at startup. | Nothing, unless you used another remote tool. | | deepctl no longer depends on `deepgram-mcp`; the docs proxy ships inside deepctl-cmd-mcp. A pip or pipx upgrade leaves the old `deepgram-mcp` package and its `deepgram-mcp` command installed (with pipx, inside deepctl's environment, not on your PATH). `uv tool upgrade deepctl` removes it. | pip: `pip uninstall deepgram-mcp`. pipx: `pipx runpip deepctl uninstall deepgram-mcp`. Point editor configs at `dg mcp`. | | The API key goes only to `api.deepgram.com`, `api.eu.deepgram.com`, `api.au.deepgram.com`, `api.in.deepgram.com` (over https on the default port only), hosts in `api.allowed_hosts`, or `DEEPGRAM_BASE_URL`. A `DEEPGRAM_BASE_URL` set in an AI agent session doesn't count. `dg mcp` sends it to `api.dx.deepgram.com` or a host in `api.allowed_hosts`, and `dg login` without `--api-key` uses `id.dx.deepgram.com` under the same rule. dg refuses a `--base-url` or profile that points anywhere else. | For a proxy or self-hosted deployment, add its host (optionally `host:port`) to `api.allowed_hosts` in your user `config.yaml`. | | A plain `http://` base URL is refused unless the host is loopback (localhost, 127.0.0.0/8 or [::1]). A loopback base URL from `--base-url` or a profile must also be listed in `api.allowed_hosts`. Only `DEEPGRAM_BASE_URL` is exempt, and not in an AI agent session. | Use https, or a local server on localhost, 127.0.0.1 or [::1]. For a local server, add its host to `api.allowed_hosts`, or set `DEEPGRAM_BASE_URL` outside an AI agent session. | | A project `deepgram.yaml` is read only for `output.*` settings and a regional Deepgram `base_url`. Everything else is ignored with a warning: `api_key`, `project_id`, the active/default profile, other `base_url`s, and the `api`, `tools`, `telemetry`, `update` and `plugins` sections. | Move those settings to your user `config.yaml`, or set them with env vars or flags. | | Any `--config` file other than the default `config.yaml` loses its `api`, `tools`, `plugins` and `update` sections, and any non-regional `base_url`. It can still hold credentials and profiles. | Same as above. | | A `--config` path that isn't a regular file (a FIFO, `<(...)` or `/dev/stdin`) is no longer read. dg warns and runs without it. | Pass a regular file. | | In an AI agent session, dg doesn't use the API key or the trust settings from a user config that another user owns or the group or others can write. It still reads the file, but drops its API keys and `dg_token_expires_at`, and handles its `api`, `tools`, `plugins` and `update` sections and any non-regional `base_url` as it does for a `--config` file. | `chmod go-w` the file and its folder, or `chown` it to yourself. | | In an AI agent session, a user config managed by a dotfile manager loses its trust settings: a symlinked file or folder on the way from the real home directory, a file with more than one hard link, or a file found through `HOME` or `XDG_CONFIG_HOME` instead of the real home. dg keeps using its API key, but drops `api.allowed_hosts` (the whole `api` section), `tools`, `plugins`, `update` and any non-regional `base_url`. | Make the file at the standard location under your real home directory a regular file with one link, or set those values outside an AI agent session. | | `DEEPGRAM_CLI_INSECURE` works only for `1`/`true`, only for localhost/127.0.0.1/[::1], and never in an AI agent session. | Use it only against a local dev server. | | 0.4.1 sends no telemetry. `DEEPCTL_TELEMETRY_DISABLED` and `telemetry.enabled` are still accepted, and the new `--no-telemetry` flag is accepted too, but none of them has an effect in this version. `DEEPCTL_TELEMETRY_DISABLED` now reads any non-empty value except `0`, `false`, `no` and `off` (in any case) as off; before, only `1`, `true` and `yes` did. | Nothing. You can leave these settings in place. | | `DEEPCTL_TELEMETRY_DSN` is honored only for a loopback host, for tests. Any other value is ignored. There is no built-in destination. The README section on overriding the destination was removed, and the README now says the variable is ignored unless it points at the local machine. | Nothing: 0.4.1 sends no reports, so a fork or self-hosted Sentry gets none either. | | Plugin command names must match `^[a-z][a-z0-9-]{0,63}$`. A plugin can't replace a built-in command: dg runs the built-in and prints a warning. A plugin whose entry point is named like a built-in command is skipped before it's imported. | Rename the entry point. To let a trusted plugin replace one, add the command to `plugins.allow_override` in your user `config.yaml` (see README, "Plugins"). | | `dg plugin search` lists only plugins that Deepgram publishes. | Install third-party plugins by package name. | | In an AI agent session, dg refuses `dg plugin install`/`update`/`remove` and `dg ffprobe --path`. | Run them yourself in a terminal. | | A configured ffprobe path must be absolute. Relative and current-directory entries on `PATH` are skipped. | Run `dg ffprobe --path /absolute/path/to/ffprobe` again if needed. | | `dg login` no longer saves `--base-url` or `DEEPGRAM_BASE_URL` to the profile; it prints that the URL was used for this login only. | To save it, run `dg login --save-base-url` with the URL and confirm at a terminal. For a non-Deepgram host, this also adds the host to `api.allowed_hosts`. | | `dg api` resolves relative paths against the profile's base URL, not always `api.deepgram.com`. An absolute URL to a host that isn't trusted is sent without your key. | Pass `--allow-foreign-host=<host>` to include the key. It must match the request host and is refused in an AI agent session. | | REST and WebSocket requests no longer follow redirects. A 3xx response now fails with an error that names both origins. `dg api` instead prints a warning that names both origins, then prints the 3xx response. | Use the final URL directly. | | `dg debug probe` refuses browser pages that aren't on localhost/127.0.0.1/[::1] (403). | Serve the page from localhost. | | The minimum versions rise for `mcp` (1.22), `websockets` in deepctl-cmd-listen (13.1), `aiohttp` in deepctl-cmd-debug-probe (3.11) and `sentry-sdk` in deepctl-telemetry (`>=2.35.0,<3`). sentry-sdk stays a dependency only for a later opt-in; 0.4.1 never imports it unless a loopback test DSN is set. | Nothing for a normal upgrade. | | A `ClickException` or `UsageError` raised inside a command is no longer printed after a "Command failed:" line; only the `Error:` line remains. Exit codes are unchanged. | Nothing, unless a script matches on "Command failed:". | | When `install.sh` or `install.ps1` has to install uv (no uv, pipx or pip found), it installs uv 0.12.24, checked against a pinned sha256, instead of the latest uv. The new `DEEPCTL_UV_INSTALLER_URL` variable points either script at a mirror of the uv installer, which must serve the same file. | Behind a firewall, set `DEEPCTL_UV_INSTALLER_URL` to a mirror of uv 0.12.24's installer. | ### Test results CI on this PR runs the full matrix, Python 3.10 to 3.14 on each OS, with 0 failures: - Linux: 3,382 passed, 9 skipped. - macOS: 3,383 passed, 9 skipped. - Windows: 2,716 passed, 676 skipped. The skipped tests are POSIX-only: file modes, POSIX paths and config layout, symlinks and fork. - Lint, types, dependency floors, the build and CodeQL pass. Sub-package floors on deepctl-core are raised to `>=0.3.1` by hand on the release PR, because the release sync job (`check_dependency_floors.py --fix`) only moves the root floors. The packages that import a deepctl-core API new in 0.3.1 are deepctl-cmd-api, deepctl-cmd-debug-audio, deepctl-cmd-debug-probe, deepctl-cmd-ffprobe, deepctl-cmd-init, deepctl-cmd-listen, deepctl-cmd-login, deepctl-cmd-mcp, deepctl-cmd-plugin, deepctl-cmd-projects, deepctl-cmd-update and deepctl-telemetry. ### Known follow-ups - Repin the skills bundle after deepgram/skills drops the SSE guidance. The pinned bundle (`deepgram-skills-v1.7.0`, also v1.8.0 in #154) still tells agents to run `dg mcp --transport sse --port 8000`, which now fails. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Points
dg skills installat the new skills release, deepgram-skills-v1.8.0. Until this ships, deepctl 0.4.0 keeps installing 1.7.0, whose CLI skill still describes deepctl 0.3.1.Changes three constants in
packages/deepctl-core/src/deepctl_core/skill_bundle.py:DEFAULT_SKILLS_COMMIT0fc13fa…(v1.7.0)02bc27cb88b97c36ad552ff0e98e7c522fd06f90(v1.8.0)DEFAULT_SKILLS_SHA2565b7f9753…33a60b2a296f70f6a0cd61b77d8fe4d7565f229136edf877b399a83278731929DEFAULT_SKILLS_RELEASEdeepgram-skills-v1.7.0deepgram-skills-v1.8.0The sha256 is of
https://codeload.github.com/deepgram/skills/tar.gz/02bc27c…. It was identical across two downloads, and the same method reproduces the old 1.7.0 value.What 1.8.0 changes in the installed skills: Voice Agent Think Live (formerly Conversational Mode), Flux TTS in 41 languages besides English, Nova-3 mid-stream
Configureandlanguage_hint, and the CLI and setup-mcp skills updated for deepctl 0.4.0. No skill is added or removed, so there are still 14.Verification
pytest: 2208 passed, 12 skippedmake check(ruff format, ruff lint, mypy): cleandg skills installwith a throwawayHOME: fetched the pinned 1.8.0 tarball, the checksum matched, it installed 14 skills, andvoice-agent/SKILL.mdcontainsthink_livetests/unit/fixtures/legacy_v03/allowlist.tsvstill names0fc13faon purpose. It records what 0.2.16–0.3.2 installs fetched frommainand is not tied to the pin.🤖 Generated with Claude Code