{"id":25265804,"url":"https://github.com/timopruesse/machine_setup","last_synced_at":"2026-04-07T22:01:17.518Z","repository":{"id":39643891,"uuid":"469520062","full_name":"timopruesse/machine_setup","owner":"timopruesse","description":"Manage your machine setup.","archived":false,"fork":false,"pushed_at":"2026-04-07T20:24:41.000Z","size":563,"stargazers_count":17,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-07T20:26:44.619Z","etag":null,"topics":["command-line-tool","config","configuration","dotfiles","environment","setup","setup-development-environment"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/timopruesse.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-03-13T23:22:30.000Z","updated_at":"2026-04-07T20:24:45.000Z","dependencies_parsed_at":"2024-01-20T14:25:49.919Z","dependency_job_id":"27381209-6398-43eb-a8e5-8fbcbd9a3c59","html_url":"https://github.com/timopruesse/machine_setup","commit_stats":{"total_commits":358,"total_committers":2,"mean_commits":179.0,"dds":0.2039106145251397,"last_synced_commit":"a7bcbf7a79fcb6ef41084317b8e69a5863d22202"},"previous_names":["chroma91/machine-setup"],"tags_count":43,"template":false,"template_full_name":null,"purl":"pkg:github/timopruesse/machine_setup","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timopruesse%2Fmachine_setup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timopruesse%2Fmachine_setup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timopruesse%2Fmachine_setup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timopruesse%2Fmachine_setup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/timopruesse","download_url":"https://codeload.github.com/timopruesse/machine_setup/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timopruesse%2Fmachine_setup/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31530647,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T16:28:08.000Z","status":"ssl_error","status_checked_at":"2026-04-07T16:28:06.951Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5: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":["command-line-tool","config","configuration","dotfiles","environment","setup","setup-development-environment"],"created_at":"2025-02-12T08:22:21.735Z","updated_at":"2026-04-07T22:01:17.502Z","avatar_url":"https://github.com/timopruesse.png","language":"Rust","readme":"# Machine Setup\n\n[![Tests](https://github.com/timopruesse/machine_setup/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/timopruesse/machine_setup/actions/workflows/test.yml)\n[![Builds](https://github.com/timopruesse/machine_setup/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/timopruesse/machine_setup/actions/workflows/build.yml)\n[![Crates.io](https://img.shields.io/crates/v/machine_setup)](https://crates.io/crates/machine_setup)\n\nThe idea is to be able to replicate a certain setup (when resetting your machine or using a completely new machine).\nAdditionally, it should be possible to update the setup easily when needed, e.g. an update to your vim config files.\nSo, it will help with managing dotfiles, symlinks, etc.\n\nA real world example can be found in my [.dotfiles repository](https://github.com/timopruesse/.dotfiles/blob/main/machine_setup.yaml).\n\nYou can also use it for other tasks such as making the onboarding process of a new colleague easier by providing them a config that installs certain dependencies and checks out important repositories.\n\n## What's New in v2\n\n- **TUI Dashboard**: Real-time progress display with task list, per-task log output, and keyboard navigation. Powered by [ratatui](https://ratatui.rs/). Disable with `--no-tui` for CI environments.\n- **Async Engine**: Task execution powered by [tokio](https://tokio.rs/) for proper concurrent I/O (file ops, git, shell commands with streaming output).\n- **Task History**: Tracks install/update/uninstall timestamps in `~/.machine_setup/history.json`. Already-installed tasks are skipped unless `--force` is used.\n- **PowerShell Support**: Use `powershell` as a shell option alongside `bash` and `zsh`.\n- **Remote Configs**: Point directly at a URL instead of a local file — great for bootstrapping a clean machine without cloning first.\n\n## Install\n\n### Quick Install (no dependencies needed)\n\n**macOS / Linux:**\n\n```sh\ncurl -fsSL https://raw.githubusercontent.com/timopruesse/machine_setup/main/install/install.sh | sh\n```\n\n**Windows (PowerShell):**\n\n```powershell\nirm https://raw.githubusercontent.com/timopruesse/machine_setup/main/install/install.ps1 | iex\n```\n\n### Other methods\n\n**Via Homebrew (macOS / Linux):**\n\n```bash\nbrew install timopruesse/repo/machine_setup\n```\n\n**Via Cargo:**\n\n```bash\ncargo install machine_setup\n```\n\n**Manual download:** Grab a binary from the [release page](https://github.com/timopruesse/machine_setup/releases).\n\n## Run\n\n### Subcommands\n\n| command   | description                   | example                    |\n| --------- | ----------------------------- | -------------------------- |\n| install   | install the defined tasks     | `machine_setup install`    |\n| update    | update the defined tasks      | `machine_setup update`     |\n| uninstall | uninstall the defined tasks   | `machine_setup uninstall`  |\n| list      | list all of the defined tasks | `machine_setup list`       |\n\nBy default, `machine_setup` will look for a file called `machine_setup` with a supported file format.\nSupported file formats are: `yaml`, `yml`, and `json`.\n\n### Command line parameters\n\n| flag              | value                                             | example                                            |\n| ----------------- | ------------------------------------------------- | -------------------------------------------------- |\n| -c\u003cbr\u003e --config   | path or URL to the config file                    | `machine_setup install -c ./config/my_setup.yaml`  |\n| -t\u003cbr\u003e --task     | only run the specified task                       | `machine_setup install -t my_task2`                |\n| -s\u003cbr\u003e --select   | select a task to run                              | `machine_setup install -s`                         |\n| -f\u003cbr\u003e --force    | force execution (bypass history checks)           | `machine_setup install --force`                    |\n| --no-tui          | disable TUI, use plain log output                 | `machine_setup install --no-tui`                   |\n| -h\u003cbr\u003e --help     | display help information                          | `machine_setup --help`                             |\n| -v\u003cbr\u003e --version  | display version information                       | `machine_setup --version`                          |\n| -d\u003cbr\u003e --debug    | print additional debug information                | `machine_setup install --debug`                    |\n| -l\u003cbr\u003e --level    | set a log level (info, warn, error, debug, trace) | `machine_setup install --level=info`               |\n\n### Remote config files\n\nYou can pass a URL instead of a local path — the config is fetched and executed directly. GitHub blob URLs are automatically converted to raw URLs.\n\n```bash\nmachine_setup install -c https://github.com/timopruesse/.dotfiles/blob/main/machine_setup.yaml\n```\n\nThis is especially useful for setting up a fresh machine without cloning your dotfiles first:\n\n```bash\n# Install machine_setup\ncurl -fsSL https://raw.githubusercontent.com/timopruesse/machine_setup/main/install/install.sh | sh\n\n# Run your dotfiles setup directly from GitHub\nmachine_setup install -c https://github.com/timopruesse/.dotfiles/blob/main/machine_setup.yaml\n```\n\n### TUI Dashboard\n\nWhen running in an interactive terminal, a TUI dashboard is shown with:\n- Task list with status indicators (pending, running, completed, failed, skipped)\n- Per-task scrollable log output\n- Progress bar with completion stats\n- Keyboard navigation: `Up/Down` to navigate tasks, `PgUp/PgDn` to scroll logs, `q` to quit\n\nThe TUI is automatically disabled in non-interactive environments (piped output, CI). You can also explicitly disable it with `--no-tui`.\n\n### Supported config file formats\n\nThe supported formats are `YAML` and `JSON`.\n\n## Configure\n\nTasks can be defined under the `tasks` root key.\nEvery task can contain an arbitrary number of commands.\n\n| key           | description                                          | values                       | default                      |\n| ------------- | ---------------------------------------------------- | ---------------------------- | ---------------------------- |\n| tasks         | root key for all of the tasks                        |                              |                              |\n| default_shell | shell that is used when not specified by the command  | `bash`, `zsh`, `powershell`  | `bash`                       |\n| temp_dir      | define where temporary files are stored              |                              | `~/.machine_setup`           |\n| parallel      | run all of the tasks in parallel                     | `true` or `false`            | `false`                      |\n| num_threads   | number of threads when run in parallel               | numeric \u003e 1                  | physical processor count - 1 |\n\n### Task specific configuration\n\n| key      | description                                                | values                                                                       | examples                      |\n| -------- | ---------------------------------------------------------- | ---------------------------------------------------------------------------- | ----------------------------- |\n| os       | only run on the specified os                               | [possible values](https://doc.rust-lang.org/std/env/consts/constant.OS.html) | \"linux\" or [\"linux\", \"macos\"] |\n| parallel | run all of the commands in parallel (1 thread per command) | `true` or `false`                                                            | `false`                       |\n\nCheck out the example configuration below:\n\n```yaml\ntemp_dir: \"~/my_temp\" # defaults to \"~/.machine_setup\"\ndefault_shell: \"zsh\" # defaults to \"bash\"\nparallel: true\nnum_threads: 2\ntasks:\n  my_task1:\n    os: [\"linux\", \"windows\"]\n    parallel: true\n    commands:\n      - copy:\n          src: \"./src/files\"\n          target: \"/tmp/target\"\n      - copy:\n          src: \"./src/files_2\"\n          target: \"/tmp/target\"\n\n  my_task2:\n    os: [\"linux\"]\n    parallel: true\n    commands:\n      - run:\n          commands: \"sudo apt-get install git -y\"\n      - symlink:\n          src: \"./src/config\"\n          target: \"~/.dotfiles\"\n```\n\n### Extend a configuration\n\nExtensibility is not explicitly built in.\nHowever, it's possible to execute tasks from another configuration via the [machine_setup](#machine_setup) command.\n\n### Available config commands\n\n#### copy\n\nThis command copies the contents of a directory to another directory.\n\n| argument | value                               | required | example                                |\n| -------- | ----------------------------------- | :------: | -------------------------------------- |\n| src      | source directory/file               |    Y     | \"./src/files\" or \"./src/test.txt\"      |\n| target   | target directory/file               |    Y     | \"/tmp/target\" or \"/tmp/target/new.txt\" |\n| ignore   | list of files/directories to ignore |    -     | [\"dist\", \"package-lock.json\"]          |\n| sudo     | run file operations with sudo       |    -     | true                                   |\n\n##### example\n\n```yaml\ncopy:\n  src: \"./src/files\"\n  target: \"/tmp/target\"\n  ignore: [\"dist\", \"package-lock.json\"]\n\n# Copy to a protected path\ncopy:\n  src: \"./etc/wsl.conf\"\n  target: \"/etc/wsl.conf\"\n  sudo: true\n```\n\n#### clone\n\nThis command clones a git repository to the specified destination.\n\n| argument | value                   | required | example                                        |\n| -------- | ----------------------- | :------: | ---------------------------------------------- |\n| url      | URL to a git repository |    Y     | \"git@github.com:timopruesse/machine_setup.git\" |\n| target   | target directory        |    Y     | \"~/machine_setup\"                              |\n\n##### example\n\n```yaml\nclone:\n  url: \"git@github.com:timopruesse/machine_setup.git\"\n  target: \"~/machine_setup\"\n```\n\n#### symlink\n\nThis command symlinks all the files from the source directory to the target directory.\n\n| argument | value                               | required | example                           |\n| -------- | ----------------------------------- | :------: | --------------------------------- |\n| src      | source directory/file               |    Y     | \"./src/files\" or \"./src/test.txt\" |\n| target   | target directory/file               |    Y     | \"/tmp/target\" or \"/tmp/new.txt\"   |\n| ignore   | list of files/directories to ignore |    -     | [\"dist\", \"package-lock.json\"]     |\n| force    | true/false                          |    -     |                                   |\n| sudo     | run file operations with sudo       |    -     | true                              |\n\n\u003e If `force` is set to `true`, existing files will be **removed** and replaced by the symlinks.\n\n##### example\n\n```yaml\nsymlink:\n  src: \"./src/files\"\n  target: \"/tmp/target\"\n  ignore: [\"dist\", \"package-lock.json\"]\n  force: true\n\n# Symlink to a protected path\nsymlink:\n  src: \"./etc/my.conf\"\n  target: \"/etc/my.conf\"\n  sudo: true\n  force: true\n```\n\n#### run\n\nThis command executes a shell command.\n\n\u003e Hint: Avoid the usage of interactive commands when possible.\n\n| argument | description           | required | default | values                       |\n| -------- | --------------------- | :------: | ------- | ---------------------------- |\n| env      | environment variables |    -     |         |                              |\n| shell    | shell that is used    |    -     | \"bash\"  | \"bash\", \"zsh\", \"powershell\"  |\n\nBy default, shell commands will only run during `install`.\nYou can provide mode-specific commands using `install`, `update`, and `uninstall` instead of `commands`:\n\n| argument  | description              | required | example                         |\n| --------- | ------------------------ | :------: | ------------------------------- |\n| commands  | commands for all modes   |    -     | \"sudo apt-get -y install git\"   |\n| install   | commands for installing  |    -     | \"sudo apt-get -y install git\"   |\n| update    | commands for updating    |    -     | \"sudo apt-get -y upgrade git\"   |\n| uninstall | commands for uninstalling|    -     | \"sudo apt-get -y uninstall git\" |\n\n\u003e Use either `commands` (runs on install only) or `install`/`update`/`uninstall` for mode-specific behavior. They are all top-level keys under `run`.\n\n##### example\n\n```yaml\ninline_command:\n  run:\n    commands: \"sudo apt-get -y install git\"\n\nmultiline_command:\n  run:\n    commands:\n      - \"sudo apt-get update\"\n      - \"sudo apt-get -y install git\"\n\nupdatable_command:\n  run:\n    env:\n      SOME_TOKEN: \"abc123\"\n    install: \"sudo apt-get -y install git\"\n    update: \"sudo apt-get -y upgrade git\"\n    uninstall: \"sudo apt-get -y uninstall git\"\n\nupdatable_multiline_command:\n  run:\n    env:\n      SOME_TOKEN: \"abc123\"\n    install:\n      - \"sudo apt update\"\n      - \"sudo apt-get -y install git\"\n    update:\n      - \"sudo apt-get -y upgrade git\"\n    uninstall:\n      - \"sudo apt-get -y uninstall git\"\n```\n\n#### machine_setup\n\nWith this command it's possible to include other `machine_setup` configuration files.\n\n| argument | description                             | required | example                  |\n| -------- | --------------------------------------- | :------: | ------------------------ |\n| config   | path to the other config file           |    Y     | \"./my_other_config.yaml\" |\n| task     | define a single task that should be run |    -     | \"my_other_task\"          |\n\n##### example\n\n```yaml\nmachine_setup:\n  config: \"./my_other_config.yaml\"\n  task: \"my_other_task\" # optional\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimopruesse%2Fmachine_setup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftimopruesse%2Fmachine_setup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimopruesse%2Fmachine_setup/lists"}