diff --git a/README.md b/README.md
index 4e411ab..fd0cc0e 100644
--- a/README.md
+++ b/README.md
@@ -1,526 +1,266 @@
-# sustech-cli
-
-[](https://www.npmjs.com/package/sustech-cli)
-[](https://github.com/wormforce/sustech-cli/actions/workflows/ci.yml)
-[](https://www.npmjs.com/package/sustech-cli)
-
-An unofficial TypeScript CLI for SUSTech services, designed for people,
-scripts, and coding agents. Text is the default for humans; versioned JSON and
-JSONL are available for software. Python is not required at runtime.
-
-> [!WARNING]
+
+
+
+
+
+ One calm command line for life at SUSTech.
+ Courses, Blackboard, calendar, library, campus services, and agent-ready context.
+
+
+`sustech-cli` brings frequently used SUSTech services into one consistent
+TypeScript CLI. It is pleasant in a terminal, predictable in scripts, and
+self-describing for coding agents. Human-readable text is the default;
+versioned JSON and JSONL are available whenever software needs a stable
+interface.
+
+> [!IMPORTANT]
> This is an independent community project, not an official SUSTech service.
-> Published npm releases may lag `main`. Inspect `sustech version` and
-> `sustech capabilities` on the installed copy before relying on a command or
-> allowing it to change state.
+> It never bypasses CAPTCHA or other interactive challenges. Review a command
+> before allowing it to change university or local state.
-## Install
+## Quick Start
-Requires Node.js 20.18 or newer:
+Requires Node.js 20.18 or newer.
```bash
npm install --global sustech-cli
-sustech version
+sustech
```
-To try one command without a global install:
-
-```bash
-npm exec --package=sustech-cli -- sustech version
-```
-
-`npm run build` only compiles a source checkout; it does not put `sustech` on
-your shell `PATH`. Package developers can use `npm install --global .` or
-`npm link` after building.
-
-The CLI checks npm for a newer stable release at most once every 24 hours when
-run in an interactive terminal. If one is available, it asks before updating.
-JSON/JSONL output, redirected commands, and CI runs are never prompted. Use
-`sustech update` to check immediately, `sustech update --yes` to install
-without the confirmation prompt, or set `SUSTECH_DISABLE_UPDATE_CHECK=1` to
-disable automatic checks.
-
-## Quick start
-
-Public data does not require an account:
+The first screen shows the active account, runtime, and useful next actions.
+Public commands work immediately:
```bash
-sustech calendar day 2026-09-01
-sustech faculty search "computer vision"
-sustech online search "校园卡" --section manual
-sustech online manual list --source service --limit 10
-sustech online manual get ID_OR_TITLE
-sustech online talks list --limit 10
+sustech calendar day
sustech talks list
-sustech online contact search "教学"
-sustech nces filter-options
-sustech nces browse --offering-unit "计算机科学与工程系" --page-size 5
-sustech nces global-stats
-sustech nces rankings top-teachers --limit 5
-sustech nces by-code CS302 --term 20252
-sustech nces reviews 244 --sort newest --page-size 5
-sustech transit lines
sustech library search "graph neural networks" --limit 5
+sustech faculty search "computer vision"
```
-Authenticated services use a named local profile:
+Sign in once for personal services:
```bash
sustech auth login
-sustech auth status
-sustech context --live --level verbose
-sustech academic watch --state ./academic-state.json --include-blackboard
-sustech academic changes before.json after.json
-sustech tis plan recommend CS330 MA203 --round bxxk --max 5
-sustech tis plan explain CS330 --round bxxk
-sustech tis degree missing
-sustech tis degree progress
-sustech bb calendar --type GradebookColumn
-sustech bb announcements --days 14
-sustech bb deadlines --days 14 --submission-state not_attempted --json
-sustech bb tree _8537_1 --max 50
-sustech bb types --course MSE306
-sustech bb roster _8537_1 --role Student --page-size 10
-sustech bb discussions _5325_1 --page-size 10
-sustech bb grades --course MSE306 --submission-state completed --limit 10 --json
-sustech bb assignments --course MSE306 --with-attempts --json
-sustech bb assignments _8537_1 --with-attempts --json
-sustech bb assignments _8537_1 --submission-state not_attempted --json
-sustech bb messages _8537_1 --folder-type Inbox --page-size 10
-sustech bb attempt-files _8537_1 _2201_1
+sustech context --live
sustech tis schedule
-sustech bb courses
+sustech bb deadlines --days 14
```
-Discover the complete command surface from the installed version:
+Try a command without installing globally:
+
+```bash
+npm exec --package=sustech-cli -- sustech version
+```
+
+## What It Does
+
+| Area | Useful commands | Access |
+| --- | --- | --- |
+| Daily snapshot | `context`, `profile show`, `academic changes` | Public calendar plus optional TIS and Blackboard reads |
+| Teaching system | courses, schedule, grades, exams, degree progress, planning, iCalendar | SUSTech account |
+| Blackboard | courses, content, assignments, deadlines, grades, announcements, discussions, files | SUSTech account |
+| Campus calendar | teaching weeks, holidays, makeup days, term dates | Public |
+| Library | live Primo search/detail, rooms and reservations | Public catalog; account for bookings |
+| Campus services | classrooms, booking, printing, programs, Wi-Fi, transit | Public, local, or account-backed |
+| Discovery | faculty, lectures, handbook, contacts, NCES, papers | Public |
+| Agent interfaces | JSON, JSONL, Agent Skill, local MCP server | Local |
+
+The installed version is the source of truth:
```bash
sustech --help
sustech capabilities --json --pretty
+sustech describe context --json --pretty
```
-## Use with an Agent
+### A useful day in one command
-The CLI is self-describing. Agents should inspect structured command and safety
-metadata instead of parsing `--help` or relying on a memorized command list:
+`context` creates a compact snapshot designed for people and assistants:
+date, teaching week and parity, holiday or makeup-day rules, current and next
+class, upcoming work, exams, weather, AQI, and library status.
```bash
-sustech version --json
-sustech capabilities --json
-sustech consequences --json
+sustech context --level terse
+sustech context --live
+sustech context --live --level verbose
+sustech context --live --json
```
-This repository also ships a portable
-[`sustech-cli` Agent Skill](skills/sustech-cli/SKILL.md). Install it directly
-from the public repository—no source clone is needed:
+Live sources run concurrently. Missing credentials and unavailable upstreams
+are reported as partial data rather than silently turned into “nothing found.”
+All academic times use Asia/Shanghai.
+
+### Live library catalog
+
+Library search reads the university's public Primo catalog directly, so results
+stay current without shipping a large offline database:
```bash
-npx skills add wormforce/sustech-cli --skill sustech-cli
+sustech library search "三体" --limit 5
+sustech library detail L:alma991001055219704181
```
-For a global Codex installation:
+The normal path uses Primo's public JSON endpoints. A manual browser transport
+is available when a host cannot complete the direct path:
```bash
-npx skills add wormforce/sustech-cli --skill sustech-cli --global --agent codex
+sustech library search "三体" --browser --interactive
```
-The [Agent Skills CLI](https://github.com/vercel-labs/skills) can target other
-supported agents and project-local scopes. Review the Skill before installing
-it: it teaches command discovery, structured output, credential boundaries,
-preview/confirm workflows, and the rule never to retry an ambiguous mutation
-automatically.
-
-Installing the npm package deliberately does **not** edit Codex, Claude Code,
-Cursor, or other agent configuration. The target agent and scope are user
-choices, so an npm `postinstall` script should not install instructions
-silently.
-
-For an agent without Skill support, provide this short instruction:
-
-> Use the installed `sustech` CLI. Start with `sustech capabilities --json` and
-> `sustech consequences --json`; request structured output, never expose login
-> secrets, and never add `--confirm` without approval for the exact target.
-
-A Skill is the onboarding layer; the CLI remains the executable source of
-truth. The package also ships a local `stdio` MCP entrypoint, `sustech-mcp`, for
-clients that support native tools. It needs no hosted server and exposes `42`
-typed read-only tools in total (`39` public allowlisted tools plus `3` metadata
-tools), plus JSON resources, resource templates, and
-prompts for discovery, public campus data, library, faculty, transit, NCES,
-papers, and selected SUSTech Online reads. Authenticated data, browser flows,
-local writes, and remote mutations remain unavailable through MCP. See
-[docs/MCP.md](docs/MCP.md) for configuration and the complete boundary.
-A repository-level `AGENTS.md` alone would only help agents that cloned the
-source.
-
-## What it covers
-
-This table is a summary. Use `sustech capabilities --json` for the installed
-version's exact command, authentication, network, and confirmation metadata.
-
-| Area | Examples | Access |
-| --- | --- | --- |
-| Diagnostics | version, capabilities, consequences, doctor | Local; optional live auth checks |
-| Academic context | calendar, Context v2 live summaries, profile reports, academic snapshots, `academic changes`, one-shot `academic watch` | Public and authenticated reads; guarded local exports |
-| TIS | catalog, schedule, grades, exams, TIS-reported degree progress, conservative missing-course report, persistent planning, `tis plan solve/explain/recommend`, local degree audit, live classrooms, iCalendar | CAS login; selection/enrollment writes are confirm-gated |
-| Blackboard | courses, roster, course messages, message send preview/apply, discussions, recursive content trees, content type summaries, announcements, deadlines, calendar reads, cross-course grades, per-course and cross-course assignment/attempt overviews, native calendar-link workflow, search, attachment download/sync, attempts, submission | CAS login for REST reads; `bb roster`, `bb messages` / `bb message-participants`, `bb message-send preview/apply`, `bb discussion-groups`, announcement aggregation, `bb tree`, cross-course `bb grades`, cross-course `bb assignments --course ...`, `bb assignments --with-attempts` / `--submission-state`, `bb deadlines --submission-state`, and `bb types` preserve partial failures. Blackboard discussions use the official Learn REST discussion API when the target course exposes it; Original-course forum lists, `bb discussion` thread reads, and `bb discussion-replies` thread-detail reads fall back to the Blackboard HTML discussion board, while group reads and discussion writes that still require the REST surface fail closed with `BLACKBOARD_DISCUSSIONS_UNSUPPORTED`. The native calendar link is a separate stored secret, and local writes are guarded |
-| Library and campus services | Primo catalog search/detail, WS programs, eHall booking, library booking, PMS jobs and usage | Public catalog reads plus authenticated reads; booking and queue writes are confirm-gated |
-| Research and courses | Crossref/OA papers, NCES browse/filter-options/global-stats/rankings/search/by-code/course/reviews/teacher/stats, SUSTech Online talks and selected handbook search | Public; OA downloads use guarded local paths; NCES and SUSTech Online remain community references only |
-| Campus and device context | faculty, resources, transit, Wi-Fi status/events | Public or local |
-| Community directory | Selected institutional SUSTech Online contacts with provenance and freshness advisories | Public community source; emergency, financial, personal, dining/chat, and professor-list sections are excluded |
-
-For the structured TIS-reported `tis degree progress` response, the derived
-`tis degree missing` report, and how both differ from local JSON
-`tis degree audit`, see
-[docs/DEGREE_PROGRESS.md](docs/DEGREE_PROGRESS.md). For the
-snapshot save/diff/change/watch workflow, see
-[docs/ACADEMIC_SNAPSHOTS.md](docs/ACADEMIC_SNAPSHOTS.md). For the
-`tis degree audit` requirements-file format, matching semantics, and current
-runtime limits, see [docs/DEGREE_AUDIT.md](docs/DEGREE_AUDIT.md).
-For the selected SUSTech Online source scope, provenance fields, freshness
-labels, and contact exclusions, see [docs/ONLINE.md](docs/ONLINE.md).
-
-Remote-state mutations are deliberately limited to these apply commands, all
-of which require an exact target plus `--confirm`:
-
-- `tis enroll apply`, `tis selection apply`, and `tis bid apply`
-- `bb submit apply`
-- `booking create apply` and `booking cancel apply`
-- `lib-booking create apply` and `lib-booking cancel apply`
-- `pms upload apply` and `pms delete apply`
-
-Local state can also change through credential login/logout, persistent
-`tis plan` edits, and explicit file outputs such as `profile export`,
-`academic snapshot save`, `tis ical --destination`, `papers fetch-oa`,
-`bb download`, and `bb sync`. File commands reject unsafe symbolic-link paths
-and do not overwrite an existing target unless the command explicitly permits
-and requests it.
-
-## Official campus lectures
-
-Official university lectures are available without login:
+## For AI Assistants
+
+The CLI exposes its capabilities, output contracts, and mutation consequences
+as structured data. Agents should inspect these instead of parsing this README
+or guessing flags.
```bash
-sustech talks list
-sustech talks list --all
-sustech talks list --json --pretty
-sustech talks search "物理" --jsonl
-sustech talks search "物理" --all
+sustech capabilities --json
+sustech consequences --json
+sustech describe "tis enroll apply" --json
```
-These commands read the lecture section of the official
-[homepage events page](https://www.sustech.edu.cn/zh/home-events.html), excluding
-notices. The default view shows lectures whose Beijing start time is still in
-the future, ordered from nearest to furthest. Records with an unparseable time
-remain visible under “time to confirm” rather than being silently omitted.
-`--all` adds lectures whose advertised start time has passed; it means all
-lectures currently displayed on the homepage, not the complete historical
-archive. Search matches titles, speakers, venues, and time text, and follows the
-same upcoming-by-default behavior. Results include title, speaker, venue,
-original time text, a normalized Beijing start time when parseable, timing
-classification, detail URL, reference time, and official source/fetch metadata.
-The existing `online talks` commands continue to use the community-maintained
-SUSTech Online source. The new official commands are CLI-only at present.
+Install the bundled Agent Skill:
-## Output contract
+```bash
+npx skills add wormforce/sustech-cli --skill sustech-cli
+```
-Course details supplement the existing TIS course search and selection commands:
+For a global Codex installation:
```bash
-sustech tis courses detail BMEB316
-sustech tis courses detail BIO102B --rwh 2026-2027-1-BIO102B-001 --round bxxk --json
+npx skills add wormforce/sustech-cli --skill sustech-cli --global --agent codex
```
-Use an exact course code; if multiple teaching tasks match, the command lists
-their identifiers and requires `--rwh`. `--semester` selects the catalog term.
-Details include course content, learning outcomes, readings, prerequisite
-descriptions and referenced courses, syllabus links, and aggregate enrollment
-counts. `--round` adds the relevant selection type's live counts, period, notes
-and conflicts. Without it, matching enrolled/cart records can supply counts;
-missing counts remain unknown. Optional read failures are reported in `sources`
-while the course details remain available.
-
-Teaching-task and course-library attributes stay separate. Syllabus documents
-may describe an older offering; links require TIS authentication and are not
-downloaded automatically. Population groups and quota-related counts retain
-their original meanings, and are not converted into guaranteed remaining seats.
-See [TIS course detail](docs/TIS_COURSE_DETAIL.md) for output fields and examples.
+Clients with MCP support can launch the local `sustech-mcp` stdio server. Its
+typed surface is intentionally read-only: authenticated data, browser flows,
+local writes, and remote mutations stay in the CLI. See [MCP setup](docs/MCP.md).
+
+## Output That Composes
```bash
-# Human-readable text
+# Friendly terminal output
sustech tis courses search "machine learning"
# One versioned JSON envelope
sustech tis courses search "machine learning" --json
-# One record per line for list commands
+# One item per line, followed by a summary
sustech tis courses search "machine learning" --jsonl
```
-`--output text|json|jsonl` is the long form, and `--pretty` formats JSON for
-review. A successful envelope looks like this:
-
-```json
-{
- "schemaVersion": "1",
- "ok": true,
- "command": "version",
- "data": {
- "version": "0.12.1",
- "runtime": "node v22.19.0"
- }
-}
-```
-
-The process exit status remains authoritative in every mode. See
-[docs/OUTPUT.md](docs/OUTPUT.md) for envelope, JSONL, error-code, and
-compatibility rules.
-
-## Credentials
-
-On a desktop, `sustech auth login` verifies the account and stores the password
-in the operating system's native credential store:
-
-- macOS: Keychain
-- Windows: Credential Manager
-- Linux desktop: Secret Service via `secret-tool`
-
-The password is entered through a hidden prompt, is never accepted as a normal
-command-line argument, and is never written to the CLI config. If no safe
-backend is available, the CLI returns `CREDENTIAL_STORE_UNAVAILABLE` instead of
-falling back to plaintext. Linux writes are verified by immediate read-back;
-locked collections and broken desktop D-Bus sessions produce distinct safe
-remediation in `auth status --json` instead of being reported as an expired
-password.
-
-On macOS, `auth status` checks Keychain item metadata without reading the
-password. Credential-helper commands are bounded to five seconds and report
-`CREDENTIAL_STORE_TIMEOUT` without an automatic retry.
-
-```bash
-sustech auth login --profile main
-sustech auth check --profile main --service bb --json
-sustech auth check --service bb --browser --interactive --json
-sustech doctor --service bb --live --browser --interactive --json
-sustech auth logout --profile main
-```
-
-Headless runners can use credentials supplied by their own secret manager via
-the documented environment variables or credentials file. Service sessions and
-cookies remain in memory. See [docs/AUTHENTICATION.md](docs/AUTHENTICATION.md)
-for precedence, backend requirements, and non-interactive use.
+Every machine-readable response has a stable envelope and the process exit
+status remains authoritative. See the [output contract](docs/OUTPUT.md).
-For Blackboard only, `auth check` and `doctor --live` also support a read-only
-browser-backed verification path with `--browser`, plus `--interactive` when
-the user needs to finish CAS manually. That path never accepts browser
-credentials in the CLI and never persists browser cookies.
+## Safety by Default
-Blackboard also exposes a private native calendar subscription link. Treat that
-link like a bearer token or password: store it only through stdin, let `show`
-mask it by default, and reveal it only with an explicit `--reveal`:
+Read commands are easy; writes are deliberately explicit. Remote mutations
+follow the same lifecycle:
-```bash
-# macOS
-pbpaste | sustech bb calendar-link set --url-stdin
-# Windows PowerShell
-Get-Clipboard | sustech bb calendar-link set --url-stdin
-sustech bb calendar-link show
-sustech bb calendar-link fetch --destination ./blackboard.ics
+```text
+resolve exact target → preview / preflight → approve → --confirm → read back
```
-The link is validated before storage and kept in the operating-system
-credential store under a separate Blackboard-calendar namespace, not in the
-credential metadata file. `bb calendar-link fetch` can later refresh that ICS
-feed without a fresh CAS login.
-
-## Guarded workflows
-
-Every remote mutation follows the same pattern: resolve the exact target, run a
-preview or read-only preflight, obtain explicit approval, apply with
-`--confirm`, then verify by reading the live state back.
-
-Enrollment example:
+For example:
```bash
-sustech tis courses available "machine learning" --round bxxk --json
sustech tis enroll preview \
--course-id TIS_INTERNAL_ID --rwh TASK_ID --round bxxk --bid 2
+
sustech tis enroll apply \
--course-id TIS_INTERNAL_ID --rwh TASK_ID --round bxxk --bid 2 --confirm
```
-Availability JSON groups lecture/lab rows into credit-deduplicated bundles and
-labels the exact `courseId` (`p_id`) and component `rwh` roles. If apply returns
-`TIS_SELECTION_OUTCOME_UNKNOWN`, preserve that exact pair and reconcile without
-repeating the write:
+If a write result is ambiguous, the CLI reports
+`DO_NOT_RETRY_AUTOMATICALLY`. It does not trade uncertainty for a duplicate
+submission.
-```bash
-sustech tis selection reconcile enroll \
- --course-id TIS_INTERNAL_ID --rwh TASK_ID --round bxxk --attempts 3 --json
-```
+
+Commands that can change remote state
-See [docs/SELECTION_CONTRACTS.md](docs/SELECTION_CONTRACTS.md) for bundle,
-identifier, bounded reconciliation, and grade-free planning-output contracts.
+- `tis enroll apply`, `tis selection apply`, `tis bid apply`
+- `bb submit apply`, `bb message-send apply`,
+ `bb discussion-post apply`, `bb discussion-reply apply`
+- `booking create apply`, `booking cancel apply`
+- `lib-booking create apply`, `lib-booking cancel apply`
+- `pms upload apply`, `pms delete apply`
-Blackboard attachment and submission example:
+All require an exact target and explicit confirmation. Local exports also use
+guarded paths and do not overwrite existing files unless the command documents
+and receives an overwrite option.
-```bash
-sustech bb attachments _8537_1 _629896_1 --json
-sustech bb grades --course CS208 --submission-state completed --limit 10 --json
-sustech bb assignments --course CS208 --with-attempts --json
-sustech bb assignments _8537_1 --with-attempts --json
-sustech bb download _8537_1 _629896_1 ATTACHMENT_ID \
- --destination ./homework.pdf
-sustech bb attempt-files _8537_1 _2201_1 --json
-sustech bb attempt-download _8537_1 _2201_1 FILE_ID \
- --destination ./submitted-homework.pdf
-
-sustech bb submit preview \
- --course-id _8537_1 --content-id _629896_1 --file homework.pdf
-sustech bb submit apply \
- --course-id _8537_1 --content-id _629896_1 --column-id _12345_1 \
- --file homework.pdf --expected-sha256 HASH --confirm
-```
+
-`bb submit preview` is authenticated but read-only. It resolves assignment IDs,
-checks attempts, due date and upload limit, hashes the file, and emits the exact
-apply command. The same preview/confirm/read-back contract applies to TIS
-selection and bid changes, booking and library-booking create/cancel actions,
-and PMS upload/delete actions. An ambiguous remote write result includes
-`DO_NOT_RETRY_AUTOMATICALLY` and must not be retried automatically.
-
-Booking and library-booking previews now also try to read exact point-in-time
-room availability before any write. If the live room calendar, room open-times,
-or reservation metadata cannot safely rule out an overlap, preview fails closed
-instead of guessing that the slot is free.
-
-## Academic change tracking
-
-```bash
-sustech academic snapshot save --destination ./before.json --include-blackboard
-sustech academic changes before.json after.json
-sustech academic watch --state ./academic-state.json --include-blackboard
-```
+## Credentials
-`academic changes BEFORE AFTER` is the read-only diff command for two saved
-snapshots. `academic watch --state PATH` is a one-shot command: it reads live
-academic state once, compares it against the existing local state file when
-present, reports the changes, and updates that local file. It does not poll, it
-does not loop in the background, and it does not write any remote campus state.
+`sustech auth login` verifies the account before storage. Passwords are entered
+through a hidden prompt, never accepted as ordinary command-line arguments, and
+never written to the normal config file.
-## Daily context for AI assistants
+| Environment | Credential storage |
+| --- | --- |
+| macOS | Keychain |
+| Windows | Credential Manager |
+| Linux desktop | Secret Service |
+| Headless Linux | Password-encrypted local store when configured |
+| Automation | Explicit environment or credentials-file override |
```bash
-sustech context --level terse
-sustech context --live --level normal
-sustech context --live --json
-sustech context --live --level verbose
+sustech auth status
+sustech auth check --service bb --json
+sustech doctor --live
+sustech auth logout
```
-`context` now has three explicit detail levels:
-
-- `terse`: date, teaching week and parity, holiday/makeup timetable, and current/next class; only the timetable is requested with `--live`
-- `normal` (default): adds the next assignment deadline, recent Blackboard announcement, evaluation, exam, weather and AQI with `--live`
-- `verbose`: also retrieves library opening status
+Service cookies remain in memory. Browser-backed authentication is
+user-completed and ephemeral. Read the full
+[authentication guide](docs/AUTHENTICATION.md) before setting up headless or
+automated use.
-All dates and display times use **Asia/Shanghai**, including on overseas machines.
-JSON includes `generatedAt` (snapshot creation), `referenceAt` (the instant used
-for class/deadline selection), `timezone`, and the full public `academicDay`.
-`schedule.currentClass`, `nextClass`, and `todayClasses` expose ISO timestamps,
-periods, locations when available, and `makeupFor` dates. Current and next classes
-can appear together; holiday/makeup dates use the same rules as ICS exports.
+## Updates
-`sourceStatus` distinguishes a successful empty result (`empty`) from unavailable
-data (`missing`). `liveSources` adds errors, missing credentials, partial coverage,
-and intentionally skipped requests (`not-requested`). An empty result describes
-only the successfully retrieved sources; it is not a claim about all university
-systems. A failed public calendar fetch does not prevent other available sources
-from being returned.
-
-Weather and air quality include source URLs and upstream `observedAt` timestamps
-when supplied. Observations older than three hours are labeled `stale`; absent
-timestamps are `unknown`. AQI uses **US EPA** categories, not China's AQI scale.
-Public environmental requests time out after eight seconds, and TIS, Blackboard,
-and environmental reads run concurrently.
-
-Without `--live`, only the date/calendar snapshot is requested. Use
-`context --date YYYY-MM-DD` for a calendar preview (reference time: noon in
-Shanghai); combining a non-today date with `--live` is rejected so today's
-observations cannot be mistaken for historical data or forecasts.
-
-## Library catalog
+Interactive terminals check npm for a newer stable release at most once every
+24 hours and ask before installing it. CI, redirected commands, JSON, and JSONL
+are never interrupted by a prompt.
```bash
-sustech library search "graph neural networks" --limit 5
-sustech library detail PC:cdi_proquest_miscellaneous_1901310093
-sustech library search "graph neural networks" --browser --interactive
-sustech library detail L:alma991234567890106575 --browser
+sustech update
+sustech update --yes
```
-`library search` and `library detail` are read-only Primo catalog commands.
-`--browser` forces the browser-backed path. If that path redirects to CAS, the
-user must complete authentication manually in the browser window. The CLI does
-not accept browser credentials, does not solve CAPTCHAs, and does not persist
-browser cookies. On some hosts, public Primo HTTP access may still be limited by
-runtime TLS behavior; `--browser` is the supported fallback.
-
-## Conservative course planning
+Set `SUSTECH_DISABLE_UPDATE_CHECK=1` to disable automatic checks.
-```bash
-sustech tis plan recommend CS330 MA203 --round bxxk --path ./tis-plan.json --max 5
-sustech tis plan explain CS330 --round bxxk --path ./tis-plan.json
-```
+## Documentation
-These commands are read-only planning helpers. They do not add courses, do not
-submit selection writes, do not treat NCES as official data, and do not guess
-prerequisites. `recommend` ranks candidate sections using the current
-selectable-course snapshot, timetable-fit evidence, seat observations, optional
-degree-progress or degree-missing data, and optional NCES matches. `explain`
-shows the same evidence for one exact course code or RWH. Degree relevance stays
-conservative: if the available evidence is ambiguous, the result stays in manual
-review instead of being promoted to a definite requirement match.
-
-## Current limitations
-
-- Blackboard submission uses a Classic/Original HTTP form with the CAS session
- and REST attempt read-back. An individual Original file resubmission passed
- live CLI submission and read-back on 2026-09-11. Text submission and the
- first-submission 404 fallback remain fixture-tested only.
-- Student-submitted attempt files are separate from teacher-provided content
- attachments. `bb attempt-files` lists one attempt's files, and
- `bb attempt-download` downloads one of them to an explicit local path when
- Blackboard exposes a working attempt-file download endpoint for that record;
- otherwise the CLI now fails closed with
- `BLACKBOARD_ATTEMPT_FILE_UNAVAILABLE`.
-- Primo catalog access has both direct and browser-backed paths, but direct
- public HTTP access can still depend on the local runtime's TLS behavior. When
- in doubt, use `--browser` and complete any CAS step manually.
-- Fresh CAS logins for TIS- and Blackboard-backed commands may stop before
- password submission with `CAS_INTERACTIVE_CHALLENGE_REQUIRED` when CAS serves
- an interactive slide CAPTCHA. The CLI will not bypass that challenge. A
- previously stored Blackboard native calendar link can still be fetched
- without CAS.
-- Blackboard submission remains entirely in the CLI: a fresh form nonce and
- exact target are validated before one multipart POST to `uploadAssignment`.
- It supports individual Classic/Original file or text submissions with no
- Playwright dependency in the write path. Ultra/group assignments and silent
- draft resumption are unsupported. An attempts-list 404 becomes empty only
- after a matching blank first-submission view form confirms that state.
-- Blackboard `bb message-send preview/apply` stays on the official course
- message create endpoint, binds apply to the previewed SHA-256 plus exact
- recipient IDs, and verifies the created message by Sent-folder read-back. It
- is still protocol/fixture-tested only.
-- Newly added TIS selection, booking, library-booking, and PMS write paths are
- protocol/fixture-tested only. No real account mutation was performed while
- building this expansion.
-- PMS may require the campus network, and first-time account linking may still
- require a browser-side step.
-- Reusable service-adapter status can differ from the CLI's wired end-to-end
- status. Inspect `sustech services status` and [docs/SERVICES.md](docs/SERVICES.md).
-
-Module-by-module migration status is tracked in
-[docs/MIGRATION.md](docs/MIGRATION.md). Architecture and safety invariants are
-documented in [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md).
+| Guide | What it covers |
+| --- | --- |
+| [Command output](docs/OUTPUT.md) | JSON envelopes, JSONL, exit codes |
+| [Authentication](docs/AUTHENTICATION.md) | profiles, credential backends, browser fallback |
+| [MCP](docs/MCP.md) | local server setup and read-only boundary |
+| [Academic snapshots](docs/ACADEMIC_SNAPSHOTS.md) | save, diff, changes, one-shot watch |
+| [Course detail](docs/TIS_COURSE_DETAIL.md) | exact teaching-task selection and enrichment |
+| [Degree progress](docs/DEGREE_PROGRESS.md) | official progress, missing courses, local audit |
+| [Selection contracts](docs/SELECTION_CONTRACTS.md) | previews, identifiers, reconciliation |
+| [Services](docs/SERVICES.md) | implementation and transport status |
+| [Architecture](docs/ARCHITECTURE.md) | module boundaries and safety invariants |
## Development
@@ -530,20 +270,25 @@ cd sustech-cli
npm ci
npm run check
npm test
-npm run build
-node dist/cli.js --help
```
-Cross-platform CI runs checks, tests, native credential-store smoke tests where
-available, and `npm pack --dry-run` on Ubuntu, macOS, and Windows. Releases use
-the tagged, manually triggered Trusted Publishing workflow in
-[.github/workflows/publish.yml](.github/workflows/publish.yml); no long-lived npm
-token is stored in GitHub.
+Cross-platform CI covers Ubuntu, macOS, and Windows on supported Node.js
+versions. Releases use npm Trusted Publishing; no long-lived npm token is
+stored in GitHub.
+
+## Project Status
+
+Upstream university systems change independently and some authenticated flows
+can stop at an interactive CAPTCHA. The CLI fails visibly when it cannot
+establish reliable state; it does not claim success from an incomplete read.
+Current transport notes and known limitations live in
+[the service matrix](docs/SERVICES.md).
+
+## Attribution and License
-## Attribution and license
+This project is informed by
+[`dumixthestpd/sustech_survival`](https://github.com/dumixthestpd/sustech_survival)
+and preserves its required copyright notice.
-This project is a TypeScript reimplementation informed by
-[`dumixthestpd/sustech_survival`](https://github.com/dumixthestpd/sustech_survival).
-It preserves that project's required copyright notice and is distributed under
-the PolyForm Noncommercial License 1.0.0. See [NOTICE.md](NOTICE.md) and
-[LICENSE](LICENSE).
+Distributed under the [PolyForm Noncommercial License 1.0.0](LICENSE). See
+[NOTICE.md](NOTICE.md) for attribution details.
diff --git a/docs/assets/sustech-cli-hero.png b/docs/assets/sustech-cli-hero.png
new file mode 100644
index 0000000..950f081
Binary files /dev/null and b/docs/assets/sustech-cli-hero.png differ
diff --git a/docs/assets/sustech-cli.svg b/docs/assets/sustech-cli.svg
new file mode 100644
index 0000000..ecca379
--- /dev/null
+++ b/docs/assets/sustech-cli.svg
@@ -0,0 +1,15 @@
+
\ No newline at end of file