{"id":16715087,"url":"https://github.com/captncodr/fli","last_synced_at":"2025-03-17T01:31:12.524Z","repository":{"id":60384473,"uuid":"541595576","full_name":"CaptnCodr/Fli","owner":"CaptnCodr","description":"Execute CLI commands from your F# code in F# style!","archived":false,"fork":false,"pushed_at":"2024-04-16T13:11:27.000Z","size":813,"stargazers_count":147,"open_issues_count":3,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-05-15T21:02:06.834Z","etag":null,"topics":["cli","command-line","computation-expressions","fsharp","process","shell"],"latest_commit_sha":null,"homepage":"","language":"F#","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/CaptnCodr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","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},"funding":{"github":"CaptnCodr"}},"created_at":"2022-09-26T13:16:00.000Z","updated_at":"2024-05-29T07:24:25.200Z","dependencies_parsed_at":"2024-04-16T14:32:29.939Z","dependency_job_id":null,"html_url":"https://github.com/CaptnCodr/Fli","commit_stats":{"total_commits":85,"total_committers":1,"mean_commits":85.0,"dds":0.0,"last_synced_commit":"ec9e8c55a67b48b00c8946821b99ee9145d9fac3"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaptnCodr%2FFli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaptnCodr%2FFli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaptnCodr%2FFli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaptnCodr%2FFli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CaptnCodr","download_url":"https://codeload.github.com/CaptnCodr/Fli/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243835959,"owners_count":20355613,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["cli","command-line","computation-expressions","fsharp","process","shell"],"created_at":"2024-10-12T21:08:20.419Z","updated_at":"2025-03-17T01:31:12.146Z","avatar_url":"https://github.com/CaptnCodr.png","language":"F#","readme":"# Fli\n[![build](https://github.com/CaptnCodr/Fli/actions/workflows/build.yml/badge.svg)](https://github.com/CaptnCodr/Fli/actions/workflows/build.yml)\n[![Nuget](https://img.shields.io/nuget/v/fli?color=33cc56)](https://www.nuget.org/packages/Fli/)\n\u003cimg align=\"right\" width=\"100\" src=\"https://raw.githubusercontent.com/CaptnCodr/Fli/main/logo.png\"\u003e\n\nExecute CLI commands from your F# code in F# style!\n\n**Fli is part of the F# Advent Calendar 2022: [A little story about Fli](https://gist.github.com/CaptnCodr/d709b30eb1191bedda090623d04bf738)**\n\n### Features\n- Starting processes easily\n- Execute CLI commands in your favourite shell\n- F# computation expression syntax\n- Wrap authenticated CLI tools\n- No external dependencies\n\n### Install\nGet it from [Nuget](https://www.nuget.org/packages/Fli/): `dotnet add package Fli`\n\n### Usage\n`open Fli` and start\n\nFor example:\n```fsharp\ncli {\n    Shell CMD\n    Command \"echo Hello World!\"\n}\n|\u003e Command.execute\n```\nthat starts `CMD.exe` as Shell and `echo Hello World!` is the command to execute.\n\nRun a file with PowerShell from a specific directory:\n```fsharp\ncli {\n    Shell PWSH\n    Command \"test.bat\"\n    WorkingDirectory (Environment.GetFolderPath Environment.SpecialFolder.UserProfile)\n}\n|\u003e Command.execute\n```\n\nExecuting programs with arguments:\n```fsharp\ncli {\n    Exec \"path/to/executable\"\n    Arguments \"--info\"\n}\n|\u003e Command.execute\n```\n\nan example with `git`:\n```fsharp\ncli {\n    Exec \"git\"\n    Arguments [\"commit\"; \"-m\"; \"\\\"Fixing issue #1337.\\\"\"]\n}\n|\u003e Command.execute\n```\n\nAdd a verb to your executing program:\n```fsharp\ncli {\n    Exec \"adobe.exe\"\n    Arguments (Path.Combine ((Environment.GetFolderPath Environment.SpecialFolder.UserProfile), \"test.pdf\"))\n    Verb \"open\"\n}\n|\u003e Command.execute\n```\nor open a file in the default/assigned program:\n```fsharp\ncli {\n    Exec \"test.pdf\"\n}\n|\u003e Command.execute\n```\n(Hint: if file extension is not assigned to any installed program, it will throw a `System.NullReferenceException`)\n\nWrite output to a specific file:\n```fsharp\ncli {\n    Exec \"dotnet\"\n    Arguments \"--list-sdks\"\n    Output @\"absolute\\path\\to\\dotnet-sdks.txt\"\n}\n|\u003e Command.execute\n```\n\nWrite output to a function (logging, printing, etc.):\n```fsharp\nlet log (output: string) = Debug.Log($\"CLI log: {output}\")\n\ncli {\n    Exec \"dotnet\"\n    Arguments \"--list-sdks\"\n    Output log\n}\n|\u003e Command.execute\n```\n\nAdd environment variables for the executing program:\n```fsharp\ncli {\n    Exec \"git\"\n    EnvironmentVariables [(\"GIT_AUTHOR_NAME\", \"Jon Doe\"); (\"GIT_AUTHOR_EMAIL\", \"jon.doe@domain.com\")]\n    Output \"\"\n}\n|\u003e Command.execute\n```\nHint: `Output \"\"` will be ignored. This is for conditional cases, e.g.: `Output (if true then logFilePath else \"\")`.\n\nAdd credentials to program:\n```fsharp\ncli {\n    Exec \"program\"\n    Credentials (\"domain\", \"bobk\", \"password123\")\n}\n|\u003e Command.execute\n```\nHint: Running a process as a different user is supported on all platforms. Other options (Domain, Password) are only available on Windows. As an alternative for not Windows based systems there is:\n```fsharp\ncli {\n    Exec \"path/to/program\"\n    Username \"admin\"\n}\n|\u003e Command.execute\n```\n\nFor Windows applications it's possible to set their visibility. There are four possible values: `Hidden`, `Maximized`, `Minimized` and `Normal`. The default is `Hidden`.\n```fsharp\ncli {\n    Exec @\"C:\\Windows\\regedit.exe\"\n    WindowStyle Normal\n}\n|\u003e Command.execute\n```\n\n#### `Command.execute`\n`Command.execute` returns record: `type Output = { Id: int; Text: string option; ExitCode: int; Error: string option }`\nwhich has getter methods to get only one value:\n```fsharp\ntoId: Output -\u003e int\ntoText: Output -\u003e string\ntoExitCode: Output -\u003e int\ntoError: Output -\u003e string\n```\nexample:\n```fsharp\ncli {\n    Shell CMD\n    Command \"echo Hello World!\"\n}\n|\u003e Command.execute // { Id = 123; Text = Some \"Hello World!\"; ExitCode = 0; Error = None }\n|\u003e Output.toText // \"Hello World!\"\n\n// same with Output.toId:\ncli { ... }\n|\u003e Command.execute // { Id = 123; Text = Some \"Hello World!\"; ExitCode = 0; Error = None }\n|\u003e Output.toId // 123\n\n// same with Output.toExitCode:\ncli { ... }\n|\u003e Command.execute // { Id = 123; Text = Some \"Hello World!\"; ExitCode = 0; Error = None }\n|\u003e Output.toExitCode // 0\n\n// in case of an error:\ncli { ... }\n|\u003e Command.execute // { Id = 123; Text = None; ExitCode = 1; Error = Some \"This is an error!\" }\n|\u003e Output.toError // \"This is an error!\"\n```\n\n#### `Output` functions\n```fsharp\nthrowIfErrored: Output -\u003e Output\nthrow: (Output -\u003e bool) -\u003e Output -\u003e Output\n```\n\n`Output.throw` and `Output.throwIfErrored` are assertion functions that if something's not right it will throw an exception.\nThat is useful for build scripts to stop the execution immediately, here is an example:\n```fsharp\ncli {\n    Exec \"dotnet\"\n    Arguments [| \"build\"; \"-c\"; \"Release\" |]\n    WorkingDirectory \"src/\"\n}\n|\u003e Command.execute // returns { Id = 123; Text = None; ExitCode = 1; Error = Some \"This is an error!\" }\n|\u003e Output.throwIfErrored // \u003c- Exception thrown!\n|\u003e Output.toError\n```\n\nor, you can define when to \"fail\":\n```fsharp\ncli { ... }\n|\u003e Command.execute // returns { Id = 123; Text = \"An error occured: ...\"; ExitCode = 1; Error = Some \"Error detail.\" }\n|\u003e Output.throw (fun output -\u003e output.Text.Contains(\"error\")) // \u003c- Exception thrown!\n|\u003e Output.toError\n```\n\n#### Printing `Output` fields\nThere are printing methods in `Output` too:\n```fsharp\nprintId: Output -\u003e unit\nprintText: Output -\u003e unit\nprintExitCode: Output -\u003e unit\nprintError: Output -\u003e unit\n```\n\nInstead of writing:\n```fsharp\ncli { ... }\n|\u003e Command.execute\n|\u003e Output.toText\n|\u003e printfn \"%s\"\n```\nFor a little shorter code you can use:\n```fsharp\ncli { ... }\n|\u003e Command.execute\n|\u003e Output.printText\n```\n\n#### `Command.toString`\n`Command.toString` concatenates only the executing shell/program + the given commands/arguments:\n```fsharp\ncli {\n    Shell PS\n    Command \"Write-Host Hello World!\"\n}\n|\u003e Command.toString // \"powershell.exe -Command Write-Host Hello World!\"\n```\nand:\n```fsharp\ncli {\n    Exec \"cmd.exe\"\n    Arguments [ \"/C\"; \"echo\"; \"Hello World!\" ]\n}\n|\u003e Command.toString // \"cmd.exe /C echo Hello World!\"\n```\n\n#### Builder operations:\n\n`ShellContext` operations (`cli { Shell ... }`):\n| Operation              |  Type                      |\n|------------------------|----------------------------|\n| `Shell`                | `Fli.Shells`               |\n| `Command`              | `string`                   |\n| `Input`                | `string`                   |\n| `Output`               | `Fli.Outputs`              |\n| `WorkingDirectory`     | `string`                   |\n| `WindowStyle`          | `Fli.WindowStyle`          |\n| `EnvironmentVariable`  | `string * string`          |\n| `EnvironmentVariables` | `(string * string) list`   |\n| `Encoding`             | `System.Text.Encoding`     |\n| `CancelAfter`          | `int`                      |\n\n`ExecContext` operations (`cli { Exec ... }`):\n| Operation              |  Type                                                    |\n|------------------------|----------------------------------------------------------|\n| `Exec`                 | `string`                                                 |\n| `Arguments`            | `string` / `string seq` / `string list` / `string array` |\n| `Input`                | `string`                                                 |\n| `Output`               | `Fli.Outputs`                                            |\n| `Verb`                 | `string`                                                 |\n| `Username`             | `string`                                                 |\n| `Credentials`          | `string * string * string`                               |\n| `WorkingDirectory`     | `string`                                                 |\n| `WindowStyle`          | `Fli.WindowStyle`                                        |\n| `EnvironmentVariable`  | `string * string`                                        |\n| `EnvironmentVariables` | `(string * string) list`                                 |\n| `Encoding`             | `System.Text.Encoding`                                   |\n| `CancelAfter`          | `int`                                                    |\n\nCurrently provided `Fli.Shells`:\n- `CMD` runs either `cmd.exe /c ...` or `cmd.exe /k ...` (if `Input` is provided)\n- `PS` runs `powershell.exe -Command ...`\n- `PWSH` runs `pwsh.exe -Command ...`\n- `WSL` runs `wsl.exe -- ...`\n- `SH` runs `sh -c ...`\n- `BASH` runs `bash -c ...`\n- `ZSH` runs `zsh -c ...`\n- `CUSTOM (shell: string * flag: string)` runs the specified `shell` with the specified starting argument (`flag`)\n\nProvided `Fli.Outputs`:\n- `File of string` a string with an absolute path of the output file.\n- `StringBuilder of StringBuilder` a StringBuilder which will be filled with the output text.\n- `Custom of Func\u003cstring, unit\u003e` a custom function (`string -\u003e unit`) that will be called with the output string (logging, printing etc.).\n\nProvided `Fli.WindowStyle`:\n- `Hidden` (default)\n- `Maximized`\n- `Minimized`\n- `Normal`\n\n### Do you miss something?\nOpen an [issue](https://github.com/CaptnCodr/Fli/issues) or start a [discussion](https://github.com/CaptnCodr/Fli/discussions).\n\n### Inspiration\nUse CE's for CLI commands came in mind while using [FsHttp](https://github.com/fsprojects/FsHttp).\n","funding_links":["https://github.com/sponsors/CaptnCodr"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcaptncodr%2Ffli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcaptncodr%2Ffli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcaptncodr%2Ffli/lists"}