# inclusive-language User Guide

Cisco's `inclusive-language` repository is **not a standalone linter**. It is a
curated set of **rule files and helper scripts** that drive two existing
open-source linters — [alex](https://alexjs.com/) (a Node.js prose linter) and
[woke](https://docs.getwoke.tech/) (a Go binary) — to detect non-inclusive
terminology such as `master`/`slave`, `whitelist`/`blacklist`,
`blackhat`/`whitehat`, and `nonwhite`. The rule files map each flagged term to
Cisco-approved alternatives like `primary`/`replica`, `allowlist`/`blocklist`,
and `unethical hacker`/`ethical hacker`.

This guide gets you scanning a single file in under a minute, then layers on
pre-commit hooks, CI integration, and the bundled GitHub-search scripts that
hunt biased terms across an entire org.

---

## 1. Quick Start

The lowest-friction path is **alex via npx** — no global install, no clone, no
config required for a one-shot scan against alex's built-in rules. Open a
terminal in any project that contains text or source files and run:

```bash
npx alex README.md
```

```text
README.md
  3:14-3:20  warning  `master` may be insensitive, use `primary`, `lead`, `hub`, `reference` instead  master-slave  retext-equality
  9:42-9:51  warning  `whitelist` may be insensitive, use `passlist`, `alrightlist`, `safelist`, `allow list` instead  whitelist-blacklist  retext-equality

⚠ 2 warnings
```

If alex prints warnings you have non-inclusive terms; if it exits silently the
file is clean. To layer the **Cisco-specific YAML rules** from this repository
on top of alex's defaults, you copy `alex-race-rules.yaml` into your project,
copy `.alexrc.js` to the project root, and re-run alex — the loader picks the
configuration up automatically.

> [!TIP]
> `npx alex` works on entire directories too: `npx alex .` scans every text
> file alex understands (Markdown, plain text, HTML) recursively from the
> current directory, honoring `.alexignore` if one is present.

### What this repo gives you

- **`alex-race-rules.yaml`** — 13 term-pair entries for the alex linter mapping `master`/`slave`/`blackhat`/`whitehat`/`nonwhite`/`blacklist`/`whitelist` (plus their plurals and `-ed`/`-ing` forms) to inclusive alternatives.
- **`cisco-rules.yaml`** — 4 rule entries (`whitelist`, `blacklist`, `master`, `slave`) for the woke linter, with longer alternative lists tailored to each term's technical context.
- **`.alexrc.js`** — the alex runtime config that disables binary-pair flagging and allowlists Cisco's custom rule pack.
- **`.alexignore`** — sample ignore patterns showing which paths alex should skip.
- **`gh_search.py`** / **`gh_default_branch.py`** — Python helpers using PyGitHub to search a GitHub or GitHub Enterprise organization for biased keywords, or to find repos whose default branch is still named `master`.
- **`exampleconfig.py`** — template `config.py` consumed by the two `gh_*` scripts; supplies the API token, endpoint, and org name.

### Prerequisites at a glance

| Goal | Need installed |
| --- | --- |
| Scan one file with alex's built-ins | Node.js 18+ (for `npx alex`) |
| Apply Cisco's alex rules | Node.js 18+ and the YAML rule file from this repo |
| Run the woke linter with Cisco rules | The `woke` Go binary in `$PATH` |
| Search a GitHub org for biased terms | Python 3.9+, `pygithub`, a personal access token |

> [!NOTE]
> The repository's `Pipfile` pins Python to **3.9.6** and the `package.json`
> declares **alex `^11.0.1`** as the only Node.js dependency. Newer Node and
> Python versions work fine in practice, but those are the versions Cisco
> tests against.

### Where to go next

- Section 2 walks through every install path (npx, global npm, woke binary, Python venv).
- Section 3 documents `.alexrc.js`, `.alexignore`, and the YAML rule formats.
- Section 5 has copy-paste recipes for pre-commit hooks, GitHub Actions, custom term mappings, and false-positive allowlisting.

---

## 2. Installation

`inclusive-language` is a configuration bundle — the actual scanners come from
the npm registry (`alex`) and from a separate Cisco/GetWoke release (`woke`).
Pick the install lane that matches how you plan to consume the rules.

### 2.1 Lane A — alex via `npx` (recommended for one-off scans)

This is the lowest-friction path. No persistent install, always uses the
latest published `alex` version.

```bash
npx alex .
```

The first invocation downloads the package into npm's cache; subsequent runs
are near-instant. If you also want this repository's Cisco-specific rules
applied, drop the YAML rule file and `.alexrc.js` into the project root before
running `npx alex`.

> [!TIP]
> Use `npx alex@11` to pin to the exact major version Cisco tests against, in
> case a future alex release changes default rule behavior.

### 2.2 Lane B — alex installed locally per project

When alex needs to be reproducible (CI, team-wide enforcement), install it as
a `devDependency`:

```bash
npm install --save-dev alex@^11.0.1
```

```text
added 142 packages in 4s
```

Then add an npm script — the `package.json` in this repository already shows
the canonical wiring:

```json
{
  "devDependencies": {
    "alex": "^11.0.1"
  },
  "scripts": {
    "lint-language": "alex"
  }
}
```

After that, `npm run lint-language` is the one command developers and CI both
invoke. Copy `alex-race-rules.yaml` and `.alexrc.js` from this repo into the
project root so the local alex installation picks up Cisco's rule pack.

### 2.3 Lane C — alex installed globally

```bash
npm install -g alex
```

```text
added 88 packages in 6s
```

After installation `alex --version` prints the installed version, and `alex`
without arguments scans the current directory. Globally installed alex is
convenient for ad-hoc use on your laptop but is **not** what you want in CI —
pin it locally instead so the version is reproducible.

> [!IMPORTANT]
> `alex` is the **only** npm dependency declared in this repository's
> `package.json`. There is no Cisco-published npm package — the rule pack
> ships as YAML files you copy into your repo, not as a wrapped binary.

### 2.4 Lane D — woke binary (the alternative scanner)

The `cisco-rules.yaml` rule file targets the [woke](https://docs.getwoke.tech/)
linter, a single Go binary. Install woke with the project's official one-line
script (Linux/macOS):

```bash
curl -sSfL https://git.io/getwoke | bash -s -- -b /usr/local/bin
```

Then point woke at the Cisco rule file copied from this repository:

```bash
woke --rule-in cisco-rules.yaml .
```

```text
README.md:14:8-14:13: `master` may be insensitive, use `primary`, `control`, `active`, `source`, `parent`, `main` instead (warning)
```

> [!NOTE]
> `cisco-rules.yaml` overrides woke's bundled defaults if you pass `--rule-in`,
> and **adds to** them if you pass `--rule-in` along with woke's stock rule
> file. The four rules in `cisco-rules.yaml` cover only `whitelist`,
> `blacklist`, `master`, and `slave` — woke's default ruleset is broader, so
> most teams keep the defaults and append.

### 2.5 Lane E — Python helper scripts

The two `gh_*.py` scripts are independent utilities for hunting biased terms
across whole GitHub organizations. Install their Python dependencies into a
virtualenv:

```bash
git clone https://github.com/cisco-open/inclusive-language.git
cd inclusive-language
python -m venv .venv
source .venv/bin/activate    # Windows: .venv\Scripts\activate
pip install -r requirements.txt
```

Then create your own `config.py` from the bundled template:

```bash
cp exampleconfig.py config.py
```

Edit `config.py` with a real GitHub personal access token, the API endpoint
(`https://api.github.com/` for github.com, your enterprise URL otherwise), and
the org name to scan.

```python
gh_api_key = "ghp_yourRealTokenGoesHere"
gh_api_endpoint = "https://api.github.com/"
gh_orgname = "your-org-name"
```

> [!WARNING]
> The bundled `exampleconfig.py` contains a fake string
> (`"ghp_TotallyaFaKeTok3nIprom1seYouS0d0ntTrYit"`) — it is a placeholder, not
> a working credential. Replace it before running. Never commit your real
> `config.py`; add it to `.gitignore`.

### 2.6 Verify your install

After whichever lane you chose, confirm the tool is wired up:

```bash
# alex
alex --version

# woke
woke --version

# Python helpers
python -c "import github; print(github.__version__)"
```

```text
11.0.1
v0.19.0
1.59.0
```

If all three commands print versions you can run any recipe in Section 5.

---

## 3. Configuration

There are three configuration surfaces in this repository, one per consumer:

| File | Linter | Format |
| --- | --- | --- |
| `.alexrc.js` | alex | CommonJS (Node) |
| `alex-race-rules.yaml` | alex | YAML — 13 term entries |
| `cisco-rules.yaml` | woke | YAML — 4 rule entries |

The fourth file, `.alexignore`, is alex's path-exclusion list (gitignore
syntax).

### 3.1 `.alexrc.js` — alex runtime configuration

```javascript
exports.allow = [
    "cisco-rules" // name of the rule you want to allow
   ];
exports.noBinary = true;
```

The shipped configuration does two things:

1. **`allow`** — accepts an array of rule names that alex should treat as exemptions even though they would otherwise warn. The shipped value `"cisco-rules"` is a placeholder; substitute the names of any specific alex rules you want to silence project-wide.
2. **`noBinary`** — when `true`, alex stops warning about pure binary pairs (e.g., `he/she`, `him/her`) and focuses on the more clearly insensitive terms. Cisco ships this enabled to reduce false-positive noise.

> [!NOTE]
> `.alexrc.js` is a JavaScript module, not JSON. That means you can compute
> values, read environment variables, or `require()` other files. Most teams
> keep it as a literal `exports.{key} = {value}` form — anything more is
> rarely needed.

### 3.2 `.alexignore` — alex exclusion patterns

This file uses the same syntax as `.gitignore` — one path or glob per line,
`#` for comments. Add entries for generated content, vendor directories, or
files where biased terms appear by design (e.g., a glossary documenting the
terms being flagged).

```text
# Skip generated docs
build/
dist/

# Skip files where the biased terms are the subject
docs/inclusive-language-glossary.md
```

If `.alexignore` is missing, alex scans every text file it understands.

### 3.3 `alex-race-rules.yaml` — the alex rule pack

Each entry is a YAML mapping with three keys: `type`, `considerate`, and
`inconsiderate`. Optional `note` adds context shown to the user.

```yaml
- type: basic
  note: Avoid using the term `master`; these suggestions are for the computer term, but there are better alternatives for other cases too
  considerate:
    - primary
    - lead
    - hub
    - reference
  inconsiderate:
    - master
```

| Field | Required | Purpose |
| --- | --- | --- |
| `type` | yes | Rule kind. Always `basic` in this file. |
| `inconsiderate` | yes | List of terms that trigger a warning when matched. |
| `considerate` | yes | List of recommended replacements shown in the warning text. |
| `note` | no | Free-text rationale shown alongside the warning. |

Cisco ships **13 entries** — singular, plural, and verb-form variants of each
core term. The full mapping is documented in Admin Guide §3.

### 3.4 `cisco-rules.yaml` — the woke rule pack

woke's rule schema is different. Each rule has a `name`, a list of `terms` to
flag, and a list of `alternatives`.

```yaml
rules:
  - name: master
    terms:
      - master
    alternatives:
      - primary
      - control
      - active
      - source
      - parent
      - main
```

The four shipped rules and their alternatives:

| `name` | `terms` | `alternatives` |
| --- | --- | --- |
| `whitelist` | `whitelist` | `permit(list)`, `allow(list)` |
| `blacklist` | `blacklist` | `ban(list)`, `block(list)` |
| `master` | `master` | `primary`, `control`, `active`, `source`, `parent`, `main` |
| `slave` | `slave` | `secondary`, `subordinate`, `data`, `standby`, `subsidiary`, `replica`, `worker`, `child`, `helper`, `follower` |

> [!WARNING]
> The two YAML rule files cover **different sets of terms**. `cisco-rules.yaml`
> (woke) handles only the four core pairs. `alex-race-rules.yaml` (alex) adds
> `blackhat`/`whitehat`/`nonwhite` and includes plural and tense variants. If
> you want full coverage with woke, you must extend `cisco-rules.yaml`
> yourself or run woke alongside woke's stock rule file.

### 3.5 `config.py` — Python helper credentials

The `gh_search.py` and `gh_default_branch.py` scripts read three module-level
constants from a sibling `config.py` file:

| Constant | Type | Example | Used by |
| --- | --- | --- | --- |
| `gh_api_key` | `str` | `"ghp_..."` | Both scripts (passed to `Github(token)`) |
| `gh_api_endpoint` | `str` | `"https://api.github.com/"` or `"https://github.example.com/api/v3/"` | `gh_search.py` only (Enterprise mode) |
| `gh_orgname` | `str` | `"cisco-open"` | Both scripts (interpolated into `org:` qualifier) |

The shipped `exampleconfig.py` is the template — copy, rename to `config.py`,
and replace the values.

> [!IMPORTANT]
> `config.py` ends up holding a real personal access token. Add `config.py` to
> your `.gitignore` immediately after creating it, and use a token scoped only
> to **`repo` (read)** if your target org is private, or no scopes at all if
> the org is fully public. Tokens with write or admin scope are unnecessary
> and dangerous in this script.

---

## 4. Core Usage

The scanners do one thing: take a path, walk the files under it, emit a
warning for every flagged term. There is no auto-fix — the developer reads the
warning and edits.

### 4.1 Scanning with alex

```bash
# A single file
alex README.md

# An entire directory tree
alex .

# Multiple specific files
alex README.md docs/architecture.md src/server.js

# Read from stdin
cat README.md | alex --stdin
```

Output goes to stdout (warnings) and stderr (errors). Exit code is `0` when
clean and `1` when warnings are present, which is what makes alex usable as a
CI gate.

### 4.2 Scanning with woke

```bash
# Default rules, current directory
woke .

# Cisco's rules only
woke --rule-in cisco-rules.yaml .

# Multiple paths
woke src/ docs/ README.md
```

> [!NOTE]
> `woke` exits non-zero on findings by default — same gate behavior as alex.
> For an inventory pass that should never fail CI, add
> `--exit-1-on-failure=false` (consult `woke --help` for the exact flag in
> your installed version, since woke's CLI surface evolves between releases).

### 4.3 Hunting biased terms across a whole org

`gh_search.py` runs an interactive prompt that searches an entire GitHub or
GitHub Enterprise organization for a single keyword.

```bash
python gh_search.py
```

```text
Enter Enterprise for Enterprise GitHub, otherwise by default search GitHub: github
Enter biased keyword such as "master", "slave", "blacklist", "whitelist": master
Enter extension for files to search within such as "py" for Python, "md" for Markdown, and enter "any" for all file types: py
You have 28/30 API calls remaining
Found 14 entries with master
Keyword,File type,GitHub URL,File match
master,py,https://raw.githubusercontent.com/.../config.py,my-repo/config.py
...
```

Output is CSV-shaped lines printed to stdout, plus an info log at
`githubsearchresultsinfo.log` (or `enterprisesearchresultsinfo.log` for
Enterprise mode). The script sleeps two seconds between every result page to
stay inside GitHub's search rate limit, and detects rate-limit exhaustion to
sleep until the reset window.

> [!CAUTION]
> Reading the source carefully reveals that `gh_search.py` always invokes
> `search_enterprise_github` because the `which_github` variable is hard-coded
> to `'Enterprise'` immediately before the dispatch. The interactive prompt's
> answer is **ignored** at the bottom of the file. If you want public-GitHub
> search, edit the script to remove the `which_github = 'Enterprise'` line
> just before the `if which_github == "Enterprise":` check.

### 4.4 Finding repos with a `master` default branch

`gh_default_branch.py` walks every public repository in the configured org and
prints the name of any repo whose default branch is still `master`.

```bash
python gh_default_branch.py
```

```text
Enter a keyword such as ansible, labs, to filter a list of repo names in an org: ansible
Your API call rate for core: 4998/5000
Repo: cisco-open/ansible-galaxy-collection has a default branch named master.
Repo: cisco-open/ansible-roles has a default branch named master.
```

Pass an empty string at the prompt to scan every repo in the org without
filtering by name.

> [!TIP]
> The script ships with the **issue-creation block commented out**. Uncomment
> the multi-line block at the bottom of `repo_default_branch()` if you want
> the script to file a tracking issue against every offending repo. Test on a
> single throwaway repo first — once filed, automated issues are awkward to
> retract.

---

## 5. Common Tasks

Six recipes that cover the day-to-day workflows.

### 5.1 Recipe — Scan a single file

```bash
npx alex CHANGELOG.md
```

```text
CHANGELOG.md
  12:5-12:11  warning  `master` may be insensitive, use `primary`, `lead`, `hub`, `reference` instead  master-slave  retext-equality

⚠ 1 warning
```

If the file is clean, alex exits silently with code `0`. To scan from outside
the file's directory:

```bash
npx alex /path/to/CHANGELOG.md
```

### 5.2 Recipe — Scan an entire repository

Drop these three files into your project root:

```bash
curl -O https://raw.githubusercontent.com/cisco-open/inclusive-language/main/.alexrc.js
curl -O https://raw.githubusercontent.com/cisco-open/inclusive-language/main/.alexignore
curl -O https://raw.githubusercontent.com/cisco-open/inclusive-language/main/alex-race-rules.yaml
```

Then:

```bash
npx alex .
```

alex automatically discovers `.alexrc.js` in the working directory, applies
`.alexignore`, and emits warnings for the 13 term-pair rules from
`alex-race-rules.yaml`.

### 5.3 Recipe — Run as a pre-commit hook

The simplest pattern uses [husky](https://typicode.github.io/husky/) plus
`lint-staged` so only the staged files are scanned, keeping the hook fast.

```bash
npm install --save-dev husky lint-staged alex
npx husky init
echo 'npx lint-staged' > .husky/pre-commit
```

Then add `lint-staged` configuration to `package.json`:

```json
{
  "lint-staged": {
    "*.{md,js,ts,py,yaml}": "alex"
  }
}
```

> [!WARNING]
> Pre-commit hooks block the commit on warnings. If your existing repo has
> historical content with biased terms, run `alex` once and fix everything
> before enabling the hook — otherwise developers cannot commit anything
> until the legacy content is cleaned up.

### 5.4 Recipe — Add to GitHub Actions CI

Save this to `.github/workflows/inclusive-language.yml`:

```yaml
name: Inclusive Language Check
on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

jobs:
  alex:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm install --save-dev alex@^11.0.1
      - run: npx alex .
```

The job exits non-zero when alex emits warnings, which fails the PR check.
Combined with branch protection on `main`, this prevents non-inclusive
terminology from landing.

> [!TIP]
> If you want **woke** instead of (or in addition to) alex, swap the last two
> steps for `getwoke/woke-action@v0` (community-maintained) and pass
> `--rule-in cisco-rules.yaml` via the action's inputs.

### 5.5 Recipe — Customize the term mapping

To change which terms alex flags or what alternatives it suggests, edit
`alex-race-rules.yaml`. Every entry follows the same shape:

```yaml
- type: basic
  note: Internal-jargon replacement
  considerate:
    - simple
    - clear
  inconsiderate:
    - oversimplified-jargon
```

Add or remove entries freely. After saving, re-run alex — there is no
reload step.

> [!NOTE]
> alex's match is **case-insensitive** and **whole-word**. Adding `master` as
> an inconsiderate term flags `master`, `Master`, and `MASTER` but does not
> flag `mastermind` or `headmaster` because they are different word stems.

### 5.6 Recipe — Allowlist false positives

When a flagged term is intentional (e.g., the word `master` appearing in a
historical quotation, in a third-party API name you cannot rename, or in a
glossary entry that documents the term itself), alex offers two escape
hatches.

**Per-line, in source:**

```markdown
<!--alex disable master-->
The Postgres `pg_replication_slots` view shows the master/slave topology.
<!--alex enable-->
```

**Project-wide, via `.alexrc.js`:**

```javascript
exports.allow = [
    "master-slave",   // never warn on this rule
    "whitelist-blacklist"
];
exports.noBinary = true;
```

**Path-wide, via `.alexignore`:**

```text
# The glossary documents the terms being flagged
docs/glossary.md
```

> [!IMPORTANT]
> The shipped `.alexrc.js` already lists `"cisco-rules"` in `allow`, but that
> is a placeholder name. Replace it with the actual rule identifiers you want
> to suppress (e.g., `"master-slave"`, `"whitelist-blacklist"`). The list is
> matched against alex's internal rule names, not against your YAML
> filenames.

---

## 6. Troubleshooting

A diagnostic decision tree:

```text
alex prints nothing AND exits 0  → file is clean (no action)
alex prints warnings AND exits 1 → fix the flagged terms or allowlist them (Section 5.6)
alex prints "command not found"  → re-run via `npx alex` or reinstall (Section 2)
woke prints "rule file not found" → verify path, must be relative to CWD or absolute
gh_search.py prints "Bad credentials" → regenerate the token, update config.py
gh_search.py hangs at "0/30 API calls remaining" → script is sleeping until the rate-limit reset; this is intentional
```

### Error: `alex: command not found`

**Cause:** alex is not installed globally and you are not invoking it via npx
or an npm script.

**Solution:**

1. Use `npx alex` instead of bare `alex`.
2. Or install globally: `npm install -g alex`.
3. Or add an `npm run lint-language` script to `package.json` and invoke it.

**Prevention:** prefer the project-local install pattern (Section 2.2) so the
tool ships with the repo.

### Error: alex finds zero issues but you know there are biased terms

**Cause:** the file extension is one alex does not recognize. alex scans
plaintext-like formats (Markdown, plain text, HTML, plus a few code formats
when prose is detected). Pure binary files and unrecognized extensions are
skipped silently.

**Solution:**

1. Verify the file extension is one of `.md`, `.markdown`, `.txt`, `.html`, `.mdx`.
2. For source files, alex only scans comments and strings — make sure the biased term is actually in a comment.
3. For full coverage of source code, switch to the **woke** linter, which scans every line of every file regardless of language.

**Prevention:** use alex for prose, woke for source code; deploy both for
maximum coverage.

### Error: `woke: rule file 'cisco-rules.yaml' not found`

**Cause:** the path passed to `--rule-in` is relative to the current working
directory, not to where `cisco-rules.yaml` actually lives.

**Solution:**

```bash
# Use an absolute path
woke --rule-in /absolute/path/to/cisco-rules.yaml .

# Or change to the directory holding the rule file
cd /path/with/cisco-rules.yaml && woke --rule-in cisco-rules.yaml /target/path
```

**Prevention:** keep `cisco-rules.yaml` checked into your repo at a stable
relative path (e.g., `.woke/cisco-rules.yaml`) and reference it consistently.

### Error: `gh_search.py` always says "Enterprise" mode regardless of the prompt

**Cause:** the script hard-codes `which_github = 'Enterprise'` immediately
before the dispatch, overriding the value collected from `input()`. This is a
bug in the shipped script.

**Solution:**

1. Open `gh_search.py`.
2. Find the line `which_github = 'Enterprise'` near line 388.
3. Comment it out or delete it.
4. Re-run.

**Prevention:** none — patch the script on first checkout if you intend to
search public github.com.

### Error: `pygithub` install fails with `cffi` build errors

**Cause:** `Pipfile` pins `cffi==1.15.1`, which lacks pre-built wheels for
Python 3.12+ on some platforms.

**Solution:**

1. Use Python 3.9-3.11 (matches `python_version = "3.9.6"` in the Pipfile).
2. Or remove the explicit `cffi` pin from `Pipfile` and let pip resolve to a newer wheel.
3. Or install build tools (`build-essential` on Linux, Xcode CLT on macOS, MS Build Tools on Windows) so cffi compiles from source.

**Prevention:** stick to the Python version pinned in the `Pipfile` for
reproducibility.

### Error: GitHub search returns far fewer results than expected

**Cause:** the GitHub search API has a hard cap of **1,000 results per query**
and indexing lag of up to several minutes for newly pushed commits. Large
orgs hit the cap regularly.

**Solution:**

1. Narrow with the file-extension prompt instead of `any`.
2. Run multiple keyword passes (`master`, then `slave`, then `whitelist`).
3. For exhaustive coverage, clone every repo and run `woke` locally instead of using the API.

**Prevention:** treat `gh_search.py` as a sampling tool, not an audit tool.
For audits, use local woke runs.

### Error: `Bad credentials` when running either Python script

**Cause:** the personal access token in `config.py` is missing, expired, or
lacks the required scope.

**Solution:**

1. Generate a new fine-grained token at <https://github.com/settings/tokens>.
2. For public repos: no scopes required.
3. For private repos in your org: grant **Contents — Read-only**.
4. Save the token to `config.py` under `gh_api_key`.

**Prevention:** set the token to expire in 90 days and rotate it; never
commit `config.py`.

### Issue tracking

The repository tracks open work in two GitHub issues:

| Issue | Status | Title |
| --- | --- | --- |
| [#30](https://github.com/cisco-open/inclusive-language/issues/30) | OPEN | Build up a test and support matrix |
| [#142](https://github.com/cisco-open/inclusive-language/issues/142) | OPEN | Investigate the status of the woke linter |

Issue #142 is particularly relevant — the woke project has had limited
maintenance activity, so teams committing to woke long-term should subscribe
to that thread for status updates.

---

## 7. FAQ

**Q: Is `inclusive-language` a linter I install and run?**

No. It is a bundle of rule files and helper scripts that drive **alex**
(npm) and **woke** (Go binary). You install one or both of those linters,
then point them at the YAML files from this repository.

**Q: Which linter should I pick — alex or woke?**

Use **alex** for prose-heavy projects (docs, READMEs, blog posts) — it
understands natural-language context and avoids flagging biased terms
inside code that needs them (e.g., a variable named `master_branch`). Use
**woke** for source code where you want every line scanned regardless of
language. Many teams run both.

**Q: Does the tool fix the issues automatically?**

No. Both alex and woke report findings only — they never edit files. The
expectation is that a developer reads the warning and chooses the right
inclusive replacement for their context (e.g., `master` → `primary` for
servers, `main` for branches, `original` for documents).

**Q: Will alex flag valid technical terms like `master.cf` (Postfix) or `cmaster`?**

alex's matcher is whole-word, so `master.cf` does match (because `master` is
the whole word before `.`). Add `master` (or the specific rule) to the
`allow` array in `.alexrc.js`, or wrap the offending line with
`<!--alex ignore master-->`. See Section 5.6.

**Q: Where do I find the full list of terms alex flags by default?**

alex's defaults come from the [retext-equality](https://github.com/retextjs/retext-equality)
rule pack — about 1,000 term pairs covering gender, race, religion,
disability, and other categories. The YAML files in this repository **add**
to that default list with Cisco's specific computer-science term mappings.

**Q: Can I run the helper scripts against `github.com` instead of GitHub Enterprise?**

In theory yes — `gh_search.py` accepts a `github` answer at the prompt — but
the shipped code overrides that input with `which_github = 'Enterprise'`
just before dispatch. Patch that line out of `gh_search.py` to enable the
public-github path. `gh_default_branch.py` already targets public github
unconditionally.

**Q: What happens if `cisco-rules.yaml` and woke's default rules disagree?**

woke merges rule files, so if both define a rule with the same `name` the
one loaded last wins. Cisco's `cisco-rules.yaml` defines `whitelist`,
`blacklist`, `master`, `slave` — woke's defaults already cover these and
more. Pass `--rule-in cisco-rules.yaml` only if you want Cisco's specific
alternative terms; otherwise use woke's defaults.

**Q: How do I update to a new alex version?**

`npm install --save-dev alex@latest` updates the `package.json` dependency.
Cisco's `package.json` pins `^11.0.1`, which permits any 11.x release. Do a
trial run after updating — major-version bumps occasionally change rule
behavior or output format.

**Q: Are there false positives on technical terms like `nonwhite` (which appears in CSS)?**

Yes — `alex-race-rules.yaml` flags `nonwhite` and `non white`. CSS, image
processing, and UI code use these terms legitimately. Allowlist
`white-supremacy-language` (alex's internal rule name for the
`nonwhite`/`non white` pair) project-wide via `.alexrc.js`, or use inline
`<!--alex ignore-->` comments at the specific line.

**Q: Why does `gh_default_branch.py` only check public repos?**

Look at the source — line 202 has `if repo.private == False:`. Private repos
are explicitly skipped. Remove that check (and ensure your token has access)
if you want it to scan everything.

**Q: How is this tool maintained?**

It is a Cisco Open Source project under the `cisco-open` GitHub
organization. The tracked open issues — [#30](https://github.com/cisco-open/inclusive-language/issues/30)
(test/support matrix) and [#142](https://github.com/cisco-open/inclusive-language/issues/142)
(woke linter status) — are the canonical roadmap. Pull requests are accepted
under the LICENSE file in the repo root.

**Q: Is there a Docker image?**

Not from this repo. Both alex and woke have community-maintained images
(`docker run --rm ghcr.io/get-alex/alex .` and
`docker run --rm getwoke/woke .`), but neither bundles Cisco's rule files —
you mount them in at runtime.

---

_Generated April 2026 from cisco-open/inclusive-language at 0486454. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
