Repository: intuit/auto
Pull request #665 (2019-11-11 04:58:09)

Add JSDoc comment to most everything

<!-- GITHUB_RELEASE PR BODY: canary-version -->
Published PR with canary version: `7.13.1-canary.665.8729.0`
<!-- GITHUB_RELEASE PR BODY: canary-version -->



Patch:
diff --git a/.eslintrc b/.eslintrc
index d3d45d34..6caba959 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -14,7 +14,7 @@
     "prettier/@typescript-eslint"
   ],
 
-  "plugins": ["prettier", "jest", "@typescript-eslint"],
+  "plugins": ["prettier", "jest", "@typescript-eslint", "eslint-plugin-jsdoc"],
 
   "rules": {
     /* xo config */
@@ -48,7 +48,31 @@
     "@typescript-eslint/camelcase": 0,
     "@typescript-eslint/interface-name-prefix": 0,
     "@typescript-eslint/no-non-null-assertion": 0,
-    "@typescript-eslint/explicit-member-accessibility": 0
+    "@typescript-eslint/explicit-member-accessibility": 0,
+
+    /* jsdoc settings */
+    "jsdoc/check-alignment": 1,
+    "jsdoc/check-param-names": 1,
+    "jsdoc/check-tag-names": 1,
+    "jsdoc/implements-on-classes": 1,
+    "jsdoc/newline-after-description": 1,
+    "jsdoc/no-types": 1,
+    "jsdoc/require-param-description": 1,
+    "jsdoc/require-returns-check": 1,
+    "jsdoc/require-returns-description": 1,
+    "jsdoc/require-hyphen-before-param-description": [1, "always"],
+    "jsdoc/require-jsdoc": [
+      2,
+      {
+        "contexts": ["TSPropertySignature", "ClassProperty"],
+        "require": {
+          "ArrowFunctionExpression": true,
+          "FunctionDeclaration": true,
+          "ClassDeclaration": true,
+          "MethodDefinition": true
+        }
+      }
+    ]
   },
 
   "overrides": [
@@ -60,7 +84,8 @@
         "@typescript-eslint/no-explicit-any": 0,
         "require-atomic-updates": 0,
         "max-nested-callbacks": 0,
-        "@typescript-eslint/ban-ts-ignore": 0
+        "@typescript-eslint/ban-ts-ignore": 0,
+        "jsdoc/require-jsdoc": 0
       }
     }
   ]
diff --git a/docs/generate-command-docs.js b/docs/generate-command-docs.js
index e34dcb66..929a0690 100755
--- a/docs/generate-command-docs.js
+++ b/docs/generate-command-docs.js
@@ -30,6 +30,7 @@ commands.map(command => {
   }
 });
 
+fs.mkdirSync(path.join(__dirname, './pages/generated'));
 fs.writeFileSync(
   path.join(__dirname, './pages/generated/init.md'),
   initCommands.join('\n')
diff --git a/docs/pages/plugins.md b/docs/pages/plugins.md
index e2b1ed9f..d286e9c7 100644
--- a/docs/pages/plugins.md
+++ b/docs/pages/plugins.md
@@ -6,30 +6,14 @@
 
 To use a plugin you can either supply the plugin via a CLI arg or in your [.autorc](./autorc.md#plugins). Specifying a plugin overrides the defaults.
 
-::: message is-warning
-:warning: By default, `auto` defaults to use the `npm` plugin if you don't configure plugins in your `.autorc` configuration file.
-:::
-
-### None
-
-If you don't want to include the default plugins (ex: you're publishing to a platform other than npm), you can supply an empty array in the `.autorc` configuration file like the following:
-
-```json
-{
-  "plugins": []
-}
-```
-
 There are three ways to load a plugin.
 
 ### 1. Official Plugins
 
 To use an official plugin all you have to do is supply the name.
 
-```json
-{
-  "plugins": ["npm"]
-}
+```sh
+auto shipit --plugins npm
 ```
 
 ### 2. `npm` package
@@ -38,19 +22,33 @@ Unofficial plugins pulled from NPM should be named in the format `auto-plugin-PL
 
 That name is provided to auto to use that particular plugin.
 
-```json
-{
-  "plugins": ["auto-plugin-my-cool-plugin", "some-package"]
-}
+```sh
+auto shipit --plugins PLUGIN_NAME
 ```
 
 ### 3. Path
 
 Or if you have a plugin locally supply the path.
 
+```sh
+auto shipit --plugins ../path/to/plugin.js
+```
+
+### Multiple
+
+If you want to use multiple plugins you can supply multiple.
+
+```sh
+auto shipit --plugins npm NPM_PACKAGE_NAME ../path/to/plugin.js
+```
+
+### None
+
+By default, `auto` defaults to use the `npm` plugin if you don't supply anything in the `.autorc` configuration file. If you don't want to include any plugins, you can supply an empty array in the `.autorc` configuration file like the following:
+
 ```json
 {
-  "plugins": ["../path/to/plugin.js"]
+  "plugins": []
 }
 ```
 
diff --git a/docs/pages/writing-plugins.md b/docs/pages/writing-plugins.md
index 81c4f5ff..b58699d5 100644
--- a/docs/pages/writing-plugins.md
+++ b/docs/pages/writing-plugins.md
@@ -246,7 +246,7 @@ auto.hooks.version.tapPromise('NPM', async (version: SEMVER) => {
 });
 ```
 
-#### postVersion
+#### afterVersion
 
 Ran after the package has been versioned.
 
@@ -273,7 +273,7 @@ auto.hooks.publish.tapPromise('NPM', async (version: SEMVER) => {
 });
 ```
 
-#### postPublish
+#### afterPublish
 
 Ran after the package has been published.
 
@@ -368,7 +368,7 @@ auto.hooks.onCreateChangelog.tapPromise('Stars', changelog =>
 
 #### renderChangelogAuthorLine
 
-Change how the changelog renders authors in the authors section. The hook provides the author object and the user created with `renderChangelogAuthor`. Here is where you might display extra info about the author, such as thier full name,.
+Change how the changelog renders authors in the authors section. The hook provides the author object and the user created with `renderChangelogAuthor`. Here is where you might display extra info about the author, such as their full name.
 
 ```ts
 auto.hooks.onCreateChangelog.tapPromise('Stars', changelog =>
diff --git a/lerna.json b/lerna.json
index 8ad3cac3..cac5af3d 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,5 +1,5 @@
 {
-  "version": "7.13.1",
+  "version": "7.13.0",
   "npmClient": "yarn",
   "useWorkspaces": true,
   "packages": [
diff --git a/package.json b/package.json
index d547bec4..87bda8f5 100644
--- a/package.json
+++ b/package.json
@@ -51,6 +51,7 @@
     "eslint-config-xo": "^0.27.1",
     "eslint-plugin-import": "^2.18.2",
     "eslint-plugin-jest": "^23.0.1",
+    "eslint-plugin-jsdoc": "^17.1.1",
     "eslint-plugin-prettier": "^3.1.1",
     "graphql": "^14.2.1",
     "husky": "^3.0.3",
diff --git a/packages/cli/package.json b/packages/cli/package.json
index bab63513..9a03b328 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -2,7 +2,7 @@
   "name": "auto",
   "bin": "dist/bin/auto.js",
   "description": "CLI tools to help facilitate semantic versioning based on GitHub PR labels",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "author": {
     "name": "Andrew Lisowski",
     "email": "lisowski54@gmail.com"
diff --git a/packages/cli/src/parse-args.ts b/packages/cli/src/parse-args.ts
index 57aab0b3..a0a35ac5 100644
--- a/packages/cli/src/parse-args.ts
+++ b/packages/cli/src/parse-args.ts
@@ -483,12 +483,14 @@ export const commands: Command[] = [
   }
 ];
 
+/** Print the current version of "auto" */
 function printVersion() {
   const packagePath = path.join(__dirname, '../package.json');
   const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
   console.log(`v${packageJson.version}`);
 }
 
+/** Parse the CLI args and return command + options provided. */
 export default function parseArgs(testArgs?: string[]) {
   const mainOptions = app(
     {
diff --git a/packages/cli/src/run.ts b/packages/cli/src/run.ts
index c708769c..8c4e6bfa 100644
--- a/packages/cli/src/run.ts
+++ b/packages/cli/src/run.ts
@@ -16,6 +16,7 @@ import Auto, {
   IVersionOptions
 } from '@auto-it/core';
 
+/** Spin up the "auto" node API and provide it the parsed CLI args. */
 export async function run(command: string, args: ApiOptions) {
   const auto = new Auto(args);
 
@@ -72,6 +73,7 @@ export async function run(command: string, args: ApiOptions) {
   }
 }
 
+/** Run "auto" for a given command. */
 export default async function main(command: string, args: ApiOptions) {
   try {
     await run(command, args);
diff --git a/packages/core/package.json b/packages/core/package.json
index 43b29e64..3d3a353b 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@auto-it/core",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "description": "Node API for using auto.",
   "main": "dist/auto.js",
   "author": {
diff --git a/packages/core/src/auto-args.ts b/packages/core/src/auto-args.ts
index 001e49f7..045b6333 100644
--- a/packages/core/src/auto-args.ts
+++ b/packages/core/src/auto-args.ts
@@ -1,96 +1,145 @@
-interface IAuthorOptions {
+export interface IAuthorOptions {
+  /** Author's name */
   name?: string;
+  /** Author's email */
   email?: string;
 }
 
 export interface IRepoOptions {
+  /** Github repo owner (user) */
   owner?: string;
+  /** GitHub project to operate on */
   repo?: string;
 }
 
 export interface ILogOptions {
+  /** Show more logs */
   verbose?: boolean;
+  /** Show a lot more logs */
   veryVerbose?: boolean;
 }
 
 export interface IInitOptions {
+  /** Only show prompts for creating labels */
   onlyLabels?: boolean;
+  /** Do not actually do anything */
   dryRun?: boolean;
 }
 
 export interface ICreateLabelsOptions {
+  /** Do not actually do anything */
   dryRun?: boolean;
 }
 
 export interface ILabelOptions {
+  /** PR to get the labels for */
   pr?: number;
 }
 
 export interface IPRCheckOptions {
+  /** PR to check the label for */
   pr?: number;
+  /** URL to attach to the checkmark */
   url?: string;
+  /** Labels to count as "skip-release" */
   skipReleaseLabels?: string[];
+  /** The context the check should be attached to */
   context?: string;
+  /** Do not actually do anything */
   dryRun?: boolean;
 }
 
 export interface IPRStatusOptions {
+  /** The commit to attach a check to */
   sha?: string;
+  /** The pr to attach a check to */
   pr?: number;
+  /** URL to attach to the checkmark */
   url: string;
+  /** The state to set the checkmark to */
   state: 'pending' | 'success' | 'error' | 'failure';
+  /** The description to attach to the checkmark */
   description: string;
+  /** The context the check should be attached to */
   context: string;
+  /** Do not actually do anything */
   dryRun?: boolean;
 }
 
 export interface IVersionOptions {
+  /** Labels to count as "skip-release" */
   skipReleaseLabels?: string[];
+  /** Instead of publishing every PR only publish when "release" label is present */
   onlyPublishWithReleaseLabel?: boolean;
+  /** Commit to start calculating the version from */
   from?: string;
 }
 
 export interface IChangelogOptions extends IAuthorOptions {
+  /** Whether to prefix the version with a "v" */
   noVersionPrefix?: boolean;
+  /** Do not actually do anything */
   dryRun?: boolean;
+  /** Commit to start calculating the changelog from */
   from?: string;
+  /** Commit to start calculating the changelog to */
   to?: string;
+  /** The commit message to commit the changelog changes with */
   message?: string;
 }
 
 export interface IReleaseOptions extends IAuthorOptions {
+  /** Whether to prefix the version with a "v" */
   noVersionPrefix?: boolean;
+  /** Do not actually do anything */
   dryRun?: boolean;
+  /** Commit to start calculating the release from */
   from?: string;
+  /** Override the version to release */
   useVersion?: string;
 }
 
 export interface ICommentOptions {
+  /** The message to use when commenting */
   message?: string;
+  /** THe PR to comment on */
   pr?: number;
+  /** The context the message should be attached to. Use to post multiple comments to a PR */
   context?: string;
+  /** Do not actually do anything */
   dryRun?: boolean;
+  /** Delete the previous comment */
   delete?: boolean;
+  /** Instead of deleting/adding a new comment. Just edit the old one */
   edit?: boolean;
 }
 
 export type IPRBodyOptions = ICommentOptions;
 
 export interface IShipItOptions {
+  /** Do not actually do anything */
   dryRun?: boolean;
 }
 
 export interface ICanaryOptions {
+  /** Do not actually do anything */
   dryRun?: boolean;
+  /** THe PR to attach the canary to */
   pr?: number;
+  /** The build to attach the canary to */
   build?: number;
+  /** THe message used when attaching the canary version to a PR */
   message?: string | 'false';
 }
 
 export type GlobalOptions = {
+  /** The GitHub api to communicate with through octokit */
   githubApi?: string;
+  /** The branch that is used as the base. defaults to master */
   baseBranch?: string;
+  /** The GitHub graphql api to communicate with through octokit */
   githubGraphqlApi?: string;
+  /** Plugins to initialize "auto" with */
   plugins?: string[];
 } & IRepoOptions &
   ILogOptions;
diff --git a/packages/core/src/auto.ts b/packages/core/src/auto.ts
index 424ac22e..86277a99 100644
--- a/packages/core/src/auto.ts
+++ b/packages/core/src/auto.ts
@@ -42,75 +42,94 @@ import execPromise from './utils/exec-promise';
 import loadPlugin, { IPlugin } from './utils/load-plugins';
 import createLog, { ILogger } from './utils/logger';
 import { makeHooks } from './utils/make-hooks';
+import { IAuthorOptions, IRepoOptions } from './auto-args';
 
 const proxyUrl = process.env.https_proxy || process.env.http_proxy;
 const env = envCi();
 
-interface IAuthor {
-  name?: string;
-  email?: string;
+interface ChangelogLifecycle {
+  /** The bump being applied to the version */
+  bump: SEMVER;
+  /** The commits included in the changelog */
+  commits: IExtendedCommit[];
+  /** The generated release notes for the commits */
+  releaseNotes: string;
+  /** The current version of the project */
+  currentVersion: string;
+  /** The last version of the project */
+  lastRelease: string;
 }
 
-interface IRepository {
-  owner?: string;
-  repo?: string;
+interface TestingToken {
+  /** A token used for testing */
   token?: string;
 }
 
 export interface IAutoHooks {
+  /** Modify what is in the config. You must return the config in this hook. */
   modifyConfig: SyncWaterfallHook<[IAutoConfig]>;
+  /** Happens before anything is done. This is a great place to check for platform specific secrets. */
   beforeRun: SyncHook<[IAutoConfig]>;
+  /** Happens before `shipit` is run. This is a great way to throw an error if a token or key is not present. */
   beforeShipIt: SyncHook<[]>;
-  beforeCommitChangelog: AsyncSeriesHook<
-    [
-      {
-        bump: SEMVER;
-        commits: IExtendedCommit[];
-        releaseNotes: string;
-        currentVersion: string;
-        lastRelease: string;
-      }
-    ]
-  >;
-  afterAddToChangelog: AsyncSeriesHook<
-    [
-      {
-        bump: SEMVER;
-        commits: IExtendedCommit[];
-        releaseNotes: string;
-        currentVersion: string;
-        lastRelease: string;
-      }
-    ]
-  >;
+  /** Ran before the `changelog` command commits the new release notes to `CHANGELOG.md`. */
+  beforeCommitChangelog: AsyncSeriesHook<[ChangelogLifecycle]>;
+  /** Ran after the `changelog` command adds the new release notes to `CHANGELOG.md`. */
+  afterAddToChangelog: AsyncSeriesHook<[ChangelogLifecycle]>;
+  /** Ran after the `shipit` command has run. */
   afterShipIt: AsyncParallelHook<[string | undefined, IExtendedCommit[]]>;
+  /** Ran after the `release` command has run. */
   afterRelease: AsyncParallelHook<
     [
       {
+        /** The last version released */
         lastRelease: string;
+        /** The version being released */
         newVersion?: string;
+        /** The commits included in the release */
         commits: IExtendedCommit[];
+        /** The generated release notes for the commits */
         releaseNotes: string;
+        /** The response from creating the new release. */
         response?: Response<ReposCreateReleaseResponse>;
       }
     ]
   >;
-  getAuthor: AsyncSeriesBailHook<[], IAuthor | void>;
+  /** Get git author. Typically from a package distribution description file. */
+  getAuthor: AsyncSeriesBailHook<[], IAuthorOptions | void>;
+  /** Get the previous version. Typically from a package distribution description file. */
   getPreviousVersion: AsyncSeriesBailHook<
     [(release: string) => string],
     string
   >;
-  getRepository: AsyncSeriesBailHook<[], IRepository | void>;
+  /** Get owner and repository. Typically from a package distribution description file. */
+  getRepository: AsyncSeriesBailHook<[], IRepoOptions & TestingToken | void>;
+  /** Tap into the things the Release class makes. This isn't the same as `auto release`, but the main class that does most of the work. */
   onCreateRelease: SyncHook<[Release]>;
+  /** This is where you hook into the LogParse's hooks. This hook is exposed for convenience on during `this.hooks.onCreateRelease` and at the root `this.hooks` */
   onCreateLogParse: SyncHook<[LogParse]>;
+  /** This is where you hook into the changelog's hooks.  This hook is exposed for convenience on during `this.hooks.onCreateRelease` and at the root `this.hooks` */
   onCreateChangelog: SyncHook<[Changelog, SEMVER | undefined]>;
+  /** Version the package. This is a good opportunity to `git tag` the release also.  */
   version: AsyncParallelHook<[SEMVER]>;
+  /** Ran after the package has been versioned. */
   afterVersion: AsyncParallelHook<[]>;
+  /** Publish the package to some package distributor. You must push the tags to github! */
   publish: AsyncParallelHook<[SEMVER]>;
-  canary: AsyncSeriesBailHook<[SEMVER, string], string | { error: string }>;
+  /** Used to publish a canary release. In this hook you get the semver bump and the unique canary postfix ID. */
+  canary: AsyncSeriesBailHook<
+    [SEMVER, string],
+    | string
+    | {
+        /** Error when creating the canary release */
+        error: string;
+      }
+  >;
+  /** Ran after the package has been published. */
   afterPublish: AsyncParallelHook<[]>;
 }
 
+/** Load the .env file into process.env. Useful for local usage. */
 const loadEnv = () => {
   const envFile = path.resolve(process.cwd(), '.env');
 
@@ -125,20 +144,35 @@ const loadEnv = () => {
   });
 };
 
+/**
+ * The "auto" node API. Its public interface matches the
+ * commands you can run from the CLI
+ */
 export default class Auto {
+  /** Plugin entry points */
   hooks: IAutoHooks;
+  /** A logger that uses log levels */
   logger: ILogger;
+  /** Options auto was initialized with */
   options: ApiOptions;
+  /** The branch auto uses as master. */
   baseBranch: string;
+  /** The user configuration of auto (.autorc) */
   config?: IAutoConfig;
 
+  /** A class that handles creating releases */
   release?: Release;
+  /** A class that handles interacting with git and GitHub */
   git?: Git;
+  /** The labels configured by the user */
   labels?: ILabelDefinitionMap;
+  /** A map of semver bumps to labels that signify those bumps */
   semVerLabels?: IVersionLabels;
 
+  /** The version bump being used during "shipit" */
   private versionBump?: SEMVER;
 
+  /** Initialize auto and it's environment */
   constructor(options: ApiOptions = {}) {
     this.options = options;
     this.baseBranch = options.baseBranch || 'master';
@@ -227,7 +261,7 @@ export default class Auto {
   /**
    * Create all of the user's labels on the git remote if the don't already exist
    *
-   * @param options Options for the createLabels functionality
+   * @param options - Options for the createLabels functionality
    */
   async createLabels(options: ICreateLabelsOptions = {}) {
     if (!this.release || !this.labels) {
@@ -240,7 +274,7 @@ export default class Auto {
   /**
    * Get the labels on a specific PR. Defaults to the labels of the last merged PR
    *
-   * @param options Options for the createLabels functionality
+   * @param options - Options for the createLabels functionality
    */
   async label({ pr }: ILabelOptions = {}) {
     if (!this.git) {
@@ -276,7 +310,7 @@ export default class Auto {
   /**
    * Create a status on a PR.
    *
-   * @param options Options for the pr status functionality
+   * @param options - Options for the pr status functionality
    */
   async prStatus({ dryRun, pr, url, ...options }: IPRStatusOptions) {
     if (!this.git) {
@@ -305,7 +339,6 @@ export default class Auto {
 
     this.logger.verbose.info('Found PR SHA:', sha);
 
-    // tslint:disable-next-line variable-name
     const target_url = url;
 
     if (dryRun) {
@@ -332,7 +365,7 @@ export default class Auto {
   /**
    * Check that a PR has a SEMVER label. Set a success status on the PR.
    *
-   * @param options Options for the pr check functionality
+   * @param options - Options for the pr check functionality
    */
   async prCheck({ dryRun, pr, url, ...options }: IPRCheckOptions) {
     if (!this.git || !this.release || !this.semVerLabels) {
@@ -341,7 +374,6 @@ export default class Auto {
 
     this.logger.verbose.info(`Using command: 'pr-check' for '${url}'`);
 
-    // tslint:disable-next-line variable-name
     const target_url = url;
     const prNumber = this.getPrNumber('prCheck', pr);
     let msg;
@@ -423,7 +455,7 @@ export default class Auto {
    * Comment on a PR. Only one comment will be present on the PR, Older comments are removed.
    * You can use the "context" option to multiple comments on a PR.
    *
-   * @param options Options for the comment functionality
+   * @param options - Options for the comment functionality
    */
   async comment(options: ICommentOptions) {
     const {
@@ -480,7 +512,7 @@ export default class Auto {
    * Older messages are removed. You can use the "context" option to multiple message
    * in a PR body.
    *
-   * @param options Options
+   * @param options - Options
    */
   async prBody(options: ICommentOptions) {
     const {
@@ -546,6 +578,7 @@ export default class Auto {
     await this.makeRelease(options);
   }
 
+  /** Create a canary (or test) version of the project */
   async canary(options: ICanaryOptions = {}) {
     if (!this.git || !this.release) {
       throw this.createErrorMessage();
@@ -668,6 +701,7 @@ export default class Auto {
     await this.hooks.afterShipIt.promise(newVersion, commitsInRelease);
   }
 
+  /** Get the latest version number of the project */
   async getCurrentVersion(lastRelease: string) {
     this.hooks.getPreviousVersion.tap('None', () => {
       this.logger.veryVerbose.info(
@@ -701,6 +735,7 @@ export default class Auto {
     }
   }
 
+  /** On master: publish a new latest version */
   private async publishLatest(options: IShipItOptions) {
     if (!this.git || !this.release) {
       throw this.createErrorMessage();
@@ -750,6 +785,7 @@ export default class Auto {
     return { newVersion, commitsInRelease };
   }
 
+  /** Get a pr number from user input or the env */
   private getPrNumber(command: string, pr?: number) {
     const envPr = 'pr' in env && Number(env.pr);
     const prNumber = pr || envPr;
@@ -763,6 +799,7 @@ export default class Auto {
     return prNumber;
   }
 
+  /** Create a client to interact with git */
   private startGit(gitOptions: IGitOptions) {
     if (!gitOptions.owner || !gitOptions.repo || !gitOptions.token) {
       throw new Error('Must set owner, repo, and GitHub token.');
@@ -790,6 +827,7 @@ export default class Auto {
     );
   }
 
+  /** Calculate a version from a tag using labels */
   private async getVersion({ from }: IVersionOptions = {}) {
     if (!this.git || !this.release) {
       throw this.createErrorMessage();
@@ -802,6 +840,7 @@ export default class Auto {
     return bump;
   }
 
+  /** Make a changelog over a range of commits */
   private async makeChangelog({
     dryRun,
     from,
@@ -855,6 +894,7 @@ export default class Auto {
     await this.hooks.afterAddToChangelog.promise(options);
   }
 
+  /** Make a release over a range of commits */
   private async makeRelease({
     dryRun,
     from,
@@ -934,6 +974,7 @@ export default class Auto {
     return newVersion;
   }
 
+  /** Prefix a version with a "v" if needed */
   private readonly prefixRelease = (release: string) => {
     if (!this.release) {
       throw this.createErrorMessage();
@@ -944,6 +985,7 @@ export default class Auto {
       : `v${release}`;
   };
 
+  /** Create an auto initialization error */
   private createErrorMessage() {
     return new Error(
       `Auto is not initialized! Make sure the have run Auto.loadConfig`
@@ -1003,9 +1045,10 @@ If a command fails manually run:
     }
   }
 
+  /** Get the repo to interact with */
   private async getRepo(config: IAutoConfig) {
     if (config.owner && config.repo) {
-      return config as IRepository;
+      return config as IRepoOptions & TestingToken;
     }
 
     return this.hooks.getRepository.promise();
diff --git a/packages/core/src/changelog.ts b/packages/core/src/changelog.ts
index d58f924b..9810dc17 100644
--- a/packages/core/src/changelog.ts
+++ b/packages/core/src/changelog.ts
@@ -8,10 +8,15 @@ import { ILogger } from './utils/logger';
 import { makeChangelogHooks } from './utils/make-hooks';
 
 export interface IGenerateReleaseNotesOptions {
+  /** Github repo owner (user) */
   owner: string;
+  /** GitHub project to operate on */
   repo: string;
+  /** The URL to the GitHub (public or enterprise) the project is using */
   baseUrl: string;
+  /** The labels configured by the user */
   labels: ILabelDefinitionMap;
+  /** The branch that is used as the base. defaults to master */
   baseBranch: string;
 }
 
@@ -20,36 +25,57 @@ interface ICommitSplit {
 }
 
 export interface IChangelogHooks {
+  /** Change how the changelog renders lines. */
   renderChangelogLine: AsyncSeriesWaterfallHook<[[IExtendedCommit, string]]>;
+  /** Change how the changelog renders titles */
   renderChangelogTitle: AsyncSeriesBailHook<
     [string, { [label: string]: string }],
     string | void
   >;
+  /** Change how the changelog renders authors. This is both the author on each commit note and the user in the author section (the part between parentheses). This is generally a link to some profile. */
   renderChangelogAuthor: AsyncSeriesBailHook<
     [ICommitAuthor, IExtendedCommit, IGenerateReleaseNotesOptions],
     string | void
   >;
+  /** Change how the changelog renders authors in the authors section. The hook provides the author object and the user created with `renderChangelogAuthor`. Here is where you might display extra info about the author, such as their full name. */
   renderChangelogAuthorLine: AsyncSeriesBailHook<
     [ICommitAuthor, string],
     string | void
   >;
+  /**
+   * Add extra content to your changelogs. This hook provide
+   * all the current "extra" notes and all of the commits for
+   * the changelog.
+   */
   addToBody: AsyncSeriesWaterfallHook<[string[], IExtendedCommit[]]>;
+  /** Control what commits effect the additional release notes section. */
   omitReleaseNotes: AsyncSeriesBailHook<[IExtendedCommit], boolean | void>;
 }
 
+/** Determine how deep the markdown headers are in a string */
 const getHeaderDepth = (line: string) =>
   line.split('').reduce((count, char) => (char === '#' ? count + 1 : count), 0);
 
+/** Filter for only commits that have a specific label */
 const filterLabel = (commits: IExtendedCommit[], label: string) =>
   commits.filter(commit => commit.labels.includes(label));
 
+/**
+ * Manages creating the "Release Notes" that are included in
+ * both the CHANGELOG.md and GitHub releases.
+ */
 export default class Changelog {
+  /** Plugin entry points */
   readonly hooks: IChangelogHooks;
+  /** The options the changelog was initialized with */
   readonly options: IGenerateReleaseNotesOptions;
 
+  /** The authors in the current changelog */
   private authors?: [IExtendedCommit, ICommitAuthor][];
+  /** A logger that uses log levels */
   private readonly logger: ILogger;
 
+  /** Initialize the changelog generator with default hooks and labels */
   constructor(logger: ILogger, options: IGenerateReleaseNotesOptions) {
     this.logger = logger;
     this.options = options;
@@ -69,6 +95,7 @@ export default class Changelog {
       : [pushToMasterLabel];
   }
 
+  /** Load the default configuration */
   loadDefaultHooks() {
     this.hooks.renderChangelogAuthor.tap('Default', (author, commit) =>
       this.createUserLink(author, commit)
@@ -102,6 +129,7 @@ export default class Changelog {
     });
   }
 
+  /** Generate the release notes for a group of commits */
   async generateReleaseNotes(commits: IExtendedCommit[]): Promise<string> {
     if (commits.length === 0) {
       return '';
@@ -133,6 +161,7 @@ export default class Changelog {
     return result;
   }
 
+  /** Create a link to a user for use in the changelog */
   createUserLink(author: ICommitAuthor, commit: IExtendedCommit) {
     const githubUrl = new URL(this.options.baseUrl).origin;
 
@@ -145,9 +174,7 @@ export default class Changelog {
       : author.email || commit.authorEmail;
   }
 
-  /**
-   * Split commits into changelogTitle sections.
-   */
+  /** Split commits into changelogTitle sections. */
   private splitCommits(commits: IExtendedCommit[]): ICommitSplit {
     let currentCommits = [...commits];
     const order = ['major', 'minor', 'patch'];
@@ -190,6 +217,7 @@ export default class Changelog {
     );
   }
 
+  /** Get the default label for a label key */
   private getFirstLabelNameFromLabelKey(
     labels: ILabelDefinitionMap,
     labelKey: string
@@ -200,6 +228,7 @@ export default class Changelog {
     );
   }
 
+  /** Create a list of users */
   private async createUserLinkList(commit: IExtendedCommit) {
     const result = new Set<string>();
 
@@ -233,6 +262,7 @@ export default class Changelog {
     return [...result].join(' ');
   }
 
+  /** Transform a commit into a line in the changelog */
   private async generateCommitNote(commit: IExtendedCommit) {
     const subject = commit.subject ? commit.subject.trim() : '';
     let pr = '';
@@ -250,6 +280,7 @@ export default class Changelog {
     return `- ${subject} ${pr}${user ? ` (${user})` : ''}`;
   }
 
+  /** Get all the authors in the provided commits */
   private getAllAuthors(split: ICommitSplit) {
     const commits = Object.values(split).reduce(
       (
@@ -273,6 +304,7 @@ export default class Changelog {
       .sort(a => ('id' in a[1] ? 0 : 1));
   }
 
+  /** Create a section in the changelog to showcase contributing authors */
   private async createAuthorSection(sections: string[]) {
     const authors = new Set<string>();
     const authorsWithFullData = this.authors!.map(
@@ -306,10 +338,11 @@ export default class Changelog {
     }
 
     let authorSection = `#### Authors: ${authors.size}\n\n`;
-    authorSection += [...authors].join('\n');
+    authorSection += [...authors].sort((a, b) => a.localeCompare(b)).join('\n');
     sections.push(authorSection);
   }
 
+  /** Create a section in the changelog to with all of the changelog notes organized by change type */
   private async createLabelSection(split: ICommitSplit, sections: string[]) {
     const changelogTitles = Object.entries(this.options.labels).reduce(
       (titles, [, labels]) => {
@@ -364,6 +397,7 @@ export default class Changelog {
       .map(section => sections.push(section));
   }
 
+  /** Gather extra release notes to display at the top of the changelog */
   private async createReleaseNotesSection(
     commits: IExtendedCommit[],
     sections: string[]
diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts
index d03224a1..6a2eef2c 100644
--- a/packages/core/src/config.ts
+++ b/packages/core/src/config.ts
@@ -16,6 +16,7 @@ import tryRequire from './utils/try-require';
 // eslint-disable-next-line @typescript-eslint/no-explicit-any
 type ConfigObject = any;
 
+/** Transform all types of label configuration into just 1 shape */
 export function normalizeLabel(
   name: string,
   label:
@@ -42,6 +43,10 @@ export function normalizeLabel(
   return [{ ...baseLabel, ...label }];
 }
 
+/**
+ * Go through all the labels in a config and make them
+ * follow the same format.
+ */
 export function normalizeLabels(config: ConfigObject) {
   let labels = defaultLabelDefinition;
 
@@ -60,9 +65,12 @@ export function normalizeLabels(config: ConfigObject) {
   return labels;
 }
 
+/** Load a user's configuration from the system and resolve any extended config */
 export default class Config {
+  /** A logger that uses log levels */
   logger: ILogger;
 
+  /** Initialize the config loader */
   constructor(logger: ILogger) {
     this.logger = logger;
   }
@@ -123,10 +131,15 @@ export default class Config {
    * ex: auto-config-MY_CONFIG
    * ex: @MY_CONFIG/auto-config
    *
-   * @param extend Path or name of config to find
+   * @param extend - Path or name of config to find
    */
   async loadExtendConfig(extend: string) {
-    let config: ConfigObject | { auto: ConfigObject };
+    let config:
+      | ConfigObject
+      | {
+          /** package.json field with auto config */
+          auto: ConfigObject;
+        };
 
     if (extend.endsWith('.js') || extend.endsWith('.mjs')) {
       throw new Error('Extended config cannot be a JavaScript file');
diff --git a/packages/core/src/git.ts b/packages/core/src/git.ts
index a9e117c2..dd2ff484 100644
--- a/packages/core/src/git.ts
+++ b/packages/core/src/git.ts
@@ -24,15 +24,23 @@ type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>> &
 export type IPRInfo = Omit<Octokit.ReposCreateStatusParams, 'owner' | 'repo'>;
 
 export interface IGitOptions {
+  /** Github repo owner (user) */
   owner: string;
+  /** GitHub project to operate on */
   repo: string;
+  /** The URL to the GitHub (public or enterprise) the project is using */
   baseUrl?: string;
+  /** The URL to the GitHub graphql API (public or enterprise) the project is using */
   graphqlBaseUrl?: string;
+  /** A token to auth to GitHub with */
   token?: string;
+  /** An optional proxy agent to route requests through */
   agent?: HttpsProxyAgent;
 }
 
+/** An error originating from the GitHub */
 class GitAPIError extends Error {
+  /** Extend the base error */
   constructor(api: string, args: object, origError: Error) {
     super(
       `Error calling github: ${api}\n\twith: ${JSON.stringify(args)}.\n\t${
@@ -42,25 +50,45 @@ class GitAPIError extends Error {
   }
 }
 
+/** Make a comment to build automation in PRs off of. */
 const makeIdentifier = (type: string, context: string) =>
   `<!-- GITHUB_RELEASE ${type}: ${context} -->`;
 
+/** Make an identifier for `auto comment` */
 const makeCommentIdentifier = (context: string) =>
   makeIdentifier('COMMENT', context);
 
+/** Make an identifier for `auto pr-body` */
 const makePrBodyIdentifier = (context: string) =>
   makeIdentifier('PR BODY', context);
 
-// A class to interact with the local git instance and the git remote.
-// currently it only interfaces with GitHub.
+interface ThrottleOpts {
+  /** The request object */
+  request: { /** What retry we are on */ retryCount: number };
+  /** API method that was throttled */
+  method: string;
+  /** URL that was throttled */
+  url: string;
+}
+
+/**
+ * A class to interact with the local git instance and the git remote.
+ * currently it only interfaces with GitHub.
+ */
 export default class Git {
+  /** An octokit instance to use to interact with GitHub */
   readonly github: Octokit;
+  /** Options the git client was initialized with */
   readonly options: IGitOptions;
 
+  /** The GitHub api to communicate with through octokit */
   private readonly baseUrl: string;
+  /** The GitHub graphql api to communicate with through octokit */
   private readonly graphqlBaseUrl: string;
+  /** A logger that uses log levels */
   private readonly logger: ILogger;
 
+  /** Initialize the git interface and auth with GitHub */
   constructor(options: IGitOptions, logger: ILogger = dummyLog()) {
     this.logger = logger;
     this.options = options;
@@ -76,10 +104,7 @@ export default class Git {
       auth: this.options.token,
       previews: ['symmetra-preview'],
       throttle: {
-        onRateLimit: (
-          retryAfter: number,
-          opts: { request: { retryCount: number }; method: string; url: string }
-        ) => {
+        onRateLimit: (retryAfter: number, opts: ThrottleOpts) => {
           this.logger.log.warn(
             `Request quota exhausted for request ${opts.method} ${opts.url}`
           );
@@ -89,10 +114,7 @@ export default class Git {
             return true;
           }
         },
-        onAbuseLimit: (
-          retryAfter: number,
-          opts: { request: { retryCount: number }; method: string; url: string }
-        ) => {
+        onAbuseLimit: (retryAfter: number, opts: ThrottleOpts) => {
           // does not retry, only logs an error
           this.logger.log.error(
             `Went over abuse rate limit ${opts.method} ${opts.url}`
@@ -109,6 +131,7 @@ export default class Git {
     });
   }
 
+  /** Get the "Latest Release" from GitHub */
   @memoize()
   async getLatestReleaseInfo() {
     const latestRelease = await this.github.repos.getLatestRelease({
@@ -119,6 +142,7 @@ export default class Git {
     return latestRelease.data;
   }
 
+  /** Get the "Latest Release" or the first commit SHA as a fallback */
   @memoize()
   async getLatestRelease(): Promise<string> {
     try {
@@ -143,6 +167,7 @@ export default class Git {
     }
   }
 
+  /** Get the date a commit sha was created */
   async getCommitDate(sha: string): Promise<string> {
     const date = await execPromise('git', ['show', '-s', '--format=%ci', sha]);
     const [day, time, timezone] = date.split(' ');
@@ -150,14 +175,13 @@ export default class Git {
     return `${day}T${time}${timezone}`;
   }
 
+  /** Get the first commit for the repo */
   async getFirstCommit(): Promise<string> {
     const list = await execPromise('git', ['rev-list', 'HEAD']);
     return list.split('\n').pop() as string;
   }
 
-  /**
-   * Get the SHA of the latest commit
-   */
+  /** Get the SHA of the latest commit */
   async getSha(short?: boolean): Promise<string> {
     const result = await execPromise('git', [
       'rev-parse',
@@ -170,6 +194,7 @@ export default class Git {
     return result;
   }
 
+  /** Get the labels for a PR */
   @memoize()
   async getLabels(prNumber: number) {
     this.logger.verbose.info(`Getting labels for PR: ${prNumber}`);
@@ -196,6 +221,7 @@ export default class Git {
     }
   }
 
+  /** Get all the information about a PR or issue */
   @memoize()
   async getPr(prNumber: number) {
     this.logger.verbose.info(`Getting info for PR: ${prNumber}`);
@@ -217,6 +243,7 @@ export default class Git {
     }
   }
 
+  /** Get the labels for a the project */
   async getProjectLabels() {
     this.logger.verbose.info(
       `Getting labels for project: ${this.options.repo}`
@@ -241,6 +268,7 @@ export default class Git {
     }
   }
 
+  /** Get the git log for a range of commits */
   @memoize()
   async getGitLog(start: string, end = 'HEAD'): Promise<ICommit[]> {
     try {
@@ -279,6 +307,7 @@ export default class Git {
     }
   }
 
+  /** Get the GitHub user for an email. Will not work if they do not have their email set to "public". */
   @memoize()
   async getUserByEmail(email: string) {
     try {
@@ -292,6 +321,7 @@ export default class Git {
     }
   }
 
+  /** Get the GitHub user for a username */
   @memoize()
   async getUserByUsername(username: string) {
     try {
@@ -305,6 +335,7 @@ export default class Git {
     }
   }
 
+  /** Get all the information about a PR or issue */
   @memoize()
   async getPullRequest(pr: number) {
     this.logger.verbose.info(`Getting Pull Request: ${pr}`);
@@ -325,6 +356,7 @@ export default class Git {
     return result;
   }
 
+  /** Search to GitHub project's issue and pull requests */
   async searchRepo(options: Octokit.SearchIssuesAndPullRequestsParams) {
     const repo = `repo:${this.options.owner}/${this.options.repo}`;
     options.q = `${repo} ${options.q}`;
@@ -339,6 +371,7 @@ export default class Git {
     return result.data;
   }
 
+  /** Run a graphql query on the GitHub project */
   async graphql(query: string) {
     this.logger.verbose.info('Querying Github using GraphQL:\n', query);
 
@@ -353,6 +386,7 @@ export default class Git {
     return data;
   }
 
+  /** Create a status (or checkmark) on a commit */
   async createStatus(prInfo: IPRInfo) {
     const args = {
       ...prInfo,
@@ -370,6 +404,7 @@ export default class Git {
     return result;
   }
 
+  /** Add a label to the project */
   async createLabel(name: string, label: ILabelDefinition) {
     this.logger.verbose.info(`Creating "${name}" label :\n${label.name}`);
 
@@ -390,6 +425,7 @@ export default class Git {
     return result;
   }
 
+  /** Update a label on the project */
   async updateLabel(name: string, label: ILabelDefinition) {
     this.logger.verbose.info(`Updating "${name}" label :\n${label.name}`);
 
@@ -411,6 +447,7 @@ export default class Git {
     return result;
   }
 
+  /** Add a label to and issue or pull request */
   async addLabelToPr(pr: number, label: string) {
     this.logger.verbose.info(`Creating "${label}" label to PR ${pr}`);
 
@@ -427,6 +464,7 @@ export default class Git {
     return result;
   }
 
+  /** Lock an issue */
   async lockIssue(issue: number) {
     this.logger.verbose.info(`Locking #${issue} issue...`);
 
@@ -442,6 +480,7 @@ export default class Git {
     return result;
   }
 
+  /** Get information about the GitHub project */
   @memoize()
   async getProject() {
     this.logger.verbose.info('Getting project from GitHub');
@@ -457,6 +496,7 @@ export default class Git {
     return result;
   }
 
+  /** Get all the pull requests for a project */
   async getPullRequests(options?: Partial<Octokit.PullsListParams>) {
     this.logger.verbose.info('Getting pull requests...');
 
@@ -472,6 +512,7 @@ export default class Git {
     return result;
   }
 
+  /** Get all the commits for a PR */
   @memoize()
   async getCommitsForPR(
     pr: number
@@ -492,6 +533,7 @@ export default class Git {
     return result;
   }
 
+  /** Find a comment that is using the context in a PR */
   async getCommentId(pr: number, context = 'default') {
     const commentIdentifier = makeCommentIdentifier(context);
 
@@ -517,6 +559,7 @@ export default class Git {
     return oldMessage.id;
   }
 
+  /** Delete a comment on an issue or pull request */
   async deleteComment(pr: number, context = 'default') {
     const commentId = await this.getCommentId(pr, context);
 
@@ -533,6 +576,7 @@ export default class Git {
     this.logger.verbose.info(`Successfully deleted comment: ${commentId}`);
   }
 
+  /** Create a comment on an issue or pull request */
   async createComment(message: string, pr: number, context = 'default') {
     const commentIdentifier = makeCommentIdentifier(context);
 
@@ -555,6 +599,7 @@ export default class Git {
     return result;
   }
 
+  /** Edit a comment on an issue or pull request */
   async editComment(message: string, pr: number, context = 'default') {
     const commentIdentifier = makeCommentIdentifier(context);
 
@@ -578,6 +623,7 @@ export default class Git {
     return result;
   }
 
+  /** Create a comment on a pull request body */
   async addToPrBody(message: string, pr: number, context = 'default') {
     const id = makePrBodyIdentifier(context);
 
@@ -617,6 +663,7 @@ export default class Git {
     return result;
   }
 
+  /** Create a release for the GitHub projecct */
   async publish(releaseNotes: string, tag: string) {
     this.logger.verbose.info('Creating release on GitHub for tag:', tag);
 
@@ -633,6 +680,7 @@ export default class Git {
     return result;
   }
 
+  /** Get the latest tag in the git tree */
   async getLatestTagInBranch() {
     return execPromise('git', ['describe', '--tags', '--abbrev=0']);
   }
diff --git a/packages/core/src/init.ts b/packages/core/src/init.ts
index 21bb8fa5..11550b86 100644
--- a/packages/core/src/init.ts
+++ b/packages/core/src/init.ts
@@ -11,8 +11,11 @@ import { defaultLabelDefinition, ILabelDefinition } from './release';
 import { ILogger } from './utils/logger';
 
 const writeFile = promisify(fs.writeFile);
+
+/** Determine if any value is an object */
 const isObject = <T>(value: T) => typeof value === 'object' && value !== null;
 
+/** Get all of the basic options for running "auto" */
 async function getFlags() {
   return prompt([
     {
@@ -70,8 +73,12 @@ async function getFlags() {
   ]);
 }
 
+/** Get label configuration from the user. */
 async function getCustomLabels(onlyLabels = false) {
-  const useCustomChangelogTitles: { value: boolean } = onlyLabels
+  const useCustomChangelogTitles: {
+    /** The result of the prompt */
+    value: boolean;
+  } = onlyLabels
     ? { value: onlyLabels }
     : await prompt({
         type: 'confirm',
@@ -136,7 +143,10 @@ async function getCustomLabels(onlyLabels = false) {
     }
   }
 
-  let getAnotherTitle: { value?: boolean } = await prompt({
+  let getAnotherTitle: {
+    /** The result of the prompt */
+    value?: boolean;
+  } = await prompt({
     type: 'confirm',
     name: 'value',
     message: 'Would you like to add additional labels?',
@@ -155,7 +165,15 @@ async function getCustomLabels(onlyLabels = false) {
         desc:   #{description}
       `,
       validate: (state: {
-        values: { name?: string; title?: string; description?: string };
+        /** The result of the prompt */
+        values: {
+          /** Name of the label */
+          name?: string;
+          /** Changelog title of the label */
+          title?: string;
+          /** Description of the label */
+          description?: string;
+        };
       }) => {
         if (!state.values.name) {
           return 'Label is required for new label';
@@ -191,6 +209,7 @@ async function getCustomLabels(onlyLabels = false) {
   return customLabels;
 }
 
+/** Run the interactive initialization prompt */
 export default async function init(
   { onlyLabels, dryRun }: IInitOptions,
   logger: ILogger
diff --git a/packages/core/src/log-parse.ts b/packages/core/src/log-parse.ts
index e870669e..1933afe1 100644
--- a/packages/core/src/log-parse.ts
+++ b/packages/core/src/log-parse.ts
@@ -3,24 +3,33 @@ import { AsyncSeriesBailHook, AsyncSeriesWaterfallHook } from 'tapable';
 import { makeLogParseHooks } from './utils/make-hooks';
 
 export interface ICommitAuthor {
+  /** Author's name */
   name?: string;
+  /** Author's email */
   email?: string;
+  /** Author's username */
   username?: string;
 }
 
 export interface IPullRequest {
+  /** The issue number for the pull request */
   number: number;
+  /** The base branch the pull request is on */
   base?: string;
+  /** The body of the PR (opening comment) */
   body?: string;
 }
 
 export type IExtendedCommit = ICommit & {
+  /** The authors that contributed to the pull request */
   authors: ICommitAuthor[];
+  /** The pull request information */
   pullRequest?: IPullRequest;
+  /** Labels associated with the commit */
   labels: string[];
-  packages?: string[];
 };
 
+/** Parse the PR information for the merge commit message */
 export function parsePR(commit: IExtendedCommit): IExtendedCommit {
   const merge = /Merge pull request #(\d+) from (.+)\n([\S\s]+)/;
   const prMatch = commit.subject.match(merge);
@@ -39,6 +48,7 @@ export function parsePR(commit: IExtendedCommit): IExtendedCommit {
   };
 }
 
+/** Parse the PR information for the squashed commit message */
 export function parseSquashPR(commit: IExtendedCommit): IExtendedCommit {
   const firstLine = commit.subject.split('\n')[0];
   const squashMerge = /\(#(\d+)\)$/;
@@ -61,13 +71,22 @@ export function parseSquashPR(commit: IExtendedCommit): IExtendedCommit {
 }
 
 export interface ILogParseHooks {
+  /** Parse information about a commit from a commit. Here is where `auto` gets the PR number from the merge commits. */
   parseCommit: AsyncSeriesWaterfallHook<[IExtendedCommit]>;
+  /** Choose to omit certain commits. If you return true the commit will be omitted. Be sure to return nothing if you don't want the commit omitted. */
   omitCommit: AsyncSeriesBailHook<[IExtendedCommit], boolean | void>;
 }
 
+/**
+ * Parse the gitlog for commits that are PRs and attach their labels.
+ * This class can also be tapped into via plugin to parse commits
+ * in other ways (ex: conventional-commits)
+ */
 export default class LogParse {
+  /** Plugin entry points */
   hooks: ILogParseHooks;
 
+  /** Initialize the log parser and tap the default functionality  */
   constructor() {
     this.hooks = makeLogParseHooks();
 
@@ -75,6 +94,7 @@ export default class LogParse {
     this.hooks.parseCommit.tap('Squash Merge Commit', parseSquashPR);
   }
 
+  /** Run the log parser over a set of commits */
   async normalizeCommits(commits: ICommit[]): Promise<IExtendedCommit[]> {
     const eCommits = await Promise.all(
       commits.map(async commit => this.normalizeCommit(commit))
@@ -83,6 +103,7 @@ export default class LogParse {
     return eCommits.filter(Boolean) as IExtendedCommit[];
   }
 
+  /** Process a commit to find it's labels and PR information */
   async normalizeCommit(commit: ICommit): Promise<IExtendedCommit | undefined> {
     const extended = await this.hooks.parseCommit.promise({
       labels: [],
diff --git a/packages/core/src/plugins/filter-non-pull-request.ts b/packages/core/src/plugins/filter-non-pull-request.ts
index d403643b..6653a2dd 100644
--- a/packages/core/src/plugins/filter-non-pull-request.ts
+++ b/packages/core/src/plugins/filter-non-pull-request.ts
@@ -2,13 +2,15 @@ import on from 'await-to-js';
 
 import { Auto, IPlugin } from '../auto';
 
+/** Filter out PR numbers that might generate errors. */
 export default class FilterNonPullRequestPlugin implements IPlugin {
+  /** The name of the plugin */
   name = 'Filter Non Pull Request';
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {
     auto.hooks.onCreateLogParse.tap(this.name, logParse => {
       logParse.hooks.omitCommit.tapPromise(this.name, async commit => {
-        // tslint:disable-next-line early-exit
         if (commit.pullRequest && commit.pullRequest.number) {
           const { number: prNumber } = commit.pullRequest;
           const [err, info] = await on(auto.git!.getPr(prNumber));
diff --git a/packages/core/src/release.ts b/packages/core/src/release.ts
index 6107c5f4..901139be 100644
--- a/packages/core/src/release.ts
+++ b/packages/core/src/release.ts
@@ -9,7 +9,11 @@ import { promisify } from 'util';
 
 import { AsyncSeriesBailHook, SyncHook } from 'tapable';
 import { Memoize as memoize } from 'typescript-memoize';
-import { ICreateLabelsOptions } from './auto-args';
+import {
+  ICreateLabelsOptions,
+  IAuthorOptions,
+  GlobalOptions
+} from './auto-args';
 import Changelog from './changelog';
 import Git from './git';
 import LogParse, { ICommitAuthor, IExtendedCommit } from './log-parse';
@@ -35,33 +39,43 @@ export const defaultLabels: VersionLabel[] = [
   'prerelease'
 ];
 
+/** Determine if a label is a label used for versioning */
 export const isVersionLabel = (label: string): label is VersionLabel =>
   defaultLabels.includes(label as VersionLabel);
 
-export interface IAutoConfig {
-  githubApi?: string;
-  baseBranch: string;
-  githubGraphqlApi?: string;
-  name?: string;
-  email?: string;
-  owner?: string;
-  repo?: string;
-  skipReleaseLabels: string[];
-  onlyPublishWithReleaseLabel?: boolean;
-  noVersionPrefix?: boolean;
-  plugins?: (string | [string, number | boolean | string | object])[];
-  labels: ILabelDefinitionMap;
-}
+export type IAutoConfig = IAuthorOptions &
+  GlobalOptions & {
+    /** The branch that is used as the base. defaults to master */
+    baseBranch: string;
+    /** Labels to count as "skip-release" */
+    skipReleaseLabels: string[];
+    /** Instead of publishing every PR only publish when "release" label is present */
+    onlyPublishWithReleaseLabel?: boolean;
+    /** Whether to prefix the version with a "v" */
+    noVersionPrefix?: boolean;
+    /** Plugins to initialize "auto" with */
+    plugins?: (string | [string, number | boolean | string | object])[];
+    /** The labels configured by the user */
+    labels: ILabelDefinitionMap;
+  };
 
 interface ISearchEdge {
+  /** Graphql search node */
   node: {
+    /** PR number */
     number: number;
+    /** State of the PR */
     state: 'MERGED' | 'CLOSED' | 'OPEN';
+    /** Body of the PR */
     body: string;
+    /** Labels attached to the PR */
     labels: {
+      /** Edges of the Query */
       edges: [
         {
+          /** Graphql search node */
           node: {
+            /** Name of the label */
             name: string;
           };
         }
@@ -71,13 +85,18 @@ interface ISearchEdge {
 }
 
 interface ISearchResult {
+  /** Results in the search */
   edges: ISearchEdge[];
 }
 
 export interface ILabelDefinition {
+  /** The label text */
   name: string;
+  /** A title to put in the changelog for the label */
   title?: string;
+  /** The color of the label */
   color?: string;
+  /** The description of the label */
   description?: string;
 }
 
@@ -142,6 +161,7 @@ export const defaultLabelDefinition: ILabelDefinitionMap = {
   ]
 };
 
+/** Construct a map of label => semver label */
 export const getVersionMap = (labels = defaultLabelDefinition) =>
   Object.entries(labels).reduce(
     (semVer, [label, labelDef]) => {
@@ -150,7 +170,6 @@ export const getVersionMap = (labels = defaultLabelDefinition) =>
       }
 
       return semVer;
-      // tslint:disable-next-line align
     },
     new Map() as IVersionLabels
   );
@@ -159,11 +178,18 @@ const readFile = promisify(fs.readFile);
 const writeFile = promisify(fs.writeFile);
 
 export interface IReleaseHooks {
+  /** This is where you hook into the changelog's hooks. This hook is exposed for convenience on during `this.hooks.onCreateRelease` and at the root `this.hooks` */
   onCreateChangelog: SyncHook<[Changelog, SEMVER | undefined]>;
+  /** Control the titles in the `CHANGELOG.md` */
   createChangelogTitle: AsyncSeriesBailHook<[], string | void>;
+  /** This is where you hook into the LogParse's hooks. This hook is exposed for convenience on during `this.hooks.onCreateRelease` and at the root `this.hooks` */
   onCreateLogParse: SyncHook<[LogParse]>;
 }
 
+/**
+ * Generate a GitHub graphql query to find all the commits related
+ * to a PR.
+ */
 export function buildSearchQuery(
   owner: string,
   project: string,
@@ -212,6 +238,7 @@ export function buildSearchQuery(
   }`;
 }
 
+/** Use the graphql query result to fill in more information about a commit */
 function processQueryResult(
   key: string,
   result: ISearchResult,
@@ -252,13 +279,19 @@ function processQueryResult(
  * A class for interacting with the git remote
  */
 export default class Release {
-  readonly options: IAutoConfig;
+  /** Plugin entry points */
   readonly hooks: IReleaseHooks;
+  /** Options Release was initialized with */
+  readonly options: IAutoConfig;
 
+  /** A class that handles interacting with git and GitHub */
   private readonly git: Git;
+  /** A logger that uses log levels */
   private readonly logger: ILogger;
+  /** The version bump being used during "shipit" */
   private readonly versionLabels: IVersionLabels;
 
+  /** Initialize the release manager */
   constructor(
     git: Git,
     options: IAutoConfig = {
@@ -275,6 +308,7 @@ export default class Release {
     this.git = git;
   }
 
+  /** Make the class that will generate changelogs for the project */
   @memoize()
   async makeChangelog(version?: SEMVER) {
     const project = await this.git.getProject();
@@ -295,8 +329,8 @@ export default class Release {
   /**
    * Generate a changelog from a range of commits.
    *
-   * @param from sha or tag to start changelog from
-   * @param to sha or tag to end changelog at (defaults to HEAD)
+   * @param from - sha or tag to start changelog from
+   * @param to - sha or tag to end changelog at (defaults to HEAD)
    */
   async generateReleaseNotes(
     from: string,
@@ -309,6 +343,7 @@ export default class Release {
     return changelog.generateReleaseNotes(commits);
   }
 
+  /** Get all the commits that will be included in a release */
   async getCommitsInRelease(from: string, to = 'HEAD') {
     const allCommits = await this.getCommits(from, to);
     const allPrCommits = await Promise.all(
@@ -383,6 +418,7 @@ export default class Release {
     );
   }
 
+  /** Update a changelog with a new set of release notes */
   async updateChangelogFile(
     title: string,
     releaseNotes: string,
@@ -411,10 +447,9 @@ export default class Release {
   /**
    * Prepend a set of release notes to the changelog.md
    *
-   * @param releaseNotes Release notes to prepend to the changelog
-   * @param lastRelease Last release version of the code. Could be the first commit SHA
-   * @param currentVersion Current version of the code
-   * @param message Message to commit the changelog with
+   * @param releaseNotes - Release notes to prepend to the changelog
+   * @param lastRelease - Last release version of the code. Could be the first commit SHA
+   * @param currentVersion - Current version of the code
    */
   async addToChangelog(
     releaseNotes: string,
@@ -452,8 +487,8 @@ export default class Release {
   /**
    * Get a range of commits. The commits will have PR numbers and labels attached
    *
-   * @param from Tag or SHA to start at
-   * @param to Tag or SHA to end at (defaults to HEAD)
+   * @param from - Tag or SHA to start at
+   * @param to - Tag or SHA to end at (defaults to HEAD)
    */
   async getCommits(from: string, to = 'HEAD'): Promise<IExtendedCommit[]> {
     this.logger.verbose.info(`Getting commits from ${from} to ${to}`);
@@ -470,6 +505,7 @@ export default class Release {
     return commits;
   }
 
+  /** Go through the configured labels and either add them to the project or update them */
   async addLabelsToProject(
     labels: Partial<ILabelDefinitionMap>,
     options: ICreateLabelsOptions = {}
@@ -549,8 +585,8 @@ export default class Release {
   /**
    * Calculate the SEMVER bump over a range of commits using the PR labels
    *
-   * @param from Tag or SHA to start at
-   * @param to Tag or SHA to end at (defaults to HEAD)
+   * @param from - Tag or SHA to start at
+   * @param to - Tag or SHA to end at (defaults to HEAD)
    */
   async getSemverBump(from: string, to = 'HEAD'): Promise<SEMVER> {
     const commits = await this.getCommits(from, to);
@@ -571,11 +607,13 @@ export default class Release {
     return result;
   }
 
+  /** Given a tag get the next incremented version */
   async calcNextVersion(lastTag: string) {
     const bump = await this.getSemverBump(lastTag);
     return inc(lastTag, bump as ReleaseType);
   }
 
+  /** Create the class that will parse the log for PR info */
   @memoize()
   private async createLogParse() {
     const logParse = new LogParse();
@@ -596,9 +634,13 @@ export default class Release {
     return logParse;
   }
 
+  /** Get a the PRs that have been merged since the last GitHub release. */
   @memoize()
   private async getPRsSinceLastRelease() {
-    let lastRelease: { published_at: string };
+    let lastRelease: {
+      /** Date the last release was published */
+      published_at: string;
+    };
 
     try {
       lastRelease = await this.git.getLatestReleaseInfo();
@@ -623,8 +665,11 @@ export default class Release {
     }
 
     const data = await Promise.all(
-      prsSinceLastRelease.items.map(async (pr: { number: number }) =>
-        this.git.getPullRequest(Number(pr.number))
+      prsSinceLastRelease.items.map(
+        async (pr: {
+          /** The issue number of the pull request */
+          number: number;
+        }) => this.git.getPullRequest(Number(pr.number))
       )
     );
 
@@ -634,7 +679,7 @@ export default class Release {
   /**
    * Add the PR info (labels and body) to the commit
    *
-   * @param commits Commits to modify
+   * @param commit - Commit to modify
    */
   private async addPrInfoToCommit(commit: IExtendedCommit) {
     const modifiedCommit = { ...commit };
@@ -672,8 +717,6 @@ export default class Release {
    * Commits from rebased PRs do not have messages that tie them to a PR
    * Instead we have to find all PRs since the last release and try to match
    * their merge commit SHAs.
-   *
-   * @param commits Commits to modify
    */
   private getPRForRebasedCommits(
     commit: IExtendedCommit,
@@ -694,10 +737,14 @@ export default class Release {
     return commit;
   }
 
+  /** Parse the commit for information about the author and any other author that might have helped. */
   private async attachAuthor(commit: IExtendedCommit) {
     const modifiedCommit = { ...commit };
     let resolvedAuthors: (
-      | (ICommitAuthor & { login?: string })
+      | (ICommitAuthor & {
+          /** The GitHub user name of the git committer */
+          login?: string;
+        })
       | Partial<GHub.UsersGetByUsernameResponse>)[] = [];
 
     // If there is a pull request we will attempt to get the authors
diff --git a/packages/core/src/semver.ts b/packages/core/src/semver.ts
index 34dfdf3b..56f4ff08 100644
--- a/packages/core/src/semver.ts
+++ b/packages/core/src/semver.ts
@@ -14,6 +14,7 @@ export type IVersionLabels = Map<VersionLabel, string[]>;
 
 export default SEMVER;
 
+/** Given two labels determine the next SEMVER bump. */
 export function getHigherSemverTag(left: SEMVER, right: string): SEMVER {
   if (left === SEMVER.major || right === SEMVER.major) {
     return SEMVER.major;
@@ -27,10 +28,17 @@ export function getHigherSemverTag(left: SEMVER, right: string): SEMVER {
 }
 
 interface ISemVerOptions {
+  /** Only publish changes when "release" label is present */
   onlyPublishWithReleaseLabel?: boolean;
+  /** Labels to treat as "skip-release" labels */
   skipReleaseLabels?: string[];
 }
 
+/**
+ * Determine the version bump from the labels on merged PRs.
+ * Respects skip-release labels and the "onlyPublishWithReleaseLabel"
+ * strategy.
+ */
 export function calculateSemVerBump(
   labels: string[][],
   labelMap: IVersionLabels,
diff --git a/packages/core/src/utils/exec-promise.ts b/packages/core/src/utils/exec-promise.ts
index ae547735..90ae27b3 100644
--- a/packages/core/src/utils/exec-promise.ts
+++ b/packages/core/src/utils/exec-promise.ts
@@ -5,7 +5,7 @@ import { spawn } from 'child_process';
  * returning the stdout as a string if the command succeeds
  * and throwing if it does not.
  *
- * @param cmd the command as a string to pass in
+ * @param cmd - the command as a string to pass in
  */
 export default async function execPromise(
   cmd: string,
diff --git a/packages/core/src/utils/load-plugins.ts b/packages/core/src/utils/load-plugins.ts
index b87e6f0d..5738d1df 100644
--- a/packages/core/src/utils/load-plugins.ts
+++ b/packages/core/src/utils/load-plugins.ts
@@ -20,7 +20,13 @@ export default function loadPlugin(
   [pluginPath, options]: [string, any],
   logger: ILogger
 ): IPlugin | undefined {
-  let plugin: IPluginConstructor | { default: IPluginConstructor } | undefined;
+  let plugin:
+    | IPluginConstructor
+    | {
+        /** The plugin under the default export */
+        default: IPluginConstructor;
+      }
+    | undefined;
 
   // Try requiring a path
   if (pluginPath.startsWith('.') || pluginPath.startsWith('/')) {
@@ -58,7 +64,10 @@ export default function loadPlugin(
   if (!plugin) {
     plugin = tryRequire(path.join('@auto-it', pluginPath)) as
       | IPluginConstructor
-      | { default: IPluginConstructor };
+      | {
+          /** The plugin under the default export */
+          default: IPluginConstructor;
+        };
   }
 
   if (!plugin) {
diff --git a/packages/core/src/utils/logger.ts b/packages/core/src/utils/logger.ts
index dc9dfcc3..b2635c59 100644
--- a/packages/core/src/utils/logger.ts
+++ b/packages/core/src/utils/logger.ts
@@ -1,12 +1,17 @@
 import signale, { Signale } from 'signale';
 
 export interface ILogger {
+  /** The level at which to log messages */
   logLevel: LogLevel;
+  /** The default logger. Always on */
   log: signale.Signale<signale.DefaultMethods>;
+  /** The verbose log. Has more debug logs */
   verbose: signale.Signale<signale.DefaultMethods>;
+  /** The very verbose log. Has all debug logs */
   veryVerbose: signale.Signale<signale.DefaultMethods>;
 }
 
+/** Create a dummy logger for testing. */
 export function dummyLog(): ILogger {
   return {
     logLevel: undefined,
@@ -18,6 +23,7 @@ export function dummyLog(): ILogger {
 
 export type LogLevel = 'verbose' | 'veryVerbose' | undefined;
 
+/** Create a logger the the given log level. */
 export default function createLog(mode: LogLevel): ILogger {
   return {
     logLevel: mode,
diff --git a/packages/core/src/utils/make-hooks.ts b/packages/core/src/utils/make-hooks.ts
index 48fa0133..9078501b 100644
--- a/packages/core/src/utils/make-hooks.ts
+++ b/packages/core/src/utils/make-hooks.ts
@@ -11,6 +11,7 @@ import { IChangelogHooks } from '../changelog';
 import { ILogParseHooks } from '../log-parse';
 import { IReleaseHooks } from '../release';
 
+/** Make the hooks for "auto" */
 export const makeHooks = (): IAutoHooks => ({
   beforeRun: new SyncHook(['config']),
   modifyConfig: new SyncWaterfallHook(['config']),
@@ -32,17 +33,20 @@ export const makeHooks = (): IAutoHooks => ({
   canary: new AsyncSeriesBailHook(['canaryVersion', 'postFix'])
 });
 
+/** Make the hooks for "Release" */
 export const makeReleaseHooks = (): IReleaseHooks => ({
   onCreateChangelog: new SyncHook(['changelog', 'version']),
   createChangelogTitle: new AsyncSeriesBailHook([]),
   onCreateLogParse: new SyncHook(['logParse'])
 });
 
+/** Make the hooks for "LogParse" */
 export const makeLogParseHooks = (): ILogParseHooks => ({
   parseCommit: new AsyncSeriesWaterfallHook(['commit']),
   omitCommit: new AsyncSeriesBailHook(['commit'])
 });
 
+/** Make the hooks for "Changelog" */
 export const makeChangelogHooks = (): IChangelogHooks => ({
   addToBody: new AsyncSeriesWaterfallHook(['notes', 'commits']),
   renderChangelogLine: new AsyncSeriesWaterfallHook(['lineData']),
diff --git a/packages/core/src/utils/try-require.ts b/packages/core/src/utils/try-require.ts
index 0ab5e4e4..fcc96fd6 100644
--- a/packages/core/src/utils/try-require.ts
+++ b/packages/core/src/utils/try-require.ts
@@ -1,5 +1,6 @@
 import importCwd from 'import-cwd';
 
+/** Try to require something either from the CWD or the regular way */
 export default function tryRequire(tryPath: string) {
   try {
     // Require from CWD
diff --git a/plugins/all-contributors/package.json b/plugins/all-contributors/package.json
index 61096275..76d210ac 100644
--- a/plugins/all-contributors/package.json
+++ b/plugins/all-contributors/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@auto-it/all-contributors",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "main": "dist/index.js",
   "description": "Automatically add contributors as changelogs are produced.",
   "author": {
diff --git a/plugins/all-contributors/src/index.ts b/plugins/all-contributors/src/index.ts
index cc7bccdc..f64d3cc8 100644
--- a/plugins/all-contributors/src/index.ts
+++ b/plugins/all-contributors/src/index.ts
@@ -73,10 +73,13 @@ const defaultOptions: IAllContributorsPluginOptions = {
 
 /** Automatically add contributors as changelogs are produced. */
 export default class AllContributorsPlugin implements IPlugin {
+  /** The name of the plugin */
   name = 'All Contributors';
 
+  /** The options of the plugin */
   readonly options: Required<IAllContributorsPluginOptions>;
 
+  /** Initialize the plugin with it's options */
   constructor(options: IAllContributorsPluginOptions = {}) {
     this.options = {
       exclude: [...(defaultOptions.exclude || []), ...(options.exclude || [])],
@@ -84,6 +87,7 @@ export default class AllContributorsPlugin implements IPlugin {
     };
   }
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {
     auto.hooks.afterAddToChangelog.tap(this.name, ({ commits }) => {
       const config: AllContributorsRc = JSON.parse(
@@ -99,6 +103,7 @@ export default class AllContributorsPlugin implements IPlugin {
 
         Object.keys(this.options.types || {})
           .filter((type): type is Contribution => {
+            /** Determine if path is the contribution type */
             const isType = (file: string) =>
               match(this.options.types[type as Contribution] || [], file);
             const isMatch = files.some(isType);
diff --git a/plugins/chrome/package.json b/plugins/chrome/package.json
index 0afcfd4f..08ab2015 100644
--- a/plugins/chrome/package.json
+++ b/plugins/chrome/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@auto-it/chrome",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "main": "dist/index.js",
   "description": "Chrome publishing plugin for auto",
   "author": {
diff --git a/plugins/chrome/src/index.ts b/plugins/chrome/src/index.ts
index 6cabfa60..4669edf8 100644
--- a/plugins/chrome/src/index.ts
+++ b/plugins/chrome/src/index.ts
@@ -7,52 +7,62 @@ const readFile = promisify(fs.readFile);
 const writeFile = promisify(fs.writeFile);
 
 interface IChromeWebStoreConfig {
+  /** The id of the chrome extension */
   id?: string;
+  /** The path to the manifest of the chrome extension */
   manifest?: string;
+  /** A path to the packaged extension */
   build: string;
 }
 
+/** Get the chrome plugin manifest. */
 async function getManifest(path: string) {
   return JSON.parse(await readFile(path, 'utf-8'));
 }
 
+/** This plugin allows you to automate the publishing of chrome extensions */
 export default class ChromeWebStorePlugin implements IPlugin {
+  /** The name of the plugin */
   readonly name = 'Chrome Web Store';
 
-  private readonly id: string;
-  private readonly manifest: string;
-  private readonly build: string;
+  /** The options of the plugin */
+  private readonly options: Required<IChromeWebStoreConfig>;
 
+  /** Initialize the plugin with it's options */
   constructor(config: IChromeWebStoreConfig) {
-    this.id = config.id || process.env.EXTENSION_ID!;
-    this.manifest = config.manifest || 'manifest.json';
-    this.build = config.build || process.env.EXTENSION_BUILD || 'extension.zip';
+    this.options = {
+      id: config.id || process.env.EXTENSION_ID!,
+      manifest: config.manifest || 'manifest.json',
+      build: config.build || process.env.EXTENSION_BUILD || 'extension.zip'
+    };
   }
 
+  /** Report a warning to the log */
   reportWarning(auto: Auto, message: string) {
     auto.logger.log.warn(`${this.name}: ${message}`);
   }
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {
     auto.hooks.beforeRun.tap(this.name, () => {
-      if (!this.id) {
+      if (!this.options.id) {
         this.reportWarning(
           auto,
           'EXTENSION_ID environment variable must be set or "id" in autorc'
         );
       }
 
-      if (!fs.existsSync(this.manifest)) {
+      if (!fs.existsSync(this.options.manifest)) {
         this.reportWarning(
           auto,
-          `"${this.manifest}" must exist to publish. Or provide a custom path in you autorc`
+          `"${this.options.manifest}" must exist to publish. Or provide a custom path in you autorc`
         );
       }
 
-      if (!fs.existsSync(this.build)) {
+      if (!fs.existsSync(this.options.build)) {
         this.reportWarning(
           auto,
-          `Path to either a zip file, or a directory to be zipped at ${this.build}`
+          `Path to either a zip file, or a directory to be zipped at ${this.options.build}`
         );
       }
 
@@ -67,9 +77,9 @@ export default class ChromeWebStorePlugin implements IPlugin {
         process.env.CLIENT_ID &&
         process.env.CLIENT_SECRET &&
         process.env.REFRESH_TOKEN &&
-        fs.existsSync(this.manifest) &&
-        this.id &&
-        fs.existsSync(this.build)
+        fs.existsSync(this.options.manifest) &&
+        this.options.id &&
+        fs.existsSync(this.options.build)
       ) {
         return;
       }
@@ -84,7 +94,7 @@ export default class ChromeWebStorePlugin implements IPlugin {
         `${this.name}: Getting author information from package.json`
       );
 
-      const manifest = await getManifest(this.manifest);
+      const manifest = await getManifest(this.options.manifest);
 
       if (manifest.author) {
         const { author } = manifest;
@@ -102,7 +112,7 @@ export default class ChromeWebStorePlugin implements IPlugin {
     });
 
     auto.hooks.getPreviousVersion.tapPromise(this.name, async prefixRelease => {
-      const manifest = await getManifest(this.manifest);
+      const manifest = await getManifest(this.options.manifest);
       const version = prefixRelease(manifest.version);
 
       auto.logger.verbose.info(
@@ -121,12 +131,15 @@ export default class ChromeWebStorePlugin implements IPlugin {
 
     auto.hooks.version.tapPromise(this.name, async version => {
       // increment version
-      const manifest = await getManifest(this.manifest);
+      const manifest = await getManifest(this.options.manifest);
       manifest.version = inc(manifest.version, version as ReleaseType);
-      await writeFile(this.manifest, JSON.stringify(manifest, undefined, 2));
+      await writeFile(
+        this.options.manifest,
+        JSON.stringify(manifest, undefined, 2)
+      );
 
       // commit new version
-      await execPromise('git', ['add', this.manifest]);
+      await execPromise('git', ['add', this.options.manifest]);
       await execPromise('git', [
         'commit',
         '-m',
@@ -142,9 +155,9 @@ export default class ChromeWebStorePlugin implements IPlugin {
       await execPromise('webstore', [
         'upload',
         '--extension-id',
-        this.id,
+        this.options.id,
         '--source',
-        this.build,
+        this.options.build,
         '--auto-publish'
       ]);
 
diff --git a/plugins/conventional-commits/package.json b/plugins/conventional-commits/package.json
index 004d4324..14a82a2a 100644
--- a/plugins/conventional-commits/package.json
+++ b/plugins/conventional-commits/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@auto-it/conventional-commits",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "main": "dist/index.js",
   "description": "Conventional commit plugin for auto",
   "author": {
diff --git a/plugins/conventional-commits/src/index.ts b/plugins/conventional-commits/src/index.ts
index c9dc2149..0fe9599b 100644
--- a/plugins/conventional-commits/src/index.ts
+++ b/plugins/conventional-commits/src/index.ts
@@ -2,9 +2,15 @@ import { applyPlugins, mappers, parse } from 'parse-commit-message';
 
 import { Auto, IPlugin, VersionLabel } from '@auto-it/core';
 
+/**
+ * Parse conventional commit messages and use them to
+ * calculate the version.
+ */
 export default class ConventionalCommitsPlugin implements IPlugin {
+  /** The name of the plugin */
   name = 'Conventional Commits Parser';
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {
     auto.hooks.onCreateLogParse.tap(this.name, logParse => {
       logParse.hooks.parseCommit.tap(this.name, commit => {
@@ -35,7 +41,6 @@ export default class ConventionalCommitsPlugin implements IPlugin {
 
       // should omit PR commit if there exists a commit with a CC commit message
       logParse.hooks.omitCommit.tapPromise(this.name, async commit => {
-        // tslint:disable-next-line early-exit
         if (
           auto.git &&
           auto.release &&
diff --git a/plugins/crates/package.json b/plugins/crates/package.json
index f6c997ba..64a4858e 100644
--- a/plugins/crates/package.json
+++ b/plugins/crates/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@auto-it/crates",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "main": "dist/index.js",
   "description": "Deploy Rust crates to crates.io",
   "author": {
diff --git a/plugins/crates/src/index.ts b/plugins/crates/src/index.ts
index 97c44158..2f83123c 100644
--- a/plugins/crates/src/index.ts
+++ b/plugins/crates/src/index.ts
@@ -8,6 +8,7 @@ import userHome from 'user-home';
 
 const { isCi } = envCi();
 
+/** Get the parsed cargo.toml for the crate */
 export const getCargoConfig = () => {
   const content = fs
     .readFileSync(path.join(process.cwd(), 'Cargo.toml'))
@@ -15,6 +16,7 @@ export const getCargoConfig = () => {
   return toml.parse(content);
 };
 
+/** Get the credentials for publishing to crates.io */
 export function checkForCreds() {
   if (isCi) {
     return process.env.CARGO_REGISTRY_TOKEN;
@@ -24,6 +26,7 @@ export function checkForCreds() {
   return fs.existsSync(credsFile);
 }
 
+/** Bump the version in cargo.toml */
 export function bumpVersion(bumpBy: SEMVER) {
   const filePath = path.join(process.cwd(), 'Cargo.toml');
   const content = fs.readFileSync(filePath).toString();
@@ -43,18 +46,24 @@ export function bumpVersion(bumpBy: SEMVER) {
 }
 
 interface ICratesPluginOptions {
+  /** Do not actually do anything. Log what would be done. */
   dryRun?: boolean;
 }
 
+/** Deploy Rust crates */
 export default class CratesPlugin implements IPlugin {
+  /** The name of the plugin */
   name = 'Crates';
 
+  /** The options of the plugin */
   readonly options: ICratesPluginOptions;
 
+  /** Initialize the plugin with it's options */
   constructor(options: ICratesPluginOptions = {}) {
     this.options = options;
   }
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {
     auto.hooks.beforeShipIt.tap(this.name, () => {
       if (!checkForCreds()) {
diff --git a/plugins/first-time-contributor/package.json b/plugins/first-time-contributor/package.json
index e27d8bce..f74dd67d 100644
--- a/plugins/first-time-contributor/package.json
+++ b/plugins/first-time-contributor/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@auto-it/first-time-contributor",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "main": "dist/index.js",
   "description": "Thank first time contributors for their work right in your release notes.",
   "author": {
diff --git a/plugins/first-time-contributor/src/index.ts b/plugins/first-time-contributor/src/index.ts
index eb5dcc3b..39713bbf 100644
--- a/plugins/first-time-contributor/src/index.ts
+++ b/plugins/first-time-contributor/src/index.ts
@@ -10,6 +10,7 @@ const JUST_EMAIL = '%cE' as const;
 
 type Format = typeof JUST_NAME | typeof JUST_EMAIL;
 
+/** Get some of the contributors from the git history */
 const getContributors = async (format: Format) => {
   const start = '$(git rev-list HEAD | tail -n 1)';
   const lastRelease = '$(git describe --tags --abbrev=0)';
@@ -19,12 +20,19 @@ const getContributors = async (format: Format) => {
   );
 };
 
+/**
+ * Thank first time contributors for their work right in your release notes.
+ */
 export default class FirstTimeContributorPlugin implements IPlugin {
+  /** The name of the plugin */
   name = 'First Time Contributor';
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {
     auto.hooks.onCreateChangelog.tap(this.name, changelog => {
       const base = new URL(changelog.options.baseUrl).origin;
+
+      /** Format a string for the contributor */
       const renderContributor = ({ name, username }: ICommitAuthor) => {
         const link = `[@${username}](${urlJoin(base, username || '')})`;
         return `${name}${username ? (name ? ` (${link})` : link) : ''}`;
diff --git a/plugins/git-tag/package.json b/plugins/git-tag/package.json
index b34c923f..eda7c3cd 100644
--- a/plugins/git-tag/package.json
+++ b/plugins/git-tag/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@auto-it/git-tag",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "main": "dist/index.js",
   "description": "Manage your projects version through just a git tag",
   "author": {
diff --git a/plugins/git-tag/src/index.ts b/plugins/git-tag/src/index.ts
index fdfd4959..c060208e 100644
--- a/plugins/git-tag/src/index.ts
+++ b/plugins/git-tag/src/index.ts
@@ -1,9 +1,12 @@
 import { Auto, execPromise, IPlugin } from '@auto-it/core';
 import { inc, ReleaseType } from 'semver';
 
+/** Manage your projects version through just a git tag. */
 export default class GitTagPlugin implements IPlugin {
+  /** The name of the plugin */
   name = 'Git Tag';
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {
     auto.hooks.getPreviousVersion.tapPromise(this.name, async () => {
       if (!auto.git) {
diff --git a/plugins/jira/package.json b/plugins/jira/package.json
index 818616ec..f18ae53e 100644
--- a/plugins/jira/package.json
+++ b/plugins/jira/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@auto-it/jira",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "main": "dist/index.js",
   "description": "Jira plugin for auto",
   "author": {
diff --git a/plugins/jira/src/index.ts b/plugins/jira/src/index.ts
index 9f9f8385..3d0c2a5d 100644
--- a/plugins/jira/src/index.ts
+++ b/plugins/jira/src/index.ts
@@ -4,17 +4,21 @@ import { Auto, IPlugin } from '@auto-it/core';
 import { IExtendedCommit } from '@auto-it/core/dist/log-parse';
 
 interface IJiraPluginOptions {
+  /** Url to a hosted JIRA instance */
   url: string;
 }
 
 interface IJiraCommit extends IExtendedCommit {
+  /** The jira info for the commit */
   jira?: {
+    /** The jira story numbers attached to teh commit */
     number: string[];
   };
 }
 
 const jira = /\[?([\w]{1,}-\d+)\]?:?\s?[-\s]*([\S ]+)?/;
 
+/** Get the jira number from a commit message. */
 export function parseJira(commit: IExtendedCommit): IJiraCommit {
   // Support 'JIRA-XXX:' and '[JIRA-XXX]' and '[JIRA-XXX] - '
   const matches = [];
@@ -44,15 +48,20 @@ export function parseJira(commit: IExtendedCommit): IJiraCommit {
   };
 }
 
+/** Include Jira story information in your changelogs */
 export default class JiraPlugin implements IPlugin {
+  /** The name of the plugin */
   name = 'Jira';
 
+  /** The options of the plugin */
   readonly options: IJiraPluginOptions;
 
+  /** Initialize the plugin with it's options */
   constructor(options: IJiraPluginOptions | string) {
     this.options = typeof options === 'string' ? { url: options } : options;
   }
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {
     auto.hooks.onCreateChangelog.tap(this.name, changelog => {
       changelog.hooks.renderChangelogLine.tap(
diff --git a/plugins/maven/package.json b/plugins/maven/package.json
index c35e1bfa..ba621f82 100644
--- a/plugins/maven/package.json
+++ b/plugins/maven/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@auto-it/maven",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "main": "dist/index.js",
   "description": "Maven publishing plugin for auto",
   "author": {
diff --git a/plugins/maven/src/index.ts b/plugins/maven/src/index.ts
index e123738a..3ee0723d 100644
--- a/plugins/maven/src/index.ts
+++ b/plugins/maven/src/index.ts
@@ -1,5 +1,3 @@
-// tslint:disable early-exit
-
 import { Auto, execPromise, IPlugin } from '@auto-it/core';
 import parseGitHubUrl from 'parse-github-url';
 import path from 'path';
@@ -8,11 +6,15 @@ import { promisify } from 'util';
 import { parse } from 'pom-parser';
 import { inc, ReleaseType } from 'semver';
 
+/** Ensure a value is an array */
 const arrayify = <T>(arg: T | T[]): T[] => (Array.isArray(arg) ? arg : [arg]);
 const parsePom = promisify(parse);
+
+/** Get the maven pom.xml for a project */
 const getPom = async () =>
   parsePom({ filePath: path.join(process.cwd(), 'pom.xml') });
 
+/** Get the previous version from the pom.xml */
 async function getPreviousVersion(auto: Auto): Promise<string> {
   const pom = await getPom();
   const previousVersion = pom.pomObject && pom.pomObject.project.version;
@@ -29,9 +31,12 @@ async function getPreviousVersion(auto: Auto): Promise<string> {
   return previousVersion.replace('-SNAPSHOT', '');
 }
 
+/** Deploy project to maven */
 export default class MavenPlugin implements IPlugin {
+  /** The name of the plugin */
   name = 'maven';
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {
     auto.hooks.onCreateLogParse.tap(this.name, logParse => {
       logParse.hooks.omitCommit.tap(this.name, commit => {
diff --git a/plugins/npm/package.json b/plugins/npm/package.json
index 7c40fb39..37e788ce 100644
--- a/plugins/npm/package.json
+++ b/plugins/npm/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@auto-it/npm",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "main": "dist/index.js",
   "description": "NPM publishing plugin for auto",
   "author": {
diff --git a/plugins/npm/src/index.ts b/plugins/npm/src/index.ts
index 72d89df1..2c1107ee 100644
--- a/plugins/npm/src/index.ts
+++ b/plugins/npm/src/index.ts
@@ -14,16 +14,20 @@ import { loadPackageJson, readFile } from './utils';
 
 const { isCi } = envCi();
 
-function isMonorepo() {
-  return fs.existsSync('lerna.json');
-}
+/** Check if the project is a monorepo */
+const isMonorepo = () => fs.existsSync('lerna.json');
 
+/** Get the last published version for a npm package */
 async function getPublishedVersion(name: string) {
   try {
     return await execPromise('npm', ['view', name, 'version']);
   } catch (error) {}
 }
 
+/**
+ * Determine the greatest version between last published version of a
+ * package and the version in the package.json.
+ */
 export async function greaterRelease(
   prefixRelease: (release: string) => string,
   name: string,
@@ -43,11 +47,15 @@ export async function greaterRelease(
 }
 
 interface IMonorepoPackage {
+  /** Path to the monorepo package */
   path: string;
+  /** Name to the monorepo package */
   name: string;
+  /** Version to the monorepo package */
   version: string;
 }
 
+/** Check if one path is within a parent path */
 const inFolder = (parent: string, child: string) => {
   const relative = path.relative(parent, child);
 
@@ -57,15 +65,27 @@ const inFolder = (parent: string, child: string) => {
 };
 
 interface ChangedPackagesArgs {
+  /** Commit hash to find changes for */
   sha: string;
+  /** All of the pacakges in the monorepo */
   packages: IMonorepoPackage[];
+  /** The lerna.json for the monorepo */
   lernaJson: {
+    /** The version of the monorepo */
     version?: string;
   };
+  /** An "auto" logger to use for loggin */
   logger: ILogger;
+  /** The semver bump being applied */
   version?: SEMVER;
 }
 
+/**
+ * Determine what packages in a monorepo have git changes.
+ * We are specifically not using `lerna changed` here because
+ * we only care about the package that changed, not what other
+ * packages that might effect.
+ */
 export async function changedPackages({
   sha,
   packages,
@@ -108,6 +128,7 @@ export async function changedPackages({
   return [...changed];
 }
 
+/** Get the package with the greatest version in a monorepo */
 export function getMonorepoPackage() {
   const packages = getPackages(process.cwd());
 
@@ -129,6 +150,11 @@ export function getMonorepoPackage() {
   );
 }
 
+/**
+ * Increment the version number of a package based the bigger
+ * release between the last published version and the version
+ * in the package.json.
+ */
 async function bumpLatest(
   { version: localVersion, name }: IPackageJSON,
   version: SEMVER
@@ -143,13 +169,21 @@ async function bumpLatest(
 const verbose = ['--loglevel', 'silly'];
 
 interface INpmConfig {
+  /** Whether to create sub-package changelogs */
   subPackageChangelogs?: boolean;
+  /** Whether to set the npm token on CI */
   setRcToken?: boolean;
+  /** Whether to force publish all the packages in a monorepo */
   forcePublish?: boolean;
 }
 
+/** Parse the lerna.json file. */
 const getLernaJson = () => JSON.parse(fs.readFileSync('lerna.json', 'utf8'));
 
+/**
+ * Check if `git status` is clean. We try to ensure that no
+ * changes haven't been staged to match the behavior of NPM.
+ */
 const checkClean = async (auto: Auto) => {
   const status = await execPromise('git', ['status', '--porcelain']);
 
@@ -163,15 +197,22 @@ const checkClean = async (auto: Auto) => {
   );
 };
 
+/** Publish to NPM. Works in both a monorepo setting and for a single package. */
 export default class NPMPlugin implements IPlugin {
+  /** The name of the plugin */
   name = 'NPM';
 
+  /** Whether to render a changelog like a monorepo's */
   private renderMonorepoChangelog: boolean;
 
+  /** Whether to create sub-package changelogs */
   private readonly subPackageChangelogs: boolean;
+  /** Whether to set the npm token in CI */
   private readonly setRcToken: boolean;
+  /** Whether to always publish all packages in a monorepo */
   private readonly forcePublish: boolean;
 
+  /** Initialize the plugin with it's options */
   constructor(config: INpmConfig = {}) {
     this.renderMonorepoChangelog = true;
     this.subPackageChangelogs = config.subPackageChangelogs || true;
@@ -181,6 +222,7 @@ export default class NPMPlugin implements IPlugin {
       typeof config.forcePublish === 'boolean' ? config.forcePublish : true;
   }
 
+  /** Get all of the packages in the lerna monorepo */
   @memoize()
   async getLernaPackages() {
     return execPromise('npx', ['lerna', 'ls', '-pl']).then(res =>
@@ -191,6 +233,7 @@ export default class NPMPlugin implements IPlugin {
     );
   }
 
+  /** Get all of the packages+version in the lerna "independent" monorepo */
   @memoize()
   async getIndependentPackageList() {
     return this.getLernaPackages().then(packages =>
@@ -200,6 +243,7 @@ export default class NPMPlugin implements IPlugin {
     );
   }
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {
     const isVerbose =
       auto.logger.logLevel === 'verbose' ||
diff --git a/plugins/npm/src/package-config.ts b/plugins/npm/src/package-config.ts
index 43c3b738..8f286588 100644
--- a/plugins/npm/src/package-config.ts
+++ b/plugins/npm/src/package-config.ts
@@ -1,21 +1,16 @@
-import fs from 'fs';
 import parseGitHubUrl from 'parse-github-url';
-import { promisify } from 'util';
+import { loadPackageJson } from './utils';
 
 export interface IRepoConfig {
+  /** Owner of the repo (or GitHub user) */
   owner: string;
+  /** The project */
   repo: string;
 }
 
-const readFile = promisify(fs.readFile);
-
-const getPackageConfig = async (): Promise<IPackageJSON> => {
-  const pkgConfig = await readFile('./package.json', 'utf-8');
-  return JSON.parse(pkgConfig);
-};
-
+/** Try to the the owner/repo from the package.json */
 export default async function getConfigFromPackageJson(): Promise<IRepoConfig> {
-  const { repository } = await getPackageConfig();
+  const { repository } = await loadPackageJson();
 
   if (!repository) {
     throw new Error('Cannot read repo info from package.json');
diff --git a/plugins/npm/src/set-npm-token.ts b/plugins/npm/src/set-npm-token.ts
index 39d67703..2fc6a2ff 100644
--- a/plugins/npm/src/set-npm-token.ts
+++ b/plugins/npm/src/set-npm-token.ts
@@ -9,6 +9,7 @@ import { loadPackageJson, readFile, writeFile } from './utils';
 
 const { isCi } = envCi();
 
+/** Set the .npmrc only when in a continuos integration environment */
 export default async function setTokenOnCI(logger: ILogger) {
   if (!isCi) {
     return;
diff --git a/plugins/npm/src/utils.ts b/plugins/npm/src/utils.ts
index 2b10d7dd..8b48f9d1 100644
--- a/plugins/npm/src/utils.ts
+++ b/plugins/npm/src/utils.ts
@@ -4,6 +4,7 @@ import { promisify } from 'util';
 export const readFile = promisify(fs.readFile);
 export const writeFile = promisify(fs.writeFile);
 
+/** Load and parse the root package json for the project */
 export async function loadPackageJson(): Promise<IPackageJSON> {
   return JSON.parse(await readFile('package.json', 'utf-8'));
 }
diff --git a/plugins/omit-commits/package.json b/plugins/omit-commits/package.json
index 2096841d..0a9f50f4 100644
--- a/plugins/omit-commits/package.json
+++ b/plugins/omit-commits/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@auto-it/omit-commits",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "main": "dist/index.js",
   "description": "Omit commits plugin for auto",
   "author": {
diff --git a/plugins/omit-commits/src/index.ts b/plugins/omit-commits/src/index.ts
index 7f61cce4..3814ad50 100644
--- a/plugins/omit-commits/src/index.ts
+++ b/plugins/omit-commits/src/index.ts
@@ -1,26 +1,41 @@
 import { Auto, IPlugin } from '@auto-it/core';
 
 export interface IOmitCommitsPluginOptions {
+  /** Usernames to omit */
   username?: string | string[];
+  /** Emails to omit */
   email?: string | string[];
+  /** Names to omit */
   name?: string | string[];
+  /** Commit messages to omit */
   subject?: string | string[];
+  /** Labels to omit */
   labels?: string | string[];
 }
 
+/** Ensure a value is an array */
 const arrayify = <T>(arr: T | T[]): T[] => (Array.isArray(arr) ? arr : [arr]);
 
+/** Filter certain commits out of the changelog and version calculation. */
 export default class OmitCommitsPlugin implements IPlugin {
+  /** The name of the plugin */
   name = 'Omit Commits';
 
+  /** The options of the plugin */
   readonly options: {
+    /** Usernames to omit */
     username: string[];
+    /** Emails to omit */
     email: string[];
+    /** Names to omit */
     name: string[];
+    /** Commit messages to omit */
     subject: string[];
+    /** Labels to omit */
     labels: string[];
   };
 
+  /** Initialize the plugin with it's options */
   constructor(options: IOmitCommitsPluginOptions) {
     this.options = {
       username: options.username ? arrayify(options.username) : [],
@@ -31,6 +46,7 @@ export default class OmitCommitsPlugin implements IPlugin {
     };
   }
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {
     auto.hooks.onCreateLogParse.tap(this.name, logParse => {
       logParse.hooks.omitCommit.tap(this.name, commit => {
diff --git a/plugins/omit-release-notes/package.json b/plugins/omit-release-notes/package.json
index 684fbb16..923d4ed1 100644
--- a/plugins/omit-release-notes/package.json
+++ b/plugins/omit-release-notes/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@auto-it/omit-release-notes",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "main": "dist/index.js",
   "description": "Omit release notes plugin for auto",
   "author": {
diff --git a/plugins/omit-release-notes/src/index.ts b/plugins/omit-release-notes/src/index.ts
index 1b45a302..6592e9b7 100644
--- a/plugins/omit-release-notes/src/index.ts
+++ b/plugins/omit-release-notes/src/index.ts
@@ -1,24 +1,37 @@
 import { Auto, IPlugin } from '@auto-it/core';
 
 export interface IReleaseNotesPluginOptions {
+  /** Usernames to omit */
   username?: string | string[];
+  /** Emails to omit */
   email?: string | string[];
+  /** Names to omit */
   name?: string | string[];
+  /** Labels to omit */
   labels?: string | string[];
 }
 
+/** Ensure a value is an array */
 const arrayify = <T>(arr: T | T[]): T[] => (Array.isArray(arr) ? arr : [arr]);
 
+/** Filter PRs with release notes that shouldn't make it into a release. */
 export default class ReleaseNotesPlugin implements IPlugin {
+  /** The name of the plugin */
   name = 'Omit Release Notes';
 
+  /** The options of the plugin */
   readonly options: {
+    /** Usernames to omit */
     username: string[];
+    /** Emails to omit */
     email: string[];
+    /** Names to omit */
     name: string[];
+    /** Labels to omit */
     labels: string[];
   };
 
+  /** Initialize the plugin with it's options */
   constructor(options: IReleaseNotesPluginOptions) {
     this.options = {
       username: options.username ? arrayify(options.username) : [],
@@ -28,6 +41,7 @@ export default class ReleaseNotesPlugin implements IPlugin {
     };
   }
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {
     auto.hooks.onCreateChangelog.tap(this.name, changelog => {
       changelog.hooks.omitReleaseNotes.tap(this.name, commit => {
diff --git a/plugins/released/package.json b/plugins/released/package.json
index 975428e7..6546f617 100644
--- a/plugins/released/package.json
+++ b/plugins/released/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@auto-it/released",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "main": "dist/index.js",
   "description": "Released plugin for auto. Comments with version + extra",
   "author": {
diff --git a/plugins/released/src/index.ts b/plugins/released/src/index.ts
index 10f42453..f11e693f 100644
--- a/plugins/released/src/index.ts
+++ b/plugins/released/src/index.ts
@@ -3,8 +3,11 @@ import { IExtendedCommit } from '@auto-it/core/dist/log-parse';
 import merge from 'deepmerge';
 
 interface IReleasedLabelPluginOptions {
+  /** Message to use when posting on issues and pull requests */
   message: string;
+  /** The label to add to issues and pull requests */
   label: string;
+  /** Whether to lock the issue once the pull request has been released */
   lockIssues: boolean;
 }
 
@@ -17,17 +20,24 @@ const defaultOptions = {
 };
 
 const closeIssue = /(?:Close|Closes|Closed|Fix|Fixes|Fixed|Resolve|Resolves|Resolved)\s((?:#\d+(?:,\s)?)+)/gi;
+
+/** Determine if string is a canary version */
 const isCanary = (version: string) => version.match('canary');
 
+/** Comment on merged pull requests and issues with the new version */
 export default class ReleasedLabelPlugin implements IPlugin {
+  /** The name of the plugin */
   name = 'Released Label';
 
+  /** The options of the plugin */
   readonly options: IReleasedLabelPluginOptions;
 
+  /** Initialize the plugin with it's options */
   constructor(options: Partial<IReleasedLabelPluginOptions> = {}) {
     this.options = merge(defaultOptions, options);
   }
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {
     auto.hooks.modifyConfig.tap(this.name, config => {
       config.labels.released = config.labels.released || {
@@ -72,6 +82,7 @@ export default class ReleasedLabelPlugin implements IPlugin {
     );
   }
 
+  /** Add the release label + other stuff to a commit */
   private async addReleased(
     auto: Auto,
     commit: IExtendedCommit,
@@ -114,6 +125,7 @@ export default class ReleasedLabelPlugin implements IPlugin {
     );
   }
 
+  /** Add the templated comment to the pr and attach the "released" label */
   private async addCommentAndLabel(
     auto: Auto,
     newVersion: string,
@@ -137,6 +149,7 @@ export default class ReleasedLabelPlugin implements IPlugin {
     }
   }
 
+  /** Create a comment that fits the context (pr of issue) */
   private createReleasedComment(isIssue: boolean, version: string) {
     return this.options.message
       .replace(new RegExp(TYPE, 'g'), isIssue ? 'Issue' : 'PR')
diff --git a/plugins/s3/package.json b/plugins/s3/package.json
index 5ff67567..ec91bc18 100644
--- a/plugins/s3/package.json
+++ b/plugins/s3/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@auto-it/s3",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "main": "dist/index.js",
   "description": "Post your built artifacts to s3",
   "author": {
diff --git a/plugins/s3/src/index.ts b/plugins/s3/src/index.ts
index c2171290..25de36a4 100644
--- a/plugins/s3/src/index.ts
+++ b/plugins/s3/src/index.ts
@@ -4,21 +4,30 @@ import { Aws, Options } from 'aws-cli-js';
 type File = [string, string];
 
 export interface IUploadAssetsPluginOptions {
+  /** S3 bucket to post the asset to */
   bucket: string;
+  /** S3 Region to post the asset to */
   region: string;
+  /** Whether this plugin should overwrite files on S3 */
   overwrite?: boolean;
+  /** Paths to the files to upload to S3 */
   files: File[];
 }
 
 type ConfigOptions = IUploadAssetsPluginOptions | IUploadAssetsPluginOptions[];
 
+/** Post your built artifacts to s3 during `auto release` */
 export default class S3Plugin implements IPlugin {
+  /** The name of the plugin */
   name = 'S3';
 
+  /** The options of the plugin */
   private readonly options: IUploadAssetsPluginOptions[];
 
+  /** A client to communicate with AWS */
   private readonly aws: Aws;
 
+  /** Initialize the plugin with it's options */
   constructor(options: ConfigOptions) {
     this.options = Array.isArray(options) ? options : [options];
 
@@ -31,6 +40,7 @@ export default class S3Plugin implements IPlugin {
     this.aws = new Aws(awsOptions);
   }
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {
     auto.hooks.beforeRun.tap(this.name, () => {
       auto.checkEnv(this.name, 'AWS_ACCESS_KEY');
@@ -45,10 +55,12 @@ export default class S3Plugin implements IPlugin {
     });
   }
 
+  /** Check if a path exists in an AWS bucket */
   private async exists(bucket: string, path: string): Promise<boolean> {
     return this.aws.command(`s3 ls s3://${bucket}/${path}`);
   }
 
+  /** Upload files to a bucket */
   private async processBucket(
     auto: Auto,
     newVersion = '',
diff --git a/plugins/slack/package.json b/plugins/slack/package.json
index fe6c1713..ed7893eb 100644
--- a/plugins/slack/package.json
+++ b/plugins/slack/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@auto-it/slack",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "main": "dist/index.js",
   "description": "Slack plugin for auto",
   "author": {
diff --git a/plugins/slack/src/index.ts b/plugins/slack/src/index.ts
index df92ec3c..b62b948b 100644
--- a/plugins/slack/src/index.ts
+++ b/plugins/slack/src/index.ts
@@ -3,6 +3,7 @@ import { Auto, IPlugin } from '@auto-it/core';
 import fetch from 'node-fetch';
 import join from 'url-join';
 
+/** Transform markdown into slack friendly text */
 const sanitizeMarkdown = (markdown: string) =>
   githubToSlack(markdown)
     .split('\n')
@@ -17,15 +18,21 @@ const sanitizeMarkdown = (markdown: string) =>
     .join('\n');
 
 interface ISlackPluginOptions {
+  /** URL of the slack to post to */
   url: string;
+  /** Who to bother when posting to the channel */
   atTarget?: string;
 }
 
+/** Post your release notes to Slack during `auto release` */
 export default class SlackPlugin implements IPlugin {
+  /** The name of the plugin */
   name = 'Slack';
 
+  /** The options of the plugin */
   readonly options: ISlackPluginOptions;
 
+  /** Initialize the plugin with it's options */
   constructor(options: ISlackPluginOptions | string) {
     if (typeof options === 'string') {
       this.options = { url: options, atTarget: 'channel' };
@@ -37,6 +44,7 @@ export default class SlackPlugin implements IPlugin {
     }
   }
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {
     auto.hooks.afterRelease.tapPromise(
       this.name,
@@ -72,6 +80,7 @@ export default class SlackPlugin implements IPlugin {
     );
   }
 
+  /** Post the release notes to slack */
   async postToSlack(auto: Auto, newVersion: string, releaseNotes: string) {
     if (!auto.git) {
       return;
diff --git a/plugins/twitter/package.json b/plugins/twitter/package.json
index dd328711..69d60778 100644
--- a/plugins/twitter/package.json
+++ b/plugins/twitter/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@auto-it/twitter",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "main": "dist/index.js",
   "description": "Twitter plugin for auto",
   "author": {
diff --git a/plugins/twitter/src/index.ts b/plugins/twitter/src/index.ts
index 79109e19..f82e62f1 100644
--- a/plugins/twitter/src/index.ts
+++ b/plugins/twitter/src/index.ts
@@ -6,7 +6,9 @@ import tweetValidation from 'twitter-text';
 import { promisify } from 'util';
 
 interface ITwitterPluginOptions {
+  /** The message template to use to post to Twitter */
   message: string;
+  /** A threshold the semver has to pass to be posted to Twitter */
   threshold: SEMVER;
 }
 
@@ -23,9 +25,11 @@ const defaults: ITwitterPluginOptions = {
 
 const RELEASE_PRECEDENCE: ReleaseType[] = ['patch', 'minor', 'major'];
 
+/** Determine the release with the biggest semver change */
 const isGreaterThan = (a: ReleaseType, b: ReleaseType) =>
   RELEASE_PRECEDENCE.indexOf(a) > RELEASE_PRECEDENCE.indexOf(b);
 
+/** Remove the last line of text from a multiline string */
 const removeLastLine = (text: string) =>
   text
     .split('\n')
@@ -34,14 +38,21 @@ const removeLastLine = (text: string) =>
     .trim();
 
 interface MakeTweetArgs {
+  /** The generated release notes for the release */
   releaseNotes: string;
+  /** The message template to use to post to Twitter */
   message: string;
+  /** The semver bump applied to the version */
   versionBump: ReleaseType;
+  /** The new version to release (already bumped) */
   newVersion: string;
+  /** GitHub project to operate on */
   repo: string;
+  /** A url to link to the release */
   url: string;
 }
 
+/** Construct a tweet that contains the release notes across multiple tweets */
 const makeTweet = ({
   releaseNotes,
   message,
@@ -50,6 +61,7 @@ const makeTweet = ({
   repo,
   url
 }: MakeTweetArgs) => {
+  /** Replace all the variables in the message */
   const build = (notes: string) =>
     message
       .replace('%release', versionBump)
@@ -76,12 +88,18 @@ const makeTweet = ({
   return tweet;
 };
 
+/** Post your release notes to twitter during `auto release` */
 export default class TwitterPlugin implements IPlugin {
+  /** The name of the plugin */
   name = 'Twitter';
 
+  /** The options of the plugin */
   readonly options: ITwitterPluginOptions;
+
+  /** Send a tweet */
   private readonly tweet: (message: string) => Promise<void>;
 
+  /** Initialize the plugin with it's options */
   constructor(options: Partial<ITwitterPluginOptions> = {}) {
     this.options = { ...defaults, ...options };
 
@@ -106,6 +124,7 @@ export default class TwitterPlugin implements IPlugin {
     );
   }
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {
     auto.hooks.afterRelease.tapPromise(
       this.name,
diff --git a/plugins/upload-assets/package.json b/plugins/upload-assets/package.json
index 5341d9de..d507950d 100644
--- a/plugins/upload-assets/package.json
+++ b/plugins/upload-assets/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@auto-it/upload-assets",
-  "version": "7.13.1",
+  "version": "7.13.0",
   "main": "dist/index.js",
   "description": "Upload assets plugin for auto",
   "author": {
diff --git a/plugins/upload-assets/src/index.ts b/plugins/upload-assets/src/index.ts
index dd72a8db..a419b8b0 100644
--- a/plugins/upload-assets/src/index.ts
+++ b/plugins/upload-assets/src/index.ts
@@ -9,18 +9,24 @@ const stat = promisify(fs.stat);
 const readFile = promisify(fs.readFile);
 
 interface IUploadAssetsPluginOptions {
+  /** Paths to assets to uploade */
   assets: string[];
 }
 
+/** Attach extra assets to a GitHub Release */
 export default class UploadAssetsPlugin implements IPlugin {
+  /** The name of the plugin */
   name = 'Upload Assets';
 
+  /** The options of the plugin */
   readonly options: IUploadAssetsPluginOptions;
 
+  /** Initialize the plugin with it's options */
   constructor(options: IUploadAssetsPluginOptions | string[]) {
     this.options = Array.isArray(options) ? { assets: options } : options;
   }
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {
     auto.hooks.afterRelease.tapPromise(this.name, async ({ response }) => {
       auto.logger.log.info(dedent`
diff --git a/scripts/template-plugin/src/index.ts b/scripts/template-plugin/src/index.ts
index 09f92d18..883d592e 100644
--- a/scripts/template-plugin/src/index.ts
+++ b/scripts/template-plugin/src/index.ts
@@ -3,13 +3,17 @@ import { Auto, IPlugin } from '@auto-it/core';
 interface I{{pascal}}PluginOptions {}
 
 export default class {{pascal}}Plugin implements IPlugin {
+  /** The name of the plugin */
   name = '{{title}}';
 
+  /** The options of the plugin */
   readonly options: I{{pascal}}PluginOptions;
 
+  /** Initialize the plugin with it's options */
   constructor(options: I{{pascal}}PluginOptions) {
     this.options = {};
   }
 
+  /** Tap into auto plugin points. */
   apply(auto: Auto) {}
 }
diff --git a/yarn.lock b/yarn.lock
index 4bbc57d9..3f98e7c5 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8,7 +8,7 @@
   integrity sha512-m2OzlTDbhvzK4hgswH9Lx0cdpq1AntXu53Klz5RGkFfuoDvKsnlU7tmtVfNWtUiP0zZbGtrb/BZYH7aB6TRnMA==
 
 "@auto-it/core@link:packages/core":
-  version "7.12.6"
+  version "7.13.0"
   dependencies:
     "@octokit/graphql" "^4.0.0"
     "@octokit/plugin-enterprise-compatibility" "1.1.1"
@@ -36,7 +36,7 @@
     url-join "^4.0.0"
 
 "@auto-it/npm@link:plugins/npm":
-  version "7.12.6"
+  version "7.13.0"
   dependencies:
     "@auto-it/core" "link:packages/core"
     env-ci "^4.1.1"
@@ -51,7 +51,7 @@
     user-home "^2.0.0"
 
 "@auto-it/released@link:plugins/released":
-  version "7.12.6"
+  version "7.13.0"
   dependencies:
     "@auto-it/core" "link:packages/core"
     deepmerge "^4.0.0"
@@ -4477,6 +4477,11 @@ commander@~2.8.1:
   dependencies:
     graceful-readlink ">= 1.0.0"
 
+comment-parser@^0.7.0:
+  version "0.7.0"
+  resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-0.7.0.tgz#9dc1f689a60d81fbcaf867d3c9eba3eb061ccfc1"
+  integrity sha512-m0SGP0RFO4P3hIBlIor4sBFPe5Y4HUeGgo/UZK/1Zdea5eUiqxroQ3lFqBDDSfWo9z9Q6LLnt2u0JqwacVEd/A==
+
 commondir@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
@@ -6052,6 +6057,18 @@ eslint-plugin-jest@^23.0.1:
   dependencies:
     "@typescript-eslint/experimental-utils" "^2.5.0"
 
+eslint-plugin-jsdoc@^17.1.1:
+  version "17.1.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-17.1.1.tgz#5bc84fcdde7c93165f3af9c7be0361d2e3bdb998"
+  integrity sha512-astLOTsj87UIzvDyiuAKbkgQgtChutazTDVxdG254tAtcvIVlWnPmlN7/dLnMYld/aHBhB4SWiUalMuKwTaynQ==
+  dependencies:
+    comment-parser "^0.7.0"
+    debug "^4.1.1"
+    jsdoctypeparser "^5.1.1"
+    lodash "^4.17.15"
+    object.entries-ponyfill "^1.0.1"
+    regextras "^0.6.1"
+
 eslint-plugin-jsx-a11y@^6.2.1:
   version "6.2.3"
   resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.2.3.tgz#b872a09d5de51af70a97db1eea7dc933043708aa"
@@ -9273,6 +9290,11 @@ jsbn@~0.1.0:
   resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
   integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
 
+jsdoctypeparser@^5.1.1:
+  version "5.1.1"
+  resolved "https://registry.yarnpkg.com/jsdoctypeparser/-/jsdoctypeparser-5.1.1.tgz#99c57412fe736c70024bf54204ed1bb93cf4a49f"
+  integrity sha512-APGygIJrT5bbz5lsVt8vyLJC0miEbQf/z9ZBfTr4RYvdia8AhWMRlYgivvwHG5zKD/VW3d6qpChCy64hpQET3A==
+
 jsdom@^11.5.1:
   version "11.12.0"
   resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8"
@@ -11129,6 +11151,11 @@ object.assign@^4.1.0:
     has-symbols "^1.0.0"
     object-keys "^1.0.11"
 
+object.entries-ponyfill@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/object.entries-ponyfill/-/object.entries-ponyfill-1.0.1.tgz#29abdf77cbfbd26566dd1aa24e9d88f65433d256"
+  integrity sha1-Kavfd8v70mVm3RqiTp2I9lQz0lY=
+
 object.entries@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.0.tgz#2024fc6d6ba246aee38bdb0ffd5cfbcf371b7519"
@@ -13004,6 +13031,11 @@ regexpu-core@^4.5.4:
     unicode-match-property-ecmascript "^1.0.4"
     unicode-match-property-value-ecmascript "^1.1.0"
 
+regextras@^0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/regextras/-/regextras-0.6.1.tgz#9689641bbb338e0ff7001a5c507c6a2008df7b36"
+  integrity sha512-EzIHww9xV2Kpqx+corS/I7OBmf2rZ0pKKJPsw5Dc+l6Zq1TslDmtRIP9maVn3UH+72MIXmn8zzDgP07ihQogUA==
+
 registry-auth-token@^3.0.1:
   version "3.4.0"
   resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.4.0.tgz#d7446815433f5d5ed6431cd5dca21048f66b397e"


Test patch:
diff --git a/packages/core/src/__tests__/__snapshots__/changelog.test.ts.snap b/packages/core/src/__tests__/__snapshots__/changelog.test.ts.snap
index 914fa2dc..b492f210 100644
--- a/packages/core/src/__tests__/__snapshots__/changelog.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/changelog.test.ts.snap
@@ -202,8 +202,8 @@ exports[`generateReleaseNotes should match authors correctly 1`] = `
 #### Authors: 3
 
 - [@rdubzz](https://github.custom.com/rdubzz)
-- kendall@email.com
-- andrew@email.com"
+- andrew@email.com
+- kendall@email.com"
 `;
 
 exports[`generateReleaseNotes should merge sections with same changelog title 1`] = `
diff --git a/packages/core/src/__tests__/__snapshots__/log-parse.test.ts.snap b/packages/core/src/__tests__/__snapshots__/log-parse.test.ts.snap
index 2a8f186d..4aea16e6 100644
--- a/packages/core/src/__tests__/__snapshots__/log-parse.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/log-parse.test.ts.snap
@@ -14,7 +14,6 @@ Array [
     "files": Array [],
     "hash": "foo",
     "labels": Array [],
-    "packages": undefined,
     "pullRequest": undefined,
     "subject": "First",
   },
@@ -30,7 +29,6 @@ Array [
     "files": Array [],
     "hash": "foo",
     "labels": Array [],
-    "packages": undefined,
     "pullRequest": undefined,
     "subject": "Second",
   },
@@ -46,7 +44,6 @@ Array [
     "files": Array [],
     "hash": "foo",
     "labels": Array [],
-    "packages": undefined,
     "pullRequest": undefined,
     "subject": "Third",
   },
diff --git a/packages/core/src/__tests__/__snapshots__/release.test.ts.snap b/packages/core/src/__tests__/__snapshots__/release.test.ts.snap
index 6d477ca3..3a8385ad 100644
--- a/packages/core/src/__tests__/__snapshots__/release.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/release.test.ts.snap
@@ -174,7 +174,6 @@ Array [
     "files": Array [],
     "hash": "foo",
     "labels": Array [],
-    "packages": undefined,
     "pullRequest": Object {
       "number": 123,
     },
@@ -197,7 +196,6 @@ Array [
     "files": Array [],
     "hash": "foo",
     "labels": Array [],
-    "packages": undefined,
     "pullRequest": Object {
       "number": 123,
     },
@@ -220,7 +218,6 @@ Array [
     "files": Array [],
     "hash": "foo",
     "labels": Array [],
-    "packages": undefined,
     "pullRequest": Object {
       "number": 124,
     },
@@ -241,7 +238,6 @@ Array [
       "skip-release",
       "minor",
     ],
-    "packages": undefined,
     "pullRequest": Object {
       "number": 123,
     },
@@ -264,7 +260,6 @@ Array [
     "files": Array [],
     "hash": "foo",
     "labels": Array [],
-    "packages": undefined,
     "pullRequest": Object {
       "number": 124,
     },
@@ -285,7 +280,6 @@ Array [
       "skip-release",
       "minor",
     ],
-    "packages": undefined,
     "pullRequest": Object {
       "number": 123,
     },
@@ -310,7 +304,6 @@ Array [
     "files": Array [],
     "hash": "foo",
     "labels": Array [],
-    "packages": undefined,
     "pullRequest": undefined,
     "subject": "First",
   },
@@ -327,7 +320,6 @@ Array [
     "files": Array [],
     "hash": "foo",
     "labels": Array [],
-    "packages": undefined,
     "pullRequest": Object {
       "number": 123,
     },
@@ -345,7 +337,6 @@ Array [
     "files": Array [],
     "hash": "foo",
     "labels": Array [],
-    "packages": undefined,
     "pullRequest": Object {
       "number": 123,
     },
@@ -365,7 +356,6 @@ Array [
     "files": Array [],
     "hash": "foo",
     "labels": Array [],
-    "packages": undefined,
     "pullRequest": undefined,
     "subject": "Third",
   },
diff --git a/packages/core/src/__tests__/auto-make-changelog.test.ts b/packages/core/src/__tests__/auto-make-changelog.test.ts
index 24d0ddd5..5173da6c 100644
--- a/packages/core/src/__tests__/auto-make-changelog.test.ts
+++ b/packages/core/src/__tests__/auto-make-changelog.test.ts
@@ -57,7 +57,6 @@ describe('Auto', () => {
     });
 
     auto.logger = dummyLog();
-    auto.hooks.getRepository.tap('test', () => ({ token: '1234' }));
     await auto.loadConfig();
 
     const addToChangelog = jest.fn();
diff --git a/packages/core/src/__tests__/config.test.ts b/packages/core/src/__tests__/config.test.ts
index 83f497cd..6f6a1c6c 100644
--- a/packages/core/src/__tests__/config.test.ts
+++ b/packages/core/src/__tests__/config.test.ts
@@ -116,7 +116,6 @@ describe('loadExtendConfig', () => {
       json: mockFetchJson
     });
 
-    // tslint:disable-next-line:no-http-string
     await config.loadExtendConfig('http://www.test.com/config.json');
     expect(fetchSpy).toHaveBeenCalled();
     expect(mockFetchJson).toHaveBeenCalled();
@@ -127,7 +126,6 @@ describe('loadExtendConfig', () => {
 
     fetchSpy.mockRejectedValueOnce(new Error());
     await expect(
-      // tslint:disable-next-line:no-http-string
       config.loadExtendConfig('http://www.test.com/config.json')
     ).rejects.toBeInstanceOf(Error);
   });
diff --git a/packages/core/src/__tests__/make-commit-from-msg.ts b/packages/core/src/__tests__/make-commit-from-msg.ts
index a13e3c2a..f566fcf7 100644
--- a/packages/core/src/__tests__/make-commit-from-msg.ts
+++ b/packages/core/src/__tests__/make-commit-from-msg.ts
@@ -1,17 +1,27 @@
 import { IExtendedCommit } from '../log-parse';
 
+/** Construct a dummy commit for testing. */
 const makeCommitFromMsg = (
   subject: string,
   options: {
+    /** Name of the committer */
     name?: string;
+    /** Hash of the commit */
     hash?: string;
+    /** Email of the committer */
     email?: string;
+    /** Labels on the commit */
     labels?: string[];
+    /** Username of the committer */
     username?: string;
+    /** Packages effected by the commit */
     packages?: string[];
+    /** PR info for the commit */
     pullRequest?: {
+      /** PR number attached to commit */
       number: number;
     };
+    /** Files included in commit */
     files?: string[];
   } = {}
 ): IExtendedCommit => ({
@@ -34,7 +44,6 @@ const makeCommitFromMsg = (
     }
   ],
   subject,
-  packages: options.packages,
   pullRequest: options.pullRequest
 });
 
diff --git a/packages/core/src/utils/__tests__/test-plugin.ts b/packages/core/src/utils/__tests__/test-plugin.ts
index 566f210d..a9df2c1c 100644
--- a/packages/core/src/utils/__tests__/test-plugin.ts
+++ b/packages/core/src/utils/__tests__/test-plugin.ts
@@ -1,7 +1,11 @@
 module.exports = class Test {
+  /** The name of the plugin */
   name = 'foo';
+
+  /** The options of the plugin */
   config: {};
 
+  /** Initialize the plugin with it's options */
   constructor(config: {}) {
     this.config = config;
   }
diff --git a/plugins/npm/__tests__/package-config.test.ts b/plugins/npm/__tests__/package-config.test.ts
index e077253e..aaaa80bf 100644
--- a/plugins/npm/__tests__/package-config.test.ts
+++ b/plugins/npm/__tests__/package-config.test.ts
@@ -1,12 +1,9 @@
 import packageConfig from '../src/package-config';
 
-let readResult = '{}';
+let readResult = {};
 
-jest.mock('fs', () => ({
-  // @ts-ignore
-  readFile: (a, b, cb) => {
-    cb(undefined, readResult);
-  }
+jest.mock('../src/utils', () => ({
+  loadPackageJson: () => readResult
 }));
 
 let parseResult: object | undefined = {};
@@ -23,9 +20,9 @@ test('should throw without a repo', async () => {
 
 test('should throw without an owner', async () => {
   expect.assertions(1);
-  readResult = JSON.stringify({
+  readResult = {
     repository: { url: 'fake.com' }
-  });
+  };
   parseResult = undefined;
 
   await expect(packageConfig()).rejects.toStrictEqual(
@@ -37,9 +34,9 @@ test('should throw without an owner', async () => {
 
 test('should throw without an package name', async () => {
   expect.assertions(1);
-  readResult = JSON.stringify({
+  readResult = {
     repository: { url: 'fake.com' }
-  });
+  };
   parseResult = {
     owner: 'black-panther'
   };
@@ -52,10 +49,10 @@ test('should throw without an package name', async () => {
 });
 
 test('should correctly parse package info', async () => {
-  readResult = JSON.stringify({
+  readResult = {
     version: '1.0.0',
     repository: { url: 'fake.com/black-panther/operation-foo' }
-  });
+  };
   parseResult = {
     owner: 'black-panther',
     name: 'operation-foo'