e3cli 1.0.2__tar.gz → 1.0.4__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 (265) hide show
  1. {e3cli-1.0.2 → e3cli-1.0.4}/.github/workflows/release.yml +36 -22
  2. {e3cli-1.0.2 → e3cli-1.0.4}/CLAUDE.md +9 -0
  3. {e3cli-1.0.2 → e3cli-1.0.4}/PKG-INFO +40 -7
  4. {e3cli-1.0.2 → e3cli-1.0.4}/README.md +39 -6
  5. {e3cli-1.0.2 → e3cli-1.0.4}/README_zh-TW.md +39 -6
  6. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/__init__.py +1 -1
  7. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/agent_prompt.md +6 -2
  8. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/cli.py +4 -3
  9. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/setup.py +59 -5
  10. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/skill.py +19 -1
  11. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/skills/e3cli/SKILL.md +5 -3
  12. {e3cli-1.0.2 → e3cli-1.0.4}/pyproject.toml +1 -1
  13. {e3cli-1.0.2 → e3cli-1.0.4}/.github/workflows/ci.yml +0 -0
  14. {e3cli-1.0.2 → e3cli-1.0.4}/.gitignore +0 -0
  15. {e3cli-1.0.2 → e3cli-1.0.4}/COMMIT_EDITMSG +0 -0
  16. {e3cli-1.0.2 → e3cli-1.0.4}/Formula/e3cli.rb +0 -0
  17. {e3cli-1.0.2 → e3cli-1.0.4}/HEAD +0 -0
  18. {e3cli-1.0.2 → e3cli-1.0.4}/LICENSE +0 -0
  19. {e3cli-1.0.2 → e3cli-1.0.4}/Makefile +0 -0
  20. {e3cli-1.0.2 → e3cli-1.0.4}/config +0 -0
  21. {e3cli-1.0.2 → e3cli-1.0.4}/description +0 -0
  22. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/__main__.py +0 -0
  23. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/ai/__init__.py +0 -0
  24. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/__init__.py +0 -0
  25. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/assignments.py +0 -0
  26. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/client.py +0 -0
  27. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/courses.py +0 -0
  28. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/files.py +0 -0
  29. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/forums.py +0 -0
  30. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/members.py +0 -0
  31. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/messages.py +0 -0
  32. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/api/site.py +0 -0
  33. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/auth.py +0 -0
  34. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/__init__.py +0 -0
  35. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/_common.py +0 -0
  36. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/announcements.py +0 -0
  37. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/assignments.py +0 -0
  38. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/courses.py +0 -0
  39. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/download.py +0 -0
  40. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/interactive.py +0 -0
  41. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/login.py +0 -0
  42. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/logout.py +0 -0
  43. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/members.py +0 -0
  44. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/message.py +0 -0
  45. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/profile.py +0 -0
  46. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/schedule.py +0 -0
  47. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/submit.py +0 -0
  48. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/commands/sync.py +0 -0
  49. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/config.py +0 -0
  50. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/course_name.py +0 -0
  51. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/credential.py +0 -0
  52. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/formatting.py +0 -0
  53. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/http.py +0 -0
  54. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/i18n.py +0 -0
  55. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/scheduler/__init__.py +0 -0
  56. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/scheduler/cron.py +0 -0
  57. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/semester.py +0 -0
  58. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/storage/__init__.py +0 -0
  59. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/storage/db.py +0 -0
  60. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/storage/models.py +0 -0
  61. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/storage/tracking.py +0 -0
  62. {e3cli-1.0.2 → e3cli-1.0.4}/e3cli/tui_menu.py +0 -0
  63. {e3cli-1.0.2 → e3cli-1.0.4}/gk/config +0 -0
  64. {e3cli-1.0.2 → e3cli-1.0.4}/hooks/applypatch-msg.sample +0 -0
  65. {e3cli-1.0.2 → e3cli-1.0.4}/hooks/commit-msg.sample +0 -0
  66. {e3cli-1.0.2 → e3cli-1.0.4}/hooks/fsmonitor-watchman.sample +0 -0
  67. {e3cli-1.0.2 → e3cli-1.0.4}/hooks/post-update.sample +0 -0
  68. {e3cli-1.0.2 → e3cli-1.0.4}/hooks/pre-applypatch.sample +0 -0
  69. {e3cli-1.0.2 → e3cli-1.0.4}/hooks/pre-commit.sample +0 -0
  70. {e3cli-1.0.2 → e3cli-1.0.4}/hooks/pre-merge-commit.sample +0 -0
  71. {e3cli-1.0.2 → e3cli-1.0.4}/hooks/pre-push.sample +0 -0
  72. {e3cli-1.0.2 → e3cli-1.0.4}/hooks/pre-rebase.sample +0 -0
  73. {e3cli-1.0.2 → e3cli-1.0.4}/hooks/pre-receive.sample +0 -0
  74. {e3cli-1.0.2 → e3cli-1.0.4}/hooks/prepare-commit-msg.sample +0 -0
  75. {e3cli-1.0.2 → e3cli-1.0.4}/hooks/push-to-checkout.sample +0 -0
  76. {e3cli-1.0.2 → e3cli-1.0.4}/hooks/sendemail-validate.sample +0 -0
  77. {e3cli-1.0.2 → e3cli-1.0.4}/hooks/update.sample +0 -0
  78. {e3cli-1.0.2 → e3cli-1.0.4}/index +0 -0
  79. {e3cli-1.0.2 → e3cli-1.0.4}/info/exclude +0 -0
  80. {e3cli-1.0.2 → e3cli-1.0.4}/logs/HEAD +0 -0
  81. {e3cli-1.0.2 → e3cli-1.0.4}/logs/refs/heads/main +0 -0
  82. {e3cli-1.0.2 → e3cli-1.0.4}/logs/refs/remotes/origin/main +0 -0
  83. {e3cli-1.0.2 → e3cli-1.0.4}/objects/00/12f54a62a13459820d72b63eee8781d5cc0fae +0 -0
  84. {e3cli-1.0.2 → e3cli-1.0.4}/objects/00/373e054c653e54b45cacae42d71dff863626bf +0 -0
  85. {e3cli-1.0.2 → e3cli-1.0.4}/objects/04/9ee8e5968a9a80f0f1ac53d12141c61e7298ba +0 -0
  86. {e3cli-1.0.2 → e3cli-1.0.4}/objects/04/e0353337b6bb0c0ba43625456e9aaf13090a90 +0 -0
  87. {e3cli-1.0.2 → e3cli-1.0.4}/objects/05/0fec5da6aa35de1058b11671dfd6255b4d6b50 +0 -0
  88. {e3cli-1.0.2 → e3cli-1.0.4}/objects/06/5c820fc3efcd99754c56197a9c4e7142da710d +0 -0
  89. {e3cli-1.0.2 → e3cli-1.0.4}/objects/07/01890044580c4644114b781d474012b2fade80 +0 -0
  90. {e3cli-1.0.2 → e3cli-1.0.4}/objects/07/fb70ff1c509aad1f137a9255b9cb98733472a3 +0 -0
  91. {e3cli-1.0.2 → e3cli-1.0.4}/objects/0e/89da06e2d2273057dfa03705c42bbc57af1a6a +0 -0
  92. {e3cli-1.0.2 → e3cli-1.0.4}/objects/13/ad53a74b643378a7aebfe32d672b256ab73bef +0 -0
  93. {e3cli-1.0.2 → e3cli-1.0.4}/objects/13/fb66226ef7de52c039b1030460c5bb9ad1d576 +0 -0
  94. {e3cli-1.0.2 → e3cli-1.0.4}/objects/14/f44dcbbf53914d2d2b5b5a43453932fb0c6dd6 +0 -0
  95. {e3cli-1.0.2 → e3cli-1.0.4}/objects/15/6da5879f795abd72f645bbcadf18a4928a7502 +0 -0
  96. {e3cli-1.0.2 → e3cli-1.0.4}/objects/19/f9906c2882926f53e77b4be8be579906954a69 +0 -0
  97. {e3cli-1.0.2 → e3cli-1.0.4}/objects/1a/3f91d11c7c9c764fcd1ed01a4a0c3f13b68fee +0 -0
  98. {e3cli-1.0.2 → e3cli-1.0.4}/objects/1c/1765c4b372bd085c6224472de72f66e8d9fbe9 +0 -0
  99. {e3cli-1.0.2 → e3cli-1.0.4}/objects/22/e1020c805f3235c5c85d711a45d70d42883de0 +0 -0
  100. {e3cli-1.0.2 → e3cli-1.0.4}/objects/24/7f60ac43c8a065926f3228575a34d0ecd6f93d +0 -0
  101. {e3cli-1.0.2 → e3cli-1.0.4}/objects/25/4d6ec800e32759015479a68a3afd096ee12680 +0 -0
  102. {e3cli-1.0.2 → e3cli-1.0.4}/objects/27/1aee134d84254ba525ce728b3ecbbcbd73fe97 +0 -0
  103. {e3cli-1.0.2 → e3cli-1.0.4}/objects/27/41f5e19bf92e37c983e7d4d307ec09726b95ed +0 -0
  104. {e3cli-1.0.2 → e3cli-1.0.4}/objects/28/265727a791db9daef09c85ab159ef799908dc4 +0 -0
  105. {e3cli-1.0.2 → e3cli-1.0.4}/objects/2d/4c64fc2752b1356569f24e6f3d53cfd8ff3236 +0 -0
  106. {e3cli-1.0.2 → e3cli-1.0.4}/objects/31/61734dcf7d8b86372753c2552746641969ca7a +0 -0
  107. {e3cli-1.0.2 → e3cli-1.0.4}/objects/33/3da47d4f7d08fc2836374614b902a27f1a7638 +0 -0
  108. {e3cli-1.0.2 → e3cli-1.0.4}/objects/35/25cb5144ca2d643d918824df0f08042f8f1f19 +0 -0
  109. {e3cli-1.0.2 → e3cli-1.0.4}/objects/35/faf439f5e7e6730398397e0988c874ec74c15e +0 -0
  110. {e3cli-1.0.2 → e3cli-1.0.4}/objects/37/2acc5a62b5a8a7cd97d3eb07614d2a71d65c34 +0 -0
  111. {e3cli-1.0.2 → e3cli-1.0.4}/objects/37/f0c29518b9df6cde4d0cd7857d95b425fcaec9 +0 -0
  112. {e3cli-1.0.2 → e3cli-1.0.4}/objects/38/8bc96a53da22ddf8d3684c10480a9ed89274a6 +0 -0
  113. {e3cli-1.0.2 → e3cli-1.0.4}/objects/38/d062de47938882cc8c951cfcd18266bfa834d0 +0 -0
  114. {e3cli-1.0.2 → e3cli-1.0.4}/objects/39/bbbcd0ade10f3066a853cca53ad5159ac78e30 +0 -0
  115. {e3cli-1.0.2 → e3cli-1.0.4}/objects/3c/dd09e594d5716969279d6e3fcf99fca00f8504 +0 -0
  116. {e3cli-1.0.2 → e3cli-1.0.4}/objects/3e/71c91d71be5667a313ecfae444718750b2bf55 +0 -0
  117. {e3cli-1.0.2 → e3cli-1.0.4}/objects/3e/7febbe12d705885c2503c3e0d785e488f60966 +0 -0
  118. {e3cli-1.0.2 → e3cli-1.0.4}/objects/3f/0235e32813f74985f0363e64a110093d979e2f +0 -0
  119. {e3cli-1.0.2 → e3cli-1.0.4}/objects/40/9ded4237099e6e52de508dd46ebe74cf769e79 +0 -0
  120. {e3cli-1.0.2 → e3cli-1.0.4}/objects/41/88bc8a7a0569fd47efb215aad2e3f4a7b7e188 +0 -0
  121. {e3cli-1.0.2 → e3cli-1.0.4}/objects/42/53425dbc4368909b4b782fd53360537d3d9033 +0 -0
  122. {e3cli-1.0.2 → e3cli-1.0.4}/objects/42/925cbdfef5b97f5ae199323a5545810207af09 +0 -0
  123. {e3cli-1.0.2 → e3cli-1.0.4}/objects/42/b238ab6f9c3c74cd23a14c094ad8eb1c66d52b +0 -0
  124. {e3cli-1.0.2 → e3cli-1.0.4}/objects/43/49874ad2cdacc9d50d6ba06df25765d077248a +0 -0
  125. {e3cli-1.0.2 → e3cli-1.0.4}/objects/43/cead7a00c7ef98e1d5c9c86e50a3ccde712277 +0 -0
  126. {e3cli-1.0.2 → e3cli-1.0.4}/objects/43/e88c1a0a115fc72390e7bcef8ce0a8328a4e05 +0 -0
  127. {e3cli-1.0.2 → e3cli-1.0.4}/objects/45/9c23839b54e81c741fd2b5241c2b164079fcc1 +0 -0
  128. {e3cli-1.0.2 → e3cli-1.0.4}/objects/47/d9fe1a890a3d711662f4f414aee1ea6ae92261 +0 -0
  129. {e3cli-1.0.2 → e3cli-1.0.4}/objects/49/da3d511c413f21dca0f072ad52b0aca2d3c167 +0 -0
  130. {e3cli-1.0.2 → e3cli-1.0.4}/objects/4f/1897fc4248a024fc88e51f53f9028f531318cc +0 -0
  131. {e3cli-1.0.2 → e3cli-1.0.4}/objects/50/f89469bbe802dad848dcfeb2a8e447d4cd5787 +0 -0
  132. {e3cli-1.0.2 → e3cli-1.0.4}/objects/51/7ac4b389a310399e096baab0af89f1e5de7b3b +0 -0
  133. {e3cli-1.0.2 → e3cli-1.0.4}/objects/52/61e3b09b4722a7003c53a643085ca69e0c7bbd +0 -0
  134. {e3cli-1.0.2 → e3cli-1.0.4}/objects/53/7671d097d835bda94f0460295ce1cf49eda99a +0 -0
  135. {e3cli-1.0.2 → e3cli-1.0.4}/objects/54/8d12b92b82f95dc93b4f069086d8214651593d +0 -0
  136. {e3cli-1.0.2 → e3cli-1.0.4}/objects/55/2cd273856516fd1a5e026ef23c9ffeb5a33876 +0 -0
  137. {e3cli-1.0.2 → e3cli-1.0.4}/objects/56/52f31ea165a3ace62d1394af754a8aac78aa9f +0 -0
  138. {e3cli-1.0.2 → e3cli-1.0.4}/objects/57/9c69b0b67ebff094514cec01f692e21ca5e965 +0 -0
  139. {e3cli-1.0.2 → e3cli-1.0.4}/objects/57/ddc6c8820bd8ec98845e7f5a29bf3302f0f481 +0 -0
  140. {e3cli-1.0.2 → e3cli-1.0.4}/objects/58/2fba780a9cb7a9f312bd21cf97f16bc5b347c3 +0 -0
  141. {e3cli-1.0.2 → e3cli-1.0.4}/objects/5c/6b70ca4f2f822429a97a84428580966d84ab3a +0 -0
  142. {e3cli-1.0.2 → e3cli-1.0.4}/objects/5e/c686a09ef712b11372e38d25c958b027b3f21f +0 -0
  143. {e3cli-1.0.2 → e3cli-1.0.4}/objects/5f/96e4a89ab06b40be8c45cd0d975bdc2f957064 +0 -0
  144. {e3cli-1.0.2 → e3cli-1.0.4}/objects/60/c9053920fd6a8cd64eb28d8df99bcc2d176d59 +0 -0
  145. {e3cli-1.0.2 → e3cli-1.0.4}/objects/62/1ab88d46df0f1b1015e250f4c8174729629400 +0 -0
  146. {e3cli-1.0.2 → e3cli-1.0.4}/objects/62/5d72f7372bae8ab3ccc056e829c277c0705d1b +0 -0
  147. {e3cli-1.0.2 → e3cli-1.0.4}/objects/64/1ee83ac5a80cc7ae2e5f036db6329eacd03deb +0 -0
  148. {e3cli-1.0.2 → e3cli-1.0.4}/objects/65/011e04aeddd4c893a7a64b7ef745e9ad1af3c3 +0 -0
  149. {e3cli-1.0.2 → e3cli-1.0.4}/objects/66/b5f21689d122c08ee3b98d35f3de096addcfcc +0 -0
  150. {e3cli-1.0.2 → e3cli-1.0.4}/objects/69/89864c6313789a85608f01eda8976e1215bd31 +0 -0
  151. {e3cli-1.0.2 → e3cli-1.0.4}/objects/69/db255149b01f9ab01b48138fbb0f2d9b8b1acd +0 -0
  152. {e3cli-1.0.2 → e3cli-1.0.4}/objects/6a/597477c08142472e4a0559811e459ae7b127fc +0 -0
  153. {e3cli-1.0.2 → e3cli-1.0.4}/objects/6a/5e5e8ca97f2dec142b2ba15ed97a8493c16a54 +0 -0
  154. {e3cli-1.0.2 → e3cli-1.0.4}/objects/6b/d7a53ed2c5cd4c0e97267b70fff1dd461b60b7 +0 -0
  155. {e3cli-1.0.2 → e3cli-1.0.4}/objects/6d/05c5aaad4ff44578bbc46b5f7fc96f0d114e04 +0 -0
  156. {e3cli-1.0.2 → e3cli-1.0.4}/objects/6d/5c36f68694ad597a4deeba39e56e561ba72f2f +0 -0
  157. {e3cli-1.0.2 → e3cli-1.0.4}/objects/6e/3f7883a133ec8310cf8ad07cba6aead4583ff9 +0 -0
  158. {e3cli-1.0.2 → e3cli-1.0.4}/objects/6f/15710e7621abc864dabb788c5dfcab181e4551 +0 -0
  159. {e3cli-1.0.2 → e3cli-1.0.4}/objects/71/6894eaf5165344374d82dda25e82eff5fce119 +0 -0
  160. {e3cli-1.0.2 → e3cli-1.0.4}/objects/71/ca2fc16d0959c7465d57077a260156674274ba +0 -0
  161. {e3cli-1.0.2 → e3cli-1.0.4}/objects/74/0db02cd55f69b9f21f49a359fc14c15ad7f8ce +0 -0
  162. {e3cli-1.0.2 → e3cli-1.0.4}/objects/76/37fd54a47bfbdf2eed4827b78dff6019b87e57 +0 -0
  163. {e3cli-1.0.2 → e3cli-1.0.4}/objects/79/15535a493620715580f5d0ce8c2481172d44bd +0 -0
  164. {e3cli-1.0.2 → e3cli-1.0.4}/objects/7b/ad63d2dd7dab6c33f73a31bd359129523ac5ce +0 -0
  165. {e3cli-1.0.2 → e3cli-1.0.4}/objects/7c/95c6bec18763286e0100ebc4fbef71df48b0ae +0 -0
  166. {e3cli-1.0.2 → e3cli-1.0.4}/objects/7f/a3240ccd3661f7786bd269a0b0875cd9037b4b +0 -0
  167. {e3cli-1.0.2 → e3cli-1.0.4}/objects/82/8511321c72b509d8b39d3a392014e2748036ad +0 -0
  168. {e3cli-1.0.2 → e3cli-1.0.4}/objects/84/3e8bf8d7bf26780eb4c44f0e1733dae7df37da +0 -0
  169. {e3cli-1.0.2 → e3cli-1.0.4}/objects/84/45dbe199e0d8e83aa85b04f68c4b4e97764c46 +0 -0
  170. {e3cli-1.0.2 → e3cli-1.0.4}/objects/85/58de1a164b671ae0c5e9867140f4d105b26c71 +0 -0
  171. {e3cli-1.0.2 → e3cli-1.0.4}/objects/85/bfef5de75cdd3313dea22060cd9f22bf6f611c +0 -0
  172. {e3cli-1.0.2 → e3cli-1.0.4}/objects/87/075d1b2ca01520a54b6e2053d2b07e30ff550e +0 -0
  173. {e3cli-1.0.2 → e3cli-1.0.4}/objects/8a/2f2b74b3a7f9b0f2969ff455d1b5a149189522 +0 -0
  174. {e3cli-1.0.2 → e3cli-1.0.4}/objects/8b/da82680cf77bd85ef26d162f09df5b555c4817 +0 -0
  175. {e3cli-1.0.2 → e3cli-1.0.4}/objects/8b/f368e49da5649603590fd2ad157fb423f91240 +0 -0
  176. {e3cli-1.0.2 → e3cli-1.0.4}/objects/8c/988f80dcde632bee9389cb52d7c2639e358676 +0 -0
  177. {e3cli-1.0.2 → e3cli-1.0.4}/objects/8d/9cc78f614e082762dfd1af4d90b83e97509ba4 +0 -0
  178. {e3cli-1.0.2 → e3cli-1.0.4}/objects/91/b7e6699fcf2d3d87bc9209c30743851b95937e +0 -0
  179. {e3cli-1.0.2 → e3cli-1.0.4}/objects/97/6c6c60bcbbfe1b2ea7dc08631420753e2a2c55 +0 -0
  180. {e3cli-1.0.2 → e3cli-1.0.4}/objects/98/414112321df2d4fef51640978555b7b0a10740 +0 -0
  181. {e3cli-1.0.2 → e3cli-1.0.4}/objects/98/5dbb79e4f3157ba4a5b967ca1f045087fe718c +0 -0
  182. {e3cli-1.0.2 → e3cli-1.0.4}/objects/9b/8451b0fde38dfc5250c52aab3ef3fd30ef616d +0 -0
  183. {e3cli-1.0.2 → e3cli-1.0.4}/objects/9d/04ed7e9c2fdc16eadb72867c45c682d0661d8e +0 -0
  184. {e3cli-1.0.2 → e3cli-1.0.4}/objects/9d/1dcfdaf1a6857c5f83dc27019c7600e1ffaff8 +0 -0
  185. {e3cli-1.0.2 → e3cli-1.0.4}/objects/9e/9190183a3e710fd6a3caabafda0395aacc4907 +0 -0
  186. {e3cli-1.0.2 → e3cli-1.0.4}/objects/a4/9ab06df8e92e9921f006c4687a8119a41f140c +0 -0
  187. {e3cli-1.0.2 → e3cli-1.0.4}/objects/a4/9e182d79178f30917cb9d5d007bf4ad4354efc +0 -0
  188. {e3cli-1.0.2 → e3cli-1.0.4}/objects/a5/374e27f1f437b7b8d795bdbba9990e1b33ac4a +0 -0
  189. {e3cli-1.0.2 → e3cli-1.0.4}/objects/a9/621b26eb6fcf44e82b8f40fe15a08db273ea94 +0 -0
  190. {e3cli-1.0.2 → e3cli-1.0.4}/objects/a9/958ca6bbbce4793eb63dfc75053f6f2c468f7d +0 -0
  191. {e3cli-1.0.2 → e3cli-1.0.4}/objects/ab/8112dc0e039a6764e18515bc8b9d25bf8cba72 +0 -0
  192. {e3cli-1.0.2 → e3cli-1.0.4}/objects/ad/86572a7a3d9c41b39f68c1509f45eeb3c47145 +0 -0
  193. {e3cli-1.0.2 → e3cli-1.0.4}/objects/ae/7c0c0693884ee9968bd46c7e3c1c4801c93f07 +0 -0
  194. {e3cli-1.0.2 → e3cli-1.0.4}/objects/af/66d7ee37e22b5b4ffcb43392bcd6fe58b7189b +0 -0
  195. {e3cli-1.0.2 → e3cli-1.0.4}/objects/b0/1eb7d29ce867088dcfec990e3a118ee7d3a3b2 +0 -0
  196. {e3cli-1.0.2 → e3cli-1.0.4}/objects/b0/6bfa35440cb0bf33a698db8b116077b885dade +0 -0
  197. {e3cli-1.0.2 → e3cli-1.0.4}/objects/b2/30e20e02ded29d01eb93f89b62ab47fb378e1f +0 -0
  198. {e3cli-1.0.2 → e3cli-1.0.4}/objects/b2/e68381120a59886f7999876775e9b3dfeaa550 +0 -0
  199. {e3cli-1.0.2 → e3cli-1.0.4}/objects/b3/a239ea6bac51a6315988af95d83e86323aa461 +0 -0
  200. {e3cli-1.0.2 → e3cli-1.0.4}/objects/b4/1e24e40f90ad6c12b6f840ecdb133b2749ca7e +0 -0
  201. {e3cli-1.0.2 → e3cli-1.0.4}/objects/b9/4bb6724a0646fb1636a66de603cec15e7dfa3e +0 -0
  202. {e3cli-1.0.2 → e3cli-1.0.4}/objects/bb/8fccf2b545f4ba46149fb07bd1f700ae7bcc87 +0 -0
  203. {e3cli-1.0.2 → e3cli-1.0.4}/objects/be/9fc276a620ea29d87e2001489e436f6e714a34 +0 -0
  204. {e3cli-1.0.2 → e3cli-1.0.4}/objects/bf/a019fa30db2df7e7732d119032e84391c3b6ce +0 -0
  205. {e3cli-1.0.2 → e3cli-1.0.4}/objects/c0/2beae1cbe94f20d2a4ef88b46bd8ade684f911 +0 -0
  206. {e3cli-1.0.2 → e3cli-1.0.4}/objects/c6/1651ba7a27cd0ff5c726c4ce79751facc64f39 +0 -0
  207. {e3cli-1.0.2 → e3cli-1.0.4}/objects/c7/f3f6ba90a1ec28fdef6ec7b10d82f4ad144969 +0 -0
  208. {e3cli-1.0.2 → e3cli-1.0.4}/objects/cb/b097bc0ed0f65614e13f563a22624f0ce078e6 +0 -0
  209. {e3cli-1.0.2 → e3cli-1.0.4}/objects/cd/3c462e6a24c9757a0fffd7c42abce926e1adf5 +0 -0
  210. {e3cli-1.0.2 → e3cli-1.0.4}/objects/ce/f38215c9c7dc239421d85ca93221ad7beb63cb +0 -0
  211. {e3cli-1.0.2 → e3cli-1.0.4}/objects/cf/286c5bf7cffc4bf93b51554d4299845172df84 +0 -0
  212. {e3cli-1.0.2 → e3cli-1.0.4}/objects/d0/aa218f92135250fa46b8490c68f4e77846b1b1 +0 -0
  213. {e3cli-1.0.2 → e3cli-1.0.4}/objects/d1/70d82f10fffbce5936fc1d0f5e1f051c354413 +0 -0
  214. {e3cli-1.0.2 → e3cli-1.0.4}/objects/d1/eccedbd9604b59bcc247b6f8a177df5486ce57 +0 -0
  215. {e3cli-1.0.2 → e3cli-1.0.4}/objects/d4/1a891e54bfd7ddd745555624ce9142a47e5fdd +0 -0
  216. {e3cli-1.0.2 → e3cli-1.0.4}/objects/d8/2d02db21187a83d77a71c8665e1b4699e481fb +0 -0
  217. {e3cli-1.0.2 → e3cli-1.0.4}/objects/d8/76cc79a2f25f4e8616805811110f700e277af2 +0 -0
  218. {e3cli-1.0.2 → e3cli-1.0.4}/objects/db/3bb89cba087a88feb4075b467732846a1d0118 +0 -0
  219. {e3cli-1.0.2 → e3cli-1.0.4}/objects/db/dc7e591f97aab4da5d2acb29194355c277acf6 +0 -0
  220. {e3cli-1.0.2 → e3cli-1.0.4}/objects/df/8c39b5b6cfcf19f8f27d5913830cb0a8fcd4c8 +0 -0
  221. {e3cli-1.0.2 → e3cli-1.0.4}/objects/df/a8267b7bcb40cc3c4524934d386516e27dd5db +0 -0
  222. {e3cli-1.0.2 → e3cli-1.0.4}/objects/e0/87a95e8c14f5d090c04d19d3a9f91a208b7841 +0 -0
  223. {e3cli-1.0.2 → e3cli-1.0.4}/objects/e0/e63743c9660300f76483d3ad27ecd85241cdc5 +0 -0
  224. {e3cli-1.0.2 → e3cli-1.0.4}/objects/e2/2ab51073af126f1b602884b02dad11f9027942 +0 -0
  225. {e3cli-1.0.2 → e3cli-1.0.4}/objects/e4/1b4051ac3bac5364f7a5ce048ecc41147857d6 +0 -0
  226. {e3cli-1.0.2 → e3cli-1.0.4}/objects/e4/1dbd057baa81d4e660a52d2486ee700f8c7b60 +0 -0
  227. {e3cli-1.0.2 → e3cli-1.0.4}/objects/e4/fba2702e9b6e30902b10ef946b8e05ee14b3d6 +0 -0
  228. {e3cli-1.0.2 → e3cli-1.0.4}/objects/e5/23965887274b5a3060bca39ec005e6fe99883b +0 -0
  229. {e3cli-1.0.2 → e3cli-1.0.4}/objects/e6/3334965c2117237f22708d1c4681be5d77574b +0 -0
  230. {e3cli-1.0.2 → e3cli-1.0.4}/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 +0 -0
  231. {e3cli-1.0.2 → e3cli-1.0.4}/objects/e8/a732d4490c14cf239dd7081c8c1d15b44c495b +0 -0
  232. {e3cli-1.0.2 → e3cli-1.0.4}/objects/eb/22d1e687a8a2dd36474c7add9535ebe9682d3b +0 -0
  233. {e3cli-1.0.2 → e3cli-1.0.4}/objects/eb/7320ad4e2f7d18b503c64b2a983c2a41fc8eb1 +0 -0
  234. {e3cli-1.0.2 → e3cli-1.0.4}/objects/ec/2badeec80e4ddc66a5168d8c3aec878a30f813 +0 -0
  235. {e3cli-1.0.2 → e3cli-1.0.4}/objects/ec/d43841d2e6e7268caf4a1bb03c3f549ca75f49 +0 -0
  236. {e3cli-1.0.2 → e3cli-1.0.4}/objects/f0/c3d899d1d7578174419e3d21fbb43d469ea0df +0 -0
  237. {e3cli-1.0.2 → e3cli-1.0.4}/objects/f2/d740d8021553398f98f1302398006e988697ef +0 -0
  238. {e3cli-1.0.2 → e3cli-1.0.4}/objects/f3/505619e9502b8a75ce04cf75ccb61e54f16cf5 +0 -0
  239. {e3cli-1.0.2 → e3cli-1.0.4}/objects/f3/681d2437d363e9865aec3eb4e3e8f5aff46ca6 +0 -0
  240. {e3cli-1.0.2 → e3cli-1.0.4}/objects/f3/b1f01d9f8fab935f87bee101fa0f1f944c30d8 +0 -0
  241. {e3cli-1.0.2 → e3cli-1.0.4}/objects/f3/e2082feab4cb9a889f623d8fe7b58628f82da9 +0 -0
  242. {e3cli-1.0.2 → e3cli-1.0.4}/objects/f4/21fa018addaacd7f59e11603b182b38207abca +0 -0
  243. {e3cli-1.0.2 → e3cli-1.0.4}/objects/f5/9e7ad7dad379a9752969e3443d3ed60a82cdf1 +0 -0
  244. {e3cli-1.0.2 → e3cli-1.0.4}/objects/f6/d28255ddf6cd98d69342c282663771093ad834 +0 -0
  245. {e3cli-1.0.2 → e3cli-1.0.4}/objects/f7/c7da26bbfca63ed8af08f9b7b1ace4930dad44 +0 -0
  246. {e3cli-1.0.2 → e3cli-1.0.4}/objects/f9/aece29cc134fc99f629129d46c712f015b00c0 +0 -0
  247. {e3cli-1.0.2 → e3cli-1.0.4}/objects/fb/4fbcdf3b0da9864651c5d50322b27c21f26fed +0 -0
  248. {e3cli-1.0.2 → e3cli-1.0.4}/objects/fb/ba70de6b161e2918d9d9e62d734abd85d01ae1 +0 -0
  249. {e3cli-1.0.2 → e3cli-1.0.4}/objects/fb/bc2db563e1d0b7a0745a04fd0a0c5b5ef7e6aa +0 -0
  250. {e3cli-1.0.2 → e3cli-1.0.4}/objects/fc/03924609632d9a9f820119bdf5a9ddf5a4c90a +0 -0
  251. {e3cli-1.0.2 → e3cli-1.0.4}/objects/fd/3fb430f4e9190752eb58cef5019660e9aa92ef +0 -0
  252. {e3cli-1.0.2 → e3cli-1.0.4}/objects/fd/d0e4feee582591e85b9d488dd4fa1794364abb +0 -0
  253. {e3cli-1.0.2 → e3cli-1.0.4}/objects/fe/092d97fe5a0e2a3d7b807e1a9f44735281a286 +0 -0
  254. {e3cli-1.0.2 → e3cli-1.0.4}/refs/heads/main +0 -0
  255. {e3cli-1.0.2 → e3cli-1.0.4}/refs/remotes/origin/main +0 -0
  256. {e3cli-1.0.2 → e3cli-1.0.4}/refs/tags/v0.1.0 +0 -0
  257. {e3cli-1.0.2 → e3cli-1.0.4}/refs/tags/v0.2.0 +0 -0
  258. {e3cli-1.0.2 → e3cli-1.0.4}/refs/tags/v0.3.0 +0 -0
  259. {e3cli-1.0.2 → e3cli-1.0.4}/refs/tags/v0.3.1 +0 -0
  260. {e3cli-1.0.2 → e3cli-1.0.4}/refs/tags/v0.3.2 +0 -0
  261. {e3cli-1.0.2 → e3cli-1.0.4}/refs/tags/v0.4.0 +0 -0
  262. {e3cli-1.0.2 → e3cli-1.0.4}/refs/tags/v0.4.1 +0 -0
  263. {e3cli-1.0.2 → e3cli-1.0.4}/refs/tags/v0.4.3 +0 -0
  264. {e3cli-1.0.2 → e3cli-1.0.4}/tests/__init__.py +0 -0
  265. {e3cli-1.0.2 → e3cli-1.0.4}/tests/test_basic.py +0 -0
@@ -41,16 +41,6 @@ jobs:
41
41
  steps:
42
42
  - uses: actions/checkout@v4
43
43
 
44
- - name: Calculate tarball sha256
45
- id: sha
46
- run: |
47
- TARBALL_URL="https://github.com/${{ github.repository }}/archive/refs/tags/${{ github.ref_name }}.tar.gz"
48
- echo "url=${TARBALL_URL}" >> "$GITHUB_OUTPUT"
49
- SHA=$(curl -sL "${TARBALL_URL}" | sha256sum | cut -d' ' -f1)
50
- echo "sha256=${SHA}" >> "$GITHUB_OUTPUT"
51
- echo "Tarball: ${TARBALL_URL}"
52
- echo "SHA256: ${SHA}"
53
-
54
44
  - name: Clone homebrew tap
55
45
  uses: actions/checkout@v4
56
46
  with:
@@ -64,29 +54,32 @@ jobs:
64
54
 
65
55
  - name: Generate formula with all transitive dependencies
66
56
  run: |
67
- python3 - "${{ github.repository }}" "${{ steps.sha.outputs.url }}" "${{ steps.sha.outputs.sha256 }}" << 'PYSCRIPT'
68
- import json, re, sys, urllib.request
57
+ python3 - "${{ github.repository }}" "${{ github.ref_name }}" << 'PYSCRIPT'
58
+ import json, re, sys, time, urllib.request
69
59
 
70
- repo, tarball_url, tarball_sha = sys.argv[1], sys.argv[2], sys.argv[3]
60
+ repo, ref_name = sys.argv[1], sys.argv[2]
61
+ e3cli_version = ref_name.lstrip("v")
71
62
 
72
- def get_info(pkg):
63
+ def get_info(pkg, version=None):
64
+ """Fetch package info from PyPI. If version is given, look up that specific
65
+ release's files; otherwise use the latest. Returns None if the version is
66
+ not yet indexed or no installable file exists."""
73
67
  pkg_normalized = re.sub(r'[-_.]+', '-', pkg).lower()
74
68
  try:
75
69
  data = json.loads(urllib.request.urlopen(f"https://pypi.org/pypi/{pkg_normalized}/json").read())
76
70
  except Exception:
77
71
  return None
78
- ver = data["info"]["version"]
72
+ ver = version or data["info"]["version"]
79
73
  requires = data["info"].get("requires_dist") or []
80
74
  deps = []
81
75
  for r in requires:
82
76
  if "extra ==" in r:
83
77
  continue
84
- # Extract package name (before any version specifier or marker)
85
78
  m = re.match(r'^([A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?)', r)
86
79
  if m:
87
80
  deps.append(m.group(1).lower())
88
- # Prefer pure-Python wheel (py3-none-any) → no compile, much faster brew install.
89
- # Fall back to sdist for packages without a universal wheel.
81
+ # Prefer pure-Python wheel (py3-none-any) → no compile, no build-isolation,
82
+ # much faster brew install. Fall back to sdist if no universal wheel exists.
90
83
  wheel_url = wheel_sha = sdist_url = sdist_sha = ""
91
84
  for f in data["releases"].get(ver, []):
92
85
  if f["packagetype"] == "bdist_wheel" and "py3-none-any" in f["filename"]:
@@ -95,7 +88,27 @@ jobs:
95
88
  sdist_url, sdist_sha = f["url"], f["digests"]["sha256"]
96
89
  url = wheel_url or sdist_url
97
90
  sha = wheel_sha or sdist_sha
98
- return {"name": pkg_normalized, "deps": deps, "url": url, "sha256": sha}
91
+ if not url:
92
+ return None
93
+ return {
94
+ "name": pkg_normalized, "deps": deps,
95
+ "url": url, "sha256": sha,
96
+ "has_wheel": bool(wheel_url),
97
+ }
98
+
99
+ # Resolve e3cli itself from PyPI (the just-uploaded version). Retry until the
100
+ # wheel appears — PyPI's JSON API may lag a few seconds after twine upload.
101
+ self_info = None
102
+ for attempt in range(12): # 12 × 5s = 60s budget
103
+ self_info = get_info("e3cli", version=e3cli_version)
104
+ if self_info and self_info["has_wheel"]:
105
+ break
106
+ print(f"PyPI wheel for e3cli {e3cli_version} not ready (attempt {attempt + 1}/12)…", file=sys.stderr)
107
+ time.sleep(5)
108
+ if not self_info:
109
+ sys.exit(f"FATAL: e3cli {e3cli_version} not found on PyPI after retries")
110
+ if not self_info["has_wheel"]:
111
+ print(f"WARNING: no wheel for e3cli {e3cli_version}; formula will use sdist and be slow", file=sys.stderr)
99
112
 
100
113
  # Resolve ALL transitive dependencies
101
114
  seen = set()
@@ -119,15 +132,16 @@ jobs:
119
132
  if dk not in seen:
120
133
  queue.append(d)
121
134
 
122
- # Build formula
135
+ # Build formula — main package URL points to PyPI wheel (NOT GitHub source
136
+ # tarball). This avoids brew triggering pip's build-isolation flow on install.
123
137
  lines = [
124
138
  'class E3cli < Formula',
125
139
  ' include Language::Python::Virtualenv',
126
140
  '',
127
141
  ' desc "NYCU E3 Moodle automation CLI — sync courses, download materials, submit assignments"',
128
142
  f' homepage "https://github.com/{repo}"',
129
- f' url "{tarball_url}"',
130
- f' sha256 "{tarball_sha}"',
143
+ f' url "{self_info["url"]}"',
144
+ f' sha256 "{self_info["sha256"]}"',
131
145
  ' license "MIT"',
132
146
  '',
133
147
  ' depends_on "python@3.12"',
@@ -54,8 +54,16 @@ e3cli i
54
54
 
55
55
  # Token expired?
56
56
  e3cli login --refresh
57
+
58
+ # AI agent skill (install SKILL.md into Claude Code / Codex / Gemini / Antigravity CLI)
59
+ e3cli skill status # check what's detected / installed
60
+ e3cli skill install # auto-install for detected agents
61
+ e3cli skill install -t claude # specific target (claude/codex/gemini/antigravity)
62
+ e3cli skill uninstall # remove
57
63
  ```
58
64
 
65
+ > **First run:** if `~/.e3cli/config.toml` doesn't exist, ANY `e3cli <cmd>` launches the interactive setup wizard. The wizard is 6 steps (Moodle URL → semester format → download dir → alias → login → AI agent skill install). After completion, re-run the original command.
66
+
59
67
  ## Workflow: When a New Assignment is Detected
60
68
 
61
69
  1. `e3cli sync` — pull latest materials and assignment status
@@ -99,6 +107,7 @@ e3cli download --course "artificial intelligence"
99
107
  3. **Check deadlines first** — prioritize urgent assignments
100
108
  4. **Token expiry** — if commands fail with auth errors, run `e3cli login --refresh`
101
109
  5. **Don't read credential files** — use CLI commands, not direct file access
110
+ 6. **First-run wizard hangs the agent** — if a command opens an interactive setup wizard (config missing) or `login --refresh` prompt, STOP and tell the user to run `e3cli setup` / `e3cli login --refresh` themselves in their terminal. Both are interactive and will hang an agent session.
102
111
 
103
112
  ## Data Locations
104
113
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: e3cli
3
- Version: 1.0.2
3
+ Version: 1.0.4
4
4
  Summary: NYCU E3 Moodle automation CLI — sync courses, download materials, submit assignments.
5
5
  Project-URL: Homepage, https://github.com/junlinwk/e3cli
6
6
  Project-URL: Repository, https://github.com/junlinwk/e3cli
@@ -52,7 +52,7 @@ Description-Content-Type: text/markdown
52
52
  <a href="#commands">Commands</a> &bull;
53
53
  <a href="#interactive-mode">Interactive</a> &bull;
54
54
  <a href="#security">Security</a> &bull;
55
- <a href="#claude-code-integration">Claude Code</a> &bull;
55
+ <a href="#ai-agent-integration">AI Agents</a> &bull;
56
56
  <a href="./README_zh-TW.md">繁體中文</a>
57
57
  </p>
58
58
 
@@ -78,6 +78,7 @@ Description-Content-Type: text/markdown
78
78
  - **Interactive TUI** — Full arrow-key interactive interface (`e3cli i`)
79
79
  - **Bilingual** — Full Chinese/English support
80
80
  - **Multi-school** — Works with any Moodle instance (configurable semester format)
81
+ - **AI Agent Skill** — Bundled SKILL.md installable into Claude Code / Codex CLI / Gemini CLI / Antigravity CLI (`agy`) (`e3cli skill install`)
81
82
 
82
83
  ## Supported Platforms
83
84
 
@@ -136,6 +137,8 @@ pip install -e ".[dev]"
136
137
 
137
138
  ## Quick Start
138
139
 
140
+ > On first run, **any** `e3cli <something>` command will launch the interactive setup wizard (language, Moodle URL, semester format, alias, login, AI agent skill). After setup, re-run your original command.
141
+
139
142
  ```bash
140
143
  # 1. Login (first time — interactive setup wizard will guide you)
141
144
  e3cli login --save
@@ -297,12 +300,29 @@ e3cli profile use ntu # → connects to NTU COOL
297
300
 
298
301
  ### `e3cli setup`
299
302
 
300
- Re-run the interactive setup wizard (language, Moodle URL, semester format, alias, download directory, login).
303
+ Re-run the interactive setup wizard. Six steps: Moodle URL semester format download directory → command alias → login → AI agent skill install.
301
304
 
302
305
  ```bash
303
306
  e3cli setup
304
307
  ```
305
308
 
309
+ > The setup wizard runs automatically the first time any `e3cli` command is invoked (config file missing).
310
+
311
+ ### `e3cli skill`
312
+
313
+ Install the bundled SKILL.md so AI coding agents (Claude Code / Codex CLI / Gemini CLI / Antigravity CLI (`agy`)) know how to use e3cli — when to sync, how to read full assignment details, when to ask before submitting.
314
+
315
+ ```bash
316
+ e3cli skill status # show which agents are detected + installed
317
+ e3cli skill install # auto-detect ~/.claude / ~/.codex / ~/.gemini / antigravity-cli
318
+ e3cli skill install -t claude # install for a specific target (claude/codex/gemini/antigravity)
319
+ e3cli skill install -t all # install for all known agents (even if undetected)
320
+ e3cli skill install --force # overwrite existing
321
+ e3cli skill uninstall # remove from all agent dirs
322
+ ```
323
+
324
+ The setup wizard offers this as Step 6; running `e3cli skill install` later is the same operation.
325
+
306
326
  ### `e3cli version`
307
327
 
308
328
  ```bash
@@ -451,18 +471,31 @@ e3cli uses **PBKDF2-HMAC-SHA256** key derivation with integrity verification to
451
471
 
452
472
  ---
453
473
 
454
- ## Claude Code Integration
474
+ ## AI Agent Integration
475
+
476
+ e3cli ships with a `SKILL.md` that teaches AI coding agents — [Claude Code](https://claude.ai/code), OpenAI Codex CLI, Google Gemini CLI, and Google Antigravity CLI (`agy`, Gemini CLI's successor) — how to use it correctly: sync first, read full assignment details before working, ask before submitting, never read credential files, etc.
477
+
478
+ ### Install the skill
479
+
480
+ The setup wizard's Step 6 offers this automatically. To install manually:
481
+
482
+ ```bash
483
+ e3cli skill install # auto-detects ~/.claude / ~/.codex / ~/.gemini / ~/.gemini/antigravity-cli
484
+ e3cli skill status # see what's detected and installed
485
+ ```
486
+
487
+ Once installed, the agent recognises Moodle-related requests ("Moodle", "NYCU", "E3", "assignment", "作業", "繳交", …) and follows the bundled workflow.
455
488
 
456
- This project includes a `CLAUDE.md` file that teaches [Claude Code](https://claude.ai/code) how to use e3cli as an automated assistant. When Claude Code is invoked in this project directory, it can:
489
+ ### What the agent can do
457
490
 
458
491
  - Sync and check for new assignments (`e3cli sync`)
459
492
  - Read assignment descriptions and downloaded materials
460
493
  - Help complete assignments (with human oversight)
461
494
  - Submit completed work (`e3cli submit`)
462
495
 
463
- See [`CLAUDE.md`](./CLAUDE.md) and [`e3cli/agent_prompt.md`](./e3cli/agent_prompt.md) for the full agent automation guide.
496
+ See [`e3cli/skills/e3cli/SKILL.md`](./e3cli/skills/e3cli/SKILL.md), [`CLAUDE.md`](./CLAUDE.md), and [`e3cli/agent_prompt.md`](./e3cli/agent_prompt.md) for the full agent automation guide.
464
497
 
465
- > **Note:** Claude Code will always ask for confirmation before submitting assignments.
498
+ > **Note:** AI agents will always ask for confirmation before submitting assignments.
466
499
 
467
500
  ---
468
501
 
@@ -18,7 +18,7 @@
18
18
  <a href="#commands">Commands</a> &bull;
19
19
  <a href="#interactive-mode">Interactive</a> &bull;
20
20
  <a href="#security">Security</a> &bull;
21
- <a href="#claude-code-integration">Claude Code</a> &bull;
21
+ <a href="#ai-agent-integration">AI Agents</a> &bull;
22
22
  <a href="./README_zh-TW.md">繁體中文</a>
23
23
  </p>
24
24
 
@@ -44,6 +44,7 @@
44
44
  - **Interactive TUI** — Full arrow-key interactive interface (`e3cli i`)
45
45
  - **Bilingual** — Full Chinese/English support
46
46
  - **Multi-school** — Works with any Moodle instance (configurable semester format)
47
+ - **AI Agent Skill** — Bundled SKILL.md installable into Claude Code / Codex CLI / Gemini CLI / Antigravity CLI (`agy`) (`e3cli skill install`)
47
48
 
48
49
  ## Supported Platforms
49
50
 
@@ -102,6 +103,8 @@ pip install -e ".[dev]"
102
103
 
103
104
  ## Quick Start
104
105
 
106
+ > On first run, **any** `e3cli <something>` command will launch the interactive setup wizard (language, Moodle URL, semester format, alias, login, AI agent skill). After setup, re-run your original command.
107
+
105
108
  ```bash
106
109
  # 1. Login (first time — interactive setup wizard will guide you)
107
110
  e3cli login --save
@@ -263,12 +266,29 @@ e3cli profile use ntu # → connects to NTU COOL
263
266
 
264
267
  ### `e3cli setup`
265
268
 
266
- Re-run the interactive setup wizard (language, Moodle URL, semester format, alias, download directory, login).
269
+ Re-run the interactive setup wizard. Six steps: Moodle URL semester format download directory → command alias → login → AI agent skill install.
267
270
 
268
271
  ```bash
269
272
  e3cli setup
270
273
  ```
271
274
 
275
+ > The setup wizard runs automatically the first time any `e3cli` command is invoked (config file missing).
276
+
277
+ ### `e3cli skill`
278
+
279
+ Install the bundled SKILL.md so AI coding agents (Claude Code / Codex CLI / Gemini CLI / Antigravity CLI (`agy`)) know how to use e3cli — when to sync, how to read full assignment details, when to ask before submitting.
280
+
281
+ ```bash
282
+ e3cli skill status # show which agents are detected + installed
283
+ e3cli skill install # auto-detect ~/.claude / ~/.codex / ~/.gemini / antigravity-cli
284
+ e3cli skill install -t claude # install for a specific target (claude/codex/gemini/antigravity)
285
+ e3cli skill install -t all # install for all known agents (even if undetected)
286
+ e3cli skill install --force # overwrite existing
287
+ e3cli skill uninstall # remove from all agent dirs
288
+ ```
289
+
290
+ The setup wizard offers this as Step 6; running `e3cli skill install` later is the same operation.
291
+
272
292
  ### `e3cli version`
273
293
 
274
294
  ```bash
@@ -417,18 +437,31 @@ e3cli uses **PBKDF2-HMAC-SHA256** key derivation with integrity verification to
417
437
 
418
438
  ---
419
439
 
420
- ## Claude Code Integration
440
+ ## AI Agent Integration
441
+
442
+ e3cli ships with a `SKILL.md` that teaches AI coding agents — [Claude Code](https://claude.ai/code), OpenAI Codex CLI, Google Gemini CLI, and Google Antigravity CLI (`agy`, Gemini CLI's successor) — how to use it correctly: sync first, read full assignment details before working, ask before submitting, never read credential files, etc.
443
+
444
+ ### Install the skill
445
+
446
+ The setup wizard's Step 6 offers this automatically. To install manually:
447
+
448
+ ```bash
449
+ e3cli skill install # auto-detects ~/.claude / ~/.codex / ~/.gemini / ~/.gemini/antigravity-cli
450
+ e3cli skill status # see what's detected and installed
451
+ ```
452
+
453
+ Once installed, the agent recognises Moodle-related requests ("Moodle", "NYCU", "E3", "assignment", "作業", "繳交", …) and follows the bundled workflow.
421
454
 
422
- This project includes a `CLAUDE.md` file that teaches [Claude Code](https://claude.ai/code) how to use e3cli as an automated assistant. When Claude Code is invoked in this project directory, it can:
455
+ ### What the agent can do
423
456
 
424
457
  - Sync and check for new assignments (`e3cli sync`)
425
458
  - Read assignment descriptions and downloaded materials
426
459
  - Help complete assignments (with human oversight)
427
460
  - Submit completed work (`e3cli submit`)
428
461
 
429
- See [`CLAUDE.md`](./CLAUDE.md) and [`e3cli/agent_prompt.md`](./e3cli/agent_prompt.md) for the full agent automation guide.
462
+ See [`e3cli/skills/e3cli/SKILL.md`](./e3cli/skills/e3cli/SKILL.md), [`CLAUDE.md`](./CLAUDE.md), and [`e3cli/agent_prompt.md`](./e3cli/agent_prompt.md) for the full agent automation guide.
430
463
 
431
- > **Note:** Claude Code will always ask for confirmation before submitting assignments.
464
+ > **Note:** AI agents will always ask for confirmation before submitting assignments.
432
465
 
433
466
  ---
434
467
 
@@ -18,7 +18,7 @@
18
18
  <a href="#指令說明">指令</a> &bull;
19
19
  <a href="#互動模式">互動模式</a> &bull;
20
20
  <a href="#安全性">安全性</a> &bull;
21
- <a href="#claude-code-整合">Claude Code</a> &bull;
21
+ <a href="#ai-agent-整合">AI Agent</a> &bull;
22
22
  <a href="./README.md">English</a>
23
23
  </p>
24
24
 
@@ -44,6 +44,7 @@
44
44
  - **互動介面** — 完整方向鍵互動介面 (`e3cli i`)
45
45
  - **雙語** — 完整中文/英文支援
46
46
  - **多校支援** — 支援任何 Moodle 平台(可設定學期格式)
47
+ - **AI Agent Skill** — 內建 SKILL.md,可一鍵安裝到 Claude Code / Codex CLI / Gemini CLI / Antigravity CLI (`agy`)(`e3cli skill install`)
47
48
 
48
49
  ## 支援平台
49
50
 
@@ -102,6 +103,8 @@ pip install -e ".[dev]"
102
103
 
103
104
  ## 快速開始
104
105
 
106
+ > 首次執行時,**任何** `e3cli <指令>` 都會自動啟動互動式設定引導(語言、Moodle 網址、學期格式、別名、登入、AI agent skill)。設定完後請再執行一次原本的指令。
107
+
105
108
  ```bash
106
109
  # 1. 登入(首次使用會啟動互動式引導)
107
110
  e3cli login --save
@@ -263,12 +266,29 @@ e3cli profile use ntu # → 連線 NTU COOL
263
266
 
264
267
  ### `e3cli setup`
265
268
 
266
- 重新執行互動式設定引導(語言、Moodle 網址、學期格式、別名、下載目錄、登入)。
269
+ 重新執行互動式設定引導。共 6 步驟:Moodle 網址 → 學期格式 → 下載目錄 → 指令別名 → 登入 → AI agent skill 安裝。
267
270
 
268
271
  ```bash
269
272
  e3cli setup
270
273
  ```
271
274
 
275
+ > 首次執行任何 `e3cli` 指令時(找不到 config 檔),會自動跑這個 wizard。
276
+
277
+ ### `e3cli skill`
278
+
279
+ 安裝內建的 SKILL.md,讓 AI 編程助手(Claude Code / Codex CLI / Gemini CLI / Antigravity CLI `agy`)知道如何正確使用 e3cli — 何時 sync、如何讀取作業完整描述、提交前必先詢問等。
280
+
281
+ ```bash
282
+ e3cli skill status # 列出偵測到 / 已安裝的 agent
283
+ e3cli skill install # 自動偵測 ~/.claude / ~/.codex / ~/.gemini / antigravity-cli
284
+ e3cli skill install -t claude # 安裝到特定目標 (claude/codex/gemini/antigravity)
285
+ e3cli skill install -t all # 安裝到所有已知 agent(即使未偵測到)
286
+ e3cli skill install --force # 覆寫既有的
287
+ e3cli skill uninstall # 從所有 agent 目錄移除
288
+ ```
289
+
290
+ setup wizard 的 Step 6 會自動詢問是否安裝;事後跑 `e3cli skill install` 效果相同。
291
+
272
292
  ### `e3cli version`
273
293
 
274
294
  ```bash
@@ -417,18 +437,31 @@ e3cli 使用 **PBKDF2-HMAC-SHA256** 金鑰衍生搭配完整性驗證來保護
417
437
 
418
438
  ---
419
439
 
420
- ## Claude Code 整合
440
+ ## AI Agent 整合
441
+
442
+ e3cli 內建一份 `SKILL.md`,教 AI 編程助手 — [Claude Code](https://claude.ai/code)、OpenAI Codex CLI、Google Gemini CLI、以及 Google Antigravity CLI (`agy`,Gemini CLI 的繼任者) — 如何正確使用:先 sync、開工前先讀完整作業描述、提交前必先詢問、不讀帳密檔等。
443
+
444
+ ### 安裝 skill
445
+
446
+ setup wizard 的 Step 6 會自動詢問。事後手動安裝:
447
+
448
+ ```bash
449
+ e3cli skill install # 自動偵測 ~/.claude / ~/.codex / ~/.gemini / antigravity-cli
450
+ e3cli skill status # 查看偵測 / 安裝狀態
451
+ ```
452
+
453
+ 裝好後,agent 偵測到 Moodle 相關需求("Moodle"、"NYCU"、"E3"、"作業"、"繳交" …)就會自動依照內建流程操作。
421
454
 
422
- 本專案提供 `CLAUDE.md` 文件,教 [Claude Code](https://claude.ai/code) 如何使用 e3cli 作為自動化助手。當 Claude Code 在此專案目錄下運行時,它可以:
455
+ ### Agent 能做的事
423
456
 
424
457
  - 同步並檢查新作業 (`e3cli sync`)
425
458
  - 讀取作業描述與已下載的教材
426
459
  - 協助完成作業(需人工審查)
427
460
  - 提交完成的作業 (`e3cli submit`)
428
461
 
429
- 詳見 [`CLAUDE.md`](./CLAUDE.md) [`e3cli/agent_prompt.md`](./e3cli/agent_prompt.md)。
462
+ 詳見 [`e3cli/skills/e3cli/SKILL.md`](./e3cli/skills/e3cli/SKILL.md)、[`CLAUDE.md`](./CLAUDE.md) [`e3cli/agent_prompt.md`](./e3cli/agent_prompt.md)。
430
463
 
431
- > **注意:** Claude Code 在提交作業前一定會先詢問確認。
464
+ > **注意:** AI agent 在提交作業前一定會先詢問確認。
432
465
 
433
466
  ---
434
467
 
@@ -1,3 +1,3 @@
1
1
  """E3CLI — NYCU E3 Moodle Automation CLI Tool"""
2
2
 
3
- __version__ = "1.0.2"
3
+ __version__ = "1.0.4"
@@ -14,6 +14,7 @@ e3cli is a CLI tool for interacting with NYCU's E3 Moodle platform. The agent ca
14
14
 
15
15
  - e3cli must be installed and logged in (`e3cli login --save`)
16
16
  - The agent must have shell access to run `e3cli` commands
17
+ - **First-run safety:** if `~/.e3cli/config.toml` does not exist, any `e3cli <cmd>` will launch an interactive setup wizard that **will hang an agent session**. Probe via `test -f ~/.e3cli/config.toml` before running real commands; if missing, tell the user to run `e3cli setup` themselves in their own terminal.
17
18
 
18
19
  ## Workflow
19
20
 
@@ -120,8 +121,11 @@ e3cli sync --quiet
120
121
  | `e3cli download --course "X"` | Download course X materials |
121
122
  | `e3cli download --all` | Download all materials |
122
123
  | `e3cli submit ID file.pdf` | Submit assignment |
123
- | `e3cli i` | Interactive mode |
124
- | `e3cli login --refresh` | Refresh expired token |
124
+ | `e3cli i` | Interactive mode (DO NOT run from agent — TUI hangs) |
125
+ | `e3cli login --refresh` | Refresh expired token (interactive — instruct user) |
126
+ | `e3cli setup` | First-run wizard (interactive — instruct user) |
127
+ | `e3cli skill install` | Install bundled SKILL.md into Claude / Codex / Gemini / Antigravity (`agy`) |
128
+ | `e3cli skill status` | List which AI agent dirs are detected + installed |
125
129
 
126
130
  ## Data Locations
127
131
 
@@ -58,15 +58,16 @@ _original_app_call = app.__call__
58
58
 
59
59
 
60
60
  def _app_with_first_run(*args, **kwargs):
61
- skip_keywords = {"--help", "-h", "version", "setup", "skill", "--show-completion", "--install-completion"}
61
+ # 只保留 shell completion 相關 這兩個是 shell 啟動時 typer 自動呼叫的,
62
+ # 若擋住會在開新 terminal 時 hang 在互動式 wizard。
63
+ skip_keywords = {"--show-completion", "--install-completion"}
62
64
  if (
63
65
  is_first_run()
64
66
  and sys.stdin.isatty()
65
67
  and not any(arg in skip_keywords for arg in sys.argv[1:])
66
68
  ):
67
69
  run_setup_wizard()
68
- if len(sys.argv) <= 1:
69
- return
70
+ return
70
71
  return _original_app_call(*args, **kwargs)
71
72
 
72
73
 
@@ -176,7 +176,7 @@ def run_setup_wizard() -> None:
176
176
  console.print()
177
177
 
178
178
  # Step 1: Moodle URL
179
- console.print(f"[bold cyan]Step 1/5[/bold cyan] — {t('setup.step_url')}")
179
+ console.print(f"[bold cyan]Step 1/6[/bold cyan] — {t('setup.step_url')}")
180
180
  if lang == "zh":
181
181
  console.print("[dim]輸入你的 Moodle 網址。支援任何學校的 Moodle 平台。[/dim]")
182
182
  else:
@@ -212,12 +212,12 @@ def run_setup_wizard() -> None:
212
212
  console.print()
213
213
 
214
214
  # Step 2: Semester format
215
- console.print("[bold cyan]Step 2/5[/bold cyan] — ", end="")
215
+ console.print("[bold cyan]Step 2/6[/bold cyan] — ", end="")
216
216
  sem_format = _choose_semester_format(lang)
217
217
  console.print()
218
218
 
219
219
  # Step 3: Download directory
220
- console.print(f"[bold cyan]Step 3/5[/bold cyan] — {t('setup.step_dir')}")
220
+ console.print(f"[bold cyan]Step 3/6[/bold cyan] — {t('setup.step_dir')}")
221
221
  console.print(f"[dim]{t('setup.step_dir_hint')}[/dim]")
222
222
  default_dir = os.path.expanduser("~/e3-downloads")
223
223
  download_dir = typer.prompt(
@@ -228,7 +228,7 @@ def run_setup_wizard() -> None:
228
228
  console.print()
229
229
 
230
230
  # Step 4: Alias
231
- console.print("[bold cyan]Step 4/5[/bold cyan] — ", end="")
231
+ console.print("[bold cyan]Step 4/6[/bold cyan] — ", end="")
232
232
  alias = _setup_alias(lang)
233
233
  console.print()
234
234
 
@@ -255,7 +255,7 @@ alias = "{alias}"
255
255
  console.print()
256
256
 
257
257
  # Step 5: Login
258
- console.print(f"[bold cyan]Step 5/5[/bold cyan] — {t('setup.step_login')}")
258
+ console.print(f"[bold cyan]Step 5/6[/bold cyan] — {t('setup.step_login')}")
259
259
  want_login = typer.confirm(t("setup.want_login"), default=True)
260
260
 
261
261
  if want_login:
@@ -296,6 +296,11 @@ alias = "{alias}"
296
296
  console.print(f"[dim] {t('setup.login_fail_hint')}[/dim]")
297
297
  console.print()
298
298
 
299
+ # Step 6: AI agent skill
300
+ console.print("[bold cyan]Step 6/6[/bold cyan] — ", end="")
301
+ _offer_skill_install(lang)
302
+ console.print()
303
+
299
304
  # Done
300
305
  console.print(Panel(
301
306
  f"[bold green]{t('setup.done_title')}[/bold green]\n\n{t('setup.done_body')}",
@@ -304,6 +309,55 @@ alias = "{alias}"
304
309
  ))
305
310
 
306
311
 
312
+ def _offer_skill_install(lang: str) -> None:
313
+ """偵測 ~/.claude / ~/.codex / ~/.gemini,有的話問要不要安裝 e3cli skill。"""
314
+ from e3cli.commands.skill import (
315
+ _bundled_skill_text,
316
+ _detected,
317
+ _install_one,
318
+ _targets,
319
+ )
320
+
321
+ if lang == "zh":
322
+ console.print("[bold cyan]AI Agent Skill[/bold cyan]")
323
+ console.print(
324
+ "[dim]安裝 SKILL.md 讓 Claude Code / Codex / Gemini CLI 知道如何使用 e3cli[/dim]"
325
+ )
326
+ else:
327
+ console.print("[bold cyan]AI Agent Skill[/bold cyan]")
328
+ console.print(
329
+ "[dim]Install SKILL.md so Claude Code / Codex / Gemini CLI know how to use e3cli[/dim]"
330
+ )
331
+
332
+ detected = _detected(_targets())
333
+ if not detected:
334
+ if lang == "zh":
335
+ console.print("[dim] 未偵測到 ~/.claude、~/.codex、~/.gemini — 跳過[/dim]")
336
+ console.print(
337
+ "[dim] 日後可執行 [cyan]e3cli skill install[/cyan] 安裝[/dim]"
338
+ )
339
+ else:
340
+ console.print("[dim] No ~/.claude, ~/.codex, ~/.gemini detected — skipping[/dim]")
341
+ console.print(
342
+ "[dim] Later run [cyan]e3cli skill install[/cyan] to install[/dim]"
343
+ )
344
+ return
345
+
346
+ names = ", ".join(tg.name for tg in detected)
347
+ if lang == "zh":
348
+ prompt = f" 偵測到 {names},要安裝 e3cli skill 嗎?"
349
+ else:
350
+ prompt = f" Detected: {names}. Install e3cli skill?"
351
+ if not typer.confirm(prompt, default=True):
352
+ return
353
+
354
+ content = _bundled_skill_text()
355
+ for tg in detected:
356
+ ok, msg = _install_one(tg, content, force=False)
357
+ marker = "[green] ✓[/green]" if ok else "[yellow] ·[/yellow]"
358
+ console.print(f"{marker} [bold]{tg.name}[/bold]: {msg}")
359
+
360
+
307
361
  @app.callback(invoke_without_command=True)
308
362
  def setup():
309
363
  """Re-run interactive setup wizard."""
@@ -39,6 +39,17 @@ def _targets() -> list[Target]:
39
39
  detect_dir=home / ".codex",
40
40
  skill_path=home / ".codex" / "skills" / SKILL_NAME / "SKILL.md",
41
41
  ),
42
+ # Antigravity CLI (`agy`) — Gemini CLI's successor. Reads skills from
43
+ # ~/.gemini/antigravity-cli/skills/. Standard SKILL.md format (our
44
+ # bundled file already has the YAML frontmatter agy expects).
45
+ Target(
46
+ name="antigravity",
47
+ detect_dir=home / ".gemini" / "antigravity-cli",
48
+ skill_path=home / ".gemini" / "antigravity-cli" / "skills" / SKILL_NAME / "SKILL.md",
49
+ ),
50
+ # Legacy Gemini CLI extension format (kept for backward compat with
51
+ # users still on the pre-agy Gemini CLI). Uses ~/.gemini/extensions/
52
+ # with a gemini-extension.json descriptor.
42
53
  Target(
43
54
  name="gemini",
44
55
  detect_dir=home / ".gemini",
@@ -68,7 +79,14 @@ def _bundled_skill_text() -> str:
68
79
 
69
80
 
70
81
  def _detected(targets: list[Target]) -> list[Target]:
71
- return [t for t in targets if t.detect_dir.is_dir()]
82
+ found = [t for t in targets if t.detect_dir.is_dir()]
83
+ # 若同時偵測到 antigravity (agy) 和 legacy gemini,自動跳過 legacy gemini。
84
+ # antigravity 的 detect_dir (~/.gemini/antigravity-cli) 是 gemini 的子目錄,
85
+ # 沒這個排除的話會在新 agy 用戶機器上重複裝。
86
+ names = {t.name for t in found}
87
+ if "antigravity" in names and "gemini" in names:
88
+ found = [t for t in found if t.name != "gemini"]
89
+ return found
72
90
 
73
91
 
74
92
  def _install_one(target: Target, content: str, force: bool) -> tuple[bool, str]:
@@ -11,14 +11,16 @@ The same `e3cli` binary is invoked from the shell — this skill only tells you
11
11
 
12
12
  ## Prerequisites — verify first
13
13
 
14
- Before doing real work, confirm the tool is installed and authenticated:
14
+ Before doing real work, confirm the tool is installed, configured, and authenticated:
15
15
 
16
16
  ```bash
17
+ test -f ~/.e3cli/config.toml && echo "configured" || echo "needs setup"
17
18
  e3cli --version # is it installed?
18
19
  e3cli courses # if this errors with "auth"/"token" → user must run: e3cli login --refresh
19
20
  ```
20
21
 
21
- If auth fails, **tell the user to run the login command themselves** — it is interactive and will hang if you run it. Do not attempt to read `~/.e3cli/credentials.enc`, `~/.e3cli/key`, or `~/.e3cli/token`.
22
+ - If config is missing **STOP**. Any `e3cli <cmd>` will launch an interactive first-run setup wizard that hangs the agent. Tell the user to run `e3cli setup` themselves in their terminal.
23
+ - If auth fails → **tell the user to run the login command themselves** — it is interactive and will hang if you run it. Do not attempt to read `~/.e3cli/credentials.enc`, `~/.e3cli/key`, or `~/.e3cli/token`.
22
24
 
23
25
  ## Core workflow
24
26
 
@@ -80,7 +82,7 @@ e3cli login --profile <name> --url <moodle-url> --save # add a new schoo
80
82
  3. **Prioritize by deadline.** When the user vaguely asks "what should I do", run `e3cli assignments --due-soon 7` first.
81
83
  4. **Never read credential files.** `~/.e3cli/credentials.enc`, `~/.e3cli/key`, `~/.e3cli/token` are encrypted/sensitive. Use CLI commands instead.
82
84
  5. **Don't run `e3cli i`** (interactive TUI). It needs a real terminal and will hang the agent.
83
- 6. **Don't run `e3cli login` or `e3cli login --refresh` yourself.** They are interactive — instruct the user to run them.
85
+ 6. **Don't run `e3cli login`, `e3cli login --refresh`, or `e3cli setup` yourself.** They are interactive — instruct the user to run them.
84
86
 
85
87
  ## Data locations (reference)
86
88
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "e3cli"
7
- version = "1.0.2"
7
+ version = "1.0.4"
8
8
  description = "NYCU E3 Moodle automation CLI — sync courses, download materials, submit assignments."
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes