A drop-in replacement for ops.pebble.Client that uses the Pebble CLI
Project description
Shimmer — a shiny Pebble client
A 100% compatible, drop-in replacement for ops.pebble.Client that drives
Pebble through its CLI instead of
the unix socket — for environments where the socket isn't reachable (such as a
Rock or a Juju container).
The same deploy-and-verify routine run over ops.pebble.Client (unix
socket, left) and shimmer.PebbleCliClient (CLI, right) — identical results.
Overview
PebbleCliClient implements the same interface as ops.pebble.Client: same
method signatures, same return types, same raised exceptions. Under the hood it
translates each call into a pebble CLI command, parses the output back into the
same Python objects ops returns, and maps CLI errors onto the matching
exceptions. The contract is parity — code written against ops.pebble.Client
should run unchanged against Shimmer.
Installation
# From PyPI
uv pip install pebble-shimmer
# Development version
git clone https://github.com/tonyandrewmeyer/shimmer
cd shimmer
uv pip install -e .
Usage
Construct the client, then use it exactly like ops.pebble.Client — the methods,
arguments, return types, and exceptions are the same:
from shimmer import PebbleCliClient as Client
client = Client()
client.replan_services()
for service in client.get_services():
print(service.name, service.current.value)
The whole point is that there's nothing new to learn: the full method surface is
documented by ops.pebble.Client.
Swapping ops.pebble.Client for shimmer.PebbleCliClient is the only change.
The constructor is where Shimmer differs, since it talks to a binary rather than a socket:
client = Client(
socket_path="/var/lib/pebble/default/.pebble.socket", # sets PEBBLE / PEBBLE_SOCKET
pebble_binary="/snap/bin/pebble", # path to the pebble binary (default: "pebble")
timeout=5.0, # default per-command timeout in seconds
)
socket_path doesn't open a socket — it points Shimmer at the daemon by setting
PEBBLE (its parent directory) and PEBBLE_SOCKET for the CLI. For drop-in
parity the constructor also accepts opener and base_url, but those only
configure the socket transport, so Shimmer accepts and ignores them. The
ops.pebble exceptions are re-exported from shimmer for convenience, but they
are the same objects, so except ops.pebble.APIError keeps working too.
Demo and verification
The GIF above is a recording of demo.md — a
Showboat document that runs one
deploy-and-verify routine against the real socket client, then the same
code against Shimmer, and diffs the two outputs to prove they're identical.
It's reproducible:
uv run python demo.py # rebuild demo.md (verifies parity live)
uv run python demo.py --record # re-record demo.cast (needs tmux + asciinema)
agg demo.cast demo.gif # regenerate the GIF from the cast
Parity is also exercised in CI by tests/integration/test_parity.py, which runs
the same operations through both clients and asserts equal results.
Limitations and parity notes
CLI invocation is the source of every limitation here — each call spawns a
pebble process, so there's more per-call overhead than the socket transport,
and some streaming is buffered rather than incremental.
A few methods can't fully match the socket client yet:
replan_services(),start_services(),stop_services(), andrestart_services()return the change ID only when no timeout is set.notify()supports custom notices only.autostart_services()is currently an alias forreplan().ack_warnings()is not yet implemented.get_warnings()is implemented for the "no warnings" case only; parsing a non-empty list raisesNotImplementedError.
get_services(), get_checks(), list_files(), get_changes(),
get_change(), and get_identities() use Pebble's structured --format json
output, so they return the same rich data as ops.pebble.Client (change
kind/tasks/err, check thresholds, real file ownership, local identity user
IDs). This requires a Pebble build that supports --format on read commands.
Comparison with ops.pebble.Client
ops.pebble.Client |
PebbleCliClient |
|
|---|---|---|
| Transport | Unix socket | pebble CLI |
| Requires | Socket access | pebble binary |
| Performance | Higher | Moderate (per-call process spawn) |
| API | Native | 100% compatible |
Troubleshooting
Pebble binary not found — pass the full path:
Client(pebble_binary="/snap/bin/pebble").
Connection error — confirm the daemon is up and PEBBLE points at its home
directory (or pass socket_path=); check pebble version.
See the commands Shimmer runs — enable debug logging:
import logging
logging.basicConfig(level=logging.DEBUG)
More
- CONTRIBUTING.md — contribution guidelines
- CHANGELOG.md — version history
- Related: ops · pebble · juju · charmcraft · rockcraft
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 pebble_shimmer-1.0.0b3.tar.gz.
File metadata
- Download URL: pebble_shimmer-1.0.0b3.tar.gz
- Upload date:
- Size: 40.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0a3f2de45f548752cd1abab43f73baa3d1c5f5de2be13d78a54636621e360802
|
|
| MD5 |
7a552d6d649473ae3716e8c0605fce94
|
|
| BLAKE2b-256 |
f64c0fe2afef3a5ec46614e144424bdb9ae1486c9f9cc4689d41a49c5edf5514
|
Provenance
The following attestation bundles were made for pebble_shimmer-1.0.0b3.tar.gz:
Publisher:
publish.yaml on tonyandrewmeyer/shimmer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pebble_shimmer-1.0.0b3.tar.gz -
Subject digest:
0a3f2de45f548752cd1abab43f73baa3d1c5f5de2be13d78a54636621e360802 - Sigstore transparency entry: 1679437490
- Sigstore integration time:
-
Permalink:
tonyandrewmeyer/shimmer@6d0dfd05341aa7c24181698207ddf6e5bea34057 -
Branch / Tag:
refs/tags/v1.0.0b3 - Owner: https://github.com/tonyandrewmeyer
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@6d0dfd05341aa7c24181698207ddf6e5bea34057 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pebble_shimmer-1.0.0b3-py3-none-any.whl.
File metadata
- Download URL: pebble_shimmer-1.0.0b3-py3-none-any.whl
- Upload date:
- Size: 22.2 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 |
f30d760a597caa5db4b726f51efbb3e0e9ffbd75885e839e62bb13baaa61679c
|
|
| MD5 |
5b9c0ccd2590dbab2eeba1f63547fa67
|
|
| BLAKE2b-256 |
f41adb28f4b5f2cdb446d9062b787313ea6f9d3dd8e932c9ae77f5fc11a2459b
|
Provenance
The following attestation bundles were made for pebble_shimmer-1.0.0b3-py3-none-any.whl:
Publisher:
publish.yaml on tonyandrewmeyer/shimmer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pebble_shimmer-1.0.0b3-py3-none-any.whl -
Subject digest:
f30d760a597caa5db4b726f51efbb3e0e9ffbd75885e839e62bb13baaa61679c - Sigstore transparency entry: 1679437576
- Sigstore integration time:
-
Permalink:
tonyandrewmeyer/shimmer@6d0dfd05341aa7c24181698207ddf6e5bea34057 -
Branch / Tag:
refs/tags/v1.0.0b3 - Owner: https://github.com/tonyandrewmeyer
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@6d0dfd05341aa7c24181698207ddf6e5bea34057 -
Trigger Event:
push
-
Statement type: