[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6BZN0X90JSYATBR2M5TXBJC":3,"skill-same:01M6BZN0X90JSYATBR2M5TXBJC":63},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":30,"linkOnly":31,"markdownContent":32,"markdownBody":33,"frontMatter":34,"refName":35,"commitSha":36,"skillDirectory":37,"forksCount":38,"repositoryHtmlUrl":39,"repositoryHomepageUrl":40,"ownerHtmlUrl":41,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":42,"install":43,"resources":56},"01M6BZN0X90JSYATBR2M5TXBJC","notebook.fix_packages",null,"Keep the Docker container aligned with the template and install Python packages directly in the notebook","causify-ai\u002Fhelpers","causify-ai","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F121828442?v=4","01M6BZFTHW2MQR7FWK8CDW0DRA","Causify.AI","01M6BZFTPJ193AB5N089Z82HQG",155,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fcausify-ai\u002Fhelpers\u002Fblob\u002Fmaster\u002F.claude\u002Fskills\u002Fnotebook.fix_packages\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000011","运维与部署","SCENARIO","使用场景",[24,25,26,27,28,29],"packages","notebook fix packages","python","docker","template","haiku","2026-11-10 10:12:30",false,"---\ndescription: Keep the Docker container aligned with the template and install Python packages directly in the notebook\nmodel: haiku\n---\n\n# Goal\n\n- When creating Docker images for projects and tutorials, we want to\n  - Try to use always the same Docker template image from the `class_project` to\n    avoid replication of Docker containers\n  - Install the needed packages in the notebooks to customize the container\n\n## Inputs\n\n- The user passes:\n  - A pointer to a target directory `\u003CTARGET_DIR>` (e.g.,\n    `msml610\u002Ftutorials\u002FL03_knowledge_representation`) that was cloned from\n    `class_project\u002Fproject_template`\n  - (Optional) pointers to Jupyter notebooks\n\n# Workflow\n\n## Use the Docker Container From the Project Teamplate\n\n- In the directory with the project (e.g.,\n  `msml610\u002Ftutorials\u002FL03_knowledge_representation`) we want to use the same\n  `Dockerfile` and `requirements.txt` as the corresponding files in\n  `class_project\u002Fproject_template` (so that the Docker container for the project is\n  the same as the template used for class project)\n- If something needs to be added to the Docker image (e.g., a package that can't be\n  installed with `pip`) then it's ok to add it to `Dockerfile` but it should be\n  clearly commented why that package is needed\n\n## Discover All Packages Needed by the Notebook\n\n- A notebook's own `import` lines are not the full picture: each notebook is paired\n  with a `*_utils.py` file (e.g., `L03_06_logic_solvers.ipynb` ->\n  `L03_06_logic_solvers_utils.py`), and that file is imported with a line like:\n\n  ```\n  import L03_06_logic_solvers_utils as utils\n  ```\n\n- Read the `*_utils.py` file (and any other local module it imports, transitively)\n  and collect every third-party `import` \u002F `from ... import` statement in it, not\n  just the ones in the notebook itself\n- Map import names to their pip package name where they differ (e.g., `cv2` ->\n  `opencv-python`, `sklearn` -> `scikit-learn`, `PIL` -> `Pillow`, `yaml` ->\n  `PyYAML`)\n- Diff this full package list against `requirements.txt` and `Dockerfile`: any\n  package used by the notebook or its utils file that is missing from both is a bug,\n  even if it happens to already be installed in whatever container was used to author\n  the notebook\n- Add every missing package to `requirements.txt` (and to `Dockerfile` only if it\n  can't be installed with `pip`, per\n  `## Use the Docker Container from the Project Teamplate` above)\n\n## Add Packages to Notebooks\n\n- Then we want to add `pip install` the packages needed in each notebook, including\n  every package found in `## Discover All Packages Needed by the Notebook` above, by\n  installing and pinning down the packages\n- For each notebook we want to add after the first call with\n\n  ```\n  %load_ext autoreload\n  %autoreload 2\n\n  import logging\n  ```\n\n  a cell with content like:\n\n  ```\n  !pip install -q python-sat==1.9.dev15 sympy==1.14.0 z3-solver==5.1.0.0\n\n  import pysat\n  print(\"pysat version: \", pysat.__version__)\n  import sympy\n  print(\"sympy version: \", sympy.__version__)\n  import z3\n  print(\"z3 version: \", z3.get_version_string())\n  ```\n\n## Sync Notebook\n\n- At the end, sync the paired `.py` file with Jupytext following the conventions in\n  `# Code Architecture and Responsibility` ->\n  `## Utilities vs. Notebook Responsibilities` in `.claude\u002Fskills\u002Fnotebook.rules.md`\n\n# Verification\n\n- [ ] Every third-party import in the notebook and its paired `*_utils.py` file has a\n      matching entry in `requirements.txt` and in the notebook's `pip install` cell\n- [ ] Build the docker container with `docker_build.sh` inside the target dir\n      `\u003CTARGET_DIR>`\n- [ ] Make sure the container builds correctly and it's the same as the Docker\n      container for the project, if possible\n- [ ] Run each notebook inside the docker container with `docker_cmd.sh` and\n      `nbconvert` to make sure they run correctly end-to-end\n\n# Conventions\n\n- Always follow the conventions and guidelines in `.claude\u002Fskills\u002Fnotebook.rules.md`","# Goal\n\n- When creating Docker images for projects and tutorials, we want to\n  - Try to use always the same Docker template image from the `class_project` to\n    avoid replication of Docker containers\n  - Install the needed packages in the notebooks to customize the container\n\n## Inputs\n\n- The user passes:\n  - A pointer to a target directory `\u003CTARGET_DIR>` (e.g.,\n    `msml610\u002Ftutorials\u002FL03_knowledge_representation`) that was cloned from\n    `class_project\u002Fproject_template`\n  - (Optional) pointers to Jupyter notebooks\n\n# Workflow\n\n## Use the Docker Container From the Project Teamplate\n\n- In the directory with the project (e.g.,\n  `msml610\u002Ftutorials\u002FL03_knowledge_representation`) we want to use the same\n  `Dockerfile` and `requirements.txt` as the corresponding files in\n  `class_project\u002Fproject_template` (so that the Docker container for the project is\n  the same as the template used for class project)\n- If something needs to be added to the Docker image (e.g., a package that can't be\n  installed with `pip`) then it's ok to add it to `Dockerfile` but it should be\n  clearly commented why that package is needed\n\n## Discover All Packages Needed by the Notebook\n\n- A notebook's own `import` lines are not the full picture: each notebook is paired\n  with a `*_utils.py` file (e.g., `L03_06_logic_solvers.ipynb` ->\n  `L03_06_logic_solvers_utils.py`), and that file is imported with a line like:\n\n  ```\n  import L03_06_logic_solvers_utils as utils\n  ```\n\n- Read the `*_utils.py` file (and any other local module it imports, transitively)\n  and collect every third-party `import` \u002F `from ... import` statement in it, not\n  just the ones in the notebook itself\n- Map import names to their pip package name where they differ (e.g., `cv2` ->\n  `opencv-python`, `sklearn` -> `scikit-learn`, `PIL` -> `Pillow`, `yaml` ->\n  `PyYAML`)\n- Diff this full package list against `requirements.txt` and `Dockerfile`: any\n  package used by the notebook or its utils file that is missing from both is a bug,\n  even if it happens to already be installed in whatever container was used to author\n  the notebook\n- Add every missing package to `requirements.txt` (and to `Dockerfile` only if it\n  can't be installed with `pip`, per\n  `## Use the Docker Container from the Project Teamplate` above)\n\n## Add Packages to Notebooks\n\n- Then we want to add `pip install` the packages needed in each notebook, including\n  every package found in `## Discover All Packages Needed by the Notebook` above, by\n  installing and pinning down the packages\n- For each notebook we want to add after the first call with\n\n  ```\n  %load_ext autoreload\n  %autoreload 2\n\n  import logging\n  ```\n\n  a cell with content like:\n\n  ```\n  !pip install -q python-sat==1.9.dev15 sympy==1.14.0 z3-solver==5.1.0.0\n\n  import pysat\n  print(\"pysat version: \", pysat.__version__)\n  import sympy\n  print(\"sympy version: \", sympy.__version__)\n  import z3\n  print(\"z3 version: \", z3.get_version_string())\n  ```\n\n## Sync Notebook\n\n- At the end, sync the paired `.py` file with Jupytext following the conventions in\n  `# Code Architecture and Responsibility` ->\n  `## Utilities vs. Notebook Responsibilities` in `.claude\u002Fskills\u002Fnotebook.rules.md`\n\n# Verification\n\n- [ ] Every third-party import in the notebook and its paired `*_utils.py` file has a\n      matching entry in `requirements.txt` and in the notebook's `pip install` cell\n- [ ] Build the docker container with `docker_build.sh` inside the target dir\n      `\u003CTARGET_DIR>`\n- [ ] Make sure the container builds correctly and it's the same as the Docker\n      container for the project, if possible\n- [ ] Run each notebook inside the docker container with `docker_cmd.sh` and\n      `nbconvert` to make sure they run correctly end-to-end\n\n# Conventions\n\n- Always follow the conventions and guidelines in `.claude\u002Fskills\u002Fnotebook.rules.md`",{"model":29,"description":7},"master","39143a859859181eff7e774457997b5278fd9e99",".claude\u002Fskills\u002Fnotebook.fix_packages",170,"https:\u002F\u002Fgithub.com\u002Fcausify-ai\u002Fhelpers","https:\u002F\u002Fcausify.ai","https:\u002F\u002Fgithub.com\u002Fcausify-ai","2026-11-02 02:09:15",{"source":8,"skillName":5,"commands":44,"prompt":54,"zipAvailable":55},[45,48,51],{"tool":46,"command":47},"npx","npx skills add causify-ai\u002Fhelpers --skill notebook.fix_packages",{"tool":49,"command":50},"bunx","bunx skills add causify-ai\u002Fhelpers --skill notebook.fix_packages",{"tool":52,"command":53},"pnpm","pnpm dlx skills add causify-ai\u002Fhelpers --skill notebook.fix_packages","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fcausify-ai\u002Fhelpers\u002Fblob\u002Fmaster\u002F.claude\u002Fskills\u002Fnotebook.fix_packages\u002FSKILL.md",true,[57],{"path":58,"resourceType":59,"resourceTypeDesc":60,"sizeBytes":61,"sourceHtmlUrl":62},"references\u002Ffields.md","REFERENCE","参考文档",116,"https:\u002F\u002Fgithub.com\u002Fsiddsachar\u002Frow-bot\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fdata_dirs\u002Fv5_0_0\u002Fskills\u002Fpdf_toolkit\u002Freferences\u002Ffields.md",[64,76,93,104,113,122],{"skillNo":65,"name":66,"nameZh":6,"description":67,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":68,"categories":69,"keywords":71,"publishedAt":30},"01M6C9ZMM0XSXCHHABMJ9XB1JB","tutorial_in_60_mins.propagate_docker_changes","Sync tutorial and class-project Docker files to match project_template","https:\u002F\u002Fgithub.com\u002Fcausify-ai\u002Fhelpers\u002Fblob\u002Fmaster\u002F.claude\u002Fskills\u002Ftutorial_in_60_mins.propagate_docker_changes\u002FSKILL.md",[70],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[72,73,27,74,29,28,75],"tutorial in 60 mins propagate docker changes","tutorial","files","sync",{"skillNo":77,"name":78,"nameZh":6,"description":79,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":80,"categories":81,"keywords":85,"publishedAt":30},"01M6C9ZJK8QJ9FNCY39WVF3GMG","tutorial_in_60_mins.merge_markdown","Merge the content of a markdown file into a Jupyter notebook","https:\u002F\u002Fgithub.com\u002Fcausify-ai\u002Fhelpers\u002Fblob\u002Fmaster\u002F.claude\u002Fskills\u002Ftutorial_in_60_mins.merge_markdown\u002FSKILL.md",[82],{"categoryNo":83,"categoryName":84,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000002","文档处理",[86,87,73,88,89,29,90,91,92],"merge","tutorial in 60 mins merge markdown","markdown","jupyter","file","content","jupyter notebook",{"skillNo":94,"name":95,"nameZh":6,"description":96,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":97,"categories":98,"keywords":99,"publishedAt":30},"01M6C9ZFYK13ZCT1E8BEEC4NG4","tutorial_in_60_mins.format","Format a directory to follow the \"Learn X in 60 Minutes\" tutorial conventions","https:\u002F\u002Fgithub.com\u002Fcausify-ai\u002Fhelpers\u002Fblob\u002Fmaster\u002F.claude\u002Fskills\u002Ftutorial_in_60_mins.format\u002FSKILL.md",[],[100,73,101,102,103,29],"tutorial in 60 mins format","format","directory","learn",{"skillNo":105,"name":106,"nameZh":6,"description":107,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":108,"categories":109,"keywords":110,"publishedAt":30},"01M6C9ZDKXSBKNKX7M3X4W38G5","tutorial_in_60_mins.create","Create a tutorial directory for the Learn X in 60 Minutes conventions","https:\u002F\u002Fgithub.com\u002Fcausify-ai\u002Fhelpers\u002Fblob\u002Fmaster\u002F.claude\u002Fskills\u002Ftutorial_in_60_mins.create\u002FSKILL.md",[],[111,73,112,102,103],"tutorial in 60 mins create","create",{"skillNo":114,"name":115,"nameZh":6,"description":116,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":117,"categories":118,"keywords":119,"publishedAt":30},"01M6BZS5Z0QE03WRS1TM3XJEY9","todo.reorg_in_progress","Reorganize ai_task_queue.md so in-progress tasks, not-started tasks, and mislabeled topic headers sit under the right H1 stage","https:\u002F\u002Fgithub.com\u002Fcausify-ai\u002Fhelpers\u002Fblob\u002Fmaster\u002F.claude\u002Fskills\u002Ftodo.reorg_in_progress\u002FSKILL.md",[],[120,121],"todo reorg in progress","tasks",{"skillNo":123,"name":124,"nameZh":6,"description":125,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":126,"categories":127,"keywords":128,"publishedAt":30},"01M6BZS4CQZ6KK2KQ26SVB7QCS","todo.reorg_headers","Reorganize ai_task_queue.md .md so every H2 topic matches ALL TOPICS and every H3 task sits under the right topic, keeping its H1 stage","https:\u002F\u002Fgithub.com\u002Fcausify-ai\u002Fhelpers\u002Fblob\u002Fmaster\u002F.claude\u002Fskills\u002Ftodo.reorg_headers\u002FSKILL.md",[],[129],"todo reorg headers"]