-
Notifications
You must be signed in to change notification settings - Fork 4
Description
Specification
Our new commandments for a better, brighter, command line:
- Send output to stdout. The primary output for your command should go to stdout. Anything that is machine readable should also go to stdout—this is where piping sends things by default.
- Send messaging to stderr. Log messages, errors, and so on should all be sent to stderr. This means that when commands are piped together, these messages are displayed to the user and not fed into the next command.
- When we are displaying output text to indicate success, we need to be brief. Feedback is always preferred, even though deviating from UNIX conventions.
- The output from stderr can be redirected to
/dev/null, but we're going to provide more verbosity options that suppresses all non-essential text (feedback, warnings, etc.). - We should ALWAYS be using
camelCasefor anything going tostdout. As we prioritize parsability, this needs to be the default. No more manually outputting strings likeName: amy. - Nested structures should always be avoided in
dictsformats wherever possible. Instead, the nested structure should be spread into thedata. - Streaming with the JSON format should output the objects in JSONL format. To parse it with
jq, one needs to use--slurp
STDOUT
Traditionally, we have constructed human readable dictionaries as such:
process.stdout.write(
binUtils.outputFormatter({
type: options.format === 'json' ? 'json' : 'list',
data: [`Root certificate:\t\t${response.getCert()}`],
}),
);This is clunky, inconsistent, worse for parsability and more...
In all cases where the output is "semantically" a list, the output should use either json or list. In all other cases, the list option should be replaced with dict. This should be done like this:
process.stdout.write(
binUtils.outputFormatter({
type: options.format === 'json' ? 'json' : 'dict',
data: { rootCertificate: response.getCert() },
}),
);The data parameter must be kept as close to the return value of the RPC call possible. This ensures that our output is predictable. Furthermore
STDERR
Log messages, errors, and so on should all be sent to stderr. This means that when commands are piped together, these messages are displayed to the user and not fed into the next command.
Most STDERR messages should either be using the raw or list format. This is because they are intended to be human readable. Under json format, the data should always be { message: "..." }.
process.stderr.write(
binUtils.outputFormatter({
type: 'list',
data: ['Message 1'],
}),
);process.stderr.write(
binUtils.outputFormatter({
type: 'raw',
data: 'Message 1',
}),
);process.stderr.write(
binUtils.outputFormatter({
type: 'json',
data: { message: "Message 1" },
}),
);STDIN
STDIN should always be checked for interactivity before asking prompts. This means that if a Polykey Client session has not already been opened, we should error before asking for a password prompt on a non-interactive terminal.
If input or output is a file, support - to read from stdin or write to stdout. This lets the output of another command be the input of your command and vice versa, without using a temporary file. For example:
cat secret.txt | polykey secret create - vault:secretPiping
There is currently issues with piping input into Polykey-CLI: #139
TBD...
Additional context
- General CLI review issue: Publishing the PK CLI for General Use Polykey#268
- https://clig.dev/#output
Tasks
- Ensure that the output formatter can correctly format output for all possible format options without modifying content
- Replace all usage of the
listformat option withdict(except in situations where the output is more semantically suited to a list) - Ensure that there are no tabs or spaces in json output (as this needs to be machine readable)
- Replace usage of the output formatter with just outputting a single string in cases where this is appropriate
- Implement
-qargument to suppress non-essential output. - Review commands for new specification changes
- Agent - 7/7
- Bootstrap - 1/1
- Identities - 13/13
- Keys - 12/12
- Nodes - 6/6
- Notifications - 3/3
- Secrets - 12/12
- Vaults - 12/12