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
12 changes: 12 additions & 0 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "hotdata-cli",
"description": "Teach Claude the Hotdata CLI: workspaces, databases, SQL, ingest, search, analytics, and geospatial",
"version": "0.43.0",
"author": {
"name": "Hotdata",
"url": "https://www.hotdata.dev"
},
"homepage": "https://www.hotdata.dev",
"repository": "https://github.com/hotdata-dev/hotdata-cli",
"license": "MIT"
}
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ pre-release-replacements = [
{ file = "skills/hotdata/subskills/search/SKILL.md", search = "^version: .+", replace = "version: {{version}}", exactly = 1 },
{ file = "skills/hotdata/subskills/analytics/SKILL.md", search = "^version: .+", replace = "version: {{version}}", exactly = 1 },
{ file = "skills/hotdata/subskills/geospatial/SKILL.md", search = "^version: .+", replace = "version: {{version}}", exactly = 1 },
{ file = ".claude-plugin/plugin.json", search = "\"version\": \"[^\"]+\"", replace = "\"version\": \"{{version}}\"", exactly = 1 },
# README.md no longer carries a hardcoded version badge — it tracks GitHub releases.
]

Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,21 @@ checks for a new release before API commands and offers to upgrade (set
`HOTDATA_NO_UPDATE_CHECK=1` to skip). Enable tab completion with
`hotdata manage completions bash|zsh|fish`.

### Claude Code plugin

To get the agent skill through Claude Code's plugin manager instead, which
updates it with each release:

```
/plugin marketplace add hotdata-dev/claude-plugins

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Merge this section only after hotdata-dev/claude-plugins is public on GitHub (not blocking).

Consequence: the PR description states that the marketplace repo does not exist yet. Until the marketplace repo exists, /plugin marketplace add hotdata-dev/claude-plugins fails for every README reader.

/plugin install hotdata-cli@hotdata
```

The plugin checks for the CLI when a session starts and offers to install it if
it's missing. Use either the plugin or the installer's skill, not both: if you
installed the CLI with the script above, install it with `HOTDATA_NO_SKILLS=1`
or Claude Code will list the skill twice.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Tell users who already ran the installer how to remove the existing skill copy (not blocking).

Suggested fix: name the command or path that removes the installer's copy, for example ~/.claude/skills/hotdata. Use hotdata manage skills instead if it has an uninstall subcommand.

Consequence: HOTDATA_NO_SKILLS=1 only skips the skill step on a new install. Re-running the installer with HOTDATA_NO_SKILLS=1 does not delete a copy that an earlier run placed. The PR description lists this case as a known limitation, but the README text implies the flag fixes the duplicate.


## Quickstart

```sh
Expand Down
37 changes: 37 additions & 0 deletions hooks/check-cli.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
# SessionStart hook for the hotdata-cli Claude Code plugin.
#
# The plugin ships the skill, not the binary. Stay silent when the CLI is
# reachable. When it isn't, stdout becomes session context asking Claude to
# offer the installer rather than run it: piping curl into sh on every session
# start is not something users agreed to by installing a skill.

set -u

DIST_BIN_DIR="$HOME/.hotdata/cli"

if command -v hotdata >/dev/null 2>&1; then
exit 0
fi

# Without Homebrew the installer puts the binary in ~/.hotdata/cli, which is
# not on PATH until the user's shell profile is reloaded.
if [ -x "$DIST_BIN_DIR/hotdata" ]; then
if [ -n "${CLAUDE_ENV_FILE:-}" ]; then
echo "export PATH=\"$DIST_BIN_DIR:\$PATH\"" >> "$CLAUDE_ENV_FILE"
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Print a context line when CLAUDE_ENV_FILE is unset (not blocking).

Suggested fix: add an else branch that tells Claude to call ~/.hotdata/cli/hotdata by full path. The missing-binary message at line 35 already gives the same instruction.

Consequence: with no CLAUDE_ENV_FILE, the hook exits silently and PATH is unchanged. Claude then runs hotdata, gets "command not found", and can offer to reinstall a CLI that is already installed.

exit 0
fi

# HOTDATA_NO_SKILLS=1: the plugin already provides the skill, so the installer
# must not add a second copy to ~/.claude/skills.
cat <<'EOF'
The hotdata CLI is not installed. Before running any hotdata command, tell the
user and ask whether to install it. If they agree, run:

curl -fsSL https://hotdata.dev/install | HOTDATA_NO_SKILLS=1 sh

If the binary lands in ~/.hotdata/cli, call it as ~/.hotdata/cli/hotdata for the
rest of this session.
EOF
exit 0
14 changes: 14 additions & 0 deletions hooks/hooks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/check-cli.sh"
}
]
}
]
}
}
10 changes: 8 additions & 2 deletions scripts/check-skills.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
# flag in its --help, must be named in skills/**/*.md, so a new command
# or flag cannot ship undocumented. Hidden flags are not in --help and
# are not checked.
# 3. Version: every SKILL.md frontmatter `version:` must equal Cargo.toml
# (finish phase only — prepare runs before cargo-release bumps them).
# 3. Version: every SKILL.md frontmatter `version:`, and the Claude Code
# plugin manifest's `version`, must equal Cargo.toml (finish phase only —
# prepare runs before cargo-release bumps them).
#
# Usage:
# scripts/check-skills.sh [--require-version]
Expand Down Expand Up @@ -125,6 +126,11 @@ if [ "$REQUIRE_VERSION" = 1 ]; then
fail=1
fi
done
pv="$(sed -nE 's/^ *"version": "([^"]+)".*/\1/p' .claude-plugin/plugin.json | head -1)"
if [ "$pv" != "$crate" ]; then
echo "error: .claude-plugin/plugin.json declares version $pv, Cargo.toml is $crate" >&2
fail=1
fi
[ "$fail" = 0 ] && echo "→ skills: version ok ($crate)"
fi

Expand Down
4 changes: 2 additions & 2 deletions skills/hotdata/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -491,10 +491,10 @@ Upgrades the CLI in place to the latest release (`brew upgrade` for Homebrew ins
If `hotdata` is not installed at all (not on PATH and not at `~/.hotdata/cli/hotdata`), install it with:

```sh
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/hotdata-dev/hotdata-cli/releases/latest/download/install.sh | sh
curl -fsSL https://hotdata.dev/install | sh
```

The installer uses Homebrew (`brew install hotdata-dev/tap/cli`) when `brew` is present, otherwise it places a prebuilt binary at `~/.hotdata/cli/hotdata`, and then installs this skill. `HOTDATA_NO_BREW=1` forces the prebuilt path; `HOTDATA_NO_SKILLS=1` skips the skill step.
The installer uses Homebrew (`brew install hotdata-dev/tap/cli`) when `brew` is present, otherwise it places a prebuilt binary at `~/.hotdata/cli/hotdata`, and then installs this skill. `HOTDATA_NO_BREW=1` forces the prebuilt path; `HOTDATA_NO_SKILLS=1` skips the skill step. When this skill came from the `hotdata-cli` Claude Code plugin, always set `HOTDATA_NO_SKILLS=1` (`curl -fsSL https://hotdata.dev/install | HOTDATA_NO_SKILLS=1 sh`) so the installer does not add a second copy.

A newer release can be incompatible with the API, so in an **interactive terminal** the CLI checks for a new release before running any API-touching command and prompts to upgrade. Declining (or `Ctrl-D`) exits without running the command — `hotdata manage upgrade` is then required to continue. The check is a **no-op in non-interactive sessions** (no TTY, `--no-input`, or `HOTDATA_NO_UPDATE_CHECK` set), so typical agent and CI usage is never blocked; set `HOTDATA_NO_UPDATE_CHECK=1` to disable it entirely.

Expand Down
Loading