Every PSX data-portal surface in one Go binary, plus the local price history the exchange itself throws away.
The PSX data portal renders only what is true right now and keeps nothing for you. This CLI mirrors the instrument master, screener metrics, sector aggregates and market snapshots into local SQLite, so longitudinal questions the portal structurally cannot answer become one command: what changed since last week (diff), which names are abnormal against their own history (unusual), and when a valuation multiple compressed (drift). Announcements, payouts and OHLCV history are read live rather than mirrored. No API key, no account, no browser.
Learn more at Pakistan Stock Exchange.
Created by @qazmataz (qazmataz).
Authentication
PSX publishes no API and requires no credentials. Every endpoint this CLI uses is unauthenticated plain HTTP, so there is nothing to configure before your first command. The CLI paces itself to stay within the portal's observed politeness ceiling.
Quick Start
# confirm the portal is reachable before anything else
psx-pp-cli doctor
# pull the instrument master once so symbol lookups work offline
psx-pp-cli sync --resources symbols
# price a single name to confirm live data flows
psx-pp-cli quote OGDC
# save the names you actually follow
psx-pp-cli watchlist track OGDC LUCK ENGRO
# record a point-in-time snapshot; diff, drift, unusual and rotation all read what this stores, so run it on a schedule
psx-pp-cli snapshot take
# the payoff: every corporate action across your names in one call
psx-pp-cli actions --watchlist --since 7d
Unique Features
These capabilities aren't available in any other tool for this API.
Cross-surface joins
-
actions — See every announcement, payout, AGM date and circuit-breaker event for the symbols you track, in one place.
Reach for this when the question is 'did anything happen to my names', instead of running four searches and merging them by hand.
psx-pp-cli actions --watchlist --since 7d --agent
-
basis — Compare futures-board prices against the regular spot board to see premium or discount per symbol.
Use this for carry and roll questions that require crossing PSX's separate market boards.
psx-pp-cli basis --market DFC --top 20 --agent
-
docs search — Search PSX regulatory documents, listing guides and notices by keyword, with last-updated dates.
Use this to locate the governing PSX rule, guide or notice for a question instead of browsing the corporate site by hand.
psx-pp-cli docs search "rule book" --agent
Local state that compounds
-
diff — Show what changed in price, volume and valuation metrics between two synced snapshots.
Use this when the user asks what moved since last week rather than what the price is right now.
psx-pp-cli diff --since 7d --agent
-
watchlist — Keep a saved symbol set and price it on demand, with change measured from the day you added each name.
Use this to give an otherwise stateless market portal a memory of which names the user actually cares about.
psx-pp-cli watchlist prices --agent
-
drift — Trace one symbol's PE, dividend yield, market cap or free float across time.
Use this when the question is about the trajectory of a multiple, not its current value.
psx-pp-cli drift OGDC --metric pe --since 90d --agent
Baselines the portal never keeps
-
unusual — Find names trading abnormally against their own trailing history, not just the day's biggest movers.
Use this to separate a genuine volume spike from a name that always trades that way.
psx-pp-cli unusual --baseline 30d --top 20 --agent
-
rotation — Rank sectors by movement over a window and name the constituents that drove each move.
Use this for 'what is leading and lagging, and why' instead of a bare current-volume ranking.
psx-pp-cli rotation --window 30d --top 5 --agent
Recipes
Weekly corporate-action sweep for your holdings
psx-pp-cli actions --watchlist --since 7d --agent --select symbol,kind,date,headline
Joins announcements, payouts, AGM dates and breaker events for saved symbols, narrowed with --select so an agent reads four fields instead of a large nested payload.
Find genuinely abnormal volume, not just big movers
psx-pp-cli unusual --baseline 30d --top 20 --agent
Ranks each name against its own trailing median and dispersion, so a thin scrip doubling on tiny size does not crowd out a real institutional print.
Trace a valuation multiple over a quarter
psx-pp-cli drift OGDC --metric pe --since 90d --agent
Reads accumulated screener snapshots to show when the multiple moved, which the portal cannot answer at all.
See which constituents drove a sector
psx-pp-cli rotation --window 30d --top 5 --agent
Ranks sectors by change over the window and attributes each move to its largest contributors.
Check futures premium to spot
psx-pp-cli basis --market DFC --top 20 --agent
Fetches the futures and regular boards and computes the per-symbol spread and percent premium.
Find the governing PSX rulebook or guide
psx-pp-cli docs search "shariah compliant" --agent --select title,url,updated
Full-text search across the corporate site's document map, returning just the fields an agent needs to cite a source.
Usage
Run psx-pp-cli --help for the full command reference and flag list.
Paths & environment variables
This CLI separates local files into four path kinds:
| Kind | Contents |
|---|
config | User-editable settings such as config.toml and saved profiles |
data | Durable local data such as data.db |
state | Runtime state such as persisted queries, jobs, and teach.log |
cache | Regenerable HTTP/cache files |
Each kind resolves independently. The ladder is:
- Per-kind env var:
PSX_CONFIG_DIR, PSX_DATA_DIR, PSX_STATE_DIR, or PSX_CACHE_DIR
--home <dir> for this invocation
PSX_HOME for a flat relocated root
- XDG env vars:
XDG_CONFIG_HOME, XDG_DATA_HOME, XDG_STATE_HOME, XDG_CACHE_HOME
- Platform defaults matching existing installs
For containers and agent sandboxes, prefer a single relocated root:
export PSX_HOME=/srv/psx
psx-pp-cli doctor
Under PSX_HOME=/srv/psx, the four dirs resolve to /srv/psx/config, /srv/psx/data, /srv/psx/state, and /srv/psx/cache.
MCP servers do not receive CLI flags from the host. Put relocation in the host env block:
{
"mcpServers": {
"psx": {
"command": "psx-pp-mcp",
"env": {
"PSX_HOME": "/srv/psx"
}
}
}
}
Precedence matters in fleets: an ambient per-kind variable such as PSX_DATA_DIR overrides an explicit --home for that kind. Use PSX_HOME or the per-kind variables for durable fleet relocation; treat --home as the weaker per-invocation lever.
Relocation is one-way. Unsetting PSX_HOME does not move files back to platform defaults, and doctor cannot find files left under a former root. Move the files manually before unsetting relocation variables.
Existing installs keep working because the platform-default rung matches the legacy layout. Run psx-pp-cli doctor --fail-on warn to check path warnings in automation.
Commands
announcements
Corporate and regulatory announcement streams
psx-pp-cli announcements - Search announcements across company, PSX, SECP, NCCPL and CDC streams
board
Live trading boards with bid/offer depth across markets
psx-pp-cli board <market> <board> - Trading board for one market and board combination
calendar
AGM and EOGM meeting calendar
psx-pp-cli calendar - AGM and EOGM events in a date window
circuit-breakers
Securities that hit price circuit breakers
psx-pp-cli circuit-breakers - Instruments halted by a price circuit breaker, with the limit band and halt state that triggered the suspension
company
Per-company profile and financial report index
psx-pp-cli company profile - Company profile and quote page for an instrument
psx-pp-cli company reports - Financial report index for an instrument
debt
Debt market instruments
psx-pp-cli debt - TFCs, Sukuks and other debt instruments with coupon, maturity and yields
eligible-scrips
Margin-trading eligible securities
psx-pp-cli eligible-scrips - Securities eligible for margin trading and margin financing
history
Full historical OHLCV series
psx-pp-cli history - Full OHLCV history for a symbol. PSX ignores date parameters and always returns the complete series
indices
Index listing and constituents
psx-pp-cli indices - All PSX indices with current level and change
listings
Listing status by board
psx-pp-cli listings <board> <status> - Listed companies filtered by board and listing status
market
Whole-market snapshots and movers
psx-pp-cli market debt-performers - Most active debt instruments by turnover, covering TFCs, Sukuks and government paper on the bonds board
psx-pp-cli market performers - Top active, gainer and loser tables for the equity market
psx-pp-cli market watch - Whole-market snapshot table: LDCP, open, high, low, current, change, volume
payouts
Dividend, bonus and right-issue payout history
psx-pp-cli payouts company - Full payout history for one instrument
psx-pp-cli payouts list - Payout history across all instruments
screener
Fundamental screening metrics for the listed universe
psx-pp-cli screener - Market cap, price, PE (TTM), dividend yield, free float, 30-day average volume and 1-year change
sectors
Sector aggregates and rankings
psx-pp-cli sectors summary - Per-sector aggregates: advances, declines, turnover and market cap
psx-pp-cli sectors top - Top sectors ranked by traded volume
symbols
Listed instrument master: equities, ETFs and debt securities
psx-pp-cli symbols - List every listed instrument with sector, ETF and debt flags
timeseries
Intraday tick and end-of-day price series
psx-pp-cli timeseries eod - End-of-day series as [epoch, close, volume, open] tuples
psx-pp-cli timeseries intraday - Intraday tick series as [epoch, price, volume] tuples (last active session)
Self-learning loop
This CLI caches per-question discovery so repeat queries skip the walk and structurally similar queries get answered via entity substitution. The loop also self-captures: every invocation is journaled locally, and failed-flag corrections plus fresh teaches surface as candidates on the next recall for confirm/reject judgment. Agents call recall before discovery and fire teach & after answering. See the ## Automatic learning section in SKILL.md for the full protocol.
psx-pp-cli recall <query> - Look up cached resources for a query before running discovery
psx-pp-cli teach - Record a query -> resource mapping (silent on success, safe to background with &)
psx-pp-cli learnings list - Inspect taught rows
psx-pp-cli learnings forget <query> - Undo a teach
psx-pp-cli learnings candidates - List auto-captured candidates awaiting confirm/reject
psx-pp-cli learnings stats - Local loop metrics: recall hit rate, teach-to-reuse, playbook resolution, candidate counts
psx-pp-cli teach-pattern - Install a query/resource template up front
psx-pp-cli teach-lookup - Add an entity mapping (e.g. country code, team alias) for pattern substitution
Pass --no-learn or set PSX_NO_LEARN=true to disable the loop for deterministic flows.
The local store's schema version stamp is one-way: once this version of psx-pp-cli opens the database, older binaries refuse it with a version error — upgrade the binary rather than downgrading.
Output Formats
# Human-readable table (default in terminal, JSON when piped)
psx-pp-cli announcements
# JSON for scripting and agents
psx-pp-cli announcements --json
# Filter to specific fields by name
psx-pp-cli announcements --json --select <field>[,<field>...]
# Dry run — show the request without sending
psx-pp-cli announcements --dry-run
# Agent mode — JSON + compact + no prompts in one flag
psx-pp-cli announcements --agent
Agent Usage
This CLI is designed for AI agent consumption:
- Non-interactive - never prompts, every input is a flag
- Pipeable -
--json output to stdout, errors to stderr
- Filterable -
--select <field>[,<field>...] returns only fields you need
- Previewable -
--dry-run shows the request without sending
- Explicit retries - add
--idempotent to create retries when a no-op success is acceptable
- Explicit confirmation -
--agent does not imply --yes; pass --yes separately only after the target, arguments, and side effects are clear
- Piped input - write commands can accept structured input when their help lists
--stdin
- Offline-friendly - sync/search commands can use the local SQLite store when available
- Agent-safe by default - no colors or formatting unless
--human-friendly is set
Exit codes: 0 success, 2 usage error, 3 not found, 5 API error, 7 rate limited, 10 config error.
Freshness
This CLI owns bounded freshness for registered store-backed read command paths. In --data-source auto mode, covered commands check the local SQLite store before serving results; stale or missing resources trigger a bounded refresh, and refresh failures fall back to the existing local data with a warning. --data-source local never refreshes, and --data-source live reads the API without mutating the local store.
Set PSX_NO_AUTO_REFRESH=1 to disable the pre-read freshness hook while preserving the selected data source.
Covered command paths:
psx-pp-cli circuit-breakers
psx-pp-cli circuit-breakers get
psx-pp-cli circuit-breakers list
psx-pp-cli circuit-breakers search
psx-pp-cli debt
psx-pp-cli debt get
psx-pp-cli debt list
psx-pp-cli debt search
psx-pp-cli eligible-scrips
psx-pp-cli eligible-scrips get
psx-pp-cli eligible-scrips list
psx-pp-cli eligible-scrips search
psx-pp-cli indices
psx-pp-cli indices get
psx-pp-cli indices list
psx-pp-cli indices search
psx-pp-cli screener
psx-pp-cli screener get
psx-pp-cli screener list
psx-pp-cli screener search
psx-pp-cli sectors
psx-pp-cli sectors get
psx-pp-cli sectors list
psx-pp-cli sectors search
psx-pp-cli symbols
psx-pp-cli symbols get
psx-pp-cli symbols list
psx-pp-cli symbols search
JSON outputs that use the generated provenance envelope include freshness metadata at meta.freshness. This metadata describes the freshness decision for the covered command path; it does not claim full historical backfill or API-specific enrichment.
Health Check
psx-pp-cli doctor
Verifies configuration and connectivity to the API.
Configuration
Run psx-pp-cli doctor to see the resolved config, data, state, and cache directories. The platform-default config path is ~/.config/psx-pp-cli/config.toml; --home, PSX_HOME, and per-kind env vars can relocate it.
Static request headers can be configured under headers; per-command header overrides take precedence.
Known Gaps
Honest limitations in this release. None block normal use; all are recorded so you are not
surprised by them.
announcements shows the link text, not the filing URL. The last column renders as
View PDF rather than the href. Capturing hrefs requires a change to the shared table extractor
that would alter the row schema for every table-backed command and the synced store.
indices values can carry an embedded as-of timestamp, e.g. HBLTTI (18-08-2026 18:30:00).
quote and market watch report sector as a numeric code (0821), not a name.
diff, drift, unusual and rotation need snapshot take first. They read local snapshot
history, not sync: diff and rotation need two captures, unusual needs three or more.
- Announcements, payouts and OHLCV history are read live, not mirrored.
sync covers symbols,
sectors, screener, indices, debt, eligible-scrips and circuit-breakers.
payouts deadline is derived, not official. PSX publishes book-closure dates rather than
ex-dates, so buy_by is the calendar day before book closure opens. Weekends and market holidays
are not modelled — confirm against the exchange calendar before acting on it.
- Rate limiting is self-imposed. PSX publishes no documented limit; this CLI defaults to a
conservative 2 requests per second. Tune with
--rate-limit.
Troubleshooting
Not found errors (exit code 3)
- Check the resource ID is correct
- Run the
list command to see available items
API-specific
- history returns far more rows than the date range you asked for — expected: PSX ignores date parameters server-side and always returns the full series, so the CLI filters locally after fetching
- intraday returns ticks dated before today — the symbol did not trade today; the portal serves the last active session, and 'market status' shows the age of the latest tick
- diff, drift, unusual or rotation report no history — these read snapshots, not sync. Run 'psx-pp-cli snapshot take' on a schedule: diff and rotation need 2 captures, unusual needs 3 or more
- sync --resources announcements (or payouts, history) fails — expected: those surfaces are read live and are not mirrored. Syncable resources are symbols, sectors, screener, indices, debt, eligible-scrips and circuit-breakers
- requests start failing after a large fan-out — lower --rate-limit; the portal publishes no limit and the CLI targets a conservative 2 requests per second by default
- an HTML-backed command returns zero rows after a portal redesign — run 'doctor' to confirm reachability, then report the table whose headers changed; extraction is keyed on header text, not column position
Discovery Signals
This CLI was generated with browser-captured traffic analysis.
- Target observed: https://dps.psx.com.pk/
- Capture coverage: 12 API entries from 235 total network entries
- Reachability: standard_http (65% confidence)
- Protocols: rest_json (75% confidence)
- Generation hints: weak_schema_confidence
- Candidate command ideas: create_calendar — Derived from observed POST /calendar traffic.; list_KSE100 — Derived from observed GET /timeseries/int/KSE100 traffic.; list_OGDC — Derived from observed GET /timeseries/int/OGDC traffic.; list_symbols — Derived from observed GET /symbols traffic.; list_top_10_sectors — Derived from observed GET /data/top-10-sectors traffic.
Warnings from discovery:
- empty_response_shapes: All endpoint clusters have empty response shapes; capture may have omitted response bodies. Re-fetch discovered endpoints with curl or another direct HTTP path before generating types.
- weak_schema_evidence: Binary or protobuf response cannot provide reliable JSON schema evidence.
Sources & Inspiration
This CLI was built by studying these projects and resources:
Generated by CLI Printing Press