All notable changes to this project will be documented in this file.
This file is the canonical release history. The English mirror at docs/en/changelog.md and the Chinese mirror at docs/zh/changelog.md are generated from the same source content and must stay in lock-step. Any release commit updates all three together.
- Replaced Desktop's duplicated Rust RSS and paper-page implementation with a bundled one-shot worker built from the existing Python CLI code.
- Desktop users still do not need to install Python or uv; the required runtime is included in each installer and exits after each operation.
- Kept direct Rust/SQLite feed reads and read/unread updates while restoring Python as the single implementation for NBER network, parsing, and metadata-cache behavior.
- Fixed the 0.9.0 architecture that would have required feed and paper parsing rules to be maintained separately in Python and Rust.
- Release validation and package smoke tests now require the bundled worker and continue to reject the legacy long-running HTTP sidecar.
- Added a native Rust data layer for Desktop feed listing, RSS refresh, paper metadata caching, settings, and read/unread state.
- Added Rust tests for CLI-compatible SQLite schema handling, custom database paths, RSS repair/parsing, paper-page parsing, and read status.
- Desktop now talks directly to the configured SQLite database and NBER endpoints; it no longer starts, bundles, or requires a Python sidecar.
- Desktop refresh now performs the same RSS upsert and
feed_fetchesaccounting asnber-cli feed fetch. - Desktop now honors the CLI's configured
feed.db-pathand refuses to overwrite malformed configuration files. - Release checks and installer smoke tests now require Python sidecar binaries to be absent.
- Removed the Desktop service-port setting and the sidecar build/runtime lifecycle from the Tauri application and release workflow.
- Added Linux x64 build support to the Desktop release workflow, producing AppImage and Debian packages alongside macOS and Windows artifacts.
- Added macOS keyboard shortcuts for Desktop:
Command-1navigates to the feed,Command-Rrefreshes papers, andCommand-Ffocuses paper search. - Added a manual "Check for Updates" control in the Desktop app.
- Ensured the Desktop sidecar process is stopped and its process group is cleaned up when the application exits.
- Added
nber-cli doctorto show installed and PyPI versions, executable/package locations, config contents, database path, schema version, size, and last recorded activity. Addednber-cli doctor --fix-versionto refreshuvxcaches or upgrade installations detected asuv tool,pipx, orpip. - Added the optional
serverextra plus thenber-serverandnber-sidecarentry points for a loopback FastAPI service. - Added a Tauri 2 Desktop app for macOS and Windows with a React research workspace, local feed sync, unread filtering, paper details, settings, and BibTeX/APA/MLA/Harvard/Chicago/GB/T citation copying.
- Added Alembic-managed database migrations and schema v3 with the
read_statustable. Existing v1 and v2 databases upgrade automatically without removing existing records. - Added cross-platform Desktop build, artifact normalization, package validation, smoke-test, signing-validation, and notarization workflows.
- Split the HTTP service into the independent
nber_serverpackage while continuing to reuse the existingnber_clicore and SQLite database. - Kept FastAPI, Uvicorn, and Alembic out of the default CLI installation; local HTTP users install them through
nber-cli[server]. - Expanded the English and Chinese architecture, persistence, configuration, getting-started, testing, and Desktop documentation.
- Stabilized Desktop smoke tests on alternate local ports and added checks for bundled sidecars, installer signatures, and macOS notarization.
- Replaced the default Tauri branding and application icons with NBER-CLI Desktop assets.
- Added a
--verboseglobal flag and a rotating debug log at~/.nber-cli/debug.log. By default only warnings and errors are logged;--verboseorNBER_CLI_DEBUG=1enables debug-level output. - Added
-c/--config <path>global flag to use a custom config file for a single invocation without changing the default~/.nber-cli/config.json.
- Added a full set of browser-like request headers (User-Agent, Accept, Accept-Language, Sec-Fetch, etc.) to all NBER requests, replacing the minimal User-Agent-only headers. This restores access after NBER's CDN began rejecting minimal requests.
- Migrated the database layer from raw
sqlite3to SQLModel/SQLAlchemy. All tables are now declared as SQLModel models with explicit indexes. db init --db-pathanddb migrate <new_db_path>now acceptsqlite:///path/to/nber.dbURLs in addition to file paths.- Feed fetching, cache cleanup, query logging, download logging, info logging, and info-cache writes now use explicit SQLAlchemy sessions and commits.
config.schema.jsonnow describes the database path as a "Path or sqlite:/// URL".
- Added
sqlmodel>=0.0.24and SQLAlchemy to project dependencies. - Added CLI tests for
sqlite:///database path handling. - Added release notes for v0.6.0.
- Updated the version fallback in
cli.pyfrom0.4.0to0.6.0.
- RSS feed parsing now uses
defusedxmlto block XML external entity (XXE) and entity expansion attacks. - CLI downloads are restricted to the current working directory and its subdirectories by default. Use
nber-cli download --restrict falseto override per invocation. Thedownload.restrict_dirconfig key is stored and validated, but the current CLI default remainstrue. - Database
initandmigratepaths on macOS and Linux must reside within the user's home directory. - Synchronous HTTP requests enforce TLS 1.2 as the minimum version.
- Selected info/download failure paths now avoid raw exception text; download-log messages and soft database warnings use sanitized summaries or exception class names.
nber-cli config show/get <key>/set <key> <value>/verifyfor inspecting and editing~/.nber-cli/config.json.download.concurrencyconfiguration option (default3) and the--concurrency/-cCLI flag to cap concurrent downloads.--restrict true|falseflag onnber-cli downloadto control directory restriction per invocation.--yesflag fornber-cli mcp-server; the existing--portoption now requires explicit confirmation when set to a non-default value.ssetransport fornber-cli mcp-server.- JSON Schema (
config.schema.json) for validating~/.nber-cli/config.json. - Strict raw-configuration validation that reports malformed JSON, invalid section/value types, and schema-minimum violations without silently injecting defaults.
- Plugin manifests and marketplace metadata now share the package version, and the Claude plugin skill path uses the case-sensitive tracked
./skills/NBER-CLIdirectory. - Domain invariant validation in all core dataclasses (
NBER,NBERSearchResults,NBERFeedItem,NBERFeedFetchResult, clean results, and download results). get_config_value,set_config_value,read_config,write_config, andvalidate_configexported from the package top level.- Paper ID format validation (
w?\d+) across CLI, download, and MCP entry points. - Validation of fetched paper titles, positive citation IDs, and response/request paper-ID agreement before metadata is accepted.
- Replaced legacy
typing.Dict,List, andOptionalaliases with modern Python 3.11 syntax. - Added
mypyconfiguration and strengthened type annotations acrosscli.py,config_store.py, andfetcher.py. mcp-servertransport name corrected tostreamable-http; the existing--portoption now uses--yesconfirmation for non-default values.- Retry loops in
fetcher.pynow use exponential backoff capped at 30 seconds. feed fetchskips malformed individual RSS items instead of failing the entire feed.- Invalid configured or per-call download concurrency values are rejected or fall back to the documented safe default instead of creating an invalid semaphore.
- Database schema-changing and data-writing operations reject databases with a future
PRAGMA user_version; the diagnostic schema-version reader remains read-only. - Feed fetching establishes/validates the local schema before the network request, then writes feed items plus fetch history transactionally after the response is parsed; cleanup operations pair schema validation/upgrade and deletion in one SQLite transaction.
download.pyenablesraise_for_status=TrueonClientSession.- Error handling narrowed to specific network/timeout exception types with preserved exception chains.
- Removed the info cache hit hint that was printed to stderr on cached
infolookups.
feed fetchnow tolerates unescaped<characters followed by whitespace or a digit in RSS title and description text while keeping strict XML parsing for all other malformed input.- RSS parse failures now report their line and column when available, and
feed fetchreports runtime parse errors with exit code1without printing command usage.
nber-cli info --refreshskips the localinfo_cacheand re-fetches the paper from NBER. The new data is written back to the cache when the cache is enabled.nber-cli info cache --turn-on/--turn-offtoggle theinfo_cachelookup globally and persist the state to~/.nber-cli/config.json.nber-cli info cache --set-refresh <N>sets the cache refresh interval in days. The value is persisted to~/.nber-cli/config.jsonand used as the TTL for every subsequentinfocall. Defaults to30days.nber-cli info cache clearwith--days,--all,--start-date, or--end-datemirrors thefeed cleanparameter set, usinglast_fetched_atfrom theinfo_cachetable.nber-cli info cache cleanis a convenience alias forclear --all.nber-cli info cache(no sub-action) prints the current cache state, TTL, and cached row count.- New
nber_cli.config_storemodule: centralised read and write of~/.nber-cli/config.jsonplus theInfoCacheSettingsdataclass and helpers (get_info_cache_settings,set_info_cache_enabled,set_info_cache_ttl_days). - New
nber_cli.info_cache.get_paper_with_info_cache_resultasync helper (in thenber_cli.info_cachemodule) that returns anInfoCacheLookupResultcarrying theNBERpaper and afrom_cacheflag, so callers (CLI and MCP) can surface a "loaded from cache" hint. - Public Python API exports from the package top level:
InfoCacheSettings,clear_info_cache,count_info_cache,get_info_cache_settings,get_info_cache_ttl_days,is_info_cache_enabled,is_info_cache_expired,set_info_cache_enabled,set_info_cache_ttl_days,NBERInfoCacheClearResult.InfoCacheLookupResultandget_paper_with_info_cache_resultare exposed from thenber_cli.info_cachemodule rather than the package top level; import them asfrom nber_cli.info_cache import ....
~/.nber-cli/config.jsonnow carries aninfosection:info.cache_enabled(defaulttrue) andinfo.cache_ttl_days(default30). Missing or malformed fields fall back to defaults.infonow prints a one-line stderr hint when the paper was served from the local cache, pointing tonber-cli info <id> --refreshfor a fresh fetch.
db initanddb migratetop-level subcommands replacefeed initandfeed migrate. The database is now general-purpose and stores feed cache, behavior logs, and paper metadata cache.info_cachetable caches paper metadata fetched viainfoand the MCPget_paper_infotool. Subsequent lookups return immediately from the cache.query_log,download_log, andinfo_logtables record search keywords, download outcomes, and paper info lookups for later auditing.schema_versionfield written to~/.nber-cli/config.jsonso future schema migrations can roll forward safely.
- Default database renamed from
feed.dbtonber.db. Existing~/.nber-cli/feed.dbinstallations continue to work without manual steps. - Database schema upgraded from
user_version = 1touser_version = 2. Existing v1 databases are upgraded automatically on next CLI invocation; originalfeed_itemsrows are preserved. - Database code consolidated into
nber_cli.db. The originalinit_feed_database,migrate_feed_database, andget_feed_database_pathhelpers are kept as thin compatibility wrappers.
feed initsubcommand: initialize a local SQLite feed cache and write its path to user config.feed fetchsubcommand: fetch NBER's new working papers RSS feed, cache seen items, and show newly discovered papers by default.feed fetch --max-items: limit displayed feed output. When used without--display-all, display-all behavior is enabled automatically.feed migratesubcommand: move the feed cache database and SQLite sidecar files to a new path, then update user config.feed cleansubcommand: clean cached feed database records by age, date range, or all records after interactive confirmation.- Python API exports for feed cache helpers and feed result models.
- Added user config support at
~/.nber-cli/config.jsonfor the feed cache database path. - Expanded English and Chinese documentation for feed commands, configuration, Python API, and release notes.
downloadsubcommand: single paper ID or batch mode (--batch), explicit file path (--file), target directory (--save-base).infosubcommand: paper metadata with--allflag for full details and--format jsonoption.searchsubcommand: full-text search with date filters (--start-date,--end-date), pagination (--page,--per-page),--format jsonoption.mcp-serversubcommand: MCP server for AI agent integration with stdio and streamable_http transports.
- Reworked CLI into subcommand syntax (
nber-cli <subcommand>). - Simplified downloader to direct async HTTP PDF fetches (removed database-backed state tracking).
- Removed legacy web UI module and script entrypoint.
- Added
--version/-vflag to display current version. - Added comprehensive help message with examples.
- Added
__main__.pyfile to supportpython -m nber_cliusage. - Added argument grouping for better CLI organization.
- Added automatic help display when no arguments are provided.