[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6F1T7K8HC7ZWC47PEB6YVNN":3,"skill-same:01M6F1T7K8HC7ZWC47PEB6YVNN":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":36,"linkOnly":37,"markdownContent":38,"markdownBody":39,"frontMatter":40,"refName":41,"commitSha":42,"skillDirectory":43,"forksCount":44,"repositoryHtmlUrl":45,"repositoryHomepageUrl":46,"ownerHtmlUrl":47,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":48,"install":49,"resources":62},"01M6F1T7K8HC7ZWC47PEB6YVNN","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","01M6F1K6CCKKF8YKTBN4ZV509G",0,"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,30,31,32,33,34,35],"packages","notebook fix packages","fix","notebook","python","docker","template","haiku","install","container","keep","with","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":31,"description":7},"master","804ae3e928c04740cec553be0eb28c8d06ff420e",".claude\u002Fskills\u002Fnotebook.fix_packages",1,"https:\u002F\u002Fgithub.com\u002Fcausify-ai\u002Fhelpers","https:\u002F\u002Fcausify-ai.github.io\u002Fhelpers\u002F","https:\u002F\u002Fgithub.com\u002Fcausify-ai","2026-11-02 21:54:29",{"source":8,"skillName":5,"commands":50,"prompt":60,"zipAvailable":61},[51,54,57],{"tool":52,"command":53},"npx","npx skills add causify-ai\u002Fhelpers --skill notebook.fix_packages",{"tool":55,"command":56},"bunx","bunx skills add causify-ai\u002Fhelpers --skill notebook.fix_packages",{"tool":58,"command":59},"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,[],[64,79,96,108,117,131],{"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":36},"01M6F209RASRBEK7GBNG5M00K0","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},[29,72,73,74,30,75,31,76,77,78],"tutorial","tutorial in 60 mins propagate docker changes","propagate","sync","files","project","match",{"skillNo":80,"name":81,"nameZh":6,"description":82,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":83,"categories":84,"keywords":88,"publishedAt":36},"01M6F207XZ5YDAJ0KNDRE6EN0R","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",[85],{"categoryNo":86,"categoryName":87,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000002","文档处理",[89,90,72,91,27,92,31,93,94,95],"markdown","merge","tutorial in 60 mins merge markdown","jupyter","file","jupyter notebook","content",{"skillNo":97,"name":98,"nameZh":6,"description":99,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":100,"categories":101,"keywords":102,"publishedAt":36},"01M6F2059X95Q1A13HD67E9JRF","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",[],[103,72,104,105,106,31,107],"tutorial in 60 mins format","format","directory","learn","conventions",{"skillNo":109,"name":110,"nameZh":6,"description":111,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":112,"categories":113,"keywords":114,"publishedAt":36},"01M6F202MDHMNYD5S1YHG2PKZD","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",[],[115,72,116,106,105,107],"tutorial in 60 mins create","create",{"skillNo":118,"name":119,"nameZh":6,"description":120,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":121,"categories":122,"keywords":123,"publishedAt":36},"01M6F2004BW13GQ59N3RGSAYVN","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",[],[124,125,126,127,128,129,130],"progress","todo","todo reorg in progress","tasks","queue","task","stage",{"skillNo":132,"name":133,"nameZh":6,"description":134,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":135,"categories":136,"keywords":137,"publishedAt":36},"01M6F1ZXN0G6HBD08GT8HE5FYA","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",[],[138,125,128,129,130],"todo reorg headers"]