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).
The recommended path installs both the psx-pp-cli binary and the pp-psx agent skill (Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, and other agents supported by the upstream skills CLI) in one shot:
npx -y @mvanhorn/printing-press-library install psxFor CLI only (no skill):
npx -y @mvanhorn/printing-press-library install psx --cli-onlyFor skill only — installs the skill into the same agents as the default command above, but skips the CLI binary (use this to update or reinstall just the skill):
npx -y @mvanhorn/printing-press-library install psx --skill-onlyTo constrain the skill install to one or more specific agents (repeatable — agent names match the skills CLI):
npx -y @mvanhorn/printing-press-library install psx --agent claude-code
npx -y @mvanhorn/printing-press-library install psx --agent claude-code --agent codexIf npx isn't available (no Node, offline), install the CLI directly via Go (requires Go 1.26.6 or newer):
go install github.com/mvanhorn/printing-press-library/library/payments/psx/cmd/psx-pp-cli@latestThis installs the CLI only — no skill.
Download a pre-built binary for your platform from the latest release. On macOS, clear the Gatekeeper quarantine: xattr -d com.apple.quarantine <binary>. On Unix, mark it executable: chmod +x <binary>.
Install the CLI binary first. The installer writes binaries to a per-user managed bin directory by default: $HOME/.local/bin on macOS/Linux and %LOCALAPPDATA%\Programs\PrintingPress\bin on Windows.
npx -y @mvanhorn/printing-press-library install psx --cli-onlyThen install the focused Hermes skill.
From the Hermes CLI:
hermes skills install mvanhorn/printing-press-library/cli-skills/pp-psx --forceInside a Hermes chat session:
/skills install mvanhorn/printing-press-library/cli-skills/pp-psx --forceRestart the Hermes session or gateway if the newly installed skill is not visible immediately.
Install both the CLI binary and the focused OpenClaw skill. The installer defaults binaries to a per-user bin directory ($HOME/.local/bin on macOS/Linux, %LOCALAPPDATA%\Programs\PrintingPress\bin on Windows):
npx -y @mvanhorn/printing-press-library install psx --agent openclawRestart the OpenClaw session or gateway if the newly installed skill is not visible immediately.
This CLI ships an MCPB bundle — Claude Desktop's standard format for one-click MCP extension installs (no JSON config required).
To install:
- Download the
.mcpbfor your platform from the latest release. - Double-click the
.mcpbfile. Claude Desktop opens and walks you through the install.
Requires Claude Desktop 1.0.0 or later. Pre-built bundles ship for macOS Apple Silicon (darwin-arm64) and Windows (amd64, arm64); for other platforms, use the manual config below.
Manual JSON config (advanced)
If you can't use the MCPB bundle (older Claude Desktop, unsupported platform), install the MCP binary and configure it manually.
go install github.com/mvanhorn/printing-press-library/library/payments/psx/cmd/psx-pp-mcp@latestAdd to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"psx": {
"command": "psx-pp-mcp"
}
}
}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.
# 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
These capabilities aren't available in any other tool for this API.
-
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
-
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
-
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
psx-pp-cli actions --watchlist --since 7d --agent --select symbol,kind,date,headlineJoins 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.
psx-pp-cli unusual --baseline 30d --top 20 --agentRanks 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.
psx-pp-cli drift OGDC --metric pe --since 90d --agentReads accumulated screener snapshots to show when the multiple moved, which the portal cannot answer at all.
psx-pp-cli rotation --window 30d --top 5 --agentRanks sectors by change over the window and attributes each move to its largest contributors.
psx-pp-cli basis --market DFC --top 20 --agentFetches the futures and regular boards and computes the per-symbol spread and percent premium.
psx-pp-cli docs search "shariah compliant" --agent --select title,url,updatedFull-text search across the corporate site's document map, returning just the fields an agent needs to cite a source.
Run psx-pp-cli --help for the full command reference and flag list.
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, orPSX_CACHE_DIR --home <dir>for this invocationPSX_HOMEfor 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 doctorUnder 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.
Corporate and regulatory announcement streams
psx-pp-cli announcements- Search announcements across company, PSX, SECP, NCCPL and CDC streams
Live trading boards with bid/offer depth across markets
psx-pp-cli board <market> <board>- Trading board for one market and board combination
AGM and EOGM meeting calendar
psx-pp-cli calendar- AGM and EOGM events in a date window
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
Per-company profile and financial report index
psx-pp-cli company profile- Company profile and quote page for an instrumentpsx-pp-cli company reports- Financial report index for an instrument
Debt market instruments
psx-pp-cli debt- TFCs, Sukuks and other debt instruments with coupon, maturity and yields
Margin-trading eligible securities
psx-pp-cli eligible-scrips- Securities eligible for margin trading and margin financing
Full historical OHLCV series
psx-pp-cli history- Full OHLCV history for a symbol. PSX ignores date parameters and always returns the complete series
Index listing and constituents
psx-pp-cli indices- All PSX indices with current level and change
Listing status by board
psx-pp-cli listings <board> <status>- Listed companies filtered by board and listing status
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 boardpsx-pp-cli market performers- Top active, gainer and loser tables for the equity marketpsx-pp-cli market watch- Whole-market snapshot table: LDCP, open, high, low, current, change, volume
Dividend, bonus and right-issue payout history
psx-pp-cli payouts company- Full payout history for one instrumentpsx-pp-cli payouts list- Payout history across all instruments
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
Sector aggregates and rankings
psx-pp-cli sectors summary- Per-sector aggregates: advances, declines, turnover and market cappsx-pp-cli sectors top- Top sectors ranked by traded volume
Listed instrument master: equities, ETFs and debt securities
psx-pp-cli symbols- List every listed instrument with sector, ETF and debt flags
Intraday tick and end-of-day price series
psx-pp-cli timeseries eod- End-of-day series as [epoch, close, volume, open] tuplespsx-pp-cli timeseries intraday- Intraday tick series as [epoch, price, volume] tuples (last active session)
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 discoverypsx-pp-cli teach- Record a query -> resource mapping (silent on success, safe to background with&)psx-pp-cli learnings list- Inspect taught rowspsx-pp-cli learnings forget <query>- Undo a teachpsx-pp-cli learnings candidates- List auto-captured candidates awaiting confirm/rejectpsx-pp-cli learnings stats- Local loop metrics: recall hit rate, teach-to-reuse, playbook resolution, candidate countspsx-pp-cli teach-pattern- Install a query/resource template up frontpsx-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.
# 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 --agentThis CLI is designed for AI agent consumption:
- Non-interactive - never prompts, every input is a flag
- Pipeable -
--jsonoutput to stdout, errors to stderr - Filterable -
--select <field>[,<field>...]returns only fields you need - Previewable -
--dry-runshows the request without sending - Explicit retries - add
--idempotentto create retries when a no-op success is acceptable - Explicit confirmation -
--agentdoes not imply--yes; pass--yesseparately 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-friendlyis set
Exit codes: 0 success, 2 usage error, 3 not found, 5 API error, 7 rate limited, 10 config error.
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-breakerspsx-pp-cli circuit-breakers getpsx-pp-cli circuit-breakers listpsx-pp-cli circuit-breakers searchpsx-pp-cli debtpsx-pp-cli debt getpsx-pp-cli debt listpsx-pp-cli debt searchpsx-pp-cli eligible-scripspsx-pp-cli eligible-scrips getpsx-pp-cli eligible-scrips listpsx-pp-cli eligible-scrips searchpsx-pp-cli indicespsx-pp-cli indices getpsx-pp-cli indices listpsx-pp-cli indices searchpsx-pp-cli screenerpsx-pp-cli screener getpsx-pp-cli screener listpsx-pp-cli screener searchpsx-pp-cli sectorspsx-pp-cli sectors getpsx-pp-cli sectors listpsx-pp-cli sectors searchpsx-pp-cli symbolspsx-pp-cli symbols getpsx-pp-cli symbols listpsx-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.
psx-pp-cli doctorVerifies configuration and connectivity to the API.
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.
Honest limitations in this release. None block normal use; all are recorded so you are not surprised by them.
announcementsshows the link text, not the filing URL. The last column renders asView PDFrather 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.indicesvalues can carry an embedded as-of timestamp, e.g.HBLTTI (18-08-2026 18:30:00).quoteandmarket watchreport sector as a numeric code (0821), not a name.diff,drift,unusualandrotationneedsnapshot takefirst. They read local snapshot history, notsync:diffandrotationneed two captures,unusualneeds three or more.- Announcements, payouts and OHLCV history are read live, not mirrored.
synccovers symbols, sectors, screener, indices, debt, eligible-scrips and circuit-breakers. payouts deadlineis derived, not official. PSX publishes book-closure dates rather than ex-dates, sobuy_byis 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.
Not found errors (exit code 3)
- Check the resource ID is correct
- Run the
listcommand to see available items
- 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
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.
This CLI was built by studying these projects and resources:
- psxdata — Python (19 stars)
- PSX-Data-Api — Python (11 stars)
- PSX-MCP-Server — Python (5 stars)
- psx-mcp — Python (3 stars)
- psx-mcp-server — Python
Generated by CLI Printing Press