diff --git a/README.md b/README.md
index a83114e48..877b98568 100644
--- a/README.md
+++ b/README.md
@@ -76,11 +76,14 @@ Set your package's manager with the `packageManager` field in `package.json`:
 ```
 
 Here, `yarn` is the name of the package manager, specified at version `3.2.3`,
-along with the SHA-224 hash of this version for validation.
-`packageManager@x.y.z` is required. The hash is optional but strongly
+along with the SHA-224 hash of this version for validation. The hash is optional but strongly
 recommended as a security practice. Permitted values for the package manager are
 `yarn`, `npm`, and `pnpm`.
 
+To set this string, it is recommended to use the
+[`corepack use` command](#corepack-use-nameversion), which will resolve the
+full version number and set the hash appropriately.
+
 ## Known Good Releases
 
 When running Corepack within projects that don't list a supported package
diff --git a/sources/commands/Base.ts b/sources/commands/Base.ts
index 01139766b..01dedf947 100644
--- a/sources/commands/Base.ts
+++ b/sources/commands/Base.ts
@@ -14,7 +14,7 @@ export abstract class BaseCommand extends Command<Context> {
 
     const resolvedSpecs = all
       ? await this.context.engine.getDefaultDescriptors()
-      : patterns.map(pattern => specUtils.parseSpec(pattern, `CLI arguments`, {enforceExactVersion: false}));
+      : patterns.map(pattern => specUtils.parseSpec(pattern, `CLI arguments`));
 
     if (resolvedSpecs.length === 0) {
       const lookup = await specUtils.loadSpec(this.context.cwd);
diff --git a/sources/commands/InstallGlobal.ts b/sources/commands/InstallGlobal.ts
index 788fb1f1b..14d146ff1 100644
--- a/sources/commands/InstallGlobal.ts
+++ b/sources/commands/InstallGlobal.ts
@@ -52,7 +52,7 @@ export class InstallGlobalCommand extends BaseCommand {
         if (arg.endsWith(`.tgz`)) {
           await this.installFromTarball(path.resolve(this.context.cwd, arg));
         } else {
-          await this.installFromDescriptor(specUtils.parseSpec(arg, `CLI arguments`, {enforceExactVersion: false}));
+          await this.installFromDescriptor(specUtils.parseSpec(arg, `CLI arguments`));
         }
       }
     } else {
diff --git a/sources/commands/Use.ts b/sources/commands/Use.ts
index aa75db9ae..e0d7df7ee 100644
--- a/sources/commands/Use.ts
+++ b/sources/commands/Use.ts
@@ -15,8 +15,14 @@ export class UseCommand extends BaseCommand {
       automatically perform an install.
     `,
     examples: [[
-      `Configure the project to use the latest Yarn release`,
-      `corepack use 'yarn@*'`,
+      `Configure the project to use the latest pnpm release`,
+      `corepack use pnpm`,
+    ], [
+      `Use a tagged version`,
+      `corepack use yarn@stable`,
+    ], [
+      `Use a partial version number`,
+      `corepack use 'yarn@3'`,
     ]],
   });
 
diff --git a/sources/commands/deprecated/Prepare.ts b/sources/commands/deprecated/Prepare.ts
index c9acc5107..19aad0937 100644
--- a/sources/commands/deprecated/Prepare.ts
+++ b/sources/commands/deprecated/Prepare.ts
@@ -58,7 +58,7 @@ export class PrepareCommand extends Command<Context> {
 
     for (const request of specs) {
       const spec = typeof request === `string`
-        ? specUtils.parseSpec(request, `CLI arguments`, {enforceExactVersion: false})
+        ? specUtils.parseSpec(request, `CLI arguments`)
         : request;
 
       const resolved = await this.context.engine.resolveDescriptor(spec, {allowTags: true});
diff --git a/sources/specUtils.ts b/sources/specUtils.ts
index f1bc1f434..1f3da7a0e 100644
--- a/sources/specUtils.ts
+++ b/sources/specUtils.ts
@@ -1,27 +1,29 @@
 import {UsageError}                                     from 'clipanion';
 import fs                                               from 'fs';
 import path                                             from 'path';
-import semver                                           from 'semver';
 
 import {Descriptor, Locator, isSupportedPackageManager} from './types';
 
 const nodeModulesRegExp = /[\\/]node_modules[\\/](@[^\\/]*[\\/])?([^@\\/][^\\/]*)$/;
 
-export function parseSpec(raw: unknown, source: string, {enforceExactVersion = true} = {}): Descriptor {
+export function parseSpec(raw: unknown, source: string): Descriptor {
   if (typeof raw !== `string`)
     throw new UsageError(`Invalid package manager specification in ${source}; expected a string`);
 
-  const match = raw.match(/^(?!_)(.+)@(.+)$/);
-  if (match === null || (enforceExactVersion && !semver.valid(match[2])))
-    throw new UsageError(`Invalid package manager specification in ${source}; expected a semver version${enforceExactVersion ? `` : `, range, or tag`}`);
+  const match = /^(@?[^@]+)(?:@(.+))?$/.exec(raw);
+  const name = match?.[1];
+  const range = match?.[2] ?? `*`;
 
-  if (!isSupportedPackageManager(match[1]))
+  if (!name) {
+    throw new UsageError(
+      `Invalid package manager specification in ${source}. Could not determine package manager name`,
+    );
+  }
+
+  if (!isSupportedPackageManager(name))
     throw new UsageError(`Unsupported package manager specification (${match})`);
 
-  return {
-    name: match[1],
-    range: match[2],
-  };
+  return {name, range};
 }
 
 /**
diff --git a/tests/main.test.ts b/tests/main.test.ts
index 3538ff3dd..fa5d2a07e 100644
--- a/tests/main.test.ts
+++ b/tests/main.test.ts
@@ -29,16 +29,16 @@ it(`should refuse to download a package manager if the hash doesn't match`, asyn
   });
 });
 
-it(`should require a version to be specified`, async () => {
+it(`should resolve version from package.json`, async () => {
   await xfs.mktempPromise(async cwd => {
     await xfs.writeJsonPromise(ppath.join(cwd, `package.json` as Filename), {
       packageManager: `yarn`,
     });
 
     await expect(runCli(cwd, [`yarn`, `--version`])).resolves.toMatchObject({
-      exitCode: 1,
+      exitCode: 0,
       stderr: ``,
-      stdout: /expected a semver version/,
+      stdout: /1\./,
     });
 
     await xfs.writeJsonPromise(ppath.join(cwd, `package.json` as Filename), {
@@ -46,9 +46,9 @@ it(`should require a version to be specified`, async () => {
     });
 
     await expect(runCli(cwd, [`yarn`, `--version`])).resolves.toMatchObject({
-      exitCode: 1,
+      exitCode: 0,
       stderr: ``,
-      stdout: /expected a semver version/,
+      stdout: /1\./,
     });
 
     await xfs.writeJsonPromise(ppath.join(cwd, `package.json` as Filename), {
@@ -56,9 +56,9 @@ it(`should require a version to be specified`, async () => {
     });
 
     await expect(runCli(cwd, [`yarn`, `--version`])).resolves.toMatchObject({
-      exitCode: 1,
+      exitCode: 0,
       stderr: ``,
-      stdout: /expected a semver version/,
+      stdout: /1\./,
     });
   });
 });