{"id":29251683,"url":"https://github.com/macrat/ayd","last_synced_at":"2026-01-23T05:48:29.141Z","repository":{"id":37039943,"uuid":"355532278","full_name":"macrat/ayd","owner":"macrat","description":"The easiest alive monitoring tool to check if your service is dead or alive","archived":false,"fork":false,"pushed_at":"2025-12-29T07:48:49.000Z","size":1541,"stargazers_count":4,"open_issues_count":3,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-01T05:29:19.560Z","etag":null,"topics":["alerting","ayd","monitoring","status-page"],"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/macrat.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,"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":"2021-04-07T12:13:07.000Z","updated_at":"2025-12-27T05:57:54.000Z","dependencies_parsed_at":"2023-02-13T21:17:00.162Z","dependency_job_id":"a76fb696-f4f4-4be1-8d3a-7849d04125c8","html_url":"https://github.com/macrat/ayd","commit_stats":null,"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"purl":"pkg:github/macrat/ayd","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macrat%2Fayd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macrat%2Fayd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macrat%2Fayd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macrat%2Fayd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/macrat","download_url":"https://codeload.github.com/macrat/ayd/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macrat%2Fayd/sbom","scorecard":{"id":609834,"data":{"date":"2025-08-11","repo":{"name":"github.com/macrat/ayd","commit":"00aeac3a876dc6e7f7a94b49cf86e5b6cd3850e9"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.8,"checks":[{"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":"Code-Review","score":0,"reason":"Found 0/6 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":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","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":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Info: no jobLevel write permissions found"],"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":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"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":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:41: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:44: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:54: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:57: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:65: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:68: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:73: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:89: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:90: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:91: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:94: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:99: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:137: update your workflow using https://app.stepsecurity.io/secureworkflow/macrat/ayd/ci.yml/main?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:4","Warn: containerImage not pinned by hash: Dockerfile:43","Info:   0 out of  11 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   9 third-party GitHubAction dependencies pinned","Info:   0 out of   2 containerImage dependencies pinned"],"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":"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":10,"reason":"project is fuzzed","details":["Info: GoBuiltInFuzzer integration found: internal/endpoint/log_fuzz_test.go:15","Info: GoBuiltInFuzzer integration found: internal/scheme/exec_internal_test.go:118","Info: GoBuiltInFuzzer integration found: internal/store/pattern_test.go:126","Info: GoBuiltInFuzzer integration found: lib-ayd/record_fuzz_test.go:12"],"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":"Branch-Protection","score":3,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'main'","Info: 'force pushes' disabled on branch 'main'","Warn: branch 'main' does not require approvers","Warn: codeowners review is not required on branch 'main'","Warn: no status checks found to merge onto branch 'main'"],"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":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v0.16.9 not signed: https://api.github.com/repos/macrat/ayd/releases/211996920","Warn: release artifact v0.16.8 not signed: https://api.github.com/repos/macrat/ayd/releases/199238992","Warn: release artifact v0.16.7 not signed: https://api.github.com/repos/macrat/ayd/releases/156076323","Warn: release artifact v0.16.6 not signed: https://api.github.com/repos/macrat/ayd/releases/138158663","Warn: release artifact v0.16.5 not signed: https://api.github.com/repos/macrat/ayd/releases/98623956","Warn: release artifact v0.16.9 does not have provenance: https://api.github.com/repos/macrat/ayd/releases/211996920","Warn: release artifact v0.16.8 does not have provenance: https://api.github.com/repos/macrat/ayd/releases/199238992","Warn: release artifact v0.16.7 does not have provenance: https://api.github.com/repos/macrat/ayd/releases/156076323","Warn: release artifact v0.16.6 does not have provenance: https://api.github.com/repos/macrat/ayd/releases/138158663","Warn: release artifact v0.16.5 does not have provenance: https://api.github.com/repos/macrat/ayd/releases/98623956"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/ci.yml:59"],"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":"SAST","score":10,"reason":"SAST tool is run on all commits","details":["Info: SAST configuration detected: CodeQL","Info: all commits (25) are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"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-21T02:22:25.280Z","repository_id":37039943,"created_at":"2025-08-21T02:22:25.280Z","updated_at":"2025-08-21T02:22:25.280Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28681326,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-23T05:48:07.525Z","status":"ssl_error","status_checked_at":"2026-01-23T05:48:07.129Z","response_time":59,"last_error":"SSL_read: 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":["alerting","ayd","monitoring","status-page"],"created_at":"2025-07-04T01:08:10.719Z","updated_at":"2026-01-23T05:48:29.130Z","avatar_url":"https://github.com/macrat.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Ayd](./assets/logo.svg)\n\n[![CI Test Status](https://github.com/macrat/ayd/actions/workflows/on-push-main.yaml/badge.svg)](https://github.com/macrat/ayd/actions/workflows/on-push-main.yaml)\n[![Codecov Test Coverage](https://img.shields.io/codecov/c/gh/macrat/ayd)](https://app.codecov.io/gh/macrat/ayd/)\n[![Docker Build Status](https://img.shields.io/docker/pulls/macrat/ayd?logo=docker\u0026logoColor=white)](https://hub.docker.com/r/macrat/ayd)\n\n**Ayd** - The easiest alive monitoring tool.\n\nWith this only one easy command, you can monitor whether your system is alive or not:\n\n``` shell\n$ ayd ping:192.168.1.1 https://example.com\n```\n\n\n## Features\n\n- Check service status using:\n  * [ICMP echo (ping)](#ping)\n  * [HTTP/HTTPS](#http--https)\n  * [FTP/FTPS](#ftp--ftps)\n  * [SSH](#ssh)\n  * [SFTP](#sftp)\n  * [TCP connect](#tcp)\n  * [DNS resolve](#dns)\n  * [file/directory existence](#file)\n  * [execute external command (or script file)](#exec)\n  * [plugin](#plugin)\n\n- The [status page](#status-pages-and-endpoints) for using by browsers, consoles, or other programs.\n\n- Built-in remote MCP server for AI tools like Claude or ChatGPT to analyze the status and logs.\n\n- Send an alert if an incident occurs or is resolved.\n\n### Good at\n\n- Monitoring small systems\n- Creating temporary status pages\n\nThis tool is designed for small systems, as easy to start using it and easy to quit using it.\n\nIt is a single binary tool that uses only plain text log files.\nSo there is no need to maintain databases or setting files.\n\n### Not good at\n\n- Customization\n- Visualization and investigation\n\nThis tool is designed for simple checks to see if a service is functioning.\nIt does not offer complex or advanced features.\n\n\n## Quick start\n\n1. Download the latest version from [release page](https://github.com/macrat/ayd/releases/).\n\n2. Extract downloaded package and put the binary to somewhere that registered to the PATH.\n\n3. Run the server with [target URLs](#url-scheme) (and [schedule](#scheduling) if need) as arguments.\n\n``` shell\n$ ayd https://your-service.example.com ping:another-host.example.com\n```\n\n4. Check the status of your services.\n\nYou can see the status page on \u003chttp://localhost:9000/\u003e, and you can use [HTTP APIs](#status-pages-and-endpoints).\n\n\n## Reference\n\nAyd checks whether the targets are alive or not, and reports to the alert targets if the target's status has changed.\nThe targets and alert targets are specified as URLs, in the command to start Ayd.\n\nA command to start Ayd looks like:\n\n``` plain text\n$ ayd  -a exec:/path/to/alert.sh  10m  ping:192.168.1.1 http://example.com\n      └────────────┬────────────┘└─┬─┘└───────────────┬───────────────────┘\n                   │               │              Target URLs\n                   │               │   Check if 192.168.1.1 is responding to ping,\n                   │               │   and if http://example.com is serving.\n                   │               │\n                   │            Schedule\n                   │        Check targets every 10 minutes.\n                   │\n               Alert URL\n       Execute /path/to/alert.sh if the target status changed.\n```\n\nThe [common schemes](#url-scheme) for targets and alerts are supported by Ayd itself.\nYou can also add other schemes using [plugin](#plugin).\n\nAyd checks the targets every 5 minutes in default, but you can change it by placing [schedule specification](#sucheduling) before target URL.\n\nWhile Ayd running, it provides [a simple dashboard and some APIs](#status-pages-and-endpoints).\nThe log files of Ayd is formatted as JSON, so you can read it or aggregate it easily using common tools like [jq](https://stedolan.github.io/jq/).\n\n- [URL scheme](#url-scheme)\n- [Scheduling](#scheduling)\n- [Status pages and endpoints](#status-pages-and-endpoints)\n- [Log file](#log-file)\n- [Tips](#tips)\n  * [Daemonize](#daemonize)\n  * [Change listen port](#change-listen-port)\n  * [Use HTTPS status page on status page](#use-https-on-status-page)\n  * [Use Basic Authentication on status page](#use-basic-authentication-on-status-page)\n  * [One-shot mode](#one-shot-mode)\n  * [Text encoding](#text-encoding)\n\n\n### URL scheme\n\nAyd supports below URL schemes in default.\n\n| scheme                             |      as Target     |      as Alert      |\n|------------------------------------|:------------------:|:------------------:|\n| [`ping:`](#ping)                   | :heavy_check_mark: | :heavy_minus_sign: |\n| [`http:` / `https:`](#http--https) | :heavy_check_mark: | :heavy_check_mark: |\n| [`ftp:` / `ftps:`](#ftp--ftps)     | :heavy_check_mark: | :heavy_check_mark: |\n| [`ssh:`](#ssh)                     | :heavy_check_mark: | :heavy_minus_sign: |\n| [`sftp:`](#sftp)                   | :heavy_check_mark: | :heavy_check_mark: |\n| [`tcp:`](#tcp)                     | :heavy_check_mark: | :heavy_minus_sign: |\n| [`dns:`](#dns)                     | :heavy_check_mark: | :heavy_minus_sign: |\n| [`file:`](#file)                   | :heavy_check_mark: | :heavy_check_mark: |\n| [`exec:`](#exec)                   | :heavy_check_mark: | :heavy_check_mark: |\n| [`source:`](#source)               | :heavy_check_mark: | :heavy_check_mark: |\n\nYou can use extra schemes with [plugin](#plugin) if you need.\n\n#### ping:\n\nSend ICMP echo request (a.k.a. ping command) and check if the target is connected or not.\n\nAyd sends 3 packets in 1 second and expects all packets to return.\nThese parameter can changed by `AYD_PING_PACKETS` and `AYD_PING_PERIOD` environment variable.\n\nYou can specify IPv4 or IPv6 with `ping4:` or `ping6:` scheme.\n\nPing will timeout in 30 seconds after sent all packets and report as failure.\n\nexamples:\n- `ping:example.com`\n- `ping:192.168.1.1`\n- `ping:192.168.1.10#my-server`\n\n##### as Alert\n\nping does not support to used as an alert URL.\n\n#### http: / https:\n\nFetch HTTP/HTTPS page and check if the status code is 2xx or not.\n\nYou can use GET, HEAD, POST, OPTIONS, and CONNECT method by specifying like `http-post://...` or `https-head://...`.\nThe default method is GET.\n\nAyd will Follow redirect maximum 10 times.\n\nHTTP will timeout in 10 minutes and report as failure.\n\nexamples:\n- `http://example.com/`\n- `https://example.com/`\n- `http-head://example.com/path/to/somewhere`\n- `https-options://example.com/abc?def=ghi`\n\n##### as Alert\n\nIf you use HTTP/HTTP as an alert URL, Ayd adds some queries to send information about the incident.\n\n| query name       | example                                    | description                        |\n|------------------|--------------------------------------------|------------------------------------|\n| `ayd_time`       | `2001-02-03T16:05:06+09:00`                | The timestamp when status changed  |\n| `ayd_status`     | `FAILURE`, `DEGRADE`, `UNKNOWN`, `HEALTHY` | The current status of the target   |\n| `ayd_latency`    | `123.456`                                  | The latency of the latest checking |\n| `ayd_target`     | `https://target.example.com`               | The target URL                     |\n| `ayd_message`    | `hello world`                              | The latest message of the target   |\n| `ayd_extra`      | `{\"hello\":\"world\"}`                        | The Extra values in JSON format    |\n\n#### ftp: / ftps:\n\nSend LIST or MLSD command of FTP and check the result.\n\nIt uses `anonymous` as username and password if absent those in the URL.\n\nFTP will timeout in 10 minutes and report as failure.\n\nexamples:\n- `ftp://example.com/`\n- `ftp://example.com/path/to/directory`\n- `ftps://foo:bar@example.com/path/to/file.txt`\n\n##### as Alert\n\nWrites the same format logs as the [normal log file](#log-file), over FTP or FTPS, when the service status changed.\nIt is pretty same as [file:](#file) scheme for alert but uses FTP/FTPS.\n\n#### ssh:\n\nEstablish a SSH connection and check if the service is listening or not.\n\nThis scheme supports these queries:\n\n- __identityfile__: Path to private key file like id\\_rsa.\n- __fingerprint__: The fingerprint of the target service, starts with `SHA256:` or `MD5:`.\n\nSSH will timeout in 10 minutes and report as failure.\n\nexamples:\n- `ssh://username:plain-password@example.com`\n- `ssh://username@example.com?identityfile=/path/to/id_rsa`\n- `ssh://username:passphrase-for-key@example.com?identityfile=/path/to/id_rsa`\n- `ssh://username@example.com?identityfile=/path/to/id_rsa\u0026fingerprint=SHA256:AAAAAA...`\n\n##### as Alert\n\n`ssh:` does not support to be used as an alert URL.\nPlease use [`exec+ssh:`](#execssh) for executing a command over SSH.\n\n#### sftp:\n\nConnect to an SFTP server and check whether if the file or directory exists or not. \n\nThis scheme supports the same queries as [ssh:](#ssh) scheme.\n\nSFTP will timeout in 10 minutes and report as failure.\nexamples:\n- `sftp://foo:bar@example.com/`\n- `sftp://foo@example.com/path/to/directory?identityfile=/path/to/id_rsa`\n\n##### as Alert\n\nWrites the same format logs as the [normal log file](#log-file), over SFTP, when the service status changed.\nIt is pretty same as [file:](#file) scheme for alert but uses SFTP.\n\n#### tcp:\n\nConnect to TCP and check if the service is listening or not.\n\n`tcp://` will select IPv4 or IPv6 automatically.\nBut you can also use `tcp4://` or `tcp6://` to choose IP protocol version.\n\nTCP will timeout in 10 seconds and report as failure.\n\nexamples:\n- `tcp://example.com:3309`\n- `tcp4://127.0.0.1:3309`\n- `tcp6://[::1]:3309`\n- `tcp://192.168.1.10:80#my-server`\n\n##### as Alert\n\nTCP does not support to used as an alert URL.\n\n#### dns:\n\nResolve hostname via DNS and check if the host exists or not.\n\nYou can specify record type as a `type` query like `dns:example.com?type=A`, or as a scheme like `dns-cname:example.com`.\nSupported type is `A`, `AAAA`, `CNAME`, `MX`, `NS`, and `TXT`.\n\nThere are `dns4:` and `dns6:` scheme for shorthand of `A` and `AAAA` type.\n\nYou also can specify the DNS server as a host name of URL like `dns://8.8.8.8/example.com`.\n\nDNS will timeout in 10 seconds and report as failure.\n\nexamples:\n- `dns:example.com`\n- `dns4:example.com`\n- `dns:example.com?type=AAAA`\n- `dns-cname:example.com`\n- `dns://8.8.8.8/example.com`\n\n##### as Alert\n\nDNS does not support to used as an alert URL.\n\n#### file:\n\nCheck the file or the directory existence.\nIt only checks existence, so it does not report error even if it has no enough permission to read the target.\n\nexamples:\n- `file:./path/to/something`\n- `file:/path/to/somewhere`\n- `file:/dev/sdc1#does-storage-connected?`\n\n##### as Alert\n\nWrites the same format logs as the [normal log file](#log-file) to the target path, when the service status changed.\nIt is pretty same as [ftp: / ftps:](ftp--ftps) for alert but writes to a local file.\n\n#### exec:\n\nExecute external command and check if the exit code is 0 or not.\nThe exit code 0 means HEALTHY, otherwise mean FAILURE. If couldn't execute command, Ayd reports as UNKNOWN.\n\nThe command's stdout and stderr will be captured as a message of the status check record.\nIt is recommended to keep output as short as possible for log readability reason.\n\nYou can specify the first argument as the fragment of URL like below.\n\n``` plain text\nexec:/path/to/command#this-is-argument\n```\n\nAbove target URL works like below command in the shell.\n(In accurate, Ayd does not use shell to execute command so you can not use some features for example shell variable.)\n\n``` shell\n$ /path/to/command this-is-argument\n```\n\nAnd, you can specify environment arguments as the query of URL like below.\n\n``` plain text\nexec:/path/to/command?something=foobar\u0026hello=world\n```\n\nAbove target URL works like below command in the shell.\n\n``` shell\n$ export something=foobar\n$ export hello=world\n$ /path/to/command\n```\n\nExec will timeout in 1 hour and report as failure.\n\nexamples:\n- `exec:./check.exe`\n- `exec:/usr/local/bin/check.sh`\n\n##### Extra report format\n\nPrograms executed by `exec:` can report extra values, such as latency or service status, using the syntax `::key::value`.\n\nFor example, the output look like this:\n\n``` plain\n::latency::123.456\n::status::failure\n::extra_count::123\n::extra_info::this is a test\nhello world\n```\n\nThis output will be parsed by Ayd like this:\n\n``` json\n{\n  \"latency\": 123.456,\n  \"status\": \"failure\",\n  \"extra_count\": 123,\n  \"extra_info\": \"this is a test\",\n  \"message\": \"hello world\"\n}\n```\n\nThe `latency` is a latency of the service, in milliseconds.\nThe `status` is one of `HEALTHY`, `DEGRADE`, `FAILURE`, `ABORTED`, `UNKNOWN`.\nThe other values are numbers, texts, or JSON values.\n\nYou can not set `time`, `target`, and `exit_code`.\nIf you need to change them, please make a [plugin](#plugin).\n\nIf there are multiple keys with the same name in the output, only the last one will be used.\n\n##### as Alert\n\nIf you use `exec:` as an alert URL, Ayd sets some environment variables about the incident.\nThe name of variable and meaning is the same as the queries of [HTTP scheme as alert](#http--https).\n\n##### exec+ssh:\n\nThe `exec+ssh:` scheme is a variant of `exec:`.\nThis scheme executes a command through a SSH connection, and check the exit code.\nPlease see also [`exec:`](#exec) and [`ssh:`](#ssh).\n\n__IMPORTANT:__ Please allow to use environment variables by SSH server's setting. If you are using OpenSSH, please write like `AllowEnv ayd_*` in to `/etc/ssh/sshd_config`.\n\nexamples:\n- `exec+ssh://user:password@example.com/usr/bin/test.sh?env_value=variable`\n- `exec+ssh://user@example.com/usr/bin/test.sh?identityfile=/path/to/id_ed25519#first-argument`\n\n#### source:\n\nThis is a special scheme for loading targets from a file, a remote host, or a command.\nLoad each line in the file as a target URL and check all targets.\n\nSource file looks like below.\n\n``` plain text\n# servers\nping:somehost.example.com\nping:anotherhost.example.com\nping:yet.anotherhost.example.com\n\n# services\nhttps://service1.example.com\nhttps://service2.example.com\n\n# you can also read another file\nsource:./another-list.txt\n```\n\nThe line that starts with `#` will ignored as a comment.\n\nSource file should encoded by UTF-8 with/without BOM or UTF-16 with BOM, but in Windows, you can use legacy encoding.\nPlease see also [text encoding chapter](#text-encoding).\n\nexamples:\n- `source:./targets.txt`\n- `source:/path/to/targets.txt`\n\n##### source+http: / source+https:\n\n`source+http:` and `source+https:` is variants of `source:`.\nThese fetch HTTP/HTTPS and load the response as a source file.\n\n__WARNING:__\nPlease don't use it if you can't completely trust the HTTP server because this scheme can be a backdoor of your server.\nFor example, Ayd will execute everything even if HTTP server responses `exec:rm#/your/important/directory`\n\nexamples:\n- `source+https://example.com/targets.txt`\n\n##### source+ftp: / source+ftps: / source+sftp:\n\n`source+ftp:` and `source+ftps:` is variants of `source:` that very similar to `source+http:`.\nThese download source file via FTP/FTPS and load it.\n\n__WARNING:__\nPlease don't use it if you can't completely trust the source file in the FTP server because this scheme can be a backdoor of your server.\nFor example, Ayd will execute everything even if the FTP server responses `exec:rm#/your/important/directory`\n\nexamples:\n- `source+ftps://user:password@example.com/targets.txt`\n- `source+sftp://user@example.com/targets.txt?identityfile=/path/to/id_rsa`\n\n##### source+exec:\n\n`source+exec:` is another variant of `source:`.\nIt is execute script as the same way as [`exec:`](#exec) and load the output as a source file.\n\nexamples:\n- `source+exec:./make-targets-list.exe`\n- `source+exec:/usr/local/bin/targets.sh`\n\n##### source+ssh:\n\n`source+ssh:` is a variant of `source:` like `source+exec:` but to execute command on remote host.\nIt is execute script as the same way as [`exec+ssh:`](#exec) and load the output as a source file.\n\n__NOTE:__\nIt's highly recommended to specify server's fingerprint for security reason.\n\nexamples:\n- `source+ssh://name:pass@target/usr/bin/make-targets-list.exe?fingerprint=SHA256:AAAA...`\n- `source+ssh://name@target/usr/bin/make-targets-list.exe?identityfile=/path/to/key\u0026fingerprint=SHA256:AAAA...`\n\n##### as Alert\n\nEven if use it as an alert URL, the behavior is almost the same, but send alert to the all URLs loaded.\n\n#### Plugin\n\nA plugin is an executable file installed in the PATH directory.\n\nThe name of plugin depends on the URL scheme its supports and its purpose, like `ayd-xxx-probe`, `ayd-xxx-alert`, or `ayd-xxx-scheme`.\nA plugin named `-probe` is for probing target, named `-alert` is for sending alerts, and named `-scheme` supports both purposes.\n\nFor example, if the target URL has the scheme `xxx-yyy:`, Ayd will search these executable files in order of priority:\n\n1. `ayd-xxx-yyy-probe`\n2. `ayd-xxx-yyy-scheme`\n3. `ayd-xxx-probe`\n4. `ayd-xxx-scheme`\n\nThe scheme names that supported by Ayd, `ayd`, and `alert`, are reserved and cannot be used by plugins.\n\nThe plugin prints result to stdout, in the same format as [log file](#log-file).\nPlugins should not report future results, or old results more than 1 hour.\n\nAyd expects the output of the plugin to be in UTF-8.\nHowever, in Windows, the system's default character encoding can be used.\nPlease see also [text encoding chapter](#text-encoding).\n\nIf a plugin takes longer than 1 hour to execute, it will be timed out and reported as a failure.\n\nThe differences from plugin to [`exec:`](#exec) are:\n\n|                                                         | `exec: `     | plugin                     |\n|---------------------------------------------------------|--------------|----------------------------|\n| URL Scheme                                              | `exec:` only | anything                   |\n| executable file directory                               | anywhere     | only in the PATH directory |\n| set argument and environment variable in URL            | can          | can not                    |\n| receive raw target URL                                  | can not      | can                        |\n| record about multiple targets like as [source](#source) | can not      | can                        |\n\nThere is [a library for creating plugin](https://pkg.go.dev/github.com/macrat/ayd/lib-ayd).\n\n##### Probe plugin\n\nThe probe plugin is for checking the target.\nIt receives the target URL as the only one argument.\n\nFor example, the target URL `foobar:your-target` will be called like:\n\n``` shell\n$ ayd-foobar-probe \"foobar:your-target\"\n```\n\n##### Alert plugin\n\nThe alert plugin is for sending an alert.\nIt receives two arguments.\nThe first argument is an alert URL.\nThe second one is the latest record that fired the alert in JSON format.\n\nFor example, the alert URL `foobar:your-alert` for plugin `ayd-foobar-alert` will be called like:\n\n``` shell\n$ ayd-foobar-alert       \\\n    \"foobar:your-alert\"  \\\n    '{\"time\":\"2001-02-30T16:05:06+09:00\", \"status\":\"FAILURE\", \"latency\":\"1.234\", \"target\":\"ping:your-target\", \"message\":\"this is message of the record\"}'\n```\n\nThe `target` URLs in the alert plugin's output, will be added `alert:` prefix before store in Ayd, and hide in the status pages.\n\n##### plugin list\n\n###### Probe plugin\n\n- [SMB (samba)](https://github.com/macrat/ayd-smb-probe#readme)\n- [NTP](https://github.com/macrat/ayd-ntp-probe#readme)\n\n###### Alert plugin\n\n- [e-mail (SMTP)](https://github.com/macrat/ayd-mailto-alert#readme)\n\n  ![The screenshot of Ayd alert in email. You can see service status, target URL, and reason to failure. And there is button to open Status Page.](./assets/email-alert.jpg)\n\n- [Slack](https://github.com/macrat/ayd-slack-alert#readme)\n\n  ![The screenshot of Ayd alert in the Slack. You can see service status, target URL, and reason to failure. And there is button to open Status Page.](./assets/slack-alert.jpg)\n\n\n### Scheduling\n\nAyd will check targets every 5 minutes in default.\nYou can place the schedule specifications before the target URLs like below if you want to change scheduling.\n\n``` shell\n$ ayd 10m https://your-service.example.com \\\n      1h  https://another-service.example.com https://yet-another-service.example.com\n```\n\nThe above command means to check `your-service.example.com` every 10 minutes, and to check `another-service.example.com` and `yet-another-service.example.com` every 1 hour.\n\nYou can also use [the Cron](https://en.wikipedia.org/wiki/Cron) style spec as a schedule spec like below.\n\n``` shell\n$ ayd '*/5  6-21 * *'     https://your-service.example.com \\\n      '*/10 *    * * 1-5' https://another-service.example.com\n```\n\nThe above command means checking `your-service.example.com` every 5 minutes from 6 a.m. to 9 p.m, and checking `another-service.example.com` every 10 minutes from monday to friday.\n\n``` plain text\n ┌─────── minute (0 - 59)\n │ ┌────── hour (0 - 23)\n │ │ ┌───── day of the month (1 - 31)\n │ │ │ ┌──── month (1 - 12)\n │ │ │ │ ┌─── [optional] day of the week (0 - 6 (sunday - saturday))\n │ │ │ │ │\n'* * * * ?'\n```\n\nThere are some special values for ease to specify.\n\n| special spec             | standard spec | description                                   |\n|--------------------------|---------------|-----------------------------------------------|\n| `@yearly` or `@annually` | `0 0 1 1 ?`   | Check once a year at 1st January.             |\n| `@monthly`               | `0 0 1 * ?`   | Check once a month at the first day of month. |\n| `@daily`                 | `0 0 * * ?`   | Check once a day at midnight.                 |\n| `@hourly`                | `0 * * * ?`   | Check once an hour.                           |\n| `@reboot`                | -             | Check once when Ayd started.                  |\n| `@after 5m`              | -             | Check once after 5 minutes after Ayd started. |\n\n\n### Status pages and endpoints\n\nAyd has these pages/endpoints.\n\n| path                                                 | description                                                          |\n|------------------------------------------------------|----------------------------------------------------------------------|\n| [/status.html](http://localhost:9000/status.html)    | Human friendly status page in HTML.                                  |\n| [/status.txt](http://localhost:9000/status.txt)      | Human friendly status page in plain text.                            |\n| [/status.json](http://localhost:9000/status.json)    | Machine readable status page in JSON format.                         |\n| [/incidents.html](http://localhost:9000/status.html) | Human friendly incident history page in HTML.                        |\n| [/incidents.rss](http://localhost:9000/status.rss)   | Incident history feed in RSS 2.0 format.                             |\n| [/incidents.csv](http://localhost:9000/status.csv)   | Incident history in CSV format.                                      |\n| [/incidents.json](http://localhost:9000/status.json) | Incident history in JSON format.                                     |\n| [/log.html](http://localhost:9000/log.html)          | Raw log data in HTML page.                                           |\n| [/log.csv](http://localhost:9000/log.csv)            | Raw log file in CSV format.                                          |\n| [/log.xlsx](http://localhost:9000/log.xlsx)          | Raw log file in Microsoft Excel (OpenXML Spreadsheet) format.        |\n| [/log.ltsv](http://localhost:9000/log.ltsv)          | Raw log file in LTSV (Labeled Tab-Separated Values) format.          |\n| [/log.json](http://localhost:9000/log.json)          | Raw log file in JSON format.                                         |\n| [/targets.txt](http://localhost:9000/targets.txt)    | The list of target URLs, separated by \\\\n.                           |\n| [/targets.json](http://localhost:9000/targets.json)  | The list of target URLs in JSON format.                              |\n| [/mcp](http://localhost:9000/mcp)                    | Remote [MCP](https://modelcontextprotocol.io/docs/getting-started/intro) server endpoint.|\n| [/metrics](http://localhost:9000/metrics)            | Minimal status page for use by [Prometheus](https://prometheus.io/). |\n| [/healthz](http://localhost:9000/healthz)            | Health status page for checking status of Ayd itself.                |\n\n\n#### Filter log entries\n\nThe log endpoints accept the following queries for filtering log entries.\n\n- `limit`: set maximum number of entries in the response.\n  You can use `offset` query to fetch more.\n\n  By default, Ayd replies all logs.\n\n- `offset`: set the offset number of the first entry in the response.\n  This is usually used in conjunction with the `limit` query for paging.\n\n- `q`: filter by a space-delimited query.\n  This query supports following syntaxes:\n\n  - `a AND b`, `a b`: matches both of **a** and **b**.\n  - `a OR b`: matches either **a** or **b**.\n  - `NOT a`, `!a`, `-a`: not matches to **a**.\n  - `field=a`, `field!=a`, `field\u003ea`, `field\u003e=a`, `field\u003ca`, `field\u003c=a`: **field** matches to **a** in the specified operator.\n\nQuery examples:\n- `time\u003e=2000-01-01 time\u003c=2000-12-31`: The logs from 2000-01-01 to 2000-12-31.\n- `time\u003e=2021-01-01 target=ping:host`: The logs about `ping:localhost` since 2021-01-01.\n- `status!=healthy target=ping:*`: The logs within recent 7 days that only about unhealthy ping targets.\n\n\n#### MCP server\n\nAyd supports [MCP (Model Context Protocol)](https://modelcontextprotocol.io/docs/getting-started/intro) for AI tools like Claude or ChatGPT to analyze the status and logs.\n\nTo use MCP server, simply run Ayd as usual and add `http://localhost:9000/mcp` as a remote MCP server URL to your AI tool.\n\n\n### Log file\n\nThe log file of Ayd is stored in [JSON Lines](https://jsonlines.org/) format, encoded UTF-8.\nEach record has at least 4 fields.\n\n- `time` when status check started, in [RFC3339 format](https://tools.ietf.org/html/rfc3339) like `2001-02-30T16:05:06+00:00`.\n  Ayd can parse some variant formats like `2001-02-03 16:05:06+0000` or `20010203_160506Z`, and the UNIX time seconds.\n\n- `status` of the record that `HEALTHY`, `DEGRADE`, `FAILURE`, `UNKNOWN`, or `ABORTED`.\n\n   * `HEALTHY` means service seems working well.\n\n   * `DEGRADE` means service seems working but partially degraded.\n     You should do something to the target system because the target is not completely healthy.\n\n   * `FAILURE` means service seems failure or stopped.\n     You should do something to the target system because the target may be broken if received this status.\n\n   * `UNKNOWN` means Ayd is failed to status checking.\n     For example, not found test script, failed to resolve service name, etc.\n     You should check the target system, other systems like DNS, or Ayd settings because maybe something worse happened if received this status.\n\n   * `ABORTED` means Ayd terminated during status checking.\n     For example, Ayd reports this when terminated Ayd with Ctrl-C.\n     You do not have to action about this status because it happens by your operation. (might be you have to check Ayd settings if you do not know why caused this)\n\n- `latency` of the service in milliseconds.\n\n   Some probes like [ping:](#ping) reports average latency, and other probes reports total value..\n\n- `target` URL.\n\n   This URL is the same to passed one as argument, but normalized.\n   For example, `ping:somehost?hello=world` to be `ping:somehost` because [ping:](#ping) does not use query values.\n\n- (optional) `message`, the detail of status, the reason for failure, or the output of the executed script.\n\nLog records can have other extra fields.\n\nFor example, log lines look like below.\n\n``` jsonl\n{\"time\":\"2001-02-30T16:00:00+09:00\", \"status\":\"FAILURE\", \"latency\":0.544, \"target\":\"http://localhost\", \"message\":\"Get \\\"http://localhost\\\": dial tcp [::1]:80: connect: connection refused\"}\n{\"time\":\"2001-02-30T16:05:00+09:00\", \"status\":\"UNKNOWN\", \"latency\":0.000, \"target\":\"tcp:somehost:1234\", \"message\":\"lookup somehost on 192.168.1.1:53: no such host\"}\n{\"time\":\"2001-02-30T16:10:00+09:00\", \"status\":\"HEALTHY\", \"latency\":0.375, \"target\":\"ping:anotherhost\", \"message\":\"All packets came back\", \"packets_recv\":3, \"packets_sent:3, \"rtt_avg\":0.38, \"rtt_max\":0.47, \"rtt_min\":0.31}\n```\n\nAyd will save log files named `ayd_%Y%m%d.log` into the current directory by default.\nThe `%Y`, `%m`, and `%d` will be replaced with the year, month, and day of month, respectively, of the record.\nYou can also use `%y` for the year in two characters, `%H` for the hour, `%M` for the minute, and `%%` for the `%` character.\n\nIt can change where the logs are saved using the `-f` option like this:\n\n``` shell\n$ ayd -f /path/to/%Y/log.json ping:example.com\n```\n\nIf you want, you can set file name without time specifications to store all logs into a single file.\nHowever, this is not recommended if you plan to run Ayd for a long time.\nA large log file is difficult to handle, and can slow down Ayd's log APIs.\n\nIf you use `-f -` option, Ayd will not write any log file.\nThis is not recommended for production use, because Ayd can not restore its last status when it is restarted.\nBut, this is may useful for [using Ayd as part of a script file](#one-shot-mode).\n\nIf you want use log file in other format like CSV, you can download via [HTTP endpoint](#status-pages-and-endpoints), or you can use `ayd conv` subcommand like below.\n\n``` shell\n$ cat ayd.log | ayd conv \u003e ayd_log.csv\n\n$ ayd conv ./ayd.log -o ayd_log.csv\n\n$ ayd conv -l ./ayd.log -o ayd_log.ltsv\n```\n\n\n### Tips\n\n#### Daemonize\n\n##### Docker\n\nThere is a [docker image](https://hub.docker.com/r/macrat/ayd) for executing Ayd.\n\n``` shell\n$ docker run --restart=always -v /var/log/ayd:/var/log/ayd macrat/ayd http://your-target.example.com\n```\n\nThe container image includes these plugins:\n\n- [SMB probe](https://github.com/macrat/ayd-smb-probe)\n- [email alert](https://github.com/macrat/ayd-mailto-alert)\n- [slack alert](https://github.com/macrat/ayd-slack-alert)\n\nThere are 3 variants of the base images:\n\n- `latest`, `alpine`: Balanced variant. This is tiny but you can use shell.\n- `scratch`: Minimal variant. You can use this if you won't use shell.\n- `ubuntu`: Large variant. You can use `apt` command for adding command that you want.\n\n##### Systemd\n\nIf you using systemd, it is easy to daemonize Ayd.\n\nPlease put `ayd` command to `/usr/local/bin/ayd` (you can use another place if you want), and write a setting like below to `/etc/systemd/system/ayd.service`.\n\n``` ini\n[Unit]\nDescription=Ayd status monitoring service\nAfter=network.target remote-fs.target\n\n[Service]\nExecStart=/usr/local/bin/ayd -f /var/log/ayd.log.%Y%m \\\n    http://your-target.example.com\n#   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ please change target\n\n[Install]\nWantedBy=multi-user.target\n```\n\nAnd then, you can enable this service.\n\n``` shell\n$ sudo systemctl daemon-reload\n$ sudo systemctl start ayd\n$ sudo systemctl enable ayd\n```\n\n#### Change listen port\n\nYou can change the HTTP server listen port with `-p` option.\nIn default, Ayd uses port 9000.\n\n#### Use HTTPS on status page\n\nYou can set certificate file and key file via `-c` option and `-k` option.\n\n``` shell\n$ ayd -c ./your-certificate.crt -k ./your-certificate.key ping:localhost\n```\n\nThe HTTP/2 will be enabled if set these options.\n\n#### Use Basic Authentication on status page\n\nAyd has very simple authentication mechanism using Basic Authentication.\nYou can use it like below.\n\n``` shell\n$ ayd -u user:p@ssword ping:localhost\n```\n\nFor above example, you can access status page using `user` as username and `p@ssword` as password.\n\nThis is not very secure because you have to write a plain password in the command argument. (Attacker can peek arguments of other process easily if you have access to the server terminal)\nBut, this is very easy to setup, and at least, it works well against end user who doesn't have access to the server.\nIf you need more secure option, please consider use reverse proxy like Nginx.\n\n#### One-shot mode\n\nIf you want to use Ayd in a script, you can use `-1` option.\nAyd will check status just once and exit when passed `-1` option.\n\nExit status code will be 0 if all targets are healthy.\nIf some targets are unhealthy, the status code will be 1.\nAnd, if your arguments are wrong (or can't resolve host names, or exec scripts not found), the status code will be 2.\n\n#### Text encoding\n\nAyd expects UTF-8 with/without BOM or UTF-8 with BOM as input character encoding.\n\nBut in Windows, you can use the system's default character encoding too, for example CP1252 or CP932.\nAyd tries to decode as UTF-8 first, and then tries to use the system's default encoding.\nIf the text has the BOM, Ayd always follow it.\n\nThe characters couldn't decode will replaced by U+FFFD that means unrecognized character before save to the log file.\nThat means;\n- The log file is always valid UTF-8 even if your external command or plugin writes invalid characters.\n- You can lose information if external commands or plugins write invalid characters as current encoding.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmacrat%2Fayd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmacrat%2Fayd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmacrat%2Fayd/lists"}