Skip to content

feat: add AdGuardHome CLI harness — first REST API service harness#65

Open
pyxl-dev wants to merge 3 commits intoHKUDS:mainfrom
pyxl-dev:main
Open

feat: add AdGuardHome CLI harness — first REST API service harness#65
pyxl-dev wants to merge 3 commits intoHKUDS:mainfrom
pyxl-dev:main

Conversation

@pyxl-dev
Copy link

Summary

This PR adds cli-anything-adguardhome, a CLI harness for AdGuardHome — a DNS-based ad blocker and privacy protection server.

This is the first REST HTTP API service harness in the collection, demonstrating that the CLI-Anything methodology extends beyond GUI desktop apps to network services and HTTP APIs.

What's included

  • Full API coverage: 58 endpoints across 14 tag groups (filtering, blocking, clients, stats, log, dhcp, rewrite, server, parental, safebrowsing, safesearch, tls, blocked-services, config)
  • CLI commands: filter, blocking, blocked-services, clients, stats, log, rewrite, dhcp, server, config
  • Features: --json output, REPL mode, --https flag, env vars (AGH_HOST, AGH_PORT, AGH_USERNAME, AGH_PASSWORD), config file
  • 36 passing tests: 24 unit tests (HTTP mocked via unittest.mock) + 12 E2E tests (Docker adguard/adguardhome)
  • Subprocess tests: _resolve_cli("cli-anything-adguardhome") with CLI_ANYTHING_FORCE_INSTALLED=1 support
  • setup.py: PEP 420 namespace package, cli-anything-adguardhome entry point
  • Documentation: ADGUARDHOME.md (API analysis, architecture, SOP) + README.md

Why this matters

CLI-Anything's vision is "Making ALL Software Agent-Native" — not just GUI desktop apps. AdGuardHome demonstrates the methodology works equally well for:

  • Network services with REST APIs
  • Services requiring authentication (HTTP Basic Auth)
  • Services deployed via Docker/containers

This opens the door for more service/API harnesses (e.g., Plex, Home Assistant, Grafana, etc.).

Test results

36 passed in 6.57s
- 24 unit tests (no AdGuardHome needed — HTTP mocked)
- 12 E2E tests (Docker adguard/adguardhome on port 3001)

Installation

cd adguardhome/agent-harness
pip install -e .
cli-anything-adguardhome --help

🤖 Generated with Claude Code

First REST HTTP API harness in the collection — AdGuardHome is a DNS-based
ad blocker and privacy protection server exposing 58 endpoints across 14
tag groups, secured with HTTP Basic Auth.

CLI covers all major API groups:
- filter: list/add/remove/enable/disable/refresh/status/toggle
- blocking: parental/safebrowsing/safesearch enable/disable/status
- blocked-services: list/set
- clients: list/add/remove/show
- stats: show/reset/config
- log: show/config/clear
- rewrite: list/add/remove
- dhcp: status/leases/add-static/remove-static
- server: status/version/restart
- config: show/save/test

Features: --json output, REPL mode, --https flag, env vars (AGH_HOST etc),
config file (~/.config/cli-anything-adguardhome.json)

Tests: 36 passing (24 unit + 12 E2E via Docker adguard/adguardhome)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c9127be914

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

continue

try:
args = line.split()

Choose a reason for hiding this comment

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

P2 Badge Parse REPL input with shell-style quoting

The REPL tokenizes commands with line.split(), which ignores shell quoting and breaks any argument that contains spaces. In practice, entering commands like clients add --name "My PC" --ip ... or filter add --name "My List" ... in the default interactive mode will be parsed into invalid tokens and fail with usage errors, even though the same command works in one-shot shell mode.

Useful? React with 👍 / 👎.

Comment on lines +175 to +178
path = project.save_config(
host=obj["host"], port=obj["port"],
username=obj["username"], password=obj["password"],
)

Choose a reason for hiding this comment

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

P2 Badge Respect --config when running config save

config save always calls project.save_config(...) without a config_path, so a user-provided --config path is ignored on write. This causes cli-anything-adguardhome --config /tmp/custom.json config save to silently write to the default ~/.config/cli-anything-adguardhome.json, which is inconsistent with reads and makes custom config workflows unreliable.

Useful? React with 👍 / 👎.

Comment on lines +25 to +27
for key in ("host", "port", "username", "password"):
if key in file_config:
config[key] = file_config[key]

Choose a reason for hiding this comment

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

P2 Badge Read HTTPS setting from saved config files

The config loader only copies host, port, username, and password from file, so a stored https flag is discarded. Since command setup later uses cfg.get("https", False), HTTPS cannot actually be enabled through config, which forces users to pass --https repeatedly and breaks non-443 TLS setups when that flag is omitted.

Useful? React with 👍 / 👎.

@yuh-yang
Copy link
Collaborator

Exciting! Please add the software to README

pyxl and others added 2 commits March 14, 2026 13:35
- Fix REPL argument parsing: use shlex.split() instead of str.split()
  so quoted args like --name "My PC" are handled correctly
- Fix config save: respect --config path by storing config_path in
  ctx.obj and passing it through to save_config()
- Fix HTTPS persistence: load_config() now reads 'https' key from
  saved config files (default False)
- docs: add AdGuardHome to README (badge 12 Apps, category table,
  project tree) per yuh-yang's request

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Extract duplicate Path(config_path) conversion to a single variable
- save_config() now accepts and persists the https flag, ensuring
  load/save roundtrip symmetry for all config fields

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@yuh-yang
Copy link
Collaborator

@pyxl-dev @claude

your Claude is changing all the hyphens in the README.md. Please recover those and only add contents about the new software and I can merge it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants