CLI Development Sandbox — Setup Guide¶
How to create an isolated sandbox for developing, testing, and validating the franklinwh-cli tool without polluting the main source repo.
Architecture¶
~/dev/franklinwh-cloud/ ← Source repo (real work, branches, commits)
├── franklinwh_cloud/ ← Library source
├── tests/ ← Unit tests (74+)
├── venv/ ← Dev venv (pytest, respx, pytest-asyncio)
└── .gitignore ← venv/ ignored
~/dev/franklinwh-cloud-test/ ← Sandbox (CLI testing, credentials, scratch)
├── franklinwh.ini ← API credentials (never committed)
├── venv/ ← CLI venv (editable install of source repo)
└── (scratch files) ← Test JSON schedules, logs, etc.
Step 1: Create the Sandbox Directory¶
Step 2: Create a Virtual Environment¶
Step 3: Install the CLI (Editable Mode)¶
Editable mode (-e) means source changes in franklinwh-cloud/ take effect immediately — no reinstall needed.
Verify the CLI is available:
Expected output: full help text with all subcommands (status, monitor, tou, mode, etc.)
Step 4: Configure Credentials¶
Create franklinwh.ini in the sandbox directory:
cat > franklinwh.ini << 'EOF'
[franklinwh]
username = your_email@example.com
password = your_password
gateway = YOUR_GATEWAY_ID
EOF
⚠️ Never commit
franklinwh.ini— it contains your Cloud API credentials. The main repo's.gitignorealready excludes it.
To find your Gateway ID, log into the FranklinWH app or use:
Running the CLI — Three Ways¶
You can run the CLI from either the sandbox or the source repo:
# 1. Entry point (requires pip install -e in active venv)
franklinwh-cli status
# 2. Python module (works from source repo without install)
cd ~/dev/franklinwh-cloud
python -m franklinwh_cloud.cli status
# 3. Direct script (works anywhere with correct Python path)
~/dev/franklinwh-cloud/venv/bin/python -m franklinwh_cloud.cli status
Credentials: All three methods look for
franklinwh.iniin the current working directory. Eithercdto where your.inifile is, or use--config /path/to/franklinwh.ini.
Step 5: Validate the CLI¶
Run these commands in order to verify everything works:
cd ~/dev/franklinwh-cloud-test
source venv/bin/activate
# 1. Basic connectivity (read-only, safe)
franklinwh-cli status
# 2. TOU schedule inspection
franklinwh-cli tou
# 3. Current/next dispatch with remaining time
franklinwh-cli tou --next
# 4. Real-time monitor (Ctrl+C to stop)
franklinwh-cli monitor
# 5. JSON output mode
franklinwh-cli status --json
All commands should return data without errors. If you see No credentials found, check that franklinwh.ini exists in the current directory.
Step 6: Set Up the Test Harness (Main Repo)¶
The unit tests use pytest — Python's most popular testing framework. If you're new to pytest, the key things to know are:
- Tests are plain Python files named
test_*.py - Each test is a function starting with
test_ - Run with
pytest tests/— it auto-discovers and runs all tests -v= verbose (show each test name),--tb=short= compact error output- Docs: docs.pytest.org
The test suite lives in the source repo, not the sandbox. Install test dependencies in the source repo's venv:
cd ~/dev/franklinwh-cloud
source venv/bin/activate
# Install the library itself
pip install -e .
# Install test dependencies
pip install pytest pytest-asyncio respx
Run the Unit Tests¶
Expected: 74+ tests passed, 0 failures.
Note:
test_live.pyrequires credentials and hits the real API. Skip it for routine testing:
Test Coverage by File¶
| Test File | Coverage |
|---|---|
test_build_payload.py |
TOU payload construction, CRC, JSON structure |
test_const.py |
Dispatch codes, wave types, predefined schedules, schema |
test_get_stats.py |
Power/stats response parsing, conditional API calls |
test_grid_status.py |
Grid status enum, outage reason mapping |
test_metrics.py |
Call counting, response times, error tracking, edge PoP |
test_modes.py |
Mode constants, enum mappings, run status codes |
test_retry.py |
HTTP retry logic, 401 refresh, timeout handling |
test_set_mode.py |
Mode validation, SoC bounds, exception types |
test_token_fetcher.py |
Login flow, token caching, credential errors |
test_live.py |
Live API integration (requires credentials) |
Day-to-Day Workflow¶
Making and Testing a Code Change¶
# 1. Edit source in franklinwh-cloud/
cd ~/dev/franklinwh-cloud
# ... edit files ...
# 2. Syntax check
python3 -c "import ast; ast.parse(open('franklinwh_cloud/cli_commands/tou.py').read()); print('OK')"
# 3. Run unit tests
./venv/bin/python -m pytest tests/ -v --tb=short
# 4. Test the CLI (editable install = changes are live instantly)
cd ~/dev/franklinwh-cloud-test
source venv/bin/activate
franklinwh-cli tou --next
# 5. Commit (back in source repo)
cd ~/dev/franklinwh-cloud
git add -A && git commit -m "feat: description" && git push
Running a Single Test File¶
Running Tests Matching a Pattern¶
Troubleshooting¶
| Issue | Fix |
|---|---|
command not found: franklinwh-cli |
Activate the sandbox venv: source ~/dev/franklinwh-cloud-test/venv/bin/activate |
No credentials found |
Run from the sandbox dir (cd ~/dev/franklinwh-cloud-test) or use --config path/to/franklinwh.ini |
ModuleNotFoundError: respx |
Install test deps: ~/dev/franklinwh-cloud/venv/bin/pip install respx pytest-asyncio |
| Code changes not reflected | Ensure editable install: pip install -e ~/dev/franklinwh-cloud |
Operation not permitted on new files |
macOS Tahoe provenance — sudo rm file && recreate |
| Tests hang | Use --timeout=30: pip install pytest-timeout && pytest --timeout=30 |