Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
node_modules/
dist/
*.log
promptless-skill-report-card.html
.DS_Store
.env
.env.*
Expand Down
66 changes: 59 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
<a href="example.com">Slack</a>
<p>

A CLI for helping tech writers. Right now it only detects the rhetorical and structural tells of LLM-generated prose and surfaces diagnostics for people to fix.
A CLI for helping tech writers and agent-instruction maintainers. It can detect
the rhetorical and structural tells of LLM-generated prose, and it can generate
a local report card for agent skills and instruction files.

## Install

Expand All @@ -35,8 +37,8 @@ npm install -g git+ssh://git@github.com/Promptless/promptless-cli.git
This exposes two binaries on your `PATH`: `promptless` and `pless`.

```sh
promptless sample.md
pless --diagnostic sample.md
promptless slop-cop sample.md
promptless skill-report-card
```

> The repo is currently internal — you'll need GitHub access to `Promptless/promptless-cli` for the install to fetch.
Expand All @@ -47,18 +49,68 @@ pless --diagnostic sample.md
git clone git@github.com:Promptless/promptless-cli.git
cd promptless-cli
npm install
npm run promptless -- path/to/file.md
npm run promptless -- slop-cop path/to/file.md
npm run promptless -- skill-report-card
```

## Usage

```
promptless [options] <file>...
promptless <command> [options]
```

Run `promptless --help` for the full option list (input format, color, diagnostic vs. human mode, pandoc passthrough).
Run `promptless --help` for the command list.

Exit codes: `0` clean, `1` violations found, `2` argument error.
### `promptless slop-cop`

Detect LLM prose tells in text files and print editor-friendly diagnostics.

```sh
promptless slop-cop docs/page.md
promptless slop-cop --format mdx docs/page.mdx
```

### `promptless skill-report-card`

Generate a local report card for agent instruction files and skills.

```sh
promptless skill-report-card
```

The default flow is interactive:

1. Searches the current directory, common home config locations, and bounded
machine locations for `AGENTS.md`, `CLAUDE.md`, `.agents/`, `.claude/`, and
`.codex/` instruction assets. Generated copies under Codex worktrees, temp
plugin storage, customer-repo clones, and plugin caches are skipped during
broad scans.
2. Groups discovered files by skill-bearing Git repo or global skill location,
then lets you check or uncheck those groups. Instruction-only groups are
shown only when no skills are found.
3. Detects whether `claude` or `codex` CLIs are installed.
4. Shows an estimated LLM token count if a provider is available.
5. Runs deterministic local checks, uses `skill-validator` when it is installed,
prints an inline summary, and writes `promptless-skill-report-card.html`.

Useful noninteractive examples:

```sh
promptless skill-report-card . --yes --llm off
promptless skill-report-card ~/work/docs-agent --llm codex --out report.html
promptless skill-report-card . --yes --fail-under 80
```

Privacy: deterministic checks are local. File contents are only sent to an LLM
when you explicitly choose `claude`, `codex`, or pass `--llm auto|claude|codex`.

Attribution: `skill-report-card` uses
[`skill-validator`](https://github.com/agent-ecosystem/skill-validator) as an
internal component when the binary is available on `PATH`. Promptless adds the
interactive report-card UX, governance scoring, and HTML report.

Exit codes: `0` clean or report generated, `1` runtime/input error, `2`
argument error or `--fail-under` threshold failure.

## License

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@promptless/promptless-cli",
"version": "0.1.0",
"license": "MPL-2.0",
"description": "CLI for helping tech writers. Right now it only detects the rhetorical and structural tells of LLM-generated prose and surfaces diagnostics for people to fix.",
"description": "CLI for helping tech writers and agent-instruction maintainers detect prose issues and score local agent skills.",
"type": "module",
"bin": {
"promptless": "./dist/cli.js",
Expand All @@ -18,6 +18,7 @@
"prepare": "npm run build",
"promptless": "tsx src/cli.ts",
"build": "tsup && chmod +x dist/cli.js",
"test": "node --import tsx --test \"src/**/*.test.ts\"",
"typecheck": "tsc --noEmit"
},
"devDependencies": {
Expand Down
6 changes: 4 additions & 2 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ import { COMMANDS } from './commands/registry'
// Naming conventions: lowercase, kebab-case, noun-ish when the command names the artifact
// it operates on (traces, event), verb-noun when the operation is the point (docs-audit).

const commandNameWidth = Math.max(...COMMANDS.map((command) => command.name.length)) + 2

const TOP_HELP = `promptless — CLI for tech writers

usage:
promptless <command> [options]

commands:
${COMMANDS.map((c) => ` ${c.name.padEnd(12)} ${c.summary}`).join('\n')}
${COMMANDS.map((c) => ` ${c.name.padEnd(commandNameWidth)} ${c.summary}`).join('\n')}

run \`promptless <command> --help\` for command-specific options.
`
Expand All @@ -43,7 +45,7 @@ async function main(): Promise<void> {
process.exit(2)
}

cmd.run(argv.slice(1))
await cmd.run(argv.slice(1))
}

main()
48 changes: 48 additions & 0 deletions src/commands/completion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,19 @@ case $state in
'(-h --help)'{-h,--help}'[show help]' \\
'*:file:_files'
;;
skill-report-card)
_arguments \\
'(-y --yes)'{-y,--yes}'[run without prompts]' \\
'--llm[LLM provider]:provider:(off auto claude codex)' \\
'--out[HTML report path]:file:_files' \\
'--no-open[do not open the generated HTML report]' \\
'--no-machine-scan[skip broader home scan]' \\
'--max-depth[recursion depth]:number:' \\
'--max-directories[directory scan cap]:number:' \\
'--fail-under[minimum passing score]:score:' \\
'(-h --help)'{-h,--help}'[show help]' \\
'*:path:_files'
;;
completion)
_arguments '1:shell:(zsh bash fish)'
;;
Expand Down Expand Up @@ -120,6 +133,13 @@ _promptless_complete() {
COMPREPLY=($(compgen -f -- "$cur"))
fi
;;
skill-report-card)
if [[ "$cur" == -* ]]; then
COMPREPLY=($(compgen -W "--yes -y --llm --out --no-open --no-machine-scan --max-depth --max-directories --fail-under -h --help" -- "$cur"))
else
COMPREPLY=($(compgen -f -- "$cur"))
fi
;;
completion)
COMPREPLY=($(compgen -W "zsh bash fish" -- "$cur"))
;;
Expand Down Expand Up @@ -180,6 +200,34 @@ function fishScript(): string {
`complete -c ${bin} -n '__fish_seen_subcommand_from slop-cop' -s h -l help -d 'Show help'`,
)
lines.push(`complete -c ${bin} -n '__fish_seen_subcommand_from slop-cop' -F`)
lines.push(
`complete -c ${bin} -n '__fish_seen_subcommand_from skill-report-card' -s y -l yes -d 'Run without prompts'`,
)
lines.push(
`complete -c ${bin} -n '__fish_seen_subcommand_from skill-report-card' -l llm -x -a 'off auto claude codex' -d 'LLM provider'`,
)
lines.push(
`complete -c ${bin} -n '__fish_seen_subcommand_from skill-report-card' -l out -r -d 'HTML report path'`,
)
lines.push(
`complete -c ${bin} -n '__fish_seen_subcommand_from skill-report-card' -l no-open -d 'Do not open HTML report'`,
)
lines.push(
`complete -c ${bin} -n '__fish_seen_subcommand_from skill-report-card' -l no-machine-scan -d 'Skip broader home scan'`,
)
lines.push(
`complete -c ${bin} -n '__fish_seen_subcommand_from skill-report-card' -l max-depth -x -d 'Recursion depth'`,
)
lines.push(
`complete -c ${bin} -n '__fish_seen_subcommand_from skill-report-card' -l max-directories -x -d 'Directory scan cap'`,
)
lines.push(
`complete -c ${bin} -n '__fish_seen_subcommand_from skill-report-card' -l fail-under -x -d 'Minimum passing score'`,
)
lines.push(
`complete -c ${bin} -n '__fish_seen_subcommand_from skill-report-card' -s h -l help -d 'Show help'`,
)
lines.push(`complete -c ${bin} -n '__fish_seen_subcommand_from skill-report-card' -F`)
lines.push(
`complete -c ${bin} -n '__fish_seen_subcommand_from completion' -a 'zsh bash fish'`,
)
Expand Down
8 changes: 7 additions & 1 deletion src/commands/registry.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { runSlopCop } from './slop-cop'
import { runSkillReportCard } from './skill-report-card'
import { runCompletion } from './completion'
import { runAgentView } from './agentview'
import { runLogin } from './login'
Expand All @@ -8,7 +9,7 @@ import { runWhoami } from './whoami'
export interface CommandEntry {
name: string
summary: string
run: (argv: string[]) => never
run: (argv: string[]) => void | Promise<void>
}

export const COMMANDS: CommandEntry[] = [
Expand All @@ -32,6 +33,11 @@ export const COMMANDS: CommandEntry[] = [
summary: 'Detect LLM prose tells in text files',
run: runSlopCop,
},
{
name: 'skill-report-card',
summary: 'Score local agent instructions and skills',
run: runSkillReportCard,
},
{
name: 'agentview',
summary: 'Fetch a docs page and show the markdown a coding agent sees',
Expand Down
Loading