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.
Files changed (119) hide show
  1. anki_agent_toolkit-0.1.0/.agent/skills/anki-operations/SKILL.md +120 -0
  2. anki_agent_toolkit-0.1.0/.agent/skills/anki-operations/agents/openai.yaml +4 -0
  3. anki_agent_toolkit-0.1.0/.agent/skills/release/SKILL.md +130 -0
  4. anki_agent_toolkit-0.1.0/.github/workflows/ci.yml +60 -0
  5. anki_agent_toolkit-0.1.0/.github/workflows/pages.yml +48 -0
  6. anki_agent_toolkit-0.1.0/.github/workflows/release.yml +60 -0
  7. anki_agent_toolkit-0.1.0/.gitignore +14 -0
  8. anki_agent_toolkit-0.1.0/AGENTS.md +174 -0
  9. anki_agent_toolkit-0.1.0/LICENSE +17 -0
  10. anki_agent_toolkit-0.1.0/Makefile +48 -0
  11. anki_agent_toolkit-0.1.0/PKG-INFO +150 -0
  12. anki_agent_toolkit-0.1.0/README.md +131 -0
  13. anki_agent_toolkit-0.1.0/docs/anki-catalog-reference.md +94 -0
  14. anki_agent_toolkit-0.1.0/docs/anki-operations-skill.md +253 -0
  15. anki_agent_toolkit-0.1.0/docs/anki-study-ux-roadmap.md +98 -0
  16. anki_agent_toolkit-0.1.0/docs/images/ankicli-hero.png +0 -0
  17. anki_agent_toolkit-0.1.0/docs/openclaw-plugin.md +189 -0
  18. anki_agent_toolkit-0.1.0/docs/spec.md +250 -0
  19. anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/README.md +90 -0
  20. anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/index.js +223 -0
  21. anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/openclaw.plugin.json +40 -0
  22. anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/package.json +12 -0
  23. anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/skills/anki-collection-management/SKILL.md +20 -0
  24. anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/skills/anki-diagnostics/SKILL.md +19 -0
  25. anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/skills/anki-note-authoring/SKILL.md +19 -0
  26. anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/skills/anki-study/SKILL.md +32 -0
  27. anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/src/ankicli-tool.js +921 -0
  28. anki_agent_toolkit-0.1.0/integrations/openclaw-plugin/test/catalog-plugin.test.mjs +649 -0
  29. anki_agent_toolkit-0.1.0/ops/test-matrix.yaml +383 -0
  30. anki_agent_toolkit-0.1.0/pyproject.toml +57 -0
  31. anki_agent_toolkit-0.1.0/scripts/audit_cli_surface.py +339 -0
  32. anki_agent_toolkit-0.1.0/scripts/audit_quality_matrix.py +62 -0
  33. anki_agent_toolkit-0.1.0/scripts/build_release_artifact.py +155 -0
  34. anki_agent_toolkit-0.1.0/scripts/generate_openclaw_artifacts.py +138 -0
  35. anki_agent_toolkit-0.1.0/scripts/install.ps1 +128 -0
  36. anki_agent_toolkit-0.1.0/scripts/install.sh +157 -0
  37. anki_agent_toolkit-0.1.0/scripts/migrate_ios_audio.py +135 -0
  38. anki_agent_toolkit-0.1.0/scripts/prepare_ankiconnect_backend.py +133 -0
  39. anki_agent_toolkit-0.1.0/scripts/prepare_real_backend.py +177 -0
  40. anki_agent_toolkit-0.1.0/scripts/run_matrix_phase3.py +116 -0
  41. anki_agent_toolkit-0.1.0/site/astro.config.mjs +7 -0
  42. anki_agent_toolkit-0.1.0/site/package-lock.json +5542 -0
  43. anki_agent_toolkit-0.1.0/site/package.json +14 -0
  44. anki_agent_toolkit-0.1.0/site/public/ankicli-hero.png +0 -0
  45. anki_agent_toolkit-0.1.0/site/src/components/DocsPage.astro +355 -0
  46. anki_agent_toolkit-0.1.0/site/src/components/InstallCards.astro +80 -0
  47. anki_agent_toolkit-0.1.0/site/src/layouts/BaseLayout.astro +166 -0
  48. anki_agent_toolkit-0.1.0/site/src/lib/docs.ts +1186 -0
  49. anki_agent_toolkit-0.1.0/site/src/lib/install.ts +43 -0
  50. anki_agent_toolkit-0.1.0/site/src/pages/docs/agent-skills.astro +9 -0
  51. anki_agent_toolkit-0.1.0/site/src/pages/docs/cli-guide.astro +9 -0
  52. anki_agent_toolkit-0.1.0/site/src/pages/docs/common-tasks.astro +9 -0
  53. anki_agent_toolkit-0.1.0/site/src/pages/docs/learning-plans.astro +9 -0
  54. anki_agent_toolkit-0.1.0/site/src/pages/docs/profiles-and-collections.astro +9 -0
  55. anki_agent_toolkit-0.1.0/site/src/pages/docs/quickstart.astro +9 -0
  56. anki_agent_toolkit-0.1.0/site/src/pages/docs/recipes.astro +9 -0
  57. anki_agent_toolkit-0.1.0/site/src/pages/docs/study.astro +9 -0
  58. anki_agent_toolkit-0.1.0/site/src/pages/docs/sync-and-backups.astro +9 -0
  59. anki_agent_toolkit-0.1.0/site/src/pages/docs/troubleshooting.astro +9 -0
  60. anki_agent_toolkit-0.1.0/site/src/pages/docs/use-cases.astro +9 -0
  61. anki_agent_toolkit-0.1.0/site/src/pages/index.astro +205 -0
  62. anki_agent_toolkit-0.1.0/site/src/pages/install/index.astro +9 -0
  63. anki_agent_toolkit-0.1.0/site/src/pages/install/linux.astro +9 -0
  64. anki_agent_toolkit-0.1.0/site/src/pages/install/macos.astro +9 -0
  65. anki_agent_toolkit-0.1.0/site/src/pages/install/windows.astro +9 -0
  66. anki_agent_toolkit-0.1.0/site/tsconfig.json +6 -0
  67. anki_agent_toolkit-0.1.0/skills/ankicli-collection-management/SKILL.md +20 -0
  68. anki_agent_toolkit-0.1.0/skills/ankicli-diagnostics/SKILL.md +20 -0
  69. anki_agent_toolkit-0.1.0/skills/ankicli-note-authoring/SKILL.md +20 -0
  70. anki_agent_toolkit-0.1.0/skills/ankicli-study/SKILL.md +29 -0
  71. anki_agent_toolkit-0.1.0/src/ankicli/__init__.py +6 -0
  72. anki_agent_toolkit-0.1.0/src/ankicli/app/catalog.py +1188 -0
  73. anki_agent_toolkit-0.1.0/src/ankicli/app/credentials.py +370 -0
  74. anki_agent_toolkit-0.1.0/src/ankicli/app/errors.py +165 -0
  75. anki_agent_toolkit-0.1.0/src/ankicli/app/ios_audio_migration.py +644 -0
  76. anki_agent_toolkit-0.1.0/src/ankicli/app/models.py +44 -0
  77. anki_agent_toolkit-0.1.0/src/ankicli/app/output.py +44 -0
  78. anki_agent_toolkit-0.1.0/src/ankicli/app/profiles.py +164 -0
  79. anki_agent_toolkit-0.1.0/src/ankicli/app/quality_matrix.py +789 -0
  80. anki_agent_toolkit-0.1.0/src/ankicli/app/releases.py +59 -0
  81. anki_agent_toolkit-0.1.0/src/ankicli/app/services.py +1787 -0
  82. anki_agent_toolkit-0.1.0/src/ankicli/app/study.py +1380 -0
  83. anki_agent_toolkit-0.1.0/src/ankicli/backends/ankiconnect.py +659 -0
  84. anki_agent_toolkit-0.1.0/src/ankicli/backends/base.py +344 -0
  85. anki_agent_toolkit-0.1.0/src/ankicli/backends/python_anki.py +1623 -0
  86. anki_agent_toolkit-0.1.0/src/ankicli/main.py +1611 -0
  87. anki_agent_toolkit-0.1.0/src/ankicli/pytest_plugin.py +92 -0
  88. anki_agent_toolkit-0.1.0/src/ankicli/runtime.py +155 -0
  89. anki_agent_toolkit-0.1.0/tests/__init__.py +1 -0
  90. anki_agent_toolkit-0.1.0/tests/conftest.py +50 -0
  91. anki_agent_toolkit-0.1.0/tests/distribution/test_built_artifact.py +86 -0
  92. anki_agent_toolkit-0.1.0/tests/e2e/test_cli_e2e.py +108 -0
  93. anki_agent_toolkit-0.1.0/tests/fixtures/README.md +12 -0
  94. anki_agent_toolkit-0.1.0/tests/fixtures/__init__.py +1 -0
  95. anki_agent_toolkit-0.1.0/tests/fixtures/build_fixture.py +40 -0
  96. anki_agent_toolkit-0.1.0/tests/fixtures/generated/minimal/collection.anki2 +0 -0
  97. anki_agent_toolkit-0.1.0/tests/fixtures/generated/minimal/manifest.json +7 -0
  98. anki_agent_toolkit-0.1.0/tests/integration/helpers.py +9 -0
  99. anki_agent_toolkit-0.1.0/tests/integration/test_python_anki_backend.py +1428 -0
  100. anki_agent_toolkit-0.1.0/tests/proof.py +28 -0
  101. anki_agent_toolkit-0.1.0/tests/real/test_ankiconnect_real.py +526 -0
  102. anki_agent_toolkit-0.1.0/tests/real/test_python_anki_backup_real.py +372 -0
  103. anki_agent_toolkit-0.1.0/tests/real/test_python_anki_real_setup.py +1142 -0
  104. anki_agent_toolkit-0.1.0/tests/smoke/test_cli_smoke.py +43 -0
  105. anki_agent_toolkit-0.1.0/tests/smoke/test_install_scripts.py +170 -0
  106. anki_agent_toolkit-0.1.0/tests/unit/test_ankiconnect_backend_unit.py +326 -0
  107. anki_agent_toolkit-0.1.0/tests/unit/test_backend_parity.py +1005 -0
  108. anki_agent_toolkit-0.1.0/tests/unit/test_catalog_and_study.py +522 -0
  109. anki_agent_toolkit-0.1.0/tests/unit/test_cli_contract.py +1801 -0
  110. anki_agent_toolkit-0.1.0/tests/unit/test_credentials.py +129 -0
  111. anki_agent_toolkit-0.1.0/tests/unit/test_ios_audio_migration.py +313 -0
  112. anki_agent_toolkit-0.1.0/tests/unit/test_openclaw_plugin_generation.py +44 -0
  113. anki_agent_toolkit-0.1.0/tests/unit/test_output.py +45 -0
  114. anki_agent_toolkit-0.1.0/tests/unit/test_profiles.py +103 -0
  115. anki_agent_toolkit-0.1.0/tests/unit/test_python_anki_backend_unit.py +2172 -0
  116. anki_agent_toolkit-0.1.0/tests/unit/test_quality_matrix.py +1062 -0
  117. anki_agent_toolkit-0.1.0/tests/unit/test_releases.py +38 -0
  118. anki_agent_toolkit-0.1.0/tests/unit/test_services.py +2123 -0
  119. 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,4 @@
1
+ interface:
2
+ display_name: "Anki Operations"
3
+ short_description: "Safe Anki workflows via ankicli and OpenClaw."
4
+ default_prompt: "Use $anki-operations to inspect, diagnose, and safely update an Anki collection with ankicli or its OpenClaw plugin."
@@ -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,14 @@
1
+ .venv/
2
+ .pytest_cache/
3
+ .ruff_cache/
4
+ .uv-cache/
5
+ __pycache__/
6
+ *.pyc
7
+ .DS_Store
8
+ dist/
9
+ build/
10
+ .worktrees/
11
+ *.swp
12
+ site/node_modules/
13
+ site/dist/
14
+ site/.astro/
@@ -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