features-cli
One binary for every feature report
A fast CLI written in Rust, distributed on npm and crates.io. Each action is a command, and PATH defaults to the current directory.
-
Run without installing
npx features-cli@latest serve ./src -
npm
npm install -g features-cli -
cargo
cargo binstall features-cli
Commands
Eight commands, one per question
-
scan
List the features. The default action, so features PATH works too.
features scan [PATH] -
serve
Start an HTTP server with the web dashboard, refreshed when files change.
features serve [PATH] -
build
Build a static version of the web dashboard to host anywhere.
features build [PATH] -
codeowners
Generate or update a CODEOWNERS file from feature ownership.
features codeowners [PATH] -
find-owner
Find the owner of a specific file or folder.
features find-owner <TARGET> [PATH] -
owners
Display only the unique list of owners.
features owners [PATH] -
check
Run validation checks on features, such as duplicate names.
features check [PATH] -
diff
List the features touched since a git ref, with their owners.
features diff [PATH] --since <ref>
Run features <command> --help for the options of a command.
Options
Options at a glance
Grouped by what they change. The second column lists the commands that accept the option.
Output
-
--jsonscan, find-owner, owners, diff - Output as JSON
-
--flatscan - Output features as a flat array instead of a nested structure
-
--descriptionscan - Include feature descriptions
-
--coveragescan - Include coverage (always on with --json, serve and build)
-
--strip-emailsall - Remove commit author emails before publishing a build; names are kept
Dashboard
-
--port <port>serve - Change the port (default: 3000)
-
--allow-origin <origin>serve - Allow another origin to read the data via CORS. Repeatable; by default only localhost is answered
-
--build-dir <path>build - Output directory for the static build (default: build)
Diff
-
--since <ref>diff - Compare with the merge base of <ref> and HEAD, uncommitted changes included
-
--committed-onlydiff - Ignore uncommitted and untracked files
-
--markdowndiff - Output a markdown table for pull request comments
-
--owners-onlydiff - Print only the unique owners, one per line
CODEOWNERS
-
--generate-codeownersserve, build, check - Also generate or update the CODEOWNERS file
-
--codeowners-path <path>codeowners - Custom path and filename (default: CODEOWNERS)
-
--codeowners-prefix <prefix>codeowners, diff - Prefix for owner names (default: @)
Scanning
-
--project-dir <path>all - Project directory for CODEOWNERS paths and extra coverage locations
-
--skip-changesall - Skip computing git history (faster for large repos)
-
--ignore-path <path>all - Ignore a folder and its subfolders. Repeatable
-
--include-skipped-dirsall - Also scan folders skipped by default (node_modules)
-
--coverage-dir <path>all - Custom coverage directory (overrides automatic search)
Legacy flags. Actions used to be flags (--serve, --build,
--check, --list-owners, --find-owner). They still work but are deprecated.
Features touched by a change
Comment on pull requests with GitHub Actions
features diff compares the merge base of a ref and HEAD with your working tree. Each changed file is mapped to its closest feature; a renamed file touches both its old and new feature. The command exits with 0 even when nothing is touched.
name: Features touched
on: pull_request
permissions:
contents: read
pull-requests: write
jobs:
features:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0 # the merge base with the target branch is needed
- name: List touched features
run: npx features-cli@latest diff src --since origin/${{ github.base_ref }} --committed-only --markdown > features.md
- name: Comment on the pull request
env:
GH_TOKEN: ${{ github.token }}
run: gh pr comment ${{ github.event.pull_request.number }} --body-file features.md --edit-last --create-if-none
Three output formats
--json— features with owner,is_owner_inheritedand changed files, plus files outside features.--markdown— a table ready to post as a comment.--owners-only— unique owners, one per line.
Request reviews from owners
Reviewers must be GitHub users or org/team slugs, so set the prefix accordingly.
features diff src --since origin/master --committed-only --owners-only --codeowners-prefix my-org/ \
| xargs -r -n1 gh pr edit "$PR_NUMBER" --add-reviewer
Pull requests from forks get a read-only token: commenting from those needs a pull_request_target
workflow. Read GitHub's security guidance before using it.
Ownership
CODEOWNERS that stay in sync
Ownership declared in feature READMEs is written to a managed section of CODEOWNERS. Anything outside the markers is preserved on each run.
# in the current directory $ features codeowners ./src # with paths relative to the project root $ features codeowners ./src --project-dir ./ # combined with serve, build or check $ features build ./src --generate-codeowners --project-dir ./
# ==== GENERATED BY FEATURES-CLI ====
/src/features/feature-1 @team1
/src/features/feature-2 @team2
# ==== END SECTION GENERATED BY FEATURES-CLI ====
Test coverage
Coverage reports, mapped to features
Run your tests with coverage enabled (for example npx jest --coverage). LCOV and Cobertura reports are found automatically in coverage or .coverage folders.
1
PATH/coveragethe scanned folder
2
./coveragewhere the CLI runs
3
project-dir/coveragewith
--project-diroverride
--coverage-dirany custom location
Full reference in the README on GitHub.
See your features in one command
No configuration, no account. Point the CLI at a folder and open the dashboard.
$ npx features-cli@latest serve ./src