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
145 changes: 145 additions & 0 deletions .claude/skills/openhue-cli/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
---
name: openhue-cli
description: Reference for the `openhue` CLI (this repo) — every command, subcommand, flag, alias and behavior for controlling Philips Hue lights, rooms, scenes and switch controls, plus setup and the MCP server. Use whenever writing, running or explaining an `openhue ...` invocation, adding or changing a CLI command, or answering "how do I do X with openhue" / "what flags does openhue set light take". Trigger: /openhue-cli, "openhue CLI", or any `openhue <verb>` you are unsure of.
---

# openhue CLI

Cobra CLI that controls a Philips Hue Bridge through [openhue-go](https://github.com/openhue/openhue-go).
Source of truth is `cmd/` — if this file and `openhue <cmd> --help` disagree, trust `--help` and fix this file.

Run from source: `go run . <args>` (or `make build` → `./dist`).

## Command map

| Group | Command | Aliases | What it does |
|---|---|---|---|
| Configuration | `setup` | | Discover the bridge (mDNS), pair by pressing the bridge button, save config |
| | `config -b <ip> -k <key>` | | Save bridge IP + application key manually |
| | `discover` | | Print bridges found via mDNS |
| | `completion` | | Shell completion scripts |
| | `install-skill` | | Write the root `SKILL.md` (embedded in the binary) to `~/.claude/skills/openhue/` (`$CLAUDE_CONFIG_DIR/skills` if set). `--project` → `./.claude/skills`, `--dir <skills dir>`, `--print` → stdout. Overwrites; reports installed / updated / already up to date |
| | `version` | | Build info |
| Philips Hue | `get light\|room\|scene\|control\|events` | `get`=`g` | Read resources |
| | `set light\|room\|scene\|control` | `set`=`s` | Change state / activate / configure |
| | `create scene` | `create`=`c` | Create a scene |
| | `update scene` | | Edit a scene |
| | `delete scene` | | Delete one scene (irreversible) |
| MCP Server | `mcp` | | stdio MCP server for LLM clients |

Every resource subcommand accepts singular or plural (`light`/`lights`, `scene`/`scenes`, ...).

## Config & lifecycle

- Config file: `~/.openhue/config.yaml`, or `$XDG_CONFIG_HOME/openhue/config.yaml`. Keys: `Bridge`, `Key`, optional `log_level`.
- Log file: `openhue.log` next to the config.
- Without config, any command not in `CommandsWithNoConfig` (`setup`, `config`, `help`, `discover`, `auth`, `version`, `completion`, `install-skill`) prints "not configured yet, please run the 'setup' command" and exits 0.
- Commands in the `hue` group load the full `HomeModel` from the bridge in `PersistentPreRun` before running (one round-trip of all resources). Config/MCP commands skip it.

## Resolving resources

- Lights, rooms, scenes, controls, devices are accepted by **name or ID** everywhere.
- Names are not unique across rooms: use `-r/--room <name|id>` to disambiguate (`set light`, `set scene`, `get scene`, `update scene`, `delete scene`).
- Quote names with spaces: `"Living Room"`.

## get

`-j/--json` is a persistent flag on `get` (works on every subcommand). Bare `openhue get` lists all resources and also takes `-t/--type <light|scene|room...>` (not inherited by subcommands).
Default output is a table.

| Command | Args | Flags |
|---|---|---|
| `get light [id\|name...]` | optional | `-r/--room` filter by room |
| `get room [id\|name...]` | optional | — |
| `get scene [id\|name...]` | optional, multiple | `-r/--room`, `--yaml` (export a single scene as a YAML definition reusable by `create`/`update scene --from-file`) |
| `get control [id...]` | optional | `-r/--room`, `-d/--device <name\|id>`, `--kind button\|rotary` |
| `get events` | — | Streams bridge SSE events as JSON until Ctrl+C (alpha) |

`get control` shows per button the "Short press" / "Hold" assignment: `scene <name>`, `cycle: a, b, ... (n)`, `time-based`, `smart-scene <id>`, `dim-up`, or `-`. `--json` adds the raw `configuration`.

## set light / set room

Up to 10 targets at once. **`--on` is required to light up**, even when setting brightness/color.

| Flag | Meaning |
|---|---|
| `--on` / `--off` | Power |
| `-b, --brightness <0-100>` | float |
| `--rgb #RRGGBB` | hex color |
| `-x, --cie-x` / `-y, --cie-y` | CIE xy color |
| `-c, --color <name>` | named color (`white`, `lime`, `powder_blue`, ...) |
| `-t, --temperature <153-500>` | Mirek |
| `--transition-time <duration>` | e.g. `5s`, default `0s` |
| `-r, --room` | (`set light` only) force the room of the lights |

```bash
openhue set light "Hue Play TV" Desk --on --brightness 60 --rgb "#3399FF"
openhue set room Studio --off
openhue set light office1 --on -t 250 --transition-time 30s
```

## set scene

`openhue set scene <id|name> [-r room] [-a active|dynamic|static]` — activates a scene; `-a dynamic` plays its dynamic palette.

## set control

Configures a button (rotary dials are read-only). Select it by control ID, or by device name/ID + `--control <n>` (button number on the device). The accessory must already be set up on the bridge (e.g. via the Hue app). Anything the flags do not cover is left untouched.

| Flag | Meaning |
|---|---|
| `--scene <name\|id>` | Short press recalls the scene (from the button's room). Repeat to cycle through scenes in order |
| `--with-off` | Second press turns lights off |
| `--repeat-timeout <dur\|secs>` | Idle time before a scene cycle restarts (default 3s) |
| `--on-hold dim-up\|dim-down\|dim-alternate\|none` | Hold behavior |
| `--repeat-interval <dur\|ms>` | Repeat interval while held |
| `--clear` | Remove the short-press action |
| `--dry-run` | Print the configuration that would be sent; send nothing |

```bash
openhue set control "Hue dimmer switch" --control 1 --scene Cozy --with-off
openhue set control "Hue dimmer switch" --control 4 --scene Soho --scene Nebula --repeat-timeout 10s --dry-run
```

## create scene / update scene

Neither command changes the real lights — they only write the scene.

**create**: `openhue create scene <name> -r <room> [flags]`. Layering: current state of every light in the room → global flags → per-light `--light` → (and global flags override `--from-file`).

**update**: `openhue update scene <id|name> [-r room] [flags]`. Applies on top of the values **stored in the scene**; unmentioned lights keep their settings (effects, gradients). `--light` for a room light not yet in the scene adds it. `--from-file` is a patch.

Shared flags: `--on`, `--off`, `-b`, `--rgb`, `-x`, `-y`, `-c`, `-t`, `--transition-time`, `--light "<light>:<settings>"` (repeatable), `--from-file <file|->`, `--auto-dynamic`, `--speed <0-100>`, `--palette-color`, `--palette-brightness`, `--palette-temperature`, `--palette-effect` (all repeatable), `-j/--json`, `--dry-run`.
Create only: `--only-listed` (lights not given with `--light` are turned off in the scene).
Update only: `--name <new>`, `--remove-light <light>` (repeatable), `--clear-palette`.

Per-light settings (comma-separated): `on`, `off`, `brightness=<0-100>`, `rgb=<#hex>`, `x=`, `y=`, `color=<name>`, `temperature=<153-500>`, `transition=<duration>`, `effect=<name>`, `gradient=<c1>;<c2>;...`, `gradient-mode=<mode>`.

```bash
openhue create scene Work -r Office --light "Desk:on,brightness=100,temperature=250" --light "Ceiling:off"
openhue create scene Aurora -r Lounge --auto-dynamic --speed 30 --palette-color blue --palette-color "#00FF88"
openhue get scene Cozy -r "Living Room" --yaml > cozy.yaml # edit, then:
openhue update scene Cozy -r "Living Room" --from-file cozy.yaml
openhue update scene Cozy --light "Shelf:on,brightness=30" --remove-light Ceiling
```

## delete scene

`openhue delete scene <id|name> [-r room]` — exactly one scene, no confirmation prompt, cannot be undone. Export first with `get scene <name> --yaml` if a copy is wanted.

## mcp

`openhue mcp` runs a stdio MCP server. It builds its own openhue-go client from the config (does not use the preloaded `HomeModel`). Tools (defined in `cmd/mcp/tools.go`): `list_lights`, `list_rooms`, `list_scenes`, `set_light`, `set_room`, `activate_scene`.

```json
{ "mcpServers": { "openhue": { "command": "openhue", "args": ["mcp"] } } }
```

## Adding or changing a command

1. Create `cmd/<verb>/<verb>_<resource>.go` with a `NewCmd...(ctx *openhue.Context)` constructor; follow an existing sibling (e.g. `cmd/get/get_control.go`).
2. Register it on its parent (`cmd/<verb>/<verb>.go`); new top-level verbs go in `addCommands` in `cmd/root.go` with `GroupID` `hue` (loads the home) or `config`.
3. Resolve resources via the `Search*` helpers in `openhue/home_service.go` (name or ID).
4. Shared scene flags live in `cmd/scenecmd/flags.go`; shared light/room setters in `cmd/set/common.go`.
5. Test with `openhue.NewTestContext(home)` and `openhue/test/assert`; run `go test ./cmd/<verb>`.
6. Update this skill (command map + flag table) and the `Example:` block in the command's help text.
37 changes: 37 additions & 0 deletions .github/workflows/skills-sh.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Checks that the openhue skill is still discoverable by the skills CLI that
# powers https://www.skills.sh after SKILL.md changes land on main.
#
# skills.sh has no publish or update API: it reads the GitHub repo directly and
# ranks skills from install telemetry. So this only verifies the listing source;
# it does not run an install, which would add a fake install to the leaderboard.

name: skills.sh

on:
push:
branches: [ "main" ]
paths:
- "SKILL.md"
- ".claude/skills/**"
- ".github/workflows/skills-sh.yml"

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

permissions:
contents: read

jobs:
verify:
runs-on: ubuntu-latest

steps:
- uses: actions/setup-node@v4
with:
node-version: '22'

- name: List skills as the skills CLI sees them
run: |
npx --yes skills add "${{ github.repository }}" --list | sed 's/\x1b\[[0-9;]*m//g' | tee skills.txt
# The root SKILL.md is named "openhue"; fail if it is not discovered.
grep -qE '^[^A-Za-z0-9]*openhue[[:space:]]*$' skills.txt
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ bin/
dist/

# go build output
openhue-cli
/openhue-cli
6 changes: 6 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ Commands in the `hue` group trigger `LoadHomeIfNeeded` in PersistentPreRun, whic

Config stored in `~/.openhue/config.yaml` (or `$XDG_CONFIG_HOME/openhue/`). Contains bridge IP and application key. Commands listed in `CommandsWithNoConfig` can run without setup.

### CLI Reference Skill

`.claude/skills/openhue-cli/SKILL.md` documents every command, alias and flag of the CLI. **Whenever you add, rename, remove or change a command, subcommand, alias, flag, default or MCP tool, update that skill in the same change.** It covers the command map, the flag tables, the examples and the MCP tool list. Check it against `go run . <cmd> --help`; if the two disagree, `--help` is right.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

The root `SKILL.md` is the user-facing guide (install, setup, everyday usage). Update it too when a change affects how users run the CLI. It is embedded in the binary (`//go:embed` in `main.go`) and written to disk by `openhue install-skill` (`cmd/skill/`).

### Testing Pattern

- Use `openhue.NewTestContext(home)` to create test contexts with mock HomeModel
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ Check that it works:
```shell
openhue help
```
To teach Claude Code how to use the CLI, install the bundled skill:
```shell
openhue install-skill
```
To upgrade when a new version is released:
```shell
brew update
Expand Down
166 changes: 166 additions & 0 deletions SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
---
name: openhue
description: Control Philips Hue lights from the terminal with the `openhue` CLI — install it, pair it with a Hue Bridge, list and switch lights and rooms, set brightness and colors, activate, create, edit and delete scenes, configure switch buttons, and run the MCP server for LLM clients. Use when the user wants to control Hue lights, rooms or scenes, or asks how to run an `openhue ...` command.
---

# Using the openhue CLI

`openhue` controls a Philips Hue Bridge on the local network. Full docs: https://www.openhue.io/cli

When unsure about a flag, run `openhue <command> --help`. It is always right.

## 1. Install

```bash
brew tap openhue/cli
brew install openhue-cli
openhue version
```

Install this skill for Claude Code (re-run after each upgrade to refresh it):

```bash
openhue install-skill # ~/.claude/skills/openhue/SKILL.md
openhue install-skill --project # ./.claude/skills/openhue/SKILL.md
```

### Docker alternative

The image has no config of its own: mount the host config folder on `/.openhue` for every command. An alias makes the rest of this guide work as written:

```bash
alias openhue='docker run -v "${HOME}/.openhue:/.openhue" --rm -it openhue/cli'
openhue setup -b 192.168.1.68 # pass the bridge IP: mDNS rarely crosses Docker's default network
openhue get lights
```

- Config under `$XDG_CONFIG_HOME/openhue` on the host? Mount that folder instead: `-v "${XDG_CONFIG_HOME}/openhue:/.openhue"`.
- On Linux, `--network host` lets `setup` and `discover` find the bridge without `-b`.
- `install-skill` writes inside the container, so use `openhue install-skill --print > ~/.claude/skills/openhue/SKILL.md` (create the folder first).

## 2. Pair with the bridge (once)

```bash
openhue setup
```

`setup` finds the bridge via mDNS, then asks you to press the bridge's link button. Other options:
Comment thread
thibauult marked this conversation as resolved.
Resolved

| Command | Use when |
|---|---|
| `openhue discover` | Only print the bridges found on the network |
| `openhue setup -b 192.168.1.68` | mDNS discovery fails; give the bridge IP |
| `openhue config -b <ip> -k <key>` | You already have an application key |

Config is saved to `~/.openhue/config.yaml` (or `$XDG_CONFIG_HOME/openhue/`). Until it exists, Hue commands print "not configured yet, please run the 'setup' command".

## 3. Find what you have

```bash
openhue get lights
openhue get rooms
openhue get scenes
openhue get light -r "Living Room" # filter by room
openhue get lights --json # machine-readable
```

- Aliases: `get` = `g`, `set` = `s`, `create` = `c`. Singular and plural both work (`light`/`lights`).
- Resources are accepted by **name or ID**. Quote names with spaces.
- Names repeat across rooms: add `-r/--room <name|id>` to pick the right one.

## 4. Control lights and rooms

**`--on` is required to light up**, even when you only set brightness or color.

```bash
openhue set light Desk --on
openhue set room Studio --off
openhue set light "Hue Play TV" Desk --on --brightness 60 --rgb "#3399FF"
openhue set light Desk --on -c powder_blue
openhue set room Bedroom --on -t 400 --transition-time 30s
```

| Flag | Meaning |
|---|---|
| `--on` / `--off` | Power |
| `-b, --brightness` | 0–100 |
| `--rgb` | Hex color, `#RRGGBB` |
| `-c, --color` | Named color (`white`, `lime`, `powder_blue`, ...) |
| `-x` / `-y` | CIE xy color |
| `-t, --temperature` | White temperature in Mirek, 153 (cool) – 500 (warm) |
| `--transition-time` | Fade duration, e.g. `5s` |

Up to 10 lights or rooms per command.

## 5. Scenes

Activate:

```bash
openhue set scene Relax -r "Living Room"
openhue set scene Aurora -a dynamic # play the dynamic palette
```

Create (writes the scene only; lights do not change). It starts from the room's current light state:

```bash
openhue create scene Work -r Office \
--light "Desk:on,brightness=100,temperature=250" \
--light "Ceiling:off"
```

Edit or copy through YAML:

```bash
openhue get scene Cozy -r "Living Room" --yaml > cozy.yaml
openhue create scene "Cozy Copy" -r "Living Room" --from-file cozy.yaml # copy, original untouched
openhue update scene Cozy -r "Living Room" --from-file cozy.yaml # or edit cozy.yaml and apply it back
openhue update scene Cozy --light "Shelf:on,brightness=30" --remove-light Ceiling
openhue update scene Cozy --name "Cozy Evening"
```

Delete (no prompt, cannot be undone — export with `--yaml` first if you want a copy):

```bash
openhue delete scene Cozy -r "Living Room"
```

Per-light settings for `--light "<light>:<settings>"`, comma-separated: `on`, `off`, `brightness=`, `rgb=`, `color=`, `temperature=`, `x=`, `y=`, `transition=`, `effect=`, `gradient=<c1>;<c2>`, `gradient-mode=`.

Add `--dry-run` to `create`/`update scene` to preview without saving.

## 6. Switches and dimmers

Accessories must already be added to the bridge (e.g. with the Hue app).

```bash
openhue get control # show button assignments
openhue set control "Hue dimmer switch" --control 1 --scene Cozy --with-off
openhue set control "Hue dimmer switch" --control 4 --scene Soho --scene Nebula --dry-run
```

Repeat `--scene` to cycle scenes on each press. Other flags: `--on-hold dim-up|dim-down|dim-alternate|none`, `--repeat-timeout`, `--clear`. Rotary dials are read-only.

## 7. Watch live events

```bash
openhue get events # streams bridge events as JSON; Ctrl+C to stop
```

## 8. Use from an LLM (MCP server)

```json
{ "mcpServers": { "openhue": { "command": "openhue", "args": ["mcp"] } } }
```

Tools exposed: `list_lights`, `list_rooms`, `list_scenes`, `set_light`, `set_room`, `activate_scene`.

## Troubleshooting

| Symptom | Fix |
|---|---|
| "not configured yet" | Run `openhue setup` |
| Bridge not discovered | `openhue setup -b <bridge-ip>` |
| Light ignores brightness/color | Add `--on` |
| Wrong light or scene picked | Add `-r <room>` or use the ID from `get ... --json` |
| Need detail | Check `openhue.log` next to the config file |
Loading
Loading