{"id":36452246,"url":"https://github.com/oblq/tmi","last_synced_at":"2026-01-17T02:58:09.584Z","repository":{"id":57608994,"uuid":"253132405","full_name":"oblq/tmi","owner":"oblq","description":"Control fan speeds with IPMI or Corsair Commander Pro based on temperature sensors (CPU, GPU...) with hot-reloading of configuration files on changes.","archived":false,"fork":false,"pushed_at":"2021-09-05T09:20:28.000Z","size":5512,"stargazers_count":10,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-12T00:33:35.645Z","etag":null,"topics":["corsair-commander-pro","fan","fancontrol","ipmi","ipmitool"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oblq.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-04-05T01:26:46.000Z","updated_at":"2025-01-03T19:20:44.000Z","dependencies_parsed_at":"2022-08-27T20:01:57.032Z","dependency_job_id":null,"html_url":"https://github.com/oblq/tmi","commit_stats":null,"previous_names":["oblq/ipmifc"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/oblq/tmi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oblq%2Ftmi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oblq%2Ftmi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oblq%2Ftmi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oblq%2Ftmi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oblq","download_url":"https://codeload.github.com/oblq/tmi/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oblq%2Ftmi/sbom","scorecard":{"id":701083,"data":{"date":"2025-08-11","repo":{"name":"github.com/oblq/tmi","commit":"27b8aff64beccd2602bdcb3e233de354d4ea6024"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.5,"checks":[{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Code-Review","score":0,"reason":"Found 0/16 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":7,"reason":"binaries present in source code","details":["Warn: binary detected: artifacts/bin/ipmifc-darwin-amd64:1","Warn: binary detected: artifacts/bin/ipmifc-linux-386:1","Warn: binary detected: artifacts/bin/ipmifc-linux-amd64:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2022-0603 / GHSA-hp87-p4gw-j4gq"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T05:13:49.914Z","repository_id":57608994,"created_at":"2025-08-22T05:13:49.915Z","updated_at":"2025-08-22T05:13:49.915Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28492593,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T02:39:23.645Z","status":"ssl_error","status_checked_at":"2026-01-17T02:34:19.649Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["corsair-commander-pro","fan","fancontrol","ipmi","ipmitool"],"created_at":"2026-01-11T22:57:49.234Z","updated_at":"2026-01-17T02:58:09.565Z","avatar_url":"https://github.com/oblq.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TMI (Thermal Management Interface)\n\n***tmi*** is a simple program to remotely (or locally) control fan/pump speeds using IPMI (Intelligent Platform Management Interface) and/or a Corsair Commander Pro, based on the readings of temperature sensors (CPU, GPU or any sensor you can grab via command line).  \nSimply install it and tweaks config files as needed, they will be hot-reloaded automatically after saving changes.\n\n#### Disclaimer\n\u003e __WARNING__: ***tmi*** is not an official Corsair product. Corsair and Corsair Commander Pro are trademarks or registered trademarks of Corsair Components, Inc. The trademark holders are not affiliated with the maker of this product and do not endorse this product.  \nThis project is born because I wanted to handle the thermal/acoustic behaviour of my personal workstation so it is not intended to be used in production environments.  \nThis program is of public domain and provided as-is, without any warranty whatsoever.  \nIt has only been tested on a SuperMicro X11SPA-TF motherboard running Ubuntu 18.04 and 19.10.  \n***tmi*** sends raw IPMI commands to your IPMI device and to the Commander Pro and may not work on your platform without some modifications.  \n**USE AT YOUR OWN RISK**.\n\n## Features\n- control ipmi fan zones duty-cycle.\n- control ipmi fans thresholds.\n- get ipmi temperature from sensors.\n- control Commander Pro fans duty-cycle.\n- control Commander Pro leds (basic control).\n- get Commander Pro temp from sensors.\n- get temp from any custom CLI command.\n\n\n## Requirements\nPrecompiled executable are inside artifacts dir, config files must reside in the working dir if you use these ...or you can build it for yourself if you have `go` installed using the included makefile for convenience.  \n\n\n- `ipmitool` to use IPMI. \n- `libusb-1.0` to communicate with the Corsair Commander Pro. \n\n## Quick start\n\n#### Ubuntu / Debian:\nSimply use the makefile and adjust the three config files according to your needs:\n```sh\nsudo make install_linux path=/opt/tmi\n```\nThis will:\n- Build the executable for the current platform to the specified path (eg.:/opt/tmi).\n- Copy the config files to the same path (will not be overwritten if exist).\n- Install `ipmitool` if not already installed.\n- Setup a systemd service (tmi), enable and start it. \n\n![service](tmi.png)\n\nAt this point you just have to play with the configs ([`tmi.yaml`](artifacts/tmi.yaml), [`ipmi.yaml`](artifacts/ipmi.yaml) and [`commanderpro.yaml`](artifacts/commanderpro.yaml)) which has been copied in '/opt/tmi'.  \nThey will be reloaded automatically after saving changes, just wait for the next check cycle (check_interval is defined in the tmi.yaml config itself).  \nYou can monitor `tmi` status at any time with:\n````bash\njournalctl -f -u tmi\n````\n\n#### Other platforms:\n1. Ensure target machine has `ipmitool` and `libusb` installed.  \n    On OSX use brew:\n    ```bash\n    brew install ipmitool\n    brew install libusb\n    ```\n2. If you have `go` installed build the executable and copy the configs to the desired path.\n    ```sh\n    sudo make build path=/opt/tmi\n    ```\n   ...otherwise manually copy the right precompiled executable and both config files in the same destination path.\n3. Run the executable as a daemon.\n4. Monitor its stdout.\n5. Stress your machine to see if it works!\n\n## Configuration \u0026 Usage\n\nThree config files are required for `tmi` to run.  \nAnytime you save some changes the configs are hot-reloaded (separately).  \nThe configuration options are documented in the sample files.\n\n[`tmi.yaml`](artifacts/tmi.yaml):  \n\n```yaml\n# disable the modules that you don't use.\nactive_modules:\n  ipmi: true\n  commanderpro: true\n\n# Number of seconds to sleep between checks.\n# Check configuration changes and sensors data every x seconds.\ncheck_interval: 6\n\n# Create a targets map to be used as reference inside the controllers configuration below.\n# \u003carbitrary_name\u003e: \u003cfan_controller\u003e.\u003cfan_controller_channel\u003e\ntargets_map:\n  pump: ipmi.0\n  side: commanderpro.0\n  top: commanderpro.1\n  front: commanderpro.2\n  rear: commanderpro.3\n\ncontrollers:\n\n  # name is arbitrary, will be printed in logs.\n  - name: CPU\n    # The minimum change in °C from the last update to actually cause another fan speed change.\n    min_temp_change: 4\n    # IPMI sensor entityID to look for.\n    # Get the ipmi sensor entityID with: `sudo ipmitool sdr elist full` at the fourth column in result.\n    # ... or with: `sudo ipmitool sensor get \u003csensor_id\u003e` (eg.: sudo ipmitool sensor get 'CPU Temp')\n    temp:\n      # commanderpro, ipmi, cli\n      method: ipmi\n      # commanderpro: sensor_channel (uint8 as string), ipmi: entityID, cli: custom_command\n      arg: 3.1\n    # Control multiple target zones with the same sensor...\n    targets:\n      pump:\n        0:  30\n        36: 50\n        54: 72\n        60: 100\n      side:\n        0: 0\n        35: 30\n        45: 50\n        55: 75\n        65: 100\n      top:\n        0: 18\n        35: 30\n        45: 50\n        55: 75\n        65: 100\n\n  - name: GPU\n    min_temp_change: 2\n    # CLI command to extract NVIDIA GPU temp.\n    # Should return a string representing a valid float number,\n    # leading and trailing spaces will be automatically removed.\n    temp:\n      method: cli\n      arg: nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader\n    targets:\n      pump:\n        0: 30\n        45: 50\n        55: 75\n        65: 100\n      side:\n        0: 0\n        35: 30\n        45: 50\n        55: 75\n        65: 100\n      top:\n        0: 18\n        35: 30\n        45: 50\n        55: 75\n        65: 100\n\n  - name: PCH\n    min_temp_change: 3\n    # temp_corsair_channel grab the temperature from a channel of the corsair commander pro\n    temp:\n      method: ipmi\n      arg: 7.1\n    targets:\n      front:\n        0: 34\n        56: 70\n        63: 100\n      rear:\n        0: 18\n        53: 30\n        56: 50\n        63: 100\n```\n## License\n\ntmi is available under the MIT license. See the [LICENSE](./LICENSE) file for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foblq%2Ftmi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foblq%2Ftmi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foblq%2Ftmi/lists"}