anki-agent-toolkit 0.1.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.
- anki_agent_toolkit-0.1.0/.agent/skills/anki-operations/SKILL.md +120 -0
- anki_agent_toolkit-0.1.0/.agent/skills/anki-operations/agents/openai.yaml +4 -0
- anki_agent_toolkit-0.1.0/.agent/skills/release/SKILL.md +130 -0
- anki_agent_toolkit-0.1.0/.github/workflows/ci.yml +60 -0
- anki_agent_toolkit-0.1.0/.github/workflows/pages.yml +48 -0
- anki_agent_toolkit-0.1.0/.github/workflows/release.yml +60 -0
- anki_agent_toolkit-0.1.0/.gitignore +14 -0
- anki_agent_toolkit-0.1.0/AGENTS.md +174 -0
- anki_agent_toolkit-0.1.0/LICENSE +17 -0
- anki_agent_toolkit-0.1.0/Makefile +48 -0
- anki_agent_toolkit-0.1.0/PKG-INFO +150 -0
- anki_agent_toolkit-0.1.0/README.md +131 -0
- anki_agent_toolkit-0.1.0/docs/anki-catalog-reference.md +94 -0
- anki_agent_toolkit-0.1.0/docs/anki-operations-skill.md +253 -0
- anki_agent_toolkit-0.1.0/docs/anki-study-ux-roadmap.md +98 -0
- anki_agent_toolkit-0.1.0/docs/images/ankicli-hero.png +0 -0
- anki_agent_toolkit-0.1.0/docs/openclaw-plugin.md +189 -0
- anki_agent_toolkit-0.1.0/docs/spec.md +250 -0
- anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/README.md +90 -0
- anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/index.js +223 -0
- anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/openclaw.plugin.json +40 -0
- anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/package.json +12 -0
- anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/skills/anki-collection-management/SKILL.md +20 -0
- anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/skills/anki-diagnostics/SKILL.md +19 -0
- anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/skills/anki-note-authoring/SKILL.md +19 -0
- anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/skills/anki-study/SKILL.md +32 -0
- anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/src/ankicli-tool.js +921 -0
- anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/test/catalog-plugin.test.mjs +649 -0
- anki_agent_toolkit-0.1.0/ops/test-matrix.yaml +383 -0
- anki_agent_toolkit-0.1.0/pyproject.toml +57 -0
- anki_agent_toolkit-0.1.0/scripts/audit_cli_surface.py +339 -0
- anki_agent_toolkit-0.1.0/scripts/audit_quality_matrix.py +62 -0
- anki_agent_toolkit-0.1.0/scripts/build_release_artifact.py +155 -0
- anki_agent_toolkit-0.1.0/scripts/generate_openclaw_artifacts.py +138 -0
- anki_agent_toolkit-0.1.0/scripts/install.ps1 +128 -0
- anki_agent_toolkit-0.1.0/scripts/install.sh +157 -0
- anki_agent_toolkit-0.1.0/scripts/migrate_ios_audio.py +135 -0
- anki_agent_toolkit-0.1.0/scripts/prepare_ankiconnect_backend.py +133 -0
- anki_agent_toolkit-0.1.0/scripts/prepare_real_backend.py +177 -0
- anki_agent_toolkit-0.1.0/scripts/run_matrix_phase3.py +116 -0
- anki_agent_toolkit-0.1.0/site/astro.config.mjs +7 -0
- anki_agent_toolkit-0.1.0/site/package-lock.json +5542 -0
- anki_agent_toolkit-0.1.0/site/package.json +14 -0
- anki_agent_toolkit-0.1.0/site/public/ankicli-hero.png +0 -0
- anki_agent_toolkit-0.1.0/site/src/components/DocsPage.astro +355 -0
- anki_agent_toolkit-0.1.0/site/src/components/InstallCards.astro +80 -0
- anki_agent_toolkit-0.1.0/site/src/layouts/BaseLayout.astro +166 -0
- anki_agent_toolkit-0.1.0/site/src/lib/docs.ts +1186 -0
- anki_agent_toolkit-0.1.0/site/src/lib/install.ts +43 -0
- anki_agent_toolkit-0.1.0/site/src/pages/docs/agent-skills.astro +9 -0
- anki_agent_toolkit-0.1.0/site/src/pages/docs/cli-guide.astro +9 -0
- anki_agent_toolkit-0.1.0/site/src/pages/docs/common-tasks.astro +9 -0
- anki_agent_toolkit-0.1.0/site/src/pages/docs/learning-plans.astro +9 -0
- anki_agent_toolkit-0.1.0/site/src/pages/docs/profiles-and-collections.astro +9 -0
- anki_agent_toolkit-0.1.0/site/src/pages/docs/quickstart.astro +9 -0
- anki_agent_toolkit-0.1.0/site/src/pages/docs/recipes.astro +9 -0
- anki_agent_toolkit-0.1.0/site/src/pages/docs/study.astro +9 -0
- anki_agent_toolkit-0.1.0/site/src/pages/docs/sync-and-backups.astro +9 -0
- anki_agent_toolkit-0.1.0/site/src/pages/docs/troubleshooting.astro +9 -0
- anki_agent_toolkit-0.1.0/site/src/pages/docs/use-cases.astro +9 -0
- anki_agent_toolkit-0.1.0/site/src/pages/index.astro +205 -0
- anki_agent_toolkit-0.1.0/site/src/pages/install/index.astro +9 -0
- anki_agent_toolkit-0.1.0/site/src/pages/install/linux.astro +9 -0
- anki_agent_toolkit-0.1.0/site/src/pages/install/macos.astro +9 -0
- anki_agent_toolkit-0.1.0/site/src/pages/install/windows.astro +9 -0
- anki_agent_toolkit-0.1.0/site/tsconfig.json +6 -0
- anki_agent_toolkit-0.1.0/skills/ankicli-collection-management/SKILL.md +20 -0
- anki_agent_toolkit-0.1.0/skills/ankicli-diagnostics/SKILL.md +20 -0
- anki_agent_toolkit-0.1.0/skills/ankicli-note-authoring/SKILL.md +20 -0
- anki_agent_toolkit-0.1.0/skills/ankicli-study/SKILL.md +29 -0
- anki_agent_toolkit-0.1.0/src/ankicli/__init__.py +6 -0
- anki_agent_toolkit-0.1.0/src/ankicli/app/catalog.py +1188 -0
- anki_agent_toolkit-0.1.0/src/ankicli/app/credentials.py +370 -0
- anki_agent_toolkit-0.1.0/src/ankicli/app/errors.py +165 -0
- anki_agent_toolkit-0.1.0/src/ankicli/app/ios_audio_migration.py +644 -0
- anki_agent_toolkit-0.1.0/src/ankicli/app/models.py +44 -0
- anki_agent_toolkit-0.1.0/src/ankicli/app/output.py +44 -0
- anki_agent_toolkit-0.1.0/src/ankicli/app/profiles.py +164 -0
- anki_agent_toolkit-0.1.0/src/ankicli/app/quality_matrix.py +789 -0
- anki_agent_toolkit-0.1.0/src/ankicli/app/releases.py +59 -0
- anki_agent_toolkit-0.1.0/src/ankicli/app/services.py +1787 -0
- anki_agent_toolkit-0.1.0/src/ankicli/app/study.py +1380 -0
- anki_agent_toolkit-0.1.0/src/ankicli/backends/ankiconnect.py +659 -0
- anki_agent_toolkit-0.1.0/src/ankicli/backends/base.py +344 -0
- anki_agent_toolkit-0.1.0/src/ankicli/backends/python_anki.py +1623 -0
- anki_agent_toolkit-0.1.0/src/ankicli/main.py +1611 -0
- anki_agent_toolkit-0.1.0/src/ankicli/pytest_plugin.py +92 -0
- anki_agent_toolkit-0.1.0/src/ankicli/runtime.py +155 -0
- anki_agent_toolkit-0.1.0/tests/__init__.py +1 -0
- anki_agent_toolkit-0.1.0/tests/conftest.py +50 -0
- anki_agent_toolkit-0.1.0/tests/distribution/test_built_artifact.py +86 -0
- anki_agent_toolkit-0.1.0/tests/e2e/test_cli_e2e.py +108 -0
- anki_agent_toolkit-0.1.0/tests/fixtures/README.md +12 -0
- anki_agent_toolkit-0.1.0/tests/fixtures/__init__.py +1 -0
- anki_agent_toolkit-0.1.0/tests/fixtures/build_fixture.py +40 -0
- anki_agent_toolkit-0.1.0/tests/fixtures/generated/minimal/collection.anki2 +0 -0
- anki_agent_toolkit-0.1.0/tests/fixtures/generated/minimal/manifest.json +7 -0
- anki_agent_toolkit-0.1.0/tests/integration/helpers.py +9 -0
- anki_agent_toolkit-0.1.0/tests/integration/test_python_anki_backend.py +1428 -0
- anki_agent_toolkit-0.1.0/tests/proof.py +28 -0
- anki_agent_toolkit-0.1.0/tests/real/test_ankiconnect_real.py +526 -0
- anki_agent_toolkit-0.1.0/tests/real/test_python_anki_backup_real.py +372 -0
- anki_agent_toolkit-0.1.0/tests/real/test_python_anki_real_setup.py +1142 -0
- anki_agent_toolkit-0.1.0/tests/smoke/test_cli_smoke.py +43 -0
- anki_agent_toolkit-0.1.0/tests/smoke/test_install_scripts.py +170 -0
- anki_agent_toolkit-0.1.0/tests/unit/test_ankiconnect_backend_unit.py +326 -0
- anki_agent_toolkit-0.1.0/tests/unit/test_backend_parity.py +1005 -0
- anki_agent_toolkit-0.1.0/tests/unit/test_catalog_and_study.py +522 -0
- anki_agent_toolkit-0.1.0/tests/unit/test_cli_contract.py +1801 -0
- anki_agent_toolkit-0.1.0/tests/unit/test_credentials.py +129 -0
- anki_agent_toolkit-0.1.0/tests/unit/test_ios_audio_migration.py +313 -0
- anki_agent_toolkit-0.1.0/tests/unit/test_openclaw_plugin_generation.py +44 -0
- anki_agent_toolkit-0.1.0/tests/unit/test_output.py +45 -0
- anki_agent_toolkit-0.1.0/tests/unit/test_profiles.py +103 -0
- anki_agent_toolkit-0.1.0/tests/unit/test_python_anki_backend_unit.py +2172 -0
- anki_agent_toolkit-0.1.0/tests/unit/test_quality_matrix.py +1062 -0
- anki_agent_toolkit-0.1.0/tests/unit/test_releases.py +38 -0
- anki_agent_toolkit-0.1.0/tests/unit/test_services.py +2123 -0
- anki_agent_toolkit-0.1.0/uv.lock +979 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: anki-operations
|
|
3
|
+
description: Use when working with Anki collections through ankicli or the repo-owned OpenClaw plugin, especially for safe inspection, backend-aware troubleshooting, dry-run-first mutation workflows, or multi-step note/card/tag/deck/media operations.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Anki Operations
|
|
7
|
+
|
|
8
|
+
This skill is the workflow layer above `ankicli` and the repo-owned OpenClaw plugin. Use it to choose the right Anki operation, sequence read and write steps safely, and react to backend-specific limits without inventing new behavior.
|
|
9
|
+
|
|
10
|
+
## Core Rules
|
|
11
|
+
|
|
12
|
+
1. Read before write. Inspect the collection, search narrowly, and fetch a representative note or card before changing anything.
|
|
13
|
+
2. Prefer `--dry-run` first whenever the command supports it, unless the user clearly wants immediate execution.
|
|
14
|
+
3. Re-verify after mutations with a follow-up read, search, or stats command.
|
|
15
|
+
4. Treat sync and backup as different tools. Sync keeps local and remote state aligned; backup is the rollback path.
|
|
16
|
+
5. Preserve structured `ankicli` errors. Do not reinterpret codes into vague summaries.
|
|
17
|
+
6. Use the narrowest command or tool that solves the task. Do not jump straight to bulk operations.
|
|
18
|
+
7. Respect backend limits. If the active backend reports `BACKEND_OPERATION_UNSUPPORTED`, switch backend or explain the limit.
|
|
19
|
+
|
|
20
|
+
## Transport Choice
|
|
21
|
+
|
|
22
|
+
- In OpenClaw, prefer the repo-owned plugin tools first.
|
|
23
|
+
- Outside OpenClaw, prefer `ankicli --json`.
|
|
24
|
+
- Treat both as the same logical surface. The CLI is the source of truth; the plugin is only an adapter.
|
|
25
|
+
|
|
26
|
+
## Workflow Playbooks
|
|
27
|
+
|
|
28
|
+
### Inspect And Diagnose
|
|
29
|
+
|
|
30
|
+
Use this before any meaningful change:
|
|
31
|
+
- identify backend and capabilities
|
|
32
|
+
- resolve the profile when local profile targeting matters
|
|
33
|
+
- inspect auth status if sync or remote state matters
|
|
34
|
+
- inspect backup status when rollback matters
|
|
35
|
+
- inspect collection info or stats
|
|
36
|
+
- use `sync status` before assuming local and remote state match
|
|
37
|
+
- list decks or models if the target is not known
|
|
38
|
+
- use `search count` or `search preview` before wide changes
|
|
39
|
+
- fetch the exact note or card before mutating it
|
|
40
|
+
|
|
41
|
+
Good command/tool progression:
|
|
42
|
+
- collection or backend info
|
|
43
|
+
- search
|
|
44
|
+
- get
|
|
45
|
+
- mutate
|
|
46
|
+
- verify
|
|
47
|
+
|
|
48
|
+
### Safe Note Mutation
|
|
49
|
+
|
|
50
|
+
Use for add, update, patch, tag changes, and note deck moves:
|
|
51
|
+
- resolve the target model, deck, note id, or search query first
|
|
52
|
+
- if the operation supports dry-run, run it first
|
|
53
|
+
- perform the real mutation only after the target is clear
|
|
54
|
+
- read the note again afterward to confirm fields, tags, or deck placement
|
|
55
|
+
|
|
56
|
+
### Safe Card State Changes
|
|
57
|
+
|
|
58
|
+
Use for suspend and unsuspend:
|
|
59
|
+
- fetch the card first
|
|
60
|
+
- confirm the deck and note context are the intended target
|
|
61
|
+
- dry-run first when available
|
|
62
|
+
- re-read the card after the change
|
|
63
|
+
|
|
64
|
+
### Bulk-Safe Changes
|
|
65
|
+
|
|
66
|
+
Use for import patch, exports, tag cleanup, and larger migrations:
|
|
67
|
+
- count first
|
|
68
|
+
- preview a small sample
|
|
69
|
+
- export or dry-run before committing writes
|
|
70
|
+
- apply the narrowest bulk action possible
|
|
71
|
+
- re-run count or preview after the change
|
|
72
|
+
|
|
73
|
+
## Backend Strategy
|
|
74
|
+
|
|
75
|
+
Default preference:
|
|
76
|
+
- use `python-anki` when local collection semantics matter
|
|
77
|
+
- use `ankiconnect` when live desktop integration is the goal
|
|
78
|
+
|
|
79
|
+
Switch to `python-anki` when you need:
|
|
80
|
+
- local collection validation or lock checks
|
|
81
|
+
- local profile resolution or backup/restore
|
|
82
|
+
- standalone sync/auth
|
|
83
|
+
- deck lifecycle writes
|
|
84
|
+
- tag lifecycle writes
|
|
85
|
+
- media operations
|
|
86
|
+
- any operation not supported by `ankiconnect`
|
|
87
|
+
|
|
88
|
+
Stay on `ankiconnect` when you need:
|
|
89
|
+
- live desktop-backed reads
|
|
90
|
+
- supported note/card operations through the running app
|
|
91
|
+
|
|
92
|
+
## Error Handling
|
|
93
|
+
|
|
94
|
+
- `COLLECTION_REQUIRED`: provide or ask for a collection path when using local collection flows.
|
|
95
|
+
- `BACKEND_UNAVAILABLE`: check installation, running services, or backend selection.
|
|
96
|
+
- `BACKEND_OPERATION_UNSUPPORTED`: switch backend or choose a narrower workflow.
|
|
97
|
+
- `NOTE_NOT_FOUND`, `CARD_NOT_FOUND`, `DECK_NOT_FOUND`, `MODEL_NOT_FOUND`, `TAG_NOT_FOUND`: stop and re-search instead of guessing.
|
|
98
|
+
- `UNSAFE_OPERATION`: retry only when the user clearly intends the real write and the command supports confirmation flags.
|
|
99
|
+
- `COLLECTION_OPEN_FAILED`: treat it as a real backend or fixture limitation, not a harmless warning.
|
|
100
|
+
- `AUTH_REQUIRED`: log in first or confirm stored sync credentials exist.
|
|
101
|
+
- `AUTH_INVALID`: stored sync credentials are stale or bad; log in again.
|
|
102
|
+
- `AUTH_STORAGE_UNAVAILABLE`: stop and fix the host secret-storage environment.
|
|
103
|
+
- `PROFILE_NOT_FOUND` and `PROFILE_RESOLUTION_FAILED`: the local Anki profile selection is wrong or unavailable.
|
|
104
|
+
- `BACKUP_RESTORE_UNSAFE`: do not force restore through an unsafe lock/open-state.
|
|
105
|
+
- `SYNC_CONFLICT`: explicit `sync pull` or `sync push` choice is required; do not guess.
|
|
106
|
+
- `SYNC_IN_PROGRESS` and `SYNC_FAILED`: stop, inspect backend details, and do not stack writes on top of unstable sync state.
|
|
107
|
+
|
|
108
|
+
## References
|
|
109
|
+
|
|
110
|
+
Read these only when you need contract detail:
|
|
111
|
+
- Plugin-facing contract: [`docs/openclaw-plugin.md`](/Users/thoffman/ankicli/docs/openclaw-plugin.md)
|
|
112
|
+
- Full CLI surface: [`docs/spec.md`](/Users/thoffman/ankicli/docs/spec.md)
|
|
113
|
+
- Longer workflow version: [`docs/anki-operations-skill.md`](/Users/thoffman/ankicli/docs/anki-operations-skill.md)
|
|
114
|
+
|
|
115
|
+
## Anti-Patterns
|
|
116
|
+
|
|
117
|
+
- Do not mutate from a broad search result without fetching the exact target.
|
|
118
|
+
- Do not skip dry-run on risky commands when dry-run exists and the user did not ask to skip it.
|
|
119
|
+
- Do not hide backend-specific unsupported behavior.
|
|
120
|
+
- Do not duplicate the CLI or plugin reference inside this skill.
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: release
|
|
3
|
+
description: Use when preparing, validating, and publishing ankicli releases, especially for GitHub Pages deploys, tagged standalone artifact releases, installer verification, and optional PyPI publishing.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Release
|
|
7
|
+
|
|
8
|
+
This skill is the release workflow layer for `ankicli`. Use it when the task involves shipping a new version, validating the public install path, publishing the product site, or checking release automation end to end.
|
|
9
|
+
|
|
10
|
+
## Core Rules
|
|
11
|
+
|
|
12
|
+
1. Treat releases as product changes, not just git tags. Validate the site, installers, standalone artifacts, and package path together.
|
|
13
|
+
2. Read before mutate. Inspect the current version, workflow state, and release assets before changing version numbers, tags, or release metadata.
|
|
14
|
+
3. Prefer the standalone artifact path as the primary user install surface. Keep `pipx install ankicli` as fallback documentation, not the hero path.
|
|
15
|
+
4. Verify both public fronts:
|
|
16
|
+
- GitHub Pages site
|
|
17
|
+
- GitHub Releases assets
|
|
18
|
+
5. Do not cut a release without checking the installer contract:
|
|
19
|
+
- raw installer script URLs exist
|
|
20
|
+
- expected asset names match the release workflow
|
|
21
|
+
- post-install verification commands still work
|
|
22
|
+
6. Preserve version consistency across Python package metadata, standalone artifact names, and release tags.
|
|
23
|
+
7. Never assume a release succeeded because a tag exists. Check workflow status and actual uploaded assets.
|
|
24
|
+
|
|
25
|
+
## Release Surfaces
|
|
26
|
+
|
|
27
|
+
- Product site: GitHub Pages
|
|
28
|
+
- Standalone artifacts: GitHub Releases
|
|
29
|
+
- Raw installer entrypoints:
|
|
30
|
+
- `scripts/install.sh`
|
|
31
|
+
- `scripts/install.ps1`
|
|
32
|
+
- Optional package distribution: PyPI/manual publish flow
|
|
33
|
+
|
|
34
|
+
## Workflow Playbooks
|
|
35
|
+
|
|
36
|
+
### Pre-Release Validation
|
|
37
|
+
|
|
38
|
+
Use this before tagging a release:
|
|
39
|
+
- inspect current package version
|
|
40
|
+
- run repo lint
|
|
41
|
+
- run unit, smoke, and distribution coverage relevant to install/release paths
|
|
42
|
+
- build the site
|
|
43
|
+
- build at least one standalone artifact locally when possible
|
|
44
|
+
- extract and execute the built artifact
|
|
45
|
+
- confirm install script URLs and asset naming still align
|
|
46
|
+
|
|
47
|
+
Good progression:
|
|
48
|
+
- inspect version and git state
|
|
49
|
+
- validate Python/package path
|
|
50
|
+
- validate site build
|
|
51
|
+
- validate installer tests
|
|
52
|
+
- validate standalone artifact build
|
|
53
|
+
- tag only after the above is green
|
|
54
|
+
|
|
55
|
+
### GitHub Pages Validation
|
|
56
|
+
|
|
57
|
+
Use when the product site is changing:
|
|
58
|
+
- build the Astro site locally
|
|
59
|
+
- verify landing page install commands
|
|
60
|
+
- verify docs links and install pages
|
|
61
|
+
- confirm the Pages workflow still targets the built static output
|
|
62
|
+
- after push, confirm the live Pages URL renders successfully
|
|
63
|
+
|
|
64
|
+
### Tagged Release
|
|
65
|
+
|
|
66
|
+
Use when shipping a real version:
|
|
67
|
+
- bump version in package metadata first
|
|
68
|
+
- commit the version change
|
|
69
|
+
- create and push a tag of the form `vX.Y.Z`
|
|
70
|
+
- confirm the release workflow ran
|
|
71
|
+
- confirm expected artifacts were uploaded:
|
|
72
|
+
- macOS x64
|
|
73
|
+
- macOS arm64
|
|
74
|
+
- Linux x64
|
|
75
|
+
- Windows x64
|
|
76
|
+
- checksums file
|
|
77
|
+
- confirm one downloaded artifact runs `ankicli --version` and `ankicli --json doctor backend`
|
|
78
|
+
|
|
79
|
+
### Installer Verification
|
|
80
|
+
|
|
81
|
+
Use when installer scripts or release artifact logic changes:
|
|
82
|
+
- verify shell installer path logic
|
|
83
|
+
- verify PowerShell parameter and path logic
|
|
84
|
+
- verify checksum mismatch behavior
|
|
85
|
+
- verify latest-version and explicit-version flows
|
|
86
|
+
- verify install location and PATH instructions are still accurate
|
|
87
|
+
|
|
88
|
+
### Optional PyPI Publish
|
|
89
|
+
|
|
90
|
+
Use only when the package distribution path matters:
|
|
91
|
+
- build the wheel/sdist
|
|
92
|
+
- run distribution validation
|
|
93
|
+
- publish manually or via the chosen release process
|
|
94
|
+
- confirm PyPI and standalone release version numbers match
|
|
95
|
+
|
|
96
|
+
## Versioning Rules
|
|
97
|
+
|
|
98
|
+
- Package version uses `X.Y.Z`
|
|
99
|
+
- Git tag uses `vX.Y.Z`
|
|
100
|
+
- Release artifacts use `ankicli-X.Y.Z-<target>`
|
|
101
|
+
- Checksums file uses `ankicli-X.Y.Z-checksums.txt`
|
|
102
|
+
|
|
103
|
+
Do not mix tag-only versions with unchanged package metadata.
|
|
104
|
+
|
|
105
|
+
## Error Handling
|
|
106
|
+
|
|
107
|
+
- Missing Pages deployment: inspect the `pages` workflow and built site artifact path.
|
|
108
|
+
- Missing release assets: inspect the `release` workflow matrix and uploaded artifact names.
|
|
109
|
+
- Installer download failure: check tag name, release asset names, and raw script URLs first.
|
|
110
|
+
- Checksum mismatch: treat as a release-blocking issue.
|
|
111
|
+
- Standalone artifact launches but backend probe fails: treat as a packaging/runtime regression, not a docs issue.
|
|
112
|
+
- PyPI publish problems: separate them from GitHub Release problems; they are parallel distribution paths.
|
|
113
|
+
|
|
114
|
+
## References
|
|
115
|
+
|
|
116
|
+
Read these when contract detail is needed:
|
|
117
|
+
- Package metadata: [`pyproject.toml`](/Users/thoffman/ankicli/pyproject.toml)
|
|
118
|
+
- CI workflow: [`.github/workflows/ci.yml`](/Users/thoffman/ankicli/.github/workflows/ci.yml)
|
|
119
|
+
- Pages workflow: [`.github/workflows/pages.yml`](/Users/thoffman/ankicli/.github/workflows/pages.yml)
|
|
120
|
+
- Release workflow: [`.github/workflows/release.yml`](/Users/thoffman/ankicli/.github/workflows/release.yml)
|
|
121
|
+
- Product site: [`site/src/pages/index.astro`](/Users/thoffman/ankicli/site/src/pages/index.astro)
|
|
122
|
+
- Installer scripts: [`scripts/install.sh`](/Users/thoffman/ankicli/scripts/install.sh) and [`scripts/install.ps1`](/Users/thoffman/ankicli/scripts/install.ps1)
|
|
123
|
+
|
|
124
|
+
## Anti-Patterns
|
|
125
|
+
|
|
126
|
+
- Do not tag first and hope validation passes later.
|
|
127
|
+
- Do not change release asset names in one place without updating installers and docs.
|
|
128
|
+
- Do not publish a release if the standalone artifact path is broken but PyPI still works.
|
|
129
|
+
- Do not treat Pages deployment as optional once the site is the public install front door.
|
|
130
|
+
- Do not overwrite user-facing install commands ad hoc in docs; keep them aligned with the installer contract.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
fast-path:
|
|
9
|
+
strategy:
|
|
10
|
+
matrix:
|
|
11
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
12
|
+
runs-on: ${{ matrix.os }}
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: astral-sh/setup-uv@v6
|
|
16
|
+
with:
|
|
17
|
+
python-version: "3.11"
|
|
18
|
+
- name: Install
|
|
19
|
+
run: uv sync --extra dev --frozen
|
|
20
|
+
- name: Ruff
|
|
21
|
+
run: uv run ruff check .
|
|
22
|
+
- name: Unit and smoke
|
|
23
|
+
run: PYTEST_PLUGINS=ankicli.pytest_plugin uv run pytest -c pyproject.toml -m "unit or smoke" --proof-report .artifacts/proof-fast.json
|
|
24
|
+
- name: Proof matrix audit
|
|
25
|
+
run: uv run python scripts/audit_quality_matrix.py --proof-report .artifacts/proof-fast.json
|
|
26
|
+
|
|
27
|
+
packaging:
|
|
28
|
+
strategy:
|
|
29
|
+
matrix:
|
|
30
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
31
|
+
runs-on: ${{ matrix.os }}
|
|
32
|
+
needs: fast-path
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
- uses: astral-sh/setup-uv@v6
|
|
36
|
+
with:
|
|
37
|
+
python-version: "3.11"
|
|
38
|
+
- name: Install
|
|
39
|
+
run: uv sync --extra dev --frozen
|
|
40
|
+
- name: Build package
|
|
41
|
+
run: uv build
|
|
42
|
+
- name: Distribution validation
|
|
43
|
+
run: uv run pytest -m distribution
|
|
44
|
+
|
|
45
|
+
site:
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
needs: fast-path
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@v4
|
|
50
|
+
- uses: actions/setup-node@v4
|
|
51
|
+
with:
|
|
52
|
+
node-version: 20
|
|
53
|
+
cache: npm
|
|
54
|
+
cache-dependency-path: site/package-lock.json
|
|
55
|
+
- name: Install site deps
|
|
56
|
+
working-directory: site
|
|
57
|
+
run: npm ci
|
|
58
|
+
- name: Build site
|
|
59
|
+
working-directory: site
|
|
60
|
+
run: npm run build
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: pages
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
pages: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: pages
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
build:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: actions/setup-node@v4
|
|
23
|
+
with:
|
|
24
|
+
node-version: 20
|
|
25
|
+
cache: npm
|
|
26
|
+
cache-dependency-path: site/package-lock.json
|
|
27
|
+
- name: Install site deps
|
|
28
|
+
working-directory: site
|
|
29
|
+
run: npm ci
|
|
30
|
+
- name: Build site
|
|
31
|
+
working-directory: site
|
|
32
|
+
run: npm run build
|
|
33
|
+
- uses: actions/configure-pages@v5
|
|
34
|
+
with:
|
|
35
|
+
enablement: true
|
|
36
|
+
- uses: actions/upload-pages-artifact@v3
|
|
37
|
+
with:
|
|
38
|
+
path: site/dist
|
|
39
|
+
|
|
40
|
+
deploy:
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
needs: build
|
|
43
|
+
environment:
|
|
44
|
+
name: github-pages
|
|
45
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
46
|
+
steps:
|
|
47
|
+
- id: deployment
|
|
48
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
include:
|
|
17
|
+
- target: darwin-x64
|
|
18
|
+
runs-on: macos-15-intel
|
|
19
|
+
- target: darwin-arm64
|
|
20
|
+
runs-on: macos-14
|
|
21
|
+
- target: linux-x64
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
- target: windows-x64
|
|
24
|
+
runs-on: windows-latest
|
|
25
|
+
runs-on: ${{ matrix.runs-on }}
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
- uses: astral-sh/setup-uv@v6
|
|
29
|
+
with:
|
|
30
|
+
python-version: "3.11"
|
|
31
|
+
- name: Install build deps
|
|
32
|
+
run: uv sync --extra dev --frozen
|
|
33
|
+
- name: Build standalone artifact
|
|
34
|
+
shell: bash
|
|
35
|
+
run: uv run python scripts/build_release_artifact.py --target ${{ matrix.target }} --version "${GITHUB_REF_NAME#v}"
|
|
36
|
+
- uses: actions/upload-artifact@v4
|
|
37
|
+
with:
|
|
38
|
+
name: release-${{ matrix.target }}
|
|
39
|
+
path: dist/release/*
|
|
40
|
+
|
|
41
|
+
publish:
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
needs: build
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/checkout@v4
|
|
46
|
+
- uses: actions/download-artifact@v4
|
|
47
|
+
with:
|
|
48
|
+
path: release-artifacts
|
|
49
|
+
pattern: release-*
|
|
50
|
+
merge-multiple: true
|
|
51
|
+
- name: Consolidate checksums
|
|
52
|
+
run: |
|
|
53
|
+
mkdir -p release-final
|
|
54
|
+
find release-artifacts -type f ! -name '*checksums.txt' -exec cp {} release-final/ \;
|
|
55
|
+
cat release-artifacts/*checksums.txt > release-final/ankicli-${GITHUB_REF_NAME#v}-checksums.txt
|
|
56
|
+
- name: Create GitHub Release
|
|
57
|
+
env:
|
|
58
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
59
|
+
run: |
|
|
60
|
+
gh release create "$GITHUB_REF_NAME" release-final/* --generate-notes --verify-tag
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
## Product
|
|
4
|
+
|
|
5
|
+
`ankicli` is a local-first Anki collection management CLI for inspection and mutation. It is not a
|
|
6
|
+
study app and not a TUI.
|
|
7
|
+
|
|
8
|
+
Supported platforms are macOS, Windows, and Linux. Product-complete support means: the default
|
|
9
|
+
packaged install works, the bundled `python-anki` runtime is usable, `--collection` workflows work,
|
|
10
|
+
`--profile` resolves the platform-default Anki data root, local backup flows work, and auth/sync
|
|
11
|
+
credential storage works.
|
|
12
|
+
|
|
13
|
+
## Working Rules
|
|
14
|
+
|
|
15
|
+
- Search first. The repo is small now, but preserve that habit as it grows.
|
|
16
|
+
- Patch minimally. Keep changes tight and avoid broad refactors unless the task requires them.
|
|
17
|
+
- Preserve the JSON output contract. Any shape change must update tests and docs in the same change.
|
|
18
|
+
- Keep backend-specific behavior inside `src/ankicli/backends/`. Do not leak it into CLI or service
|
|
19
|
+
contracts.
|
|
20
|
+
- Prefer the smallest relevant verification scope before broadening to larger suites.
|
|
21
|
+
- Treat `uv.lock` as mandatory. If dependency resolution changes, update the lockfile in the same
|
|
22
|
+
change.
|
|
23
|
+
- Do not confuse placeholder command wiring with backend completeness. Expand behavior coverage as
|
|
24
|
+
commands are implemented.
|
|
25
|
+
|
|
26
|
+
## Commands
|
|
27
|
+
|
|
28
|
+
Install:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
uv sync --extra dev --frozen
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Lint:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
uv run ruff check .
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Fast tests:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
uv run pytest -m "unit or smoke"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Fixture integration:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
uv run pytest tests/integration/test_python_anki_backend.py
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Editable-entrypoint e2e:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
uv run pytest tests/e2e/test_cli_e2e.py
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Distribution validation:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
uv build
|
|
62
|
+
uv run pytest -m distribution
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Real python-anki setup check:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
export ANKI_SOURCE_PATH=/absolute/path/to/anki
|
|
69
|
+
uv run pytest -m backend_python_anki_real -k anki_source_path_enables_import
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Full tests:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
uv run pytest
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Single file:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
uv run pytest tests/unit/test_output.py
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Build package:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
uv build
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Test Tiers
|
|
91
|
+
|
|
92
|
+
- `unit`: logic, parsing, safety checks, output shapes, error mapping
|
|
93
|
+
- `smoke`: fastest CLI checks for local loops and CI
|
|
94
|
+
- `fixture_integration`: deterministic SQLite fixture and contract-level command coverage
|
|
95
|
+
- `e2e`: editable-install CLI entrypoint checks through `uv run`
|
|
96
|
+
- `distribution`: built artifact install and entrypoint validation in an isolated environment
|
|
97
|
+
- `backend_python_anki_real`: opt-in local source setup checks and future true `import anki`
|
|
98
|
+
integration coverage
|
|
99
|
+
|
|
100
|
+
Preferred loops:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
uv run pytest -m "unit or smoke"
|
|
104
|
+
uv run pytest tests/integration/test_python_anki_backend.py
|
|
105
|
+
uv run pytest tests/e2e/test_cli_e2e.py
|
|
106
|
+
uv build && uv run pytest -m distribution
|
|
107
|
+
export ANKI_SOURCE_PATH=/absolute/path/to/anki && uv run pytest -m backend_python_anki_real -k anki_source_path_enables_import
|
|
108
|
+
uv run python scripts/prepare_real_backend.py --reset
|
|
109
|
+
uv run python scripts/prepare_ankiconnect_backend.py
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Safety
|
|
113
|
+
|
|
114
|
+
- Destructive commands must stay explicit and gated by `--yes` or `--force`.
|
|
115
|
+
- Do not casually mutate shared fixtures. Clone or generate per test when write isolation matters.
|
|
116
|
+
- Diagnostics should succeed as diagnostics even when the environment is incomplete. Report state;
|
|
117
|
+
do not hide it behind generic crashes.
|
|
118
|
+
- E2E should exercise the editable installed CLI entrypoint, not `python -m ...` shortcuts.
|
|
119
|
+
- Distribution validation should cover built artifacts separately from editable-entrypoint e2e.
|
|
120
|
+
- `ANKI_SOURCE_PATH` is the only supported local source override for real `python-anki` work.
|
|
121
|
+
- A raw upstream checkout currently proves import-path setup only unless that checkout has already
|
|
122
|
+
generated the required Python build artifacts.
|
|
123
|
+
|
|
124
|
+
## Fixture Policy
|
|
125
|
+
|
|
126
|
+
- Keep at least one small canonical fixture collection for fast tests.
|
|
127
|
+
- Prefer deterministic fixture setup over ad hoc local state.
|
|
128
|
+
- The default fixture is repo-owned and generated by `tests/fixtures/build_fixture.py`.
|
|
129
|
+
- That default fixture is a contract fixture, not yet a true Anki collection fixture.
|
|
130
|
+
- If a fixture format changes, update the generator and document the change in
|
|
131
|
+
`tests/fixtures/README.md`.
|
|
132
|
+
- Real backend work should use a separate local Anki source checkout, not mutate the contract
|
|
133
|
+
fixture assumptions.
|
|
134
|
+
- For true collection-level validation, prefer an installed official `anki` wheel or a built
|
|
135
|
+
upstream checkout over an unbuilt raw source tree.
|
|
136
|
+
|
|
137
|
+
## Confidence Model
|
|
138
|
+
|
|
139
|
+
- Do not describe `fixture_integration` as proof of real Anki behavior.
|
|
140
|
+
- Keep `fixture_integration` resilient in mixed local environments, including when an official
|
|
141
|
+
`anki` wheel is installed for real-backend work.
|
|
142
|
+
- Do not describe `e2e` as proof that built wheels or sdists install correctly.
|
|
143
|
+
- Reserve “real backend integration” for tests that actually open collections through `import anki`.
|
|
144
|
+
- Treat `backend_python_anki_real` as opt-in and local unless CI is explicitly expanded later.
|
|
145
|
+
|
|
146
|
+
## Release And Packaging
|
|
147
|
+
|
|
148
|
+
- `uv build` must succeed before calling the package shape stable.
|
|
149
|
+
- `uv` is the workflow frontend; `hatchling` is the build backend configured in `pyproject.toml`.
|
|
150
|
+
- Packaging regressions should be caught by the `distribution` suite or dedicated build checks, not
|
|
151
|
+
discovered manually.
|
|
152
|
+
|
|
153
|
+
## Real Anki Source Setup
|
|
154
|
+
|
|
155
|
+
- Use a sibling checkout of upstream [ankitects/anki](https://github.com/ankitects/anki).
|
|
156
|
+
- Pin local setup docs to tag `25.09.2` until deliberately updated.
|
|
157
|
+
- Set `ANKI_SOURCE_PATH` to that checkout root.
|
|
158
|
+
- Import-path verification:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
UV_CACHE_DIR=.uv-cache uv run python -c "from ankicli.runtime import configure_anki_source_path; import importlib.util; configure_anki_source_path(); print(importlib.util.find_spec('anki') is not None)"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
- For real `Collection`-level validation, use one of:
|
|
165
|
+
- official `anki==25.9.2` installed into the project environment, or
|
|
166
|
+
- an upstream checkout that has been built far enough to provide generated Python artifacts
|
|
167
|
+
- A raw upstream source checkout may fail at `Collection` import/use time due to missing generated
|
|
168
|
+
modules such as protobuf outputs.
|
|
169
|
+
- Set `ANKICLI_REAL_COLLECTION` only when you want the real-backend suite to run `collection info`
|
|
170
|
+
against an actual collection.
|
|
171
|
+
- Use `uv run python scripts/prepare_real_backend.py --reset` to automate the wheel-backed local
|
|
172
|
+
validation path and emit the required env vars.
|
|
173
|
+
- Use `uv run python scripts/prepare_ankiconnect_backend.py` to probe a live AnkiConnect instance
|
|
174
|
+
and emit the env vars for `backend_ankiconnect_real`.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
GNU AFFERO GENERAL PUBLIC LICENSE
|
|
2
|
+
Version 3, 19 November 2007
|
|
3
|
+
|
|
4
|
+
SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
Copyright (C) 2026 ankicli contributors
|
|
7
|
+
|
|
8
|
+
This repository is licensed under the GNU Affero General Public License,
|
|
9
|
+
version 3 or, at your option, any later version.
|
|
10
|
+
|
|
11
|
+
`ankicli` depends on and distributes the upstream Anki runtime, which is
|
|
12
|
+
licensed under the GNU Affero General Public License, version 3 or later.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU Affero General Public License
|
|
15
|
+
along with this program. If not, see:
|
|
16
|
+
|
|
17
|
+
https://www.gnu.org/licenses/agpl-3.0.txt
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
.PHONY: lint build test-fast test-unit test-smoke test-fixture-integration test-e2e test-distribution test-all test-backup-real test-matrix test-matrix-phase3 real-backend-setup ankiconnect-backend-setup
|
|
2
|
+
|
|
3
|
+
PROOF_REPORT ?= /tmp/ankicli-proof-report.json
|
|
4
|
+
MATRIX_AUDIT_ARGS ?= --proof-report $(PROOF_REPORT)
|
|
5
|
+
|
|
6
|
+
lint:
|
|
7
|
+
UV_CACHE_DIR=.uv-cache uv run ruff check .
|
|
8
|
+
|
|
9
|
+
build:
|
|
10
|
+
UV_CACHE_DIR=.uv-cache uv build
|
|
11
|
+
|
|
12
|
+
test-fast:
|
|
13
|
+
PYTEST_PLUGINS=ankicli.pytest_plugin UV_CACHE_DIR=.uv-cache uv run pytest -c pyproject.toml -m "unit or smoke" --proof-report $(PROOF_REPORT)
|
|
14
|
+
|
|
15
|
+
test-unit:
|
|
16
|
+
UV_CACHE_DIR=.uv-cache uv run pytest -m unit
|
|
17
|
+
|
|
18
|
+
test-smoke:
|
|
19
|
+
UV_CACHE_DIR=.uv-cache uv run pytest -m smoke
|
|
20
|
+
|
|
21
|
+
test-fixture-integration:
|
|
22
|
+
UV_CACHE_DIR=.uv-cache uv run pytest tests/integration/test_python_anki_backend.py
|
|
23
|
+
|
|
24
|
+
test-e2e:
|
|
25
|
+
UV_CACHE_DIR=.uv-cache uv run pytest tests/e2e/test_cli_e2e.py
|
|
26
|
+
|
|
27
|
+
test-distribution:
|
|
28
|
+
UV_CACHE_DIR=.uv-cache uv build
|
|
29
|
+
UV_CACHE_DIR=.uv-cache uv run pytest -m distribution
|
|
30
|
+
|
|
31
|
+
test-all:
|
|
32
|
+
UV_CACHE_DIR=.uv-cache uv run pytest
|
|
33
|
+
|
|
34
|
+
test-backup-real:
|
|
35
|
+
UV_CACHE_DIR=.uv-cache uv run pytest -m backend_python_anki_backup_real
|
|
36
|
+
|
|
37
|
+
test-matrix:
|
|
38
|
+
PYTEST_PLUGINS=ankicli.pytest_plugin UV_CACHE_DIR=.uv-cache uv run pytest -c pyproject.toml -m "unit or smoke" --proof-report $(PROOF_REPORT)
|
|
39
|
+
UV_CACHE_DIR=.uv-cache uv run python scripts/audit_quality_matrix.py $(MATRIX_AUDIT_ARGS)
|
|
40
|
+
|
|
41
|
+
test-matrix-phase3:
|
|
42
|
+
UV_CACHE_DIR=.uv-cache uv run python scripts/run_matrix_phase3.py
|
|
43
|
+
|
|
44
|
+
real-backend-setup:
|
|
45
|
+
UV_CACHE_DIR=.uv-cache uv run python scripts/prepare_real_backend.py
|
|
46
|
+
|
|
47
|
+
ankiconnect-backend-setup:
|
|
48
|
+
UV_CACHE_DIR=.uv-cache uv run python scripts/prepare_ankiconnect_backend.py
|