Replace the simple nil-title → "Unknown" logic in printDeal with a fallbackDealTitle() function that tries multiple fields in priority order before giving up: 1. Title (cleaned) — the happy path, same as before 2. Brand + Department — e.g. "Publix deal (Meat)" 3. Brand alone — e.g. "Publix deal" 4. Department alone — e.g. "Meat deal" 5. Description truncated to 48 chars — last-resort meaningful text 6. Item ID — e.g. "Deal 12345" 7. "Untitled deal" — only when every field is empty This makes the output more useful for the ~5-10% of weekly ad items that ship with a nil Title from the Publix API, which previously all showed as "Unknown" and were indistinguishable from each other. Tests: - TestPrintDeals_FallbackTitleFromBrandAndDepartment - TestPrintDeals_FallbackTitleFromID Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
pubcli
pubcli is a Go CLI for fetching current Publix weekly ad deals by store number or ZIP code.
Features
- Fetch weekly ad deals for a specific store
- Resolve nearest Publix store from a ZIP code
- Filter deals by category, department, keyword, and BOGO status
- List weekly categories with deal counts
- Output data as formatted terminal text or JSON
- Generate shell completions (
bash,zsh,fish,powershell) - Tolerate minor CLI syntax mistakes when intent is clear
- Robot-mode behavior for AI agents (compact help, auto JSON when piped, structured errors, meaningful exit codes)
Requirements
- Go
1.24.4or newer to build from source - Network access to:
https://services.publix.com/api/v4/savingshttps://services.publix.com/api/v1/storelocation
Installation
Build locally
git clone https://github.com/tayloree/publix-deals.git
cd publix-deals
go build -o pubcli ./cmd/pubcli
Install with go install
go install github.com/tayloree/publix-deals/cmd/pubcli@latest
Quick Start
Find nearby stores:
pubcli stores --zip 33101
Fetch deals using a store number:
pubcli --store 1425
Fetch deals by ZIP (uses the nearest store):
pubcli --zip 33101
Fetch JSON output:
pubcli --zip 33101 --json
Commands
pubcli
Fetch weekly ad deals.
pubcli [flags]
pubcli stores
List up to 5 nearby stores for a ZIP code.
pubcli stores --zip 33101
pubcli stores -z 32801 --json
pubcli categories
List available categories for the current week.
pubcli categories --store 1425
pubcli categories -z 33101 --json
Flags
Global flags:
-s, --store stringPublix store number (example:1425)-z, --zip stringZIP code for store lookup--jsonOutput JSON instead of styled terminal output
Deal filtering flags (pubcli root command):
--bogoShow only BOGO deals-c, --category stringFilter by category (example:bogo,meat,produce)-d, --department stringFilter by department (substring match, case-insensitive)-q, --query stringSearch title/description (case-insensitive)-n, --limit intLimit results (0means no limit)
Behavior Notes
- Either
--storeor--zipis required for deal and category lookups. - If only
--zipis provided, the nearest store is selected automatically. - When using text output and ZIP-based store resolution, the selected store is shown.
- Filtering is applied in this order:
bogo,category,department,query,limit. - Category matching is exact and case-insensitive.
- Department and query filters use case-insensitive substring matching.
- Running
pubcliwith no args prints compact quick-start help. - When stdout is not a TTY (for example piping to another process), JSON output is enabled automatically unless explicitly set.
CLI Input Tolerance
The CLI auto-corrects common input mistakes and prints a note: describing the normalization:
-zip 33101->--zip 33101zip=33101->--zip=33101--ziip 33101->--zip 33101stores zip 33101->stores --zip 33101
Command argument tokens are preserved for command workflows like:
pubcli completion zshpubcli help stores
JSON Output
Deals (pubcli ... --json)
Array of objects with fields:
title(string)savings(string)description(string)department(string)categories(string[])additionalDealInfo(string)brand(string)validFrom(string)validTo(string)isBogo(boolean)imageUrl(string)
Stores (pubcli stores ... --json)
Array of objects with fields:
number(string)name(string)address(string)distance(string)
Categories (pubcli categories ... --json)
Object map of category name to deal count:
{
"bogo": 175,
"meat": 88,
"produce": 81
}
Structured Errors
When command execution fails, errors include:
code(example:INVALID_ARGS,NOT_FOUND,UPSTREAM_ERROR)messagesuggestions(when available)exitCode
JSON-mode errors are emitted as:
{"error":{"code":"INVALID_ARGS","message":"unknown flag: --ziip","suggestions":["Try `--zip`.","pubcli --zip 33101"],"exitCode":2}}
Exit Codes
0success1not found2invalid arguments3upstream/network failure4internal failure
Shell Completion
Generate completions:
pubcli completion bash
pubcli completion zsh
pubcli completion fish
pubcli completion powershell
Development
Run tests:
go test ./...
Run without building:
go run ./cmd/pubcli --zip 33101 --limit 10