# Feedback on \`cargo-add\` before its merged

**URL:** <https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024>\
**Category:** cargo\
**Created:** [January 25, 2022, 8:32pm UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024 "2022-01-25T20:32:25Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![epage](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/epage/32/3171_2.png) [@epage](https://internals.rust-lang.org/u/epage)\
**Post date:** [January 25, 2022, 8:32pm UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/1 "2022-01-25T20:32:25Z")

</div>

In preparation for [merging cargo-add into cargo](https://github.com/rust-lang/cargo/issues/5586), I want to solicit input on the CLI before we restrict its evolution by shipping it with cargo.

As a reminder, our options are

- Remove features (for now or forever)
- Make features unstable (require `-Z` to use)
- Re-work features

### Background

[`cargo add`](https://github.com/killercup/cargo-edit) allows you to add or modify dependencies in your `Cargo.toml` file.

Example commands

```console
cargo add regex
cargo add regex serde
cargo add regex@1 --dev
cargo add regex@~1.0 --build
cargo add regex --vers 1.0 --optional
cargo add regex --upgrade minor # for some reason this is the policy name for `^`
cargo add https://github.com/rust-lang/regex
cargo add regex --git https://github.com/rust-lang/regex
cargo add ../dependency
cargo add dep --path ../dependency

```

For full `--help` output, see [the README](https://github.com/killercup/cargo-edit#usage)

Particular points

- Effectively there are two modes
  - Fill in any relevant field for one package
  - Add multiple packages, erroring for fields that are package-specific (`--vers`, `--features`, etc)

- We infer if the `dependencies` table is sorted and preserve that sorting when adding a new dependency
- [Adding a workspace dependency](https://github.com/killercup/cargo-edit/issues/480)
  - dev-dependencies always use path
  - all other dependencies use version + path

- Re-add to modify an existing entry
  - No `--rename` will remove a prior `--rename`
  - `--optional` is never removed ([cargo-edit#298](https://github.com/killercup/cargo-edit/issues/298))
  - Only explicit `--features` removes a prior one
  - `--vers`, `--path`, and `--git` overwrite each other

### Known Points of Concern

**1. This is feature rife with minutia that could become a maintenance burden for the cargo team**

There are many different users with different needs and different formatting styles. We get a lot of feedback about trying to maintain the existing style or changing a default here or there.

Examples:

- ["cargo add" should use dotted keys if already used in `Cargo.toml` #521](https://github.com/killercup/cargo-edit/issues/521)
- [cargo add: use predominant string style #217](https://github.com/killercup/cargo-edit/issues/217)
- [`cargo add` : include only MAJOR.MINOR #126](https://github.com/killercup/cargo-edit/issues/126)

**Proposal:** We adopt a couple of guiding principles

- cargo-add is meant to help users on the default path; users always can edit `Cargo.toml`
- cargo-add should be opinionated in style but not get in the way of a user communicating intent
  - `rustfmt` is a prime example of this. A lot of syntax minutia is handled for you but you can still organize your code to clarify intent (e.g. whitespace, ordering, etc).

- Impact:
  - Use a consistent style run-to-run independent of the existing `Cargo.toml` (e.g. string and table styles)
  - Have a default version requirement style that users explicitly override per call (part of "default" path)
  - Sorting is something we will infer and preserve since that is tied more into the organization than in the minutia
  - **Close out the above issues as `wont-fix`**
  - We will not re-format existing entries but leave that to a future `rustfmt for Cargo.toml` (this means **removing `--sort`** )

**2. `--upgrade <policy>` isn't quite clear**

The policy names don't map well to what Rust developers are used to (operator characters) and the policy name for `^` isn't correct, calling it `minor`.

**Proposal:** Remove `--upgrade <policy>`

- Most people use or should use the default policy
- Redundant with `--vers <req>` and `<name>@<req>` except when no version is specified and cargo-add looks up the latest. If some does want to specify it, they are most likely to specify `=` which means they probably have a reason and a specific version in mind rather than "latest".

**3. Is our story around pre-release strong enough to have `--allow-preleease` in the default path?**

See [Changing Cargo semver compatibility for pre-releases](https://internals.rust-lang.org/t/changing-cargo-semver-compatibility-for-pre-releases/14820) for one case where we need to improve on pre-release. With clap3, this was a frustration point.

**Proposal:** Remove the flag (or make it unstable)

- Pre-releases are uncommon enough that requiring people to explicitly set the version rather than "pick latest" seems sufficient
- Pre-releases can break from one to the next, so people probably should be explicit about what they are intending to use

**4. The sourcing / constraining parts of the CLI don't seem quite polished**

- `--vers` is redundant with `@` and is a non-obvious name
  - Due to `--version` / `-V` flags though `--version` will go away when this is upstreamed into cargo

- We overload the positional argument between name, path, and git url
  - Have to disambiguate them
  - git url limits future evolution because we can't tell it apart from anything else
  - This leaves `--path` and `--git` as redundant

- `<name>@<version-req>` is common in external prior art but [`cargo` tends to use `:` for pkg ids](https://doc.rust-lang.org/cargo/commands/cargo-pkgid.html), maybe we should do the same

**Proposal:**

- As positional, accept zero or more `<name>[:<version-req>]` or `<path>`
- Accept `--git <url>[#<type>=<ref>]` where type is one of `branch` , `tag,` or `rev`
  - If possible, we auto detect the type from the remote and allow `#<ref>` (maybe only do this?)
  - I chose to use a fragment since its client side, it won't conflict with any requirements from the server
  - Will get name from remote if needed
  - Alternative, replace `--git <url>` with `git+<url>` positional like Poetry

- Remove `--branch` (now handled through fragment)
- `--vers` (specified as part of `<name>[:<version-req>]` or extracted from `<path>`. Chance of needing it in other cases is low

### Prior Art

- _(Python)_ [poetry add](https://python-poetry.org/docs/cli/#add)
  - `git+` is needed to specify git dependencies
  - Has dry-run, which we lack
  - Doesn't have separate `--vers` and `--git` flags
  - git branch is specified via a URL fragment, instead of a `--branch`
  - No `--upgrade <policy>` argument to control the version requirement operator
  - No `--sort` to force sorting of dependencies

- _(Javascript)_ [yarn add](https://yarnpkg.com/cli/add)
  - `name@data` where data can be version, git (with fragment for branch), etc
  - `-E` / `--exact` , `-T` / `--tilde` , `-C` / `--caret` to control version requirement operator instead of `--upgrade <policy>` (also controlled through `defaultSemverRangePrefix` in config)

  - `--cached` for using the lock file ([`cargo add` : Be clever and infer version from Cargo.lock #41](https://github.com/killercup/cargo-edit/issues/41))

  - In addition to `--dev` , it has `--prefer-dev` which will only add the dependency if it doesn't already exist in `dependencies` as well as `dev-dependencies`
  - `--mode update-lockfile` will ensure the lock file gets updated as well

- _(Javascript)_ npm doesn't have a native solution
- _(Javascript)_ [pnpm-add](https://pnpm.io/cli/add)
  - Specify version with `@<version>`
  - Also overloads `<name>[@<version>]` with path and repo
    - Supports a git host-specific protocol for shorthand, like `github:user/repo`
    - Uses fragment for git ref, seems to have some kind of special semver syntax for tags?

  - Only supports `--save-exact` / `-E` for operators outside of the default

- _(Go)_ [go get](https://go.dev/ref/mod#go-get)
  - Specify version with `@<version>`
  - Remove dependency with `@none`

- _(Haskell)_ stack doesn't seem to have a native solution
- _(Julia)_ [pkg Add](https://docs.julialang.org/en/v1/stdlib/Pkg/)
- _(Ruby)_ [bundle add](https://bundler.io/v2.2/man/bundle-add.1.html)
  - Uses `--version` / `-v` instead of `--vers` (we use `--vers` because of `--version` / `-V` )
  - `--source` instead of `path` ( `path` correlates to manifest field)
  - Uses `--git` / `--branch` like `cargo-add`

- _(Dart)_ [pub add](https://dart.dev/tools/pub/cmd/pub-add)
  - Uses `--git-url` instead of `--git`
  - Uses `--git-ref` instead of `--branch` , `--tag` , `--rev`

### Status Update

_(As of Feb 3, 2022)_

You can check out the [`-h` output](https://github.com/killercup/cargo-edit#usage) or install it via `cargo install --git https://github.com/killercup/cargo-edit cargo-edit`

Summary of UI changes:

- [`--sort` has been removed](https://github.com/killercup/cargo-edit/pull/576) as part of decoupling reformatting from adding
- [`--upgrade <policy>` has been removed](https://github.com/killercup/cargo-edit/pull/575) due to the unclear interface and low probability of need
- [`--allow-prerelease` has been removed](https://github.com/killercup/cargo-edit/pull/581) awaiting further work on our pre-release story in cargo. It wasn't marked unstable because it is a relatively small feature that seems to have limited application, so it didn't seem worth it
- [Git URLs as positional arguments has been removed](https://github.com/killercup/cargo-edit/pull/578) as detecting them is ambiguous and limits future evolution (any other kind of URLs we might want to accept)
- ~~[`<name>@<req>` has switched to `<name>:<req>`](https://github.com/killercup/cargo-edit/pull/577) as a parallel with the pkgid syntax~~ This was reverted, we'll instead request cargo to add support for `@` to pkgids
- [`--vers` was removed in favor of `<name>:<req>`](https://github.com/killercup/cargo-edit/pull/584) due to being redundant and reduces the difference between the "multiple add" vs "single add" modes, making it easier to explain
- [`--git <url>` is now unstable and has been put behind `-Z git` feature flag](https://github.com/killercup/cargo-edit/pull/586) as we work out how we want to expose git support
- [Added `-F` short for `--features](https://github.com/killercup/cargo-edit/pull/615) and we'll request other cargo commands to update accordingly
- [Unstable support for inline feature activation (e.g. `cargo add serde +derive serde_json`)](https://github.com/killercup/cargo-edit/pull/609)
  - An alternative not-implemented proposal is for [position-sensitive options](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/50)

- Overwrite mode is polished (calling cargo add multiple times on same dep)
  - [Toggle default features on/off](https://github.com/killercup/cargo-edit/pull/593)
  - [Features get appended](https://github.com/killercup/cargo-edit/pull/594)
  - [Toggling of optional](https://github.com/killercup/cargo-edit/pull/595)
  - And preserving of unspecified fields ([1](https://github.com/killercup/cargo-edit/pull/604), [2](https://github.com/killercup/cargo-edit/pull/607), [3](https://github.com/killercup/cargo-edit/pull/608)).

- [Reuse version reqs from other tables](https://github.com/killercup/cargo-edit/pull/616)

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [January 25, 2022, 8:43pm UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/2 "2022-01-25T20:43:36Z")

</div>

👍 for removing `--upgrade`, removing `--vers` in favor of `name@version`, and removing `--allow-prerelease` or making it unstable.

---

<div class="post-metadata">

**Author:** ![epage](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/epage/32/3171_2.png) [@epage](https://internals.rust-lang.org/u/epage)\
**Post date:** [January 25, 2022, 9:01pm UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/3 "2022-01-25T21:01:22Z")

</div>

I'm wondering if we should put the "modify" case behind an unstable flag.

I've been considering the case:

```rust
$ cargo add foo
...
$ cargo add foo --features regex
...
$ cargo add foo --features serde

```

The intent is to change the features but

- The version will change
- The version requirement operator will be set back to default
- We don't report what we changed from, leaving it to the user to diff the manifest to realize they thought it was going to append `serde` and it instead overwrote it, removing `regex`

The user can compensate for these but the extra work to make it not change the version and to discover and deal with the feature behavior negates the benefit of `cargo add`

I can easily adjust this but I worry there might be more like this. The modify feature seems like it could be useful or else I'd say remove it.

---

<div class="post-metadata">

**Author:** ![djc](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/djc/32/1592_2.png) [@djc](https://internals.rust-lang.org/u/djc)\
**Post date:** [January 25, 2022, 9:43pm UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/4 "2022-01-25T21:43:54Z")

</div>

> [@epage](#):
>
> ```rust
> cargo add regex
> cargo add regex serde
> cargo add regex@1 --dev
> cargo add regex@~1.0 --build
> cargo add regex --vers 1.0 --optional
> cargo add regex --upgrade minor # for some reason this is the policy name for `^`
> cargo add https://github.com/rust-lang/regex
> cargo add regex --git https://github.com/rust-lang/regex
> cargo add ../dependency
> cargo add dep --path ../dependency
> 
> ```

In order to review this, it would be really helpful if there was a short example for each of these (like a one-line diff?) on what they did? Like, if I write `cargo add regex`, what does it use for the version?

My intuition here is that this is a lot to add in one go. Are we concerned about keeping CLI compatibility with the existing externally installed cargo add command? It would seem attractive to me to start from scratch with a minimal feature set and figure out the right syntax for a bunch of the edge cases later on. (For example, I would probably not add the `cargo add https://github.com/rust-lang/regex` interface in favor of the version with `--git`.)

---

<div class="post-metadata">

**Author:** ![epage](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/epage/32/3171_2.png) [@epage](https://internals.rust-lang.org/u/epage)\
**Post date:** [January 25, 2022, 9:55pm UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/5 "2022-01-25T21:55:48Z")

</div>

> In order to review this, it would be really helpful if there was a short example for each of these (like a one-line diff?) on what they did?

Good call. I was mostly thinking in terms of people already using it but this is also important context for others to catch up on this

```console
$ cargo add regex # Adds `regex = "1.5.4"`
cargo add regex serde # The above with `serde = "1.0.136"`
cargo add regex@1 --dev # Adds `regex = "1" to `dev-dependencies`
cargo add regex@~1.0 --build # Adds `regex = "~1.0" to `build-dependencies`
cargo add regex --vers 1.0 --optional # Adds `regex = { version = "1.0", optional = true}` 
cargo add regex --upgrade minor # Adds `regex = "^1.5.4"`
cargo add https://github.com/rust-lang/regex # Adds `regex = { git = "https://github.com/rust-lang/regex" }`
cargo add regex --git https://github.com/rust-lang/regex # Adds `regex = { git = "https://github.com/rust-lang/regex" }`
cargo add ../dependency # Adds `dep = { version = "1.0.3", path = "../dependency" }`

```

> My intuition here is that this is a lot to add in one go. Are we concerned about keeping CLI compatibility with the existing externally installed cargo add command? It would seem attractive to me to start from scratch with a minimal feature set and figure out the right syntax for a bunch of the edge cases later on.

We can break things from cargo-edit but I feel we should limit the scope of impact in removing functionality, erring towards unstable features (`-Z`), if the impact is too much. The built-in version will take precedence so if we reduce the feature set too much, so that people are wanting the `cargo-edit` version, then we'll have to rename it and people will have to go through hoops to use it.

> (For example, I would probably not add the `cargo add https://github.com/rust-lang/regex` interface in favor of the version with `--git` .)

Same. I feel we should either only support `--git` or have s special indicator of a git path, like poetry does (`git+<url>`). The part that is appealing to me about the latter (combined with some of my other proposals like dropping `--path`) is we have the benefits of a flag but we are also able to consistently process all positional arguments as dependencies to add and only use the flags for modifying how we add them. While it complicates the syntax for specifying a dependency, it simplifies teaching how the args interact and simplifies the arg validation implementation.

We could also put both kinds of git support behind a `-Z` flag to see how they work and hold off on any decision.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [January 25, 2022, 10:40pm UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/6 "2022-01-25T22:40:27Z")

</div>

I get the impression that `cargo add` is used more commonly for crate names (to avoid having to look up version numbers) than for git URLs, so making that bit unstable seems fine.

Modification, though, seems too useful to leave unstable for long, for two reasons:

- It's helpful to be able to `cargo add x` without knowing if you already depend on `x`, and that shouldn't explode with a "that's nightly only" message.
- It's helpful to be able to add features, whether or not you have the dependency already.

---

<div class="post-metadata">

**Author:** ![djc](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/djc/32/1592_2.png) [@djc](https://internals.rust-lang.org/u/djc)\
**Post date:** [January 25, 2022, 11:17pm UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/7 "2022-01-25T23:17:50Z")

</div>

> [@epage](#):
>
> Good call. I was mostly thinking in terms of people already using it but this is also important context for others to catch up on this
> 
> ```rust
> $ cargo add regex # Adds `regex = "1.5.4"`
> cargo add regex serde # The above with `serde = "1.0.136"`
> cargo add regex@1 --dev # Adds `regex = "1" to `dev-dependencies`
> cargo add regex@~1.0 --build # Adds `regex = "~1.0" to `build-dependencies`
> cargo add regex --vers 1.0 --optional # Adds `regex = { version = "1.0", optional = true}` 
> cargo add regex --upgrade minor # Adds `regex = "^1.5.4"`
> cargo add https://github.com/rust-lang/regex # Adds `regex = { git = "https://github.com/rust-lang/regex" }`
> cargo add regex --git https://github.com/rust-lang/regex # Adds `regex = { git = "https://github.com/rust-lang/regex" }`
> cargo add ../dependency # Adds `dep = { version = "1.0.3", path = "../dependency" }`
> 
> ```

Some feedback:

- I don't think the `@` syntax for versions fits very well, I've only seen it in the JavaScript ecosystem. I'd prefer an explicit switch like `--vers` though I also find it a little jarring. Do we use `--vers` in other places in the cargo CLI?
- The `--dev`, `--build` and `--optional` flags make intuitive sense to me.
- The `--upgrade minor` flag definitely doesn't. Maybe leave that out for now? I think a next step could be to work on an integration of `cargo upgrade` which could do that better.

> [@epage](#):
>
> We can break things from cargo-edit but I feel we should limit the scope of impact in removing functionality, erring towards unstable features ( `-Z` ), if the impact is too much. The built-in version will take precedence so if we reduce the feature set too much, so that people are wanting the `cargo-edit` version, then we'll have to rename it and people will have to go through hoops to use it.

Yeah, so the trick is to strike a good balance.

> [@epage](#):
>
> Same. I feel we should either only support `--git` or have s special indicator of a git path, like poetry does ( `git+<url>` ). The part that is appealing to me about the latter (combined with some of my other proposals like dropping `--path` ) is we have the benefits of a flag but we are also able to consistently process all positional arguments as dependencies to add and only use the flags for modifying how we add them. While it complicates the syntax for specifying a dependency, it simplifies teaching how the args interact and simplifies the arg validation implementation.
> 
> We could also put both kinds of git support behind a `-Z` flag to see how they work and hold off on any decision.

I don't like the `git+<url>` option that much because it's just different from what the TOML does. I think the `--git` version is fairly obvious/intuitive, so I wouldn't mind making that stable.

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [January 25, 2022, 11:29pm UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/8 "2022-01-25T23:29:35Z")

</div>

Probably doesn't matter since this looks backwards compatible to fix, but I just stumbled upon the fact that `--manifest-path` and `--package` can't be combined in the existing `cargo-edit`, while this should be valid to select a workspace manifest and then a package within that workspace to modify.

I also agree that `@` looks really weird for the version constraint and I never knew it was supported, always using `--vers`. There seems to be a variety of operators used for this in third-party tools, I know that `cargo-download` writes this `<name>=<version-request>` (so `tokio==1.0.0` to download specifically 1.0.0).

Similarly I never knew this supported upgrading, that seems quite an overlap with `cargo-upgrade` also from `cargo-edit` 🤔

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [January 26, 2022, 3:30am UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/9 "2022-01-26T03:30:45Z")

</div>

I think it'd be fine to hide all advanced features that aren't rock-solid. The main use-case is `cargo add crate_name`, and it's better to have that standardized ASAP than to wait for other improvements.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [January 26, 2022, 3:32am UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/10 "2022-01-26T03:32:26Z")

</div>

I'd keep `--vers`, because `cargo yank` uses `--vers`. Not having it would create inconsistency within `cargo`.

---

<div class="post-metadata">

**Author:** ![epage](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/epage/32/3171_2.png) [@epage](https://internals.rust-lang.org/u/epage)\
**Post date:** [January 26, 2022, 3:39am UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/11 "2022-01-26T03:39:09Z")

</div>

> [@Nemo157](#):
>
> also agree that `@` looks really weird for the version constraint and I never knew it was supported, always using `--vers` . There seems to be a variety of operators used for this in third-party tools,

What are your thoughts on `:` which is what cargo uses?

---

<div class="post-metadata">

**Author:** ![sanxiyn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/sanxiyn/32/8824_2.png) [@sanxiyn](https://internals.rust-lang.org/u/sanxiyn)\
**Post date:** [January 26, 2022, 4:55am UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/12 "2022-01-26T04:55:50Z")

</div>

I like `:` instead of `@`.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [January 26, 2022, 5:44am UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/13 "2022-01-26T05:44:43Z")

</div>

> [@epage](#):
>
> I've been considering the case:
> 
> ```rust
> $ cargo add foo
> ...
> $ cargo add foo --features regex
> ...
> $ cargo add foo --features serde
> 
> ```

I definitely think that `cargo add` should (strive to) be semantically append-only — that is, doing `cargo add [anything]` will not remove any dependency, only add them. Cargo features are strictly additive, adding new dependencies is strictly additive, and theoretically (barring version conflicts and assuming semver-correctness), adding new "I use this" metadata into the manifest (the domain of `cargo add`) should never cause a compiling workspace to stop compiling.

My suggestion would be to `-Zunstable` gate or remove any functionality which doesn't meet the ideal of "semantically append-only."

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [January 26, 2022, 9:22am UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/14 "2022-01-26T09:22:03Z")

</div>

Cargo uses `:` to separate package name and _version_ in package ids, I don't know that it has ever used a shorthand notation for _version requirements_. Maybe using the same symbol for both would make sense, `foobar:=1.2.3` is probably understandable.

Trying to trigger an error message containing a version requirement just now I used `--rename` for the first time. I would consider its behavior as implemented in `cargo-edit` buggy and don't think that should be stabilized in `cargo`; `cargo add foo@1 && cargo add foo@2 --rename foo2` will result in the second add _replacing_ the existing `foo` dependency with a renamed `foo2` dependency instead of having two dependencies for the different versions.

---

<div class="post-metadata">

**Author:** ![Kixunil](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kixunil/32/4110_2.png) [@Kixunil](https://internals.rust-lang.org/u/Kixunil)\
**Post date:** [January 26, 2022, 12:52pm UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/15 "2022-01-26T12:52:25Z")

</div>

I only use `cargo add dep` so I guess I'm fine with most things but would like to mention two features I'm missing to hopefully avoid decisions that could conflict with adding those features in the future:

- MSRV-aware adding - if I set MSRV of my project then `cargo add` should pick latest version of the dependency that obeys MSRV or has unknown MSRV. In case of unknown a warning could be printed.
- Adding whole group at once. A typical example is Json - one often adds `serde`, `serde-derive` and `serde_json` together. I'd like to configure a group called `json` in a config file (`~/.config/cargo/crate_groups` or so) and refer to it by some symbol. E.g. `cargo add %json` could add all crates from the group. Features would be very helpful too because e.g. adding `rt` to `tokio` is common.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [January 26, 2022, 1:59pm UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/16 "2022-01-26T13:59:25Z")

</div>

> [@Kixunil](#):
>
> one often adds `serde` , `serde-derive`

I would usually use just `serde`, but with the `"derive"` feature enabled, since it re-exports the derive macros.

---

<div class="post-metadata">

**Author:** ![Kixunil](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kixunil/32/4110_2.png) [@Kixunil](https://internals.rust-lang.org/u/Kixunil)\
**Post date:** [January 26, 2022, 4:04pm UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/17 "2022-01-26T16:04:14Z")

</div>

Sure, it's not the only example... (`hyper` implying `tokio` comes to mind) But maybe this supports allowing features. One quite big annoyance about it is having to add `{ version = ` and `}` when specifying features. (Edit at two places.)

---

<div class="post-metadata">

**Author:** ![epage](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/epage/32/3171_2.png) [@epage](https://internals.rust-lang.org/u/epage)\
**Post date:** [January 26, 2022, 4:16pm UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/18 "2022-01-26T16:16:59Z")

</div>

> [@Kixunil](#):
>
> MSRV-aware adding - if I set MSRV of my project then `cargo add` should pick latest version of the dependency that obeys MSRV or has unknown MSRV. In case of unknown a warning could be printed.

This would be a great feature. I feel like we wouldn't do it though unless the data is in the Index which it unfortunately isn't.

---

<div class="post-metadata">

**Author:** ![197g](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/197g/32/7276_2.png) [@197g](https://internals.rust-lang.org/u/197g)\
**Post date:** [January 26, 2022, 5:05pm UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/19 "2022-01-26T17:05:01Z")

</div>

As an experienced user, a mere mapping of all fields a crate can have into command line arguments would not make a particularly convincing tool to me. I'm better served opening Cargo.toml in my favorite editor and adding them to the section. This has advantages:

- Ensures a consistent style, as for example dependencies that use _any_ features including default ones are always scrutinized and I tend to add summaries justifying their use. I would have to do this process anyways, and the tool just makes it harder to implement such policy of well-documented code (and Cargo.toml _is_ code in a machine readable sense).
- Editor integration, copy&paste for multiple, user-defined templates, …

I'd be much more convinced by some process that brings cargo-specific information _into_ the regular editor workflow. Maybe not unlike `git commit`. That is, have the tool fill in fields it can automatically determine such as the most recent release (for an msrv) or _necessary_ renames due to conflict. Maybe with an explicit `--edit` flag or the inverse, with my bias that I've always been content with git's default of requiring an explicit `--no-edit` in most places. Closing the editor directly without changes isn't that much of a deal.

Another question would be if it a 'transactional' property in the sense of `sudoedit` could bring anything to the table. Maybe the opened file to edit could be a copy and only when it _parses_ according to cargo's rules, and dependency resolution works, the original file is replaced.

---

<div class="post-metadata">

**Author:** ![Kixunil](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kixunil/32/4110_2.png) [@Kixunil](https://internals.rust-lang.org/u/Kixunil)\
**Post date:** [January 26, 2022, 5:15pm UTC](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024/20 "2022-01-26T17:15:12Z")

</div>

Crates can set it already which is the initial step towards solving it. 🙂

[Next page](https://internals.rust-lang.org/t/feedback-on-cargo-add-before-its-merged/16024.md?page=2)
