Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "nber-cli",
"description": "Claude Code marketplace for NBER-CLI research workflows.",
"version": "0.6.0",
"version": "0.8.0",
"owner": {
"name": "Song Tan",
"email": "sepinetam@gmail.com",
Expand All @@ -12,7 +12,7 @@
{
"name": "nber-cli",
"description": "Use NBER-CLI to search, inspect, download, and serve NBER working paper workflows.",
"version": "0.6.0",
"version": "0.8.0",
"author": {
"name": "Song Tan",
"email": "sepinetam@gmail.com"
Expand Down
1 change: 1 addition & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"permissions": {
"allow": [
"Read(~/.nber-cli/*)",
"Bash(uv add *)",
"Bash(uv run *)",
"Bash(uv lock *)",
Expand Down
41 changes: 22 additions & 19 deletions .github/workflows/desktop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
- main
- master
tags:
- "desktop-v*"
- "v*"
workflow_dispatch:

permissions:
Expand All @@ -18,22 +18,22 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7

- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: "3.11"

- uses: astral-sh/setup-uv@v3
- uses: astral-sh/setup-uv@v8

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Pin setup-uv to a resolvable immutable tag

The new astral-sh/setup-uv@v8 reference is used across the updated workflows, but setup-uv's v8 release notes say they stopped publishing major/minor tags and that @v8 cannot be used, recommending an immutable tag such as astral-sh/setup-uv@v8.0.0 instead (https://github.com/astral-sh/setup-uv/releases/tag/v8.0.0). As written, GitHub Actions cannot resolve this action, so the Desktop, pytest, lint, docs, and publish jobs fail before any project commands run.

Useful? React with 👍 / 👎.


- uses: actions/setup-node@v4
- uses: actions/setup-node@v6
with:
node-version: "20"
cache: npm
cache-dependency-path: desktop/package-lock.json

- name: Install Python dependencies
run: uv sync --dev
run: uv sync --dev --extra server

- name: Run Python lint
run: uv run ruff check .
Expand All @@ -59,7 +59,7 @@ jobs:

build:
needs: check
if: startsWith(github.ref, 'refs/tags/desktop-v') || github.event_name == 'workflow_dispatch'
if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch'
permissions:
contents: write
strategy:
Expand All @@ -84,15 +84,15 @@ jobs:
runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7

- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: "3.11"

- uses: astral-sh/setup-uv@v3
- uses: astral-sh/setup-uv@v8

- uses: actions/setup-node@v4
- uses: actions/setup-node@v6
with:
node-version: "20"
cache: npm
Expand All @@ -103,14 +103,17 @@ jobs:
targets: ${{ matrix.target }}

- name: Install Python dependencies
run: uv sync --dev
run: uv sync --dev --extra server --group desktop-build

- name: Install desktop dependencies
working-directory: desktop
run: npm ci

# Signing is opt-in while the project ships without paid certificates.
# Once certificates are funded, configure the secrets and set
# DESKTOP_REQUIRE_SIGNING=true to restore mandatory signing checks.
- name: Validate macOS release signing secrets
if: startsWith(github.ref, 'refs/tags/desktop-v') && runner.os == 'macOS'
if: startsWith(github.ref, 'refs/tags/v') && runner.os == 'macOS' && vars.DESKTOP_REQUIRE_SIGNING == 'true'
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
Expand All @@ -122,7 +125,7 @@ jobs:
run: uv run python scripts/validate-desktop-signing.py --platform macos --require-signed

- name: Validate Windows release signing secrets
if: startsWith(github.ref, 'refs/tags/desktop-v') && runner.os == 'Windows'
if: startsWith(github.ref, 'refs/tags/v') && runner.os == 'Windows' && vars.DESKTOP_REQUIRE_SIGNING == 'true'
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
Expand Down Expand Up @@ -212,15 +215,15 @@ jobs:
run: uv run python scripts/smoke-desktop-app.py --install-from-package

- name: Check signed and notarized macOS release artifacts
if: startsWith(github.ref, 'refs/tags/desktop-v') && matrix.release-platform == 'macos'
if: startsWith(github.ref, 'refs/tags/v') && matrix.release-platform == 'macos' && vars.DESKTOP_REQUIRE_SIGNING == 'true'
run: uv run python scripts/check-desktop-release.py --platform macos --max-mb 80 --require-signed --require-notarized

- name: Check signed Windows release artifacts
if: startsWith(github.ref, 'refs/tags/desktop-v') && matrix.release-platform == 'windows'
if: startsWith(github.ref, 'refs/tags/v') && matrix.release-platform == 'windows' && vars.DESKTOP_REQUIRE_SIGNING == 'true'
run: uv run python scripts/check-desktop-release.py --platform ${{ matrix.release-platform }} --max-mb 80 --require-signed

- name: Upload desktop artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: ${{ matrix.artifact-name }}
path: |
Expand All @@ -230,8 +233,8 @@ jobs:
desktop/src-tauri/target/**/release/bundle/**/*.msi

- name: Upload GitHub Release assets
if: startsWith(github.ref, 'refs/tags/desktop-v')
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v3
with:
draft: true
files: |
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7

- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "3.11"

- name: Install uv
uses: astral-sh/setup-uv@v3
uses: astral-sh/setup-uv@v8

- name: Install dependencies
run: uv sync --group docs
Expand All @@ -38,7 +38,7 @@ jobs:

- name: Upload Pages artifact
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
uses: actions/upload-pages-artifact@v3
uses: actions/upload-pages-artifact@v5
with:
path: site

Expand All @@ -58,4 +58,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
uses: actions/deploy-pages@v5
6 changes: 3 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7

- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "3.11"

- name: Install uv
uses: astral-sh/setup-uv@v3
uses: astral-sh/setup-uv@v8

- name: Install dependencies
run: uv sync --dev
Expand Down
9 changes: 4 additions & 5 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,20 @@ on:

jobs:
publish:
if: startsWith(github.event.release.tag_name, 'v')
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7

- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v6
with:
python-version: '3.11'

- name: Install uv
uses: astral-sh/setup-uv@v3
uses: astral-sh/setup-uv@v8

- name: Install dependencies
run: uv sync
Expand All @@ -28,5 +29,3 @@ jobs:

- name: Publish to PyPI
run: uv publish --token ${{ secrets.PYPI_TOKEN }}


8 changes: 4 additions & 4 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7

- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "3.11"

- name: Install uv
uses: astral-sh/setup-uv@v3
uses: astral-sh/setup-uv@v8

- name: Install dependencies
run: uv sync --dev
run: uv sync --dev --extra server

- name: Run pytest
run: uv run pytest
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@ site/

# Files
*.pdf

# uv
.python-version
uv.lock
1 change: 0 additions & 1 deletion .python-version

This file was deleted.

15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,23 @@ This file is the canonical release history. The English mirror at `docs/en/chang

## [Unreleased]

## [0.8.0] - 2026-07-13

### Added
- Added `nber-cli doctor` to show installed and PyPI versions, executable/package locations, config contents, database path, schema version, size, and last recorded activity. Added `nber-cli doctor --fix-version` to refresh `uvx` caches or upgrade installations detected as `uv tool`, `pipx`, or `pip`.
- Added the optional `server` extra plus the `nber-server` and `nber-sidecar` entry 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_status` table. 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.

### Changed
- Split the HTTP service into the independent `nber_server` package while continuing to reuse the existing `nber_cli` core 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.

### Fixed
- 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.

## [0.7.0] - 2026-07-08

Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ A command line interface for reaching the National Bureau of Economic Research (
- Cache paper metadata locally (`nber-cli info` writes to `info_cache`) with a sliding TTL, plus a behavior log for `search`, `download`, and `info` lookups.
- Store the cache, RSS items, and behavior logs in a local SQLite database at `~/.nber-cli/nber.db`, managed through SQLModel/SQLAlchemy and configurable with a filesystem path or `sqlite:///...` URL.
- Expose the same core workflows as MCP tools for AI agents.
- Provide an optional loopback-only HTTP server for the Desktop app and local integrations.
- Return human-readable output by default, with JSON output for automation.
- Provide `--verbose` debug logging and a rotating log file for troubleshooting.
- Use `-c/--config <path>` to temporarily override the config file for a single run.
Expand Down Expand Up @@ -98,6 +99,16 @@ Example MCP client configuration:

The MCP server exposes tools for paper lookup, search, and PDF download.

### Local HTTP Server

The HTTP API is an optional extra. Run it without installing the server dependencies into the normal CLI environment:

```bash
uvx --from "nber-cli[server]" nber-server --host 127.0.0.1 --port 31527
```

The server upgrades the local SQLite database to schema v3 on startup and exposes health, feed, paper, read-status, and settings endpoints under `/api/v1`.

## Documentation

More usage details, command references, MCP setup, Python API examples, development notes, and release history are available in the [documentation](docs/en/index.md).
Expand Down
11 changes: 11 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- 本地缓存论文元数据(`nber-cli info` 会写入 `info_cache`),采用滑动 TTL;同时为 `search`、`download` 和 `info` 查询记录行为日志。
- 把缓存、RSS 条目和行为日志统一存放在本地 SQLite 数据库 `~/.nber-cli/nber.db`,由 SQLModel/SQLAlchemy 管理,路径可用普通文件路径或 `sqlite:///...` URL 配置。
- 通过 MCP 工具把核心能力暴露给 AI Agent。
- 提供可选的 loopback-only HTTP server,供 Desktop 应用和本地集成使用。
- 默认输出适合阅读的文本,也支持 JSON 输出用于自动化流程。
- 提供 `--verbose` 调试日志与轮转日志文件,便于排查问题。
- 通过 `-c/--config <path>` 可在单次运行中临时指定配置文件。
Expand Down Expand Up @@ -97,6 +98,16 @@ MCP 客户端配置示例:

MCP server 提供论文查询、搜索和 PDF 下载工具。

### 本地 HTTP Server

HTTP API 属于可选依赖,不会进入普通 CLI 环境。可以直接运行:

```bash
uvx --from "nber-cli[server]" nber-server --host 127.0.0.1 --port 31527
```

Server 启动时会把本地 SQLite 数据库升级到 schema v3,并在 `/api/v1` 下提供健康检查、feed、论文详情、已读状态和设置接口。

## 文档

更完整的用法、命令参考、MCP 配置、Python API 示例、开发说明和发布记录请见 [中文文档](docs/zh/index.md)。
Expand Down
16 changes: 13 additions & 3 deletions desktop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ NBER-CLI Desktop is the desktop shell for NBER-CLI V1. It uses Tauri v2, React,
From the repository root:

```bash
uv sync
uv sync --dev --extra server
cd desktop
npm install
npm run tauri dev
Expand Down Expand Up @@ -38,6 +38,7 @@ Useful endpoints:
## Build Sidecar

```bash
uv sync --extra server --group desktop-build
uv run python scripts/build-sidecar.py --clean
```

Expand All @@ -51,7 +52,7 @@ npm run build
npm run tauri build
```

Code signing requires the Apple Developer ID and Windows code signing secrets described in `docs/desktop/ci-cd-signing.md`.
Code signing requires the Apple Developer ID and Windows code signing secrets listed in the Release section below.

## Verification

Expand Down Expand Up @@ -79,7 +80,16 @@ On Windows CI or a Windows machine, use the same release checker and smoke scrip

## Release

GitHub Actions builds release artifacts when a `desktop-v*` tag is pushed or the Desktop workflow is manually dispatched. The build job depends on the full check job, so Python lint/tests and frontend lint/tests must pass before installers are produced.
GitHub Actions builds Desktop artifacts from the same `v*` tag used by the Python package release, or when the Desktop workflow is manually dispatched. Pushing a tag such as `v0.8.0` runs the full checks and creates one draft GitHub Release containing the macOS and Windows installers. Publishing that same Release triggers the PyPI workflow, so the CLI and Desktop ship under one version and one Release.

Desktop releases are unsigned by default. To require signed Windows artifacts plus signed and notarized macOS artifacts in the future, set the repository variable `DESKTOP_REQUIRE_SIGNING` to `true` and configure the signing secrets below.

Before tagging, keep these versions aligned:

- `pyproject.toml`
- `desktop/package.json` and `desktop/package-lock.json`
- `desktop/src-tauri/tauri.conf.json`, `Cargo.toml`, and `Cargo.lock`
- Claude and Codex plugin manifests

Required release signing inputs:

Expand Down
4 changes: 2 additions & 2 deletions desktop/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading