Privacy notice
What Emendant sends, what it never sends, and what the feed origin can see.
Last updated 18 October 2026
Emendant is a command line tool you install and run on your own machine. There is no account, no sign-in and no service that receives your source code. This notice describes every place data exists, and every network request the tool can make: the feed download, the registry request that proves a fix, the excerpt an assisted fix sends to a provider you name, and, if you switched it on, the record a failed patch sends back about what a release broke. A scan makes no request unless you have already enabled automatic feed refresh.
Who operates Emendant
Emendant is operated by Soham Jain, an individual established in the United Kingdom, who is the data controller for the processing described here. Contact: privacy@emendant.com.
There is no telemetry
There is no usage counter, no error reporting, no crash reporter and no licence check. Nothing reports that you ran Emendant, when, or on what. A scan makes no network request unless you have already enabled automatic feed refresh, and a feed refresh uses one of four fixed paths and carries nothing about the repository it is scanning.
Two other requests exist, and both go somewhere you chose rather than to us: proving a fix asks your own package manager's registry for a release, and an assisted fix sends a bounded excerpt to a model provider you name on the command line. Each has its own section below, and neither reaches anything the operator of Emendant runs.
There is one request that does reach us, and only if you said yes to it. When a patch fails its checks against a new release, Emendant can send back what that release broke: the package, the two versions, the error codes and the names the release's own type declarations contain. It carries no path, no line, no code and nothing that says which repository it is, and it goes with a random identifier so that you can ask for it to be deleted. It is off on any machine nobody asked, and the section below is the whole of it.
The feed download
Emendant ships with a copy of the change feed, so it works with no network access. A newer feed is fetched only when you ask for it, either by running emendant feed update or by turning automatic refresh on, which is off until you turn it on once.
A refresh requests one of exactly four paths from feed.emendant.com:
timestamp.jsonroots/<sequence>.jsonsnapshots/<id>/manifest.jsonsnapshots/<id>/feed/<path>
There is no query string, no custom header, no request body and no cookie. Emendant downloads one whole snapshot, identical for every user, rather than the entries for the packages you depend on. That is deliberate: a per-package request would write your dependency list into an access log one line at a time, and this design has nowhere to put it.
Who serves it, and what they can see
| Operator | Cloudflare, Inc. R2 object storage behind a custom domain, on the operator's Cloudflare account. Cloudflare serves the files from its global network, so a request may be answered outside the United Kingdom |
|---|---|
| What is requested | one of the four paths above |
| What is observable anyway | your IP address, the time, a TLS fingerprint and a user agent, as with any HTTPS request |
| Request logging | R2 access logging and Logpush are not enabled for this bucket. Cloudflare's own analytics for the hostname are aggregate rather than per request, and are retained for Cloudflare's standard period for the account plan |
| Who can read it | the operator named above, and Cloudflare under its own terms |
An access log, if one were enabled, could show that some address fetched some snapshot at some time. It could not show what that machine depends on, because no repository fact appears in anything Emendant constructs. Where this processing happens, the lawful basis is legitimate interests: serving and securing a file download that somebody asked for.
Your choices
| Make no request at all | automatic refresh is off until you turn it on, and --offline makes no request in any mode |
|---|---|
| Fetch from somewhere else | set EMENDANT_FEED_ORIGIN to your own mirror. It is safe to point elsewhere: an origin decides what bytes arrive and never whether they are accepted, because signatures are checked against a trust root inside the installed package |
| Delete what was fetched | remove the cache directory below. Nothing else on your machine records that a fetch happened |
What Emendant writes to your machine
None of this leaves your machine. It is listed because a tool should say what it writes.
| Feed cache | ~/Library/Caches/emendant/feed, $XDG_CACHE_HOME/emendant/feed or the platform equivalent: verified snapshots, the accepted sequence floor and the last refresh time. The newest three snapshots are kept |
|---|---|
| User configuration | $XDG_CONFIG_HOME/emendant/config.json or the platform equivalent: whether automatic refresh is allowed, the selected model provider settings, the fact that first-run setup is complete, whether a failed patch contributes what the release broke, and the random identifier those contributions carry if you have ever sent one. It never holds a credential |
| Project configuration | emendant.json in your repository, written by your project rather than by Emendant |
The cache holds published feed files, which are public. It holds no scan result, no finding, no repository path and no dependency list.
Assisted fixes, which you have to switch on
A few changes have no mechanical remedy. For those, and only when you name a model provider with--model-provider, Emendant sends the matched block, about twenty lines of context and the file's import block from your machine directly to that provider. Nothing else about the repository goes with it, and Emendant never receives or stores any of it. That provider's own terms and privacy policy govern what it does with the excerpt. Without an explicit provider those findings are reported unfixed and nothing is sent anywhere.
The provider you name decides who that is. codex uses a Codex CLI already logged in on your machine; openai and anthropic call those vendors with your own API key; azure calls one Azure AI Foundry resource in your own tenant, so the excerpt reaches the Azure resource your organisation selected rather than a vendor endpoint. Microsoft and your organisation's Azure terms govern that route.--model-endpoint points the request at a gateway you run instead. Emendant prints the host that will receive the excerpt before it sends the first one, and that line names the host it actually calls rather than the vendor a flag is spelled after.
Emendant never obtains a credential. It reads the key or token you exported, at the moment the request is made, and stores no part of it. For Microsoft Entra ID authentication you obtain the token yourself, with your tenant's own command, and Emendant only forwards it.
Proving a fix asks your registry for a version
A patch for an upgrade you have not made yet describes your code after that upgrade, so Emendant cannot prove it without the new release on disk. To get it, emendant fixruns your own package manager (npm, pnpm or yarn) in a scratch tree that holds this repository's manifests, lockfiles and package manager configuration, and none of your source code.
| Who receives it | whichever registry your package manager is configured to use, which is npm's public registry unless your project says otherwise. If that is a private registry inside your organisation, the request goes there and not to npm |
|---|---|
| What they receive | the ordinary install request your own npm install would make: the packages named in your manifests and lockfiles, plus recognized registry credential variables and any additional variable you explicitly allow with --allow-registry-credential |
| What they do not receive | your source code, which is never in that tree. The install scripts that come back are run afterwards with the network taken away and none of your credentials |
| What Emendant receives | nothing. This request is between your machine and your registry, and no part of it reaches the operator of Emendant |
| How to avoid it | --dry-run previews patches without proving them, and --no-verify skips the step. Both grade the patch structurally checked instead, which the report says plainly |
This is the same request your own upgrade would make, a day earlier. It is written down here because a notice that lists only the requests we invented would be describing something narrower than what running the tool actually does.
If you contribute what a release broke
Emendant only reports breaking changes its feed already describes, so a release that breaks your code in a way the feed does not cover produces nothing. The one place that break is visible is a patch that failed: Emendant wrote the fix, moved a copy of your repository to the new release, ran your own typecheck or tests, and they went red. The errors say which of that release's names broke. Sending that back is what makes the feed cover it for the next person.
The first time a patch fails its checks while you run emendant fix at a terminal, you are asked whether to do that. Pressing return says yes. Typing n says no, andemendant feed contribute --disable says no later.
A machine nobody asked sends nothing. That question is only ever put at a terminal, never in CI, never in a pipe and never under --json, and a machine with no recorded answer contributes nothing. Answering at your own terminal turns it on for that machine and for no other.
| What is sent | the package, the version you were on and the version the patch was proved against, the identifiers of the feed entries whose patches failed, whether the typecheck or the tests went red, and the compiler error codes with the quoted names that appear in the new release's own .d.ts files |
|---|---|
| What is not, and cannot be | no file path, no line number, no code, no repository name, no directory name, no package name of your own and no name the new release does not itself declare. Anything else in a compiler message is dropped before the record exists, and dropped again on arrival |
| You can read it first | it is written to .emendant/contribution.json in your repository every time, before it is sent, and emendant feed contribute prints it |
| The one thing that identifies anything | a random identifier this machine generates for itself, the first time it sends anything. It is not derived from your machine, your name, your address or your repository. It exists so that you can ask for your records to be deleted |
| Where it goes | contributions.emendant.com, a Cloudflare Worker and a Cloudflare D1 database on the operator's Cloudflare account. Cloudflare, Inc. processes it as our processor, and it may be served from outside the United Kingdom. Your record stays there: the automated job that reads it runs on GitHub Actions and is given only the per-release totals described under retention, never the records themselves |
| What is not kept about the sender | your IP address, and any value derived from it. The rate limit counts in memory at Cloudflare's edge and writes nothing down, so no address and no hash of one is stored |
| Who reads it | the operator named above, and an automated job that turns it into a pointer at which release to examine. Every fact written into the feed is derived from the published package, never from your record |
| Lawful basis | legitimate interests: describing the breaking changes that real code actually breaks on |
| Retention | a record is deleted within 30 days whatever happens, and sooner if it has been read into the feed pipeline before then. What is kept after that is the release it named, how many records named it, and the package's own type names, error codes and change identifiers those records mentioned. None of that can be traced to a machine, and none of it came from your repository |
| How to avoid it entirely | answer n, or run emendant feed contribute --disable. --offline also sends nothing, in any mode. A machine that has never sent one has no identifier at all |
To have your records deleted, run emendant feed contribute to read the identifier off your own machine and send it to privacy@emendant.com. It is the only way to find them, because nothing else about you is stored.
Installing the package
Installing Emendant is a request to the npm registry, operated by npm, Inc. (GitHub). What npm logs is governed by npm's own privacy policy, and the operator of Emendant receives nothing from it beyond the aggregate download counts npm publishes for every package. The package has no install script.
This website
emendant.com is static, hosted on Cloudflare. It sets no cookies, runs no analytics and embeds no third party scripts. Your colour theme choice is kept in your browser's local storage and is never sent anywhere. Cloudflare processes request metadata to serve the site, as above.
Two addresses on the site are not static files. /api/request-provider receives the form on the request an API or SDK page, and runs only when that form is submitted. /api/status reads our public status page, which is hosted by Atlassian, so that a page can show a notice when the change feed is down. Your browser never contacts Atlassian: that request is made by emendant.com and carries nothing about the person reading. It stores nothing and records nothing about you. Every page, including the form page itself, is still a file served without running any code, and the form needs no JavaScript to work.
If you request an API or SDK
The request form exists so we can see which APIs people want the change feed to cover. It is the only place on this site that stores anything.
| What is stored | what you typed: the API or SDK name, whether it ships as a package and under what name, the version you said you are on, and your note |
|---|---|
| What is not asked for | your name and your email address. There is no field for either, so a request cannot be answered and there is no mailing list to be added to |
| The one thing derived from you | a salted hash of your IP address. It exists so that one person asking twice counts once, and so that the endpoint can be rate limited. The salt is a secret, so the hash cannot be turned back into an address, and the address itself is not stored |
| Cookies and scripts | none. The form is an ordinary HTML form post and sets nothing in your browser |
| Where it is kept | Cloudflare D1, a database on the operator's Cloudflare account. Cloudflare, Inc. processes it as our processor, and it may be served from outside the United Kingdom |
| Who reads it | the operator named above, as counts of how many people asked for each API |
| Lawful basis | legitimate interests: deciding which APIs to cover next, on the basis of what users actually ask for |
| Retention | a request is deleted 24 months after it is made |
If you name a package and say it is on npm or PyPI, that registry is asked for the package's canonical name, repository and latest version, so that a request arrives with the details curation needs. That request carries the package name and nothing about you. If the registry does not answer, or the API has no package at all, the request is still recorded.
The note field is free text, so it can hold whatever you put in it. Please do not put personal details in it. If you do, or if you want a request removed before the 24 months are up, write to privacy@emendant.com with enough detail to find it.
If you contact us
An email you send is kept for as long as it takes to deal with it and to keep a record of security reports, and is not used for anything else. Reports of a vulnerability are kept indefinitely as part of the security record, because a fix has to stay explicable.
Your rights
Under UK data protection law you can ask what personal data is held about you, ask for it to be corrected or erased, and object to processing. Write to privacy@emendant.com. In practice there is very little to ask about: no account exists, and the only thing that identifies anything to Emendant is the random identifier on your own machine, if you turned contributions on and quote it. If you are not satisfied with the response you can complain to the Information Commissioner's Office at ico.org.uk.
Changes to this notice
This notice is dated at the top. A change is published here with a new date, and a change that materially affects what leaves your machine is also stated in the release notes for the version that makes it.