zotero-agent 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zotero_agent-0.2.0/.github/ISSUE_TEMPLATE/bug_report.yml +37 -0
- zotero_agent-0.2.0/.github/ISSUE_TEMPLATE/config.yml +8 -0
- zotero_agent-0.2.0/.github/ISSUE_TEMPLATE/feature_request.yml +21 -0
- zotero_agent-0.2.0/.github/pull_request_template.md +17 -0
- zotero_agent-0.2.0/.github/workflows/ci.yml +57 -0
- zotero_agent-0.2.0/.github/workflows/pages.yml +68 -0
- zotero_agent-0.2.0/.github/workflows/release.yml +44 -0
- zotero_agent-0.2.0/.gitignore +26 -0
- zotero_agent-0.2.0/AGENTS.md +65 -0
- zotero_agent-0.2.0/CHANGELOG.md +60 -0
- zotero_agent-0.2.0/CONTRIBUTING.md +43 -0
- zotero_agent-0.2.0/LICENSE +21 -0
- zotero_agent-0.2.0/PKG-INFO +138 -0
- zotero_agent-0.2.0/README.md +112 -0
- zotero_agent-0.2.0/SECURITY.md +34 -0
- zotero_agent-0.2.0/cli/zot +20 -0
- zotero_agent-0.2.0/docs/ai-agents.md +95 -0
- zotero_agent-0.2.0/docs/architecture.md +59 -0
- zotero_agent-0.2.0/docs/commands.md +430 -0
- zotero_agent-0.2.0/docs/install.md +84 -0
- zotero_agent-0.2.0/docs/security.md +73 -0
- zotero_agent-0.2.0/install.sh +67 -0
- zotero_agent-0.2.0/marketing/README.md +64 -0
- zotero_agent-0.2.0/marketing/awesome-lists.md +97 -0
- zotero_agent-0.2.0/marketing/github-repo-metadata.md +67 -0
- zotero_agent-0.2.0/marketing/metrics.md +80 -0
- zotero_agent-0.2.0/marketing/reddit-r-zotero.md +44 -0
- zotero_agent-0.2.0/marketing/show-hn.md +62 -0
- zotero_agent-0.2.0/marketing/zotero-forums-post.md +35 -0
- zotero_agent-0.2.0/packaging/homebrew/zotero-agent.rb +30 -0
- zotero_agent-0.2.0/plugin/build.sh +28 -0
- zotero_agent-0.2.0/plugin/zotero-agent-bridge/bootstrap.js +225 -0
- zotero_agent-0.2.0/plugin/zotero-agent-bridge/manifest.json +15 -0
- zotero_agent-0.2.0/pyproject.toml +56 -0
- zotero_agent-0.2.0/scripts/gen_cli_reference.py +99 -0
- zotero_agent-0.2.0/skill/SKILL.md +195 -0
- zotero_agent-0.2.0/skill/evals/evals.json +68 -0
- zotero_agent-0.2.0/skill/references/pdf-and-notes.md +158 -0
- zotero_agent-0.2.0/skill/references/recipes.md +268 -0
- zotero_agent-0.2.0/skill/references/setup.md +20 -0
- zotero_agent-0.2.0/src/zotero_agent/__init__.py +10 -0
- zotero_agent-0.2.0/src/zotero_agent/__main__.py +4 -0
- zotero_agent-0.2.0/src/zotero_agent/audit.py +59 -0
- zotero_agent-0.2.0/src/zotero_agent/cli.py +217 -0
- zotero_agent-0.2.0/src/zotero_agent/commands/__init__.py +5 -0
- zotero_agent-0.2.0/src/zotero_agent/commands/admin.py +184 -0
- zotero_agent-0.2.0/src/zotero_agent/commands/features.py +394 -0
- zotero_agent-0.2.0/src/zotero_agent/commands/read.py +392 -0
- zotero_agent-0.2.0/src/zotero_agent/commands/write.py +218 -0
- zotero_agent-0.2.0/src/zotero_agent/config.py +73 -0
- zotero_agent-0.2.0/src/zotero_agent/constants.py +26 -0
- zotero_agent-0.2.0/src/zotero_agent/http.py +200 -0
- zotero_agent-0.2.0/src/zotero_agent/jslib.py +131 -0
- zotero_agent-0.2.0/src/zotero_agent/mcp_server.py +187 -0
- zotero_agent-0.2.0/src/zotero_agent/output.py +47 -0
- zotero_agent-0.2.0/src/zotero_agent/resolve.py +32 -0
- zotero_agent-0.2.0/src/zotero_agent/term.py +61 -0
- zotero_agent-0.2.0/tests/fake_zotero.py +95 -0
- zotero_agent-0.2.0/tests/test_zot.py +181 -0
- zotero_agent-0.2.0/updates.json +18 -0
- zotero_agent-0.2.0/web/.gitignore +15 -0
- zotero_agent-0.2.0/web/README.md +46 -0
- zotero_agent-0.2.0/web/astro.config.mjs +80 -0
- zotero_agent-0.2.0/web/package.json +18 -0
- zotero_agent-0.2.0/web/pnpm-lock.yaml +4403 -0
- zotero_agent-0.2.0/web/pnpm-workspace.yaml +4 -0
- zotero_agent-0.2.0/web/public/favicon.svg +4 -0
- zotero_agent-0.2.0/web/src/content/docs/ai-agents/claude-code.md +37 -0
- zotero_agent-0.2.0/web/src/content/docs/ai-agents/codex-cli.md +31 -0
- zotero_agent-0.2.0/web/src/content/docs/ai-agents/cursor.md +26 -0
- zotero_agent-0.2.0/web/src/content/docs/ai-agents/gemini-cli.md +30 -0
- zotero_agent-0.2.0/web/src/content/docs/ai-agents/mcp.md +66 -0
- zotero_agent-0.2.0/web/src/content/docs/architecture.md +70 -0
- zotero_agent-0.2.0/web/src/content/docs/compare.md +56 -0
- zotero_agent-0.2.0/web/src/content/docs/cookbook/bulk-tag-by-topic.md +62 -0
- zotero_agent-0.2.0/web/src/content/docs/cookbook/clean-500-items.md +62 -0
- zotero_agent-0.2.0/web/src/content/docs/cookbook/dedupe-and-merge.md +57 -0
- zotero_agent-0.2.0/web/src/content/docs/cookbook/find-missing-metadata.md +54 -0
- zotero_agent-0.2.0/web/src/content/docs/cookbook/import-by-identifier.md +46 -0
- zotero_agent-0.2.0/web/src/content/docs/cookbook/index.md +31 -0
- zotero_agent-0.2.0/web/src/content/docs/cookbook/summarize-pdf-to-note.md +51 -0
- zotero_agent-0.2.0/web/src/content/docs/faq.md +74 -0
- zotero_agent-0.2.0/web/src/content/docs/getting-started/install.md +100 -0
- zotero_agent-0.2.0/web/src/content/docs/getting-started/quickstart-agent.md +79 -0
- zotero_agent-0.2.0/web/src/content/docs/getting-started/quickstart-cli.md +102 -0
- zotero_agent-0.2.0/web/src/content/docs/index.mdx +99 -0
- zotero_agent-0.2.0/web/src/content/docs/reference/commands.md +94 -0
- zotero_agent-0.2.0/web/src/content/docs/reference/configuration.md +74 -0
- zotero_agent-0.2.0/web/src/content/docs/reference/zot-exec-js.md +204 -0
- zotero_agent-0.2.0/web/src/content/docs/security.md +72 -0
- zotero_agent-0.2.0/web/src/content.config.ts +7 -0
- zotero_agent-0.2.0/web/tsconfig.json +5 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something isn't working
|
|
3
|
+
labels: ["bug"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: Thanks for the report! Please include the diagnostics below — they resolve most issues quickly.
|
|
8
|
+
- type: textarea
|
|
9
|
+
id: ping
|
|
10
|
+
attributes:
|
|
11
|
+
label: Output of `zot ping`
|
|
12
|
+
description: Run `zot ping` and paste the full output.
|
|
13
|
+
render: text
|
|
14
|
+
validations:
|
|
15
|
+
required: true
|
|
16
|
+
- type: input
|
|
17
|
+
id: version
|
|
18
|
+
attributes:
|
|
19
|
+
label: Version
|
|
20
|
+
description: Output of `zot --version`
|
|
21
|
+
placeholder: zot (zotero-agent) 0.2.0
|
|
22
|
+
validations:
|
|
23
|
+
required: true
|
|
24
|
+
- type: input
|
|
25
|
+
id: platform
|
|
26
|
+
attributes:
|
|
27
|
+
label: Platform + Zotero version
|
|
28
|
+
placeholder: macOS 14 / Zotero 7.0.15
|
|
29
|
+
validations:
|
|
30
|
+
required: true
|
|
31
|
+
- type: textarea
|
|
32
|
+
id: what
|
|
33
|
+
attributes:
|
|
34
|
+
label: What happened
|
|
35
|
+
description: What you did (the exact command or agent prompt), what you expected, and what happened instead.
|
|
36
|
+
validations:
|
|
37
|
+
required: true
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: Security vulnerability
|
|
4
|
+
url: https://github.com/alex-roc/zotero-agent/security/advisories/new
|
|
5
|
+
about: Please report security issues privately, not as a public issue.
|
|
6
|
+
- name: Question / discussion
|
|
7
|
+
url: https://github.com/alex-roc/zotero-agent/discussions
|
|
8
|
+
about: Ask a question or share how you use zotero-agent.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Suggest an idea or a new command/tool
|
|
3
|
+
labels: ["enhancement"]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: The problem / use case
|
|
9
|
+
description: What are you trying to do with your Zotero library that's hard today?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: idea
|
|
14
|
+
attributes:
|
|
15
|
+
label: Proposed solution
|
|
16
|
+
description: A command, MCP tool, or behaviour you have in mind (rough is fine).
|
|
17
|
+
- type: dropdown
|
|
18
|
+
id: surface
|
|
19
|
+
attributes:
|
|
20
|
+
label: Which surface?
|
|
21
|
+
options: ["CLI", "MCP server", "Claude Code skill", "the bridge plugin", "not sure"]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!-- Thanks for contributing! Keep the core stdlib-only and writes guarded. -->
|
|
2
|
+
|
|
3
|
+
## What & why
|
|
4
|
+
|
|
5
|
+
<!-- What does this change and what problem does it solve? -->
|
|
6
|
+
|
|
7
|
+
## How I verified
|
|
8
|
+
|
|
9
|
+
- [ ] `python -m unittest discover -s tests` passes
|
|
10
|
+
- [ ] `uvx ruff check src tests cli/zot` is clean
|
|
11
|
+
- [ ] Rebuilt the XPI (`bash plugin/build.sh`) if the plugin changed
|
|
12
|
+
- [ ] Updated `docs/` / `skill/` / `CHANGELOG.md` (Unreleased) if behaviour changed
|
|
13
|
+
- [ ] (If a live test was relevant) ran `zot ping` / the affected command against a real library
|
|
14
|
+
|
|
15
|
+
## Notes
|
|
16
|
+
|
|
17
|
+
<!-- Anything reviewers should know: trade-offs, follow-ups, screenshots. -->
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.9", "3.13"]
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: ${{ matrix.python-version }}
|
|
19
|
+
- name: Run tests (stdlib only, no network)
|
|
20
|
+
run: python -m unittest discover -s tests -v
|
|
21
|
+
|
|
22
|
+
lint:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
- uses: astral-sh/ruff-action@v3
|
|
27
|
+
with:
|
|
28
|
+
args: check src tests cli/zot
|
|
29
|
+
|
|
30
|
+
build-xpi:
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v4
|
|
34
|
+
- uses: actions/setup-python@v5
|
|
35
|
+
with:
|
|
36
|
+
python-version: "3.13"
|
|
37
|
+
- name: Build the bridge XPI
|
|
38
|
+
run: bash plugin/build.sh
|
|
39
|
+
- name: Verify the XPI is a valid zip with a manifest
|
|
40
|
+
run: |
|
|
41
|
+
unzip -l dist/zotero-agent-bridge.xpi | grep -q manifest.json
|
|
42
|
+
- uses: actions/upload-artifact@v4
|
|
43
|
+
with:
|
|
44
|
+
name: zotero-agent-bridge-xpi
|
|
45
|
+
path: dist/zotero-agent-bridge-*.xpi
|
|
46
|
+
|
|
47
|
+
build-package:
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
steps:
|
|
50
|
+
- uses: actions/checkout@v4
|
|
51
|
+
- uses: astral-sh/setup-uv@v5
|
|
52
|
+
- name: Build wheel + sdist
|
|
53
|
+
run: uv build
|
|
54
|
+
- uses: actions/upload-artifact@v4
|
|
55
|
+
with:
|
|
56
|
+
name: dist
|
|
57
|
+
path: dist/*.whl
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
name: Deploy docs to GitHub Pages
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- 'web/**'
|
|
8
|
+
- '.github/workflows/pages.yml'
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
# Allow the GITHUB_TOKEN to deploy to Pages.
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
pages: write
|
|
15
|
+
id-token: write
|
|
16
|
+
|
|
17
|
+
# Allow one concurrent deployment; don't cancel in-progress production deploys.
|
|
18
|
+
concurrency:
|
|
19
|
+
group: pages
|
|
20
|
+
cancel-in-progress: false
|
|
21
|
+
|
|
22
|
+
defaults:
|
|
23
|
+
run:
|
|
24
|
+
working-directory: web
|
|
25
|
+
|
|
26
|
+
jobs:
|
|
27
|
+
build:
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
steps:
|
|
30
|
+
- name: Checkout
|
|
31
|
+
uses: actions/checkout@v4
|
|
32
|
+
|
|
33
|
+
- name: Install pnpm
|
|
34
|
+
uses: pnpm/action-setup@v4
|
|
35
|
+
with:
|
|
36
|
+
version: 11
|
|
37
|
+
|
|
38
|
+
- name: Setup Node
|
|
39
|
+
uses: actions/setup-node@v4
|
|
40
|
+
with:
|
|
41
|
+
node-version: 22
|
|
42
|
+
cache: pnpm
|
|
43
|
+
cache-dependency-path: web/pnpm-lock.yaml
|
|
44
|
+
|
|
45
|
+
- name: Install dependencies
|
|
46
|
+
run: pnpm install --frozen-lockfile
|
|
47
|
+
|
|
48
|
+
- name: Build with Astro
|
|
49
|
+
run: pnpm build
|
|
50
|
+
|
|
51
|
+
- name: Configure Pages
|
|
52
|
+
uses: actions/configure-pages@v5
|
|
53
|
+
|
|
54
|
+
- name: Upload artifact
|
|
55
|
+
uses: actions/upload-pages-artifact@v3
|
|
56
|
+
with:
|
|
57
|
+
path: web/dist
|
|
58
|
+
|
|
59
|
+
deploy:
|
|
60
|
+
needs: build
|
|
61
|
+
runs-on: ubuntu-latest
|
|
62
|
+
environment:
|
|
63
|
+
name: github-pages
|
|
64
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
65
|
+
steps:
|
|
66
|
+
- name: Deploy to GitHub Pages
|
|
67
|
+
id: deployment
|
|
68
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Tag a version (vX.Y.Z) to build the XPI + wheel, publish a GitHub Release with
|
|
4
|
+
# the XPI attached, and publish the package to PyPI via Trusted Publishing.
|
|
5
|
+
#
|
|
6
|
+
# One-time setup on pypi.org: add a Trusted Publisher for this repo + workflow
|
|
7
|
+
# (Publishing → Add a new pending publisher) so no API token is needed here.
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
push:
|
|
11
|
+
tags: ["v*"]
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: write # create the GitHub Release
|
|
15
|
+
id-token: write # PyPI Trusted Publishing (OIDC)
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
release:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- uses: astral-sh/setup-uv@v5
|
|
24
|
+
- name: Build wheel + sdist (into dist/)
|
|
25
|
+
run: uv build
|
|
26
|
+
|
|
27
|
+
- name: Build the bridge XPI (into release-assets/, keeping dist/ PyPI-only)
|
|
28
|
+
run: |
|
|
29
|
+
bash plugin/build.sh
|
|
30
|
+
mkdir -p release-assets
|
|
31
|
+
mv dist/zotero-agent-bridge-*.xpi release-assets/
|
|
32
|
+
rm -f dist/zotero-agent-bridge.xpi # drop the symlink so dist/ is PyPI-only
|
|
33
|
+
|
|
34
|
+
- name: Create GitHub Release with the XPI
|
|
35
|
+
uses: softprops/action-gh-release@v2
|
|
36
|
+
with:
|
|
37
|
+
files: release-assets/zotero-agent-bridge-*.xpi
|
|
38
|
+
generate_release_notes: true
|
|
39
|
+
|
|
40
|
+
- name: Publish to PyPI (Trusted Publishing)
|
|
41
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
42
|
+
with:
|
|
43
|
+
packages-dir: dist # wheel + sdist only
|
|
44
|
+
verbose: true
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Built artifacts (produced by plugin/build.sh)
|
|
2
|
+
/dist/
|
|
3
|
+
|
|
4
|
+
# Self-contained skill bundle (produced by install.sh from cli/ and plugin/)
|
|
5
|
+
/skill/scripts/
|
|
6
|
+
|
|
7
|
+
# OS / editor cruft
|
|
8
|
+
.DS_Store
|
|
9
|
+
*.swp
|
|
10
|
+
|
|
11
|
+
# Python
|
|
12
|
+
__pycache__/
|
|
13
|
+
*.pyc
|
|
14
|
+
*.egg-info/
|
|
15
|
+
.venv/
|
|
16
|
+
|
|
17
|
+
# Website (Astro Starlight)
|
|
18
|
+
/web/node_modules/
|
|
19
|
+
/web/dist/
|
|
20
|
+
/web/.astro/
|
|
21
|
+
|
|
22
|
+
# Release scratch
|
|
23
|
+
/release-assets/
|
|
24
|
+
|
|
25
|
+
# skill-creator eval workspace (artefactos + backup)
|
|
26
|
+
/zotero-workspace/
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# AGENTS.md — driving Zotero with the `zot` CLI
|
|
2
|
+
|
|
3
|
+
This file gives coding/agent tools (Codex CLI, Gemini CLI, Aider, and any agent
|
|
4
|
+
that reads `AGENTS.md`) what they need to control a **local Zotero library**
|
|
5
|
+
through the `zot` command. It mirrors the Claude Code skill in `skill/SKILL.md`.
|
|
6
|
+
|
|
7
|
+
## Setup check
|
|
8
|
+
|
|
9
|
+
Run `zot ping`. It must show the local API up, the bridge endpoint answering
|
|
10
|
+
`1+1 == 2`, and a known userID. If it fails, the bridge plugin isn't installed —
|
|
11
|
+
see `docs/install.md`; do **not** work around it.
|
|
12
|
+
|
|
13
|
+
## Reading (fast, prefer these)
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
zot search "<query>" [--limit N] [--tag T] [--item-type book] # full-text
|
|
17
|
+
zot get <KEY|@citekey> # one item's fields
|
|
18
|
+
zot pdf <KEY|@citekey> # local PDF path(s) — then read the file directly
|
|
19
|
+
zot collections | zot tags # list
|
|
20
|
+
zot stats # analytics
|
|
21
|
+
zot missing abstract|date|doi [--collection C]
|
|
22
|
+
zot author "<name>" | zot recent | zot lint
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Add `--json` to any command for machine-readable output.
|
|
26
|
+
|
|
27
|
+
## Writing (guarded — pass `--yes` for non-interactive)
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
zot add doi|isbn|arxiv <id> [--pdf] [--collection C]
|
|
31
|
+
zot set <field> <value> <KEY…> --yes
|
|
32
|
+
zot tag add|rm <tag> <KEY…> --yes | zot tag rename <old> --new <n> --yes
|
|
33
|
+
zot move <collection> <KEY…> --yes
|
|
34
|
+
zot note <KEY> --file note.html
|
|
35
|
+
zot dedupe [--by title|doi] [--fuzzy] [--merge --yes]
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Batch edits (preferred for anything at scale — undoable)
|
|
39
|
+
|
|
40
|
+
Write a JSONL file, one edit per line, then apply it:
|
|
41
|
+
|
|
42
|
+
```jsonl
|
|
43
|
+
{"key":"ABCD1234","set":{"abstract":"…","date":"2021"},"addTags":["review"]}
|
|
44
|
+
{"key":"EFGH5678","addToCollection":"To Read","removeTags":["old"]}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
zot apply edits.jsonl --dry-run # preview
|
|
49
|
+
zot apply edits.jsonl # apply (snapshots first)
|
|
50
|
+
zot undo last # roll back the last apply/enrich
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**You** decide the values (e.g. cleaned titles, topic tags) and write the JSONL;
|
|
54
|
+
`zot` performs the writes. The CLI never calls an LLM itself.
|
|
55
|
+
|
|
56
|
+
## Safety rules (follow these)
|
|
57
|
+
|
|
58
|
+
1. `zot backup` before any bulk or destructive change — always before `dedupe --merge`.
|
|
59
|
+
2. Prefer `--dry-run` and scope with `--collection` before touching the whole library.
|
|
60
|
+
3. Apply to 1–2 items and verify before the full set.
|
|
61
|
+
4. Deletions: prefer trash (`"trash": true` in `apply`), not permanent erase.
|
|
62
|
+
5. Merges are **not** reversible; everything via `zot apply`/`zot enrich` is.
|
|
63
|
+
|
|
64
|
+
Full JS recipe book: `skill/references/recipes.md`. PDF/notes workflow:
|
|
65
|
+
`skill/references/pdf-and-notes.md`.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format is based on
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
|
|
5
|
+
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- **`apply`/`update_items` dry-run no longer executes any JS**, so it can never
|
|
11
|
+
persist changes (the old monkey-patch-`save()` interception could leak writes
|
|
12
|
+
on Zotero 7). The preview is reported straight from the parsed edits.
|
|
13
|
+
- `dedupe --fuzzy` is now tractable on large libraries (prefix-blocking instead
|
|
14
|
+
of O(n²) over the whole library) — seconds instead of timing out.
|
|
15
|
+
- Bridge/read calls that time out now return a clean error instead of an
|
|
16
|
+
uncaught traceback (`post_code` and `main` handle `TimeoutError`/`OSError`).
|
|
17
|
+
- `exec --dry-run` now states honestly that it executes the script with
|
|
18
|
+
best-effort interception and may still persist (backup is the guarantee).
|
|
19
|
+
|
|
20
|
+
## [0.2.0] — 2026-07-23
|
|
21
|
+
|
|
22
|
+
The project was renamed from `zotero-cli-skill` to **`zotero-agent`** and rebuilt
|
|
23
|
+
into an installable Python package with an MCP server.
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
- **Python package** `zotero-agent` (installable from PyPI; entry point `zot`).
|
|
27
|
+
The former single-file CLI is now a modular package under `src/zotero_agent/`.
|
|
28
|
+
- **MCP server** (`zot mcp`) exposing ~18 high-level tools to any Model Context
|
|
29
|
+
Protocol client (Claude Desktop, Codex CLI, Gemini CLI, Cursor). Optional
|
|
30
|
+
`[mcp]` extra.
|
|
31
|
+
- **`zot apply`** — declarative JSONL batch edits (set fields / add-remove tags /
|
|
32
|
+
add to collection / trash), with a pre-image snapshot.
|
|
33
|
+
- **`zot undo`** — restore items to their state before an `apply`/`enrich`.
|
|
34
|
+
- **`zot enrich`** — fill missing DOI / date / abstract from Crossref or OpenAlex.
|
|
35
|
+
- **`zot tag normalize`** — fold case- and whitespace-variant tags together.
|
|
36
|
+
- **`zot dedupe --fuzzy`** — group near-identical titles (Levenshtein).
|
|
37
|
+
- **Audit log** of every bridge execution at `~/.local/state/zotero-agent/audit.jsonl`.
|
|
38
|
+
- `--version` flag; `--json` is now a global flag on every command.
|
|
39
|
+
- Fake-Zotero test server; expanded unit + integration tests. CI on GitHub Actions.
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
- **Rebranding:** endpoint `POST /zotexec` → `POST /zotero-agent`; token header
|
|
43
|
+
`X-Zotexec-Token` → `X-Zotero-Agent-Token`; pref `extensions.zotexec.token` →
|
|
44
|
+
`extensions.zotero-agent.token`; config dir `~/.config/zotero-exec` →
|
|
45
|
+
`~/.config/zotero-agent`; env `ZOTEXEC_*` → `ZOTERO_AGENT_*`; plugin →
|
|
46
|
+
"Zotero Agent Bridge" (`zotero-agent-bridge-<version>.xpi`).
|
|
47
|
+
- `export`/`bib` no longer silently truncate large collections (paginate fully).
|
|
48
|
+
- Minimum Python is now 3.9.
|
|
49
|
+
|
|
50
|
+
### Migration
|
|
51
|
+
Single-user project, no back-compat shim: reinstall the bridge XPI and run
|
|
52
|
+
`zot init` to regenerate `~/.config/zotero-agent/config.json`.
|
|
53
|
+
|
|
54
|
+
## [0.1.0] — 2026-07-23
|
|
55
|
+
- Initial release as `zotero-cli-skill`: `zotexec` plugin + `zot` CLI + Claude
|
|
56
|
+
Code skill.
|
|
57
|
+
|
|
58
|
+
[Unreleased]: https://github.com/alex-roc/zotero-agent/compare/v0.2.0...HEAD
|
|
59
|
+
[0.2.0]: https://github.com/alex-roc/zotero-agent/releases/tag/v0.2.0
|
|
60
|
+
[0.1.0]: https://github.com/alex-roc/zotero-agent/releases/tag/v0.1.0
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Contributing to zotero-agent
|
|
2
|
+
|
|
3
|
+
Thanks for your interest! This is a small, focused project — a CLI + MCP server +
|
|
4
|
+
Zotero bridge plugin for **local** library control. Contributions that keep it
|
|
5
|
+
simple, safe, and dependency-light are very welcome.
|
|
6
|
+
|
|
7
|
+
## Ground rules
|
|
8
|
+
|
|
9
|
+
- **Core stays stdlib-only.** The `zotero_agent` core must not add runtime
|
|
10
|
+
dependencies. Anything heavier goes behind an optional extra (like `[mcp]`).
|
|
11
|
+
- **Writes are guarded.** New write commands must respect `confirm_write` (refuse
|
|
12
|
+
non-interactive runs without `--yes`) and, where sensible, support `--dry-run`
|
|
13
|
+
and snapshot for `zot undo`.
|
|
14
|
+
- **Behaviour parity.** MCP tools reuse the CLI command functions — don't fork the
|
|
15
|
+
logic.
|
|
16
|
+
|
|
17
|
+
## Dev setup
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
git clone https://github.com/alex-roc/zotero-agent.git && cd zotero-agent
|
|
21
|
+
./install.sh # dev shim on PATH + skill + XPI
|
|
22
|
+
python3 -m unittest discover -s tests # tests (no network, no live Zotero)
|
|
23
|
+
uvx ruff check src tests # lint
|
|
24
|
+
uv build # build wheel + sdist
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The tests use a fake in-process Zotero server (`tests/fake_zotero.py`), so they
|
|
28
|
+
run without Zotero. For a real end-to-end check against your own library, set
|
|
29
|
+
`ZOT_LIVE=1` and run `zot ping` with Zotero open.
|
|
30
|
+
|
|
31
|
+
## Making a change
|
|
32
|
+
|
|
33
|
+
1. Branch from `main`.
|
|
34
|
+
2. Keep commits focused; update `docs/`, the `skill/`, and `CHANGELOG.md` when you
|
|
35
|
+
change behaviour (see the "Unreleased" section).
|
|
36
|
+
3. Run tests + ruff. Rebuild the XPI (`bash plugin/build.sh`) if you touched the
|
|
37
|
+
plugin.
|
|
38
|
+
4. Open a PR describing what changed and how you verified it.
|
|
39
|
+
|
|
40
|
+
## Reporting bugs / requesting features
|
|
41
|
+
|
|
42
|
+
Use the issue templates. For bugs, include the output of `zot ping` and
|
|
43
|
+
`zot --version`. For anything security-related, see [`SECURITY.md`](SECURITY.md).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 zotero-cli-skill contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: zotero-agent
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Local read-write control of a Zotero library — from your terminal or your AI agent. No cloud, no API key.
|
|
5
|
+
Project-URL: Homepage, https://github.com/alex-roc/zotero-agent
|
|
6
|
+
Project-URL: Documentation, https://alex-roc.github.io/zotero-agent
|
|
7
|
+
Project-URL: Repository, https://github.com/alex-roc/zotero-agent
|
|
8
|
+
Project-URL: Issues, https://github.com/alex-roc/zotero-agent/issues
|
|
9
|
+
Author: Alex Ojeda Copa
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: ai-agent,bibliography,cli,local-first,mcp,reference-manager,zotero
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Topic :: Text Processing :: Markup
|
|
19
|
+
Classifier: Topic :: Utilities
|
|
20
|
+
Requires-Python: >=3.9
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
23
|
+
Provides-Extra: mcp
|
|
24
|
+
Requires-Dist: mcp>=1.2.0; extra == 'mcp'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# zotero-agent
|
|
28
|
+
|
|
29
|
+
**Full local control of your Zotero library — from your terminal or your AI agent. No cloud, no API key.**
|
|
30
|
+
|
|
31
|
+
`zot` is a CLI and AI-agent toolkit that gives you full **read-write** control of
|
|
32
|
+
your *local* Zotero library: search, bulk-edit metadata, tag, deduplicate, import
|
|
33
|
+
by DOI/ISBN/arXiv, export, and summarize PDFs into notes. Zotero's local API is
|
|
34
|
+
read-only, so writes go through a tiny plugin exposing a single token-protected
|
|
35
|
+
endpoint, with a documented [three-layer security model](docs/security.md). No
|
|
36
|
+
zotero.org account, no API key, no cloud — **your library never leaves your machine.**
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
Agent / user → [ MCP server | agent skill | zot CLI ] ─┬─ read → Zotero local API /api/… (GET, fast)
|
|
40
|
+
└─ write → POST /zotero-agent (bridge plugin, JS)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Why this exists
|
|
44
|
+
|
|
45
|
+
The dominant Zotero automation tools (zotero-mcp, pyzotero) can only *write* via
|
|
46
|
+
the zotero.org web API — which needs an account, an API key and sync. Zotero's
|
|
47
|
+
**local** HTTP API returns `501` on every write. The only way to write locally is
|
|
48
|
+
a plugin, and that is exactly what the `zotero-agent` bridge is. That makes this
|
|
49
|
+
the local-first, offline, private option: batch metadata edits, real dedup, and
|
|
50
|
+
tag cleanup that people have asked Zotero for [since 2016](https://forums.zotero.org/discussion/111815/feature-batch-editing-metadata-for-multiple-items) — done on your own machine.
|
|
51
|
+
|
|
52
|
+
## Three ways to use it
|
|
53
|
+
|
|
54
|
+
- **AI agents via MCP** — `zot mcp` is a Model Context Protocol server for Claude
|
|
55
|
+
Desktop, **Codex CLI**, **Gemini CLI**, Cursor, and any MCP client. See
|
|
56
|
+
[`docs/ai-agents.md`](docs/ai-agents.md).
|
|
57
|
+
- **Claude Code skill** — the `zotero` skill drives `zot` with a safe workflow.
|
|
58
|
+
- **Plain CLI** — script it in bash, pipe it, put it in a Makefile.
|
|
59
|
+
|
|
60
|
+
## What's inside
|
|
61
|
+
|
|
62
|
+
| Path | What |
|
|
63
|
+
|------|------|
|
|
64
|
+
| `src/zotero_agent/` | The Python package: CLI, command modules, JS builders, MCP server. Stdlib-only core. |
|
|
65
|
+
| `plugin/zotero-agent-bridge/` | The write endpoint (`POST /zotero-agent`), token-protected, ~200 lines. |
|
|
66
|
+
| `skill/` | The `zotero` skill for Claude Code (SKILL.md + recipe book + evals). |
|
|
67
|
+
| `docs/` | Install, security model, architecture, AI-agent setup. |
|
|
68
|
+
| `web/` | The documentation site (Astro Starlight → GitHub Pages). |
|
|
69
|
+
|
|
70
|
+
## Install
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# CLI (+ optional MCP server):
|
|
74
|
+
uv tool install zotero-agent # or: pipx install zotero-agent
|
|
75
|
+
uv tool install "zotero-agent[mcp]" # include the MCP server
|
|
76
|
+
|
|
77
|
+
# then install the bridge plugin in Zotero:
|
|
78
|
+
# Tools → Plugins → gear → "Install Plugin From File" → the .xpi from Releases
|
|
79
|
+
zot init # generates a token, writes config, auto-detects your userID
|
|
80
|
+
zot ping # verify: local API up, bridge answering, userID known
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
From a checkout, `./install.sh` wires up the skill, a dev `zot`, and builds the
|
|
84
|
+
XPI. Full instructions: [`docs/install.md`](docs/install.md).
|
|
85
|
+
|
|
86
|
+
## Using the CLI
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
zot search "bolivia" --limit 10 # read (fast API)
|
|
90
|
+
zot get ABCD1234 # one item (Zotero key or BBT citekey)
|
|
91
|
+
zot missing abstract --collection SS5MVVB6 # items lacking a field
|
|
92
|
+
zot stats # library analytics
|
|
93
|
+
zot add doi 10.1371/journal.pmed.0020124 --pdf # import by identifier (+ OA PDF)
|
|
94
|
+
zot dedupe --by title --fuzzy # find near-duplicate titles
|
|
95
|
+
zot dedupe --merge --yes # merge duplicates (oldest = master)
|
|
96
|
+
zot enrich --field doi --dry-run # fill missing DOIs from Crossref
|
|
97
|
+
zot apply edits.jsonl # declarative batch edit (undoable)
|
|
98
|
+
zot undo last # roll it back
|
|
99
|
+
zot tag normalize --dry-run # fold case/space tag variants
|
|
100
|
+
zot export "My Collection" --format bibtex --out refs.bib
|
|
101
|
+
zot exec 'return Zotero.version;' # escape hatch: run privileged JS
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Add `--json` to any command for machine-readable output. Writes refuse to run
|
|
105
|
+
non-interactively without `--yes`. The canonical JS recipe book is
|
|
106
|
+
[`skill/references/recipes.md`](skill/references/recipes.md).
|
|
107
|
+
|
|
108
|
+
## Using with an AI agent
|
|
109
|
+
|
|
110
|
+
Ask *"tag every abstract-less item #review and merge duplicate titles in
|
|
111
|
+
collection X"*, *"fill in missing DOIs"*, or *"summarize this paper's PDF chapter
|
|
112
|
+
by chapter and save it as a note"*. The agent drives `zot` and follows a safe
|
|
113
|
+
workflow (backup → sync-off → dry-run → small batch) for bulk or destructive edits.
|
|
114
|
+
Batch edits are **undoable** (`zot undo`).
|
|
115
|
+
|
|
116
|
+
## Requirements
|
|
117
|
+
|
|
118
|
+
- Zotero 7+ (tested through 9.x) running, local API enabled (default).
|
|
119
|
+
- Python 3.9+ (stdlib-only core; the MCP server needs the `[mcp]` extra).
|
|
120
|
+
- macOS and Linux; Windows paths are noted in `docs/install.md`.
|
|
121
|
+
|
|
122
|
+
## Security
|
|
123
|
+
|
|
124
|
+
Arbitrary local JS execution, gated by a required token + browser-origin
|
|
125
|
+
rejection + loopback binding, with an append-only audit log. This is a deliberate
|
|
126
|
+
capability; read [`docs/security.md`](docs/security.md) before installing.
|
|
127
|
+
License: [MIT](LICENSE).
|
|
128
|
+
|
|
129
|
+
## Development
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
python3 -m unittest discover -s tests # unit + fake-server tests (no network, no Zotero)
|
|
133
|
+
uvx ruff check src tests # lint
|
|
134
|
+
uv build # build wheel + sdist
|
|
135
|
+
bash plugin/build.sh # rebuild the bridge XPI
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
See [`CONTRIBUTING.md`](CONTRIBUTING.md) and [`CHANGELOG.md`](CHANGELOG.md).
|