@almyty/cli 0.1.3 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -15
- package/dist/commands.d.ts +61 -0
- package/dist/commands.js +204 -0
- package/dist/exit-codes.d.ts +26 -0
- package/dist/exit-codes.js +32 -0
- package/dist/index.d.ts +1 -3
- package/dist/index.js +36 -79
- package/dist/version.d.ts +2 -0
- package/dist/version.js +22 -0
- package/package.json +30 -9
package/README.md
CHANGED
|
@@ -1,43 +1,113 @@
|
|
|
1
1
|
# @almyty/cli
|
|
2
2
|
|
|
3
|
-
Umbrella CLI for almyty. One install, every command.
|
|
3
|
+
Umbrella CLI for almyty. One install, one login, every command.
|
|
4
4
|
|
|
5
5
|
## Quick start
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
$ npm install -g @almyty/cli
|
|
9
|
+
$ almyty # a short tour
|
|
9
10
|
$ almyty login
|
|
10
11
|
$ almyty agents list
|
|
11
12
|
```
|
|
12
13
|
|
|
14
|
+
`almyty` on its own prints a five-line tour. `almyty help` prints the
|
|
15
|
+
full reference, and `almyty <command> --help` prints that command's own
|
|
16
|
+
options — the umbrella forwards `--help` to the package it delegates to.
|
|
17
|
+
|
|
13
18
|
## Commands
|
|
14
19
|
|
|
15
20
|
| Command | Delegates to | Description |
|
|
16
21
|
|---------|-------------|-------------|
|
|
17
|
-
| `almyty login` | `@almyty/auth` | Browser-based login |
|
|
22
|
+
| `almyty login` | `@almyty/auth` | Browser-based login (writes `~/.almyty/credentials.json`) |
|
|
18
23
|
| `almyty logout` | `@almyty/auth` | Remove stored credentials |
|
|
19
|
-
| `almyty whoami` | `@almyty/auth` | Show current identity |
|
|
20
|
-
| `almyty
|
|
21
|
-
| `almyty
|
|
22
|
-
| `almyty
|
|
23
|
-
| `almyty
|
|
24
|
+
| `almyty whoami` | `@almyty/auth` | Show the current identity and when it expires |
|
|
25
|
+
| `almyty auth <cmd>` | `@almyty/auth` | The same three, spelled out |
|
|
26
|
+
| `almyty agents <cmd>` | `@almyty/agents` | List, run, inspect and trace agents |
|
|
27
|
+
| `almyty chat [ref]` | `@almyty/chat` | Interactive chat REPL |
|
|
28
|
+
| `almyty skills <cmd>` | `@almyty/skills` | Install API skills into AI coding agents |
|
|
29
|
+
| `almyty models <cmd>` | `@almyty/models` | Model catalog: cards, validation, deployments |
|
|
30
|
+
| `almyty connections <cmd>` | `@almyty/connections` | Connect third-party accounts, validate, grant |
|
|
31
|
+
| `almyty runner <cmd>` | `@almyty/runner` | Run agents on this machine as a daemon |
|
|
32
|
+
| `almyty mcp <args>` | `@almyty/mcp-server` | Serve your agents and tools over MCP |
|
|
33
|
+
| `almyty acp <args>` | `@almyty/acp-server` | Serve an agent over the Agent Client Protocol |
|
|
34
|
+
|
|
35
|
+
Handled by the umbrella itself:
|
|
36
|
+
|
|
37
|
+
| Command | Description |
|
|
38
|
+
|---------|-------------|
|
|
39
|
+
| `almyty help`, `--help` | The full command reference |
|
|
40
|
+
| `almyty version`, `--version` | The installed version |
|
|
41
|
+
| `almyty completion <shell>` | A completion script for `bash`, `zsh` or `fish` |
|
|
42
|
+
|
|
43
|
+
An unknown command exits `2` and suggests the nearest real one
|
|
44
|
+
(`almyty agent list` → "Did you mean `almyty agents`?").
|
|
45
|
+
|
|
46
|
+
## Shell completion
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# bash — add to ~/.bashrc
|
|
50
|
+
eval "$(almyty completion bash)"
|
|
51
|
+
|
|
52
|
+
# zsh — add to ~/.zshrc
|
|
53
|
+
eval "$(almyty completion zsh)"
|
|
54
|
+
|
|
55
|
+
# fish
|
|
56
|
+
almyty completion fish > ~/.config/fish/completions/almyty.fish
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Exit codes
|
|
60
|
+
|
|
61
|
+
The same table in every almyty CLI, so `almyty <anything>` can be
|
|
62
|
+
scripted the same way:
|
|
63
|
+
|
|
64
|
+
| Code | Meaning |
|
|
65
|
+
|------|---------|
|
|
66
|
+
| `0` | success |
|
|
67
|
+
| `1` | unexpected error |
|
|
68
|
+
| `2` | usage error (bad flags, unknown command) |
|
|
69
|
+
| `3` | not authenticated — run `almyty login` |
|
|
70
|
+
| `4` | not found (agent, gateway, skill, or run) |
|
|
71
|
+
| `5` | the operation ran and failed |
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
almyty agents run deploy-check --watch || case $? in
|
|
75
|
+
3) almyty login ;;
|
|
76
|
+
5) echo "the check failed"; exit 1 ;;
|
|
77
|
+
esac
|
|
78
|
+
```
|
|
24
79
|
|
|
25
80
|
## Standalone packages
|
|
26
81
|
|
|
27
|
-
Every subcommand is also
|
|
82
|
+
Every subcommand is also a standalone package, so the umbrella is a
|
|
83
|
+
convenience and not a requirement:
|
|
28
84
|
|
|
29
85
|
```bash
|
|
86
|
+
$ npx @almyty/auth login
|
|
30
87
|
$ npx @almyty/agents list
|
|
31
|
-
$ npx @almyty/chat my-bot
|
|
32
|
-
$ npx @almyty/skills install
|
|
88
|
+
$ npx @almyty/chat myorg/my-bot
|
|
89
|
+
$ npx @almyty/skills install org/gateway
|
|
33
90
|
```
|
|
34
91
|
|
|
35
|
-
|
|
92
|
+
They all read the same credentials file (`~/.almyty/credentials.json`),
|
|
93
|
+
so logging in once works everywhere.
|
|
94
|
+
|
|
95
|
+
## Piping
|
|
96
|
+
|
|
97
|
+
Every read command takes `--json` and prints nothing but JSON on stdout.
|
|
98
|
+
No almyty CLI emits ANSI colour of its own, so `NO_COLOR` is honoured
|
|
99
|
+
and there is nothing to strip when you pipe.
|
|
100
|
+
|
|
101
|
+
## About almyty
|
|
36
102
|
|
|
37
|
-
|
|
103
|
+
almyty is the full-stack platform for AI agents, agnostic by design: any LLM, any
|
|
104
|
+
API turned into tools, served over MCP, A2A, UTCP, and Agent Skills. Open source,
|
|
105
|
+
no lock-in.
|
|
38
106
|
|
|
39
|
-
https://almyty.com
|
|
107
|
+
- Website: https://almyty.com
|
|
108
|
+
- Docs: https://docs.almyty.com
|
|
109
|
+
- Source: https://github.com/almyty-inc/almyty
|
|
40
110
|
|
|
41
|
-
|
|
111
|
+
This CLI is part of the `@almyty/*` suite (versioned together at 1.x) and works with the almyty platform 0.1 and later.
|
|
42
112
|
|
|
43
|
-
|
|
113
|
+
Apache-2.0 © Almyty Inc.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The umbrella's routing table, help text, and shell completion.
|
|
3
|
+
*
|
|
4
|
+
* Kept out of index.ts so it can be unit-tested without spawning a
|
|
5
|
+
* child process: every entry here must be listed in the help text and
|
|
6
|
+
* must name a package the umbrella actually depends on, and there are
|
|
7
|
+
* tests that assert both.
|
|
8
|
+
*/
|
|
9
|
+
export interface Subcommand {
|
|
10
|
+
/** Package name to delegate to. */
|
|
11
|
+
pkg: string;
|
|
12
|
+
/**
|
|
13
|
+
* Optional argv prefix injected before the user-supplied args.
|
|
14
|
+
* Used for top-level shortcuts like `almyty login` -> `@almyty/auth login`.
|
|
15
|
+
*/
|
|
16
|
+
prefixArgs?: string[];
|
|
17
|
+
/** Short help line shown by `almyty help`. */
|
|
18
|
+
help: string;
|
|
19
|
+
/** Section heading this command is grouped under in the help output. */
|
|
20
|
+
group: string;
|
|
21
|
+
/** Subcommand names, for shell completion. Empty when it takes free-form args. */
|
|
22
|
+
subcommands?: string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Top-level subcommand routing table. Order = display order in help.
|
|
26
|
+
*
|
|
27
|
+
* Every `pkg` here must be a dependency of @almyty/cli. `models` and
|
|
28
|
+
* `connections` were listed in the help text while the umbrella did
|
|
29
|
+
* not depend on them, so `almyty models list` answered "package
|
|
30
|
+
* @almyty/models is not installed" for a command its own --help
|
|
31
|
+
* advertised.
|
|
32
|
+
*/
|
|
33
|
+
export declare const SUBCOMMANDS: Record<string, Subcommand>;
|
|
34
|
+
/** Commands the umbrella answers itself, rather than delegating. */
|
|
35
|
+
export declare const BUILTIN_COMMANDS: readonly ["help", "version", "completion"];
|
|
36
|
+
/** Every name `almyty <x>` accepts, for completion and suggestions. */
|
|
37
|
+
export declare function allCommandNames(): string[];
|
|
38
|
+
/**
|
|
39
|
+
* A short tour, printed when `almyty` is run with no arguments.
|
|
40
|
+
*
|
|
41
|
+
* A bare `almyty` used to print the entire command reference, which is
|
|
42
|
+
* the least useful thing to show someone who has just installed it and
|
|
43
|
+
* does not yet know what the product does.
|
|
44
|
+
*/
|
|
45
|
+
export declare function tourText(version: string): string;
|
|
46
|
+
/** The full command reference, printed by `almyty help` / `--help`. */
|
|
47
|
+
export declare function helpText(version: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* The closest command name to what the user typed, or null.
|
|
50
|
+
* `almyty agent list` (singular) should not just say "unknown command".
|
|
51
|
+
*/
|
|
52
|
+
export declare function suggestCommand(input: string): string | null;
|
|
53
|
+
export declare const COMPLETION_SHELLS: readonly ["bash", "zsh", "fish"];
|
|
54
|
+
export type CompletionShell = (typeof COMPLETION_SHELLS)[number];
|
|
55
|
+
export declare function isCompletionShell(value: string): value is CompletionShell;
|
|
56
|
+
/**
|
|
57
|
+
* A completion script for one shell. Static — it lists the top-level
|
|
58
|
+
* commands and each one's own subcommands from the table above, so it
|
|
59
|
+
* never has to shell out to the sub-CLIs to build a candidate list.
|
|
60
|
+
*/
|
|
61
|
+
export declare function completionScript(shell: CompletionShell): string;
|
package/dist/commands.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The umbrella's routing table, help text, and shell completion.
|
|
3
|
+
*
|
|
4
|
+
* Kept out of index.ts so it can be unit-tested without spawning a
|
|
5
|
+
* child process: every entry here must be listed in the help text and
|
|
6
|
+
* must name a package the umbrella actually depends on, and there are
|
|
7
|
+
* tests that assert both.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Top-level subcommand routing table. Order = display order in help.
|
|
11
|
+
*
|
|
12
|
+
* Every `pkg` here must be a dependency of @almyty/cli. `models` and
|
|
13
|
+
* `connections` were listed in the help text while the umbrella did
|
|
14
|
+
* not depend on them, so `almyty models list` answered "package
|
|
15
|
+
* @almyty/models is not installed" for a command its own --help
|
|
16
|
+
* advertised.
|
|
17
|
+
*/
|
|
18
|
+
export const SUBCOMMANDS = {
|
|
19
|
+
// Auth shortcuts at top level (gh-style: `almyty login` not `almyty auth login`)
|
|
20
|
+
login: { pkg: '@almyty/auth', prefixArgs: ['login'], group: 'Auth', help: 'Browser-based login (writes ~/.almyty/credentials.json)' },
|
|
21
|
+
logout: { pkg: '@almyty/auth', prefixArgs: ['logout'], group: 'Auth', help: 'Remove stored credentials' },
|
|
22
|
+
whoami: { pkg: '@almyty/auth', prefixArgs: ['whoami'], group: 'Auth', help: 'Show the current identity' },
|
|
23
|
+
auth: { pkg: '@almyty/auth', group: 'Auth', help: 'Auth subcommands', subcommands: ['login', 'logout', 'whoami'] },
|
|
24
|
+
// Domain CLIs
|
|
25
|
+
agents: { pkg: '@almyty/agents', group: 'Agents', help: 'List, run, and inspect agents', subcommands: ['list', 'get', 'run', 'runs', 'inspect', 'executions', 'trace', 'cancel'] },
|
|
26
|
+
chat: { pkg: '@almyty/chat', group: 'Agents', help: 'Interactive chat REPL with an agent' },
|
|
27
|
+
skills: { pkg: '@almyty/skills', group: 'Skills', help: 'Install API skills into AI coding agents', subcommands: ['install', 'list', 'search', 'run', 'installed', 'remove', 'gateways', 'daemon', 'watch'] },
|
|
28
|
+
models: { pkg: '@almyty/models', group: 'Platform', help: 'Model catalog: cards, validation, deployments' },
|
|
29
|
+
connections: { pkg: '@almyty/connections', group: 'Platform', help: 'Connect third-party accounts: connectors, validate, grants' },
|
|
30
|
+
runner: { pkg: '@almyty/runner', group: 'Serving', help: 'Run agents on this machine as a daemon' },
|
|
31
|
+
mcp: { pkg: '@almyty/mcp-server', group: 'Serving', help: 'Serve your agents and tools over MCP' },
|
|
32
|
+
acp: { pkg: '@almyty/acp-server', group: 'Serving', help: 'Serve an agent over the Agent Client Protocol' },
|
|
33
|
+
};
|
|
34
|
+
/** Commands the umbrella answers itself, rather than delegating. */
|
|
35
|
+
export const BUILTIN_COMMANDS = ['help', 'version', 'completion'];
|
|
36
|
+
/** Every name `almyty <x>` accepts, for completion and suggestions. */
|
|
37
|
+
export function allCommandNames() {
|
|
38
|
+
return [...Object.keys(SUBCOMMANDS), ...BUILTIN_COMMANDS];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* A short tour, printed when `almyty` is run with no arguments.
|
|
42
|
+
*
|
|
43
|
+
* A bare `almyty` used to print the entire command reference, which is
|
|
44
|
+
* the least useful thing to show someone who has just installed it and
|
|
45
|
+
* does not yet know what the product does.
|
|
46
|
+
*/
|
|
47
|
+
export function tourText(version) {
|
|
48
|
+
return `almyty v${version} — build, run, and serve AI agents.
|
|
49
|
+
|
|
50
|
+
Start here:
|
|
51
|
+
almyty login Authenticate this machine
|
|
52
|
+
almyty agents list See the agents in your organization
|
|
53
|
+
almyty agents run <agent> Run one and print its output
|
|
54
|
+
almyty chat <agent> Talk to one in your terminal
|
|
55
|
+
almyty skills install <ref> Teach your coding agent an API
|
|
56
|
+
|
|
57
|
+
almyty help Every command, grouped
|
|
58
|
+
almyty <command> --help Detail for one command
|
|
59
|
+
|
|
60
|
+
Docs: https://docs.almyty.com`;
|
|
61
|
+
}
|
|
62
|
+
/** The full command reference, printed by `almyty help` / `--help`. */
|
|
63
|
+
export function helpText(version) {
|
|
64
|
+
const groups = new Map();
|
|
65
|
+
const width = Math.max(...Object.keys(SUBCOMMANDS).map((n) => n.length), 'completion <shell>'.length);
|
|
66
|
+
for (const [name, sub] of Object.entries(SUBCOMMANDS)) {
|
|
67
|
+
const lines = groups.get(sub.group) ?? [];
|
|
68
|
+
lines.push(` ${name.padEnd(width)} ${sub.help}`);
|
|
69
|
+
groups.set(sub.group, lines);
|
|
70
|
+
}
|
|
71
|
+
const sections = [...groups.entries()]
|
|
72
|
+
.map(([group, lines]) => `${group}:\n${lines.join('\n')}`)
|
|
73
|
+
.join('\n\n');
|
|
74
|
+
return `almyty CLI v${version}
|
|
75
|
+
|
|
76
|
+
Usage:
|
|
77
|
+
almyty <command> [args]
|
|
78
|
+
almyty <command> --help Full options for that command
|
|
79
|
+
|
|
80
|
+
${sections}
|
|
81
|
+
|
|
82
|
+
Other:
|
|
83
|
+
${'help'.padEnd(width)} Show this help
|
|
84
|
+
${'version'.padEnd(width)} Print the version
|
|
85
|
+
${'completion <shell>'.padEnd(width)} Print a completion script (bash, zsh, fish)
|
|
86
|
+
|
|
87
|
+
Exit codes (the same in every almyty CLI):
|
|
88
|
+
0 success
|
|
89
|
+
1 unexpected error
|
|
90
|
+
2 usage error (bad flags, unknown command)
|
|
91
|
+
3 not authenticated — run \`almyty login\`
|
|
92
|
+
4 not found (agent, gateway, skill, or run)
|
|
93
|
+
5 the operation ran and failed
|
|
94
|
+
|
|
95
|
+
Every subcommand is also a standalone package, so nothing here is
|
|
96
|
+
required in order to use one of them:
|
|
97
|
+
|
|
98
|
+
npx @almyty/auth login
|
|
99
|
+
npx @almyty/agents list
|
|
100
|
+
npx @almyty/chat my-research-bot
|
|
101
|
+
npx @almyty/skills install org/gateway
|
|
102
|
+
|
|
103
|
+
They all read the same credentials file (~/.almyty/credentials.json),
|
|
104
|
+
so \`almyty login\` logs all of them in at once.`;
|
|
105
|
+
}
|
|
106
|
+
/** Levenshtein distance, capped — only used to suggest a command name. */
|
|
107
|
+
function distance(a, b) {
|
|
108
|
+
const rows = a.length + 1;
|
|
109
|
+
const cols = b.length + 1;
|
|
110
|
+
let prev = Array.from({ length: cols }, (_, j) => j);
|
|
111
|
+
for (let i = 1; i < rows; i++) {
|
|
112
|
+
const curr = [i];
|
|
113
|
+
for (let j = 1; j < cols; j++) {
|
|
114
|
+
curr[j] = Math.min(prev[j] + 1, curr[j - 1] + 1, prev[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
115
|
+
}
|
|
116
|
+
prev = curr;
|
|
117
|
+
}
|
|
118
|
+
return prev[cols - 1];
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The closest command name to what the user typed, or null.
|
|
122
|
+
* `almyty agent list` (singular) should not just say "unknown command".
|
|
123
|
+
*/
|
|
124
|
+
export function suggestCommand(input) {
|
|
125
|
+
const typed = input.toLowerCase();
|
|
126
|
+
let best = null;
|
|
127
|
+
let bestScore = Infinity;
|
|
128
|
+
for (const name of allCommandNames()) {
|
|
129
|
+
const d = distance(typed, name);
|
|
130
|
+
if (d < bestScore) {
|
|
131
|
+
bestScore = d;
|
|
132
|
+
best = name;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const tolerance = typed.length <= 4 ? 1 : 2;
|
|
136
|
+
return best !== null && bestScore <= tolerance ? best : null;
|
|
137
|
+
}
|
|
138
|
+
export const COMPLETION_SHELLS = ['bash', 'zsh', 'fish'];
|
|
139
|
+
export function isCompletionShell(value) {
|
|
140
|
+
return COMPLETION_SHELLS.includes(value);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* A completion script for one shell. Static — it lists the top-level
|
|
144
|
+
* commands and each one's own subcommands from the table above, so it
|
|
145
|
+
* never has to shell out to the sub-CLIs to build a candidate list.
|
|
146
|
+
*/
|
|
147
|
+
export function completionScript(shell) {
|
|
148
|
+
const top = allCommandNames().join(' ');
|
|
149
|
+
if (shell === 'bash') {
|
|
150
|
+
const cases = Object.entries(SUBCOMMANDS)
|
|
151
|
+
.filter(([, s]) => s.subcommands?.length)
|
|
152
|
+
.map(([name, s]) => ` ${name}) subs="${s.subcommands.join(' ')}" ;;`)
|
|
153
|
+
.join('\n');
|
|
154
|
+
return `# almyty bash completion — add to ~/.bashrc:
|
|
155
|
+
# eval "$(almyty completion bash)"
|
|
156
|
+
_almyty_complete() {
|
|
157
|
+
local cur prev subs
|
|
158
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
159
|
+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
160
|
+
if [ "$COMP_CWORD" -eq 1 ]; then
|
|
161
|
+
COMPREPLY=( $(compgen -W "${top}" -- "$cur") )
|
|
162
|
+
return
|
|
163
|
+
fi
|
|
164
|
+
subs=""
|
|
165
|
+
case "\${COMP_WORDS[1]}" in
|
|
166
|
+
${cases}
|
|
167
|
+
completion) subs="bash zsh fish" ;;
|
|
168
|
+
esac
|
|
169
|
+
if [ -n "$subs" ] && [ "$COMP_CWORD" -eq 2 ]; then
|
|
170
|
+
COMPREPLY=( $(compgen -W "$subs" -- "$cur") )
|
|
171
|
+
fi
|
|
172
|
+
}
|
|
173
|
+
complete -F _almyty_complete almyty`;
|
|
174
|
+
}
|
|
175
|
+
if (shell === 'zsh') {
|
|
176
|
+
const descs = Object.entries(SUBCOMMANDS)
|
|
177
|
+
.map(([name, s]) => ` '${name}:${s.help.replace(/'/g, '')}'`)
|
|
178
|
+
.join('\n');
|
|
179
|
+
return `# almyty zsh completion — add to ~/.zshrc:
|
|
180
|
+
# eval "$(almyty completion zsh)"
|
|
181
|
+
_almyty() {
|
|
182
|
+
local -a commands
|
|
183
|
+
commands=(
|
|
184
|
+
${descs}
|
|
185
|
+
'help:Show help'
|
|
186
|
+
'version:Print the version'
|
|
187
|
+
'completion:Print a shell completion script'
|
|
188
|
+
)
|
|
189
|
+
if (( CURRENT == 2 )); then
|
|
190
|
+
_describe -t commands 'almyty command' commands
|
|
191
|
+
fi
|
|
192
|
+
}
|
|
193
|
+
compdef _almyty almyty`;
|
|
194
|
+
}
|
|
195
|
+
const fishLines = Object.entries(SUBCOMMANDS)
|
|
196
|
+
.map(([name, s]) => `complete -c almyty -n __fish_use_subcommand -a ${name} -d '${s.help.replace(/'/g, '')}'`)
|
|
197
|
+
.join('\n');
|
|
198
|
+
return `# almyty fish completion — save as ~/.config/fish/completions/almyty.fish:
|
|
199
|
+
# almyty completion fish > ~/.config/fish/completions/almyty.fish
|
|
200
|
+
${fishLines}
|
|
201
|
+
complete -c almyty -n __fish_use_subcommand -a help -d 'Show help'
|
|
202
|
+
complete -c almyty -n __fish_use_subcommand -a version -d 'Print the version'
|
|
203
|
+
complete -c almyty -n __fish_use_subcommand -a completion -d 'Print a shell completion script'`;
|
|
204
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exit codes shared by every almyty CLI.
|
|
3
|
+
*
|
|
4
|
+
* Scripts need to tell "you are not logged in" apart from "that agent
|
|
5
|
+
* does not exist" apart from "the run you asked for failed" without
|
|
6
|
+
* grepping stderr. Every almyty CLI uses this same table, so
|
|
7
|
+
* `almyty agents run x || case $? in 3) almyty login;; esac` behaves
|
|
8
|
+
* the same whichever binary produced the code.
|
|
9
|
+
*/
|
|
10
|
+
export declare const EXIT: {
|
|
11
|
+
/** Success. */
|
|
12
|
+
readonly OK: 0;
|
|
13
|
+
/** Unexpected failure (a thrown error with no better classification). */
|
|
14
|
+
readonly ERROR: 1;
|
|
15
|
+
/** Bad or missing arguments, or an unknown command. */
|
|
16
|
+
readonly USAGE: 2;
|
|
17
|
+
/** No stored credential, or the API rejected the one we had. */
|
|
18
|
+
readonly AUTH: 3;
|
|
19
|
+
/** The named agent / gateway / skill / run does not exist. */
|
|
20
|
+
readonly NOT_FOUND: 4;
|
|
21
|
+
/** The command ran; the operation it asked for failed. */
|
|
22
|
+
readonly FAILED: 5;
|
|
23
|
+
};
|
|
24
|
+
export type ExitCode = (typeof EXIT)[keyof typeof EXIT];
|
|
25
|
+
/** One line per code, for `--help` output and READMEs. */
|
|
26
|
+
export declare const EXIT_CODE_HELP: string;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exit codes shared by every almyty CLI.
|
|
3
|
+
*
|
|
4
|
+
* Scripts need to tell "you are not logged in" apart from "that agent
|
|
5
|
+
* does not exist" apart from "the run you asked for failed" without
|
|
6
|
+
* grepping stderr. Every almyty CLI uses this same table, so
|
|
7
|
+
* `almyty agents run x || case $? in 3) almyty login;; esac` behaves
|
|
8
|
+
* the same whichever binary produced the code.
|
|
9
|
+
*/
|
|
10
|
+
export const EXIT = {
|
|
11
|
+
/** Success. */
|
|
12
|
+
OK: 0,
|
|
13
|
+
/** Unexpected failure (a thrown error with no better classification). */
|
|
14
|
+
ERROR: 1,
|
|
15
|
+
/** Bad or missing arguments, or an unknown command. */
|
|
16
|
+
USAGE: 2,
|
|
17
|
+
/** No stored credential, or the API rejected the one we had. */
|
|
18
|
+
AUTH: 3,
|
|
19
|
+
/** The named agent / gateway / skill / run does not exist. */
|
|
20
|
+
NOT_FOUND: 4,
|
|
21
|
+
/** The command ran; the operation it asked for failed. */
|
|
22
|
+
FAILED: 5,
|
|
23
|
+
};
|
|
24
|
+
/** One line per code, for `--help` output and READMEs. */
|
|
25
|
+
export const EXIT_CODE_HELP = [
|
|
26
|
+
' 0 success',
|
|
27
|
+
' 1 unexpected error',
|
|
28
|
+
' 2 usage error (bad flags, unknown command)',
|
|
29
|
+
' 3 not authenticated — run `almyty login`',
|
|
30
|
+
' 4 not found (agent, gateway, skill, or run)',
|
|
31
|
+
' 5 the operation ran and failed',
|
|
32
|
+
].join('\n');
|
package/dist/index.d.ts
CHANGED
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
* almyty login
|
|
7
7
|
* almyty agents list
|
|
8
8
|
* almyty chat my-research-bot
|
|
9
|
-
* almyty skills install
|
|
10
|
-
* almyty mcp <args>
|
|
9
|
+
* almyty skills install org/gateway
|
|
11
10
|
*
|
|
12
11
|
* The umbrella delegates each subcommand to a standalone @almyty/<thing>
|
|
13
12
|
* package by spawning its bin. Each package can ALSO be invoked directly:
|
|
@@ -15,7 +14,6 @@
|
|
|
15
14
|
* npx @almyty/auth login
|
|
16
15
|
* npx @almyty/agents list
|
|
17
16
|
* npx @almyty/chat my-research-bot
|
|
18
|
-
* …
|
|
19
17
|
*
|
|
20
18
|
* The standalone packages and the umbrella stay in sync because they
|
|
21
19
|
* share the same on-disk credentials store at ~/.almyty/credentials.json.
|
package/dist/index.js
CHANGED
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
* almyty login
|
|
7
7
|
* almyty agents list
|
|
8
8
|
* almyty chat my-research-bot
|
|
9
|
-
* almyty skills install
|
|
10
|
-
* almyty mcp <args>
|
|
9
|
+
* almyty skills install org/gateway
|
|
11
10
|
*
|
|
12
11
|
* The umbrella delegates each subcommand to a standalone @almyty/<thing>
|
|
13
12
|
* package by spawning its bin. Each package can ALSO be invoked directly:
|
|
@@ -15,79 +14,18 @@
|
|
|
15
14
|
* npx @almyty/auth login
|
|
16
15
|
* npx @almyty/agents list
|
|
17
16
|
* npx @almyty/chat my-research-bot
|
|
18
|
-
* …
|
|
19
17
|
*
|
|
20
18
|
* The standalone packages and the umbrella stay in sync because they
|
|
21
19
|
* share the same on-disk credentials store at ~/.almyty/credentials.json.
|
|
22
20
|
*/
|
|
23
|
-
import { spawn } from 'child_process';
|
|
24
|
-
import { createRequire } from 'module';
|
|
25
|
-
import { dirname, join } from 'path';
|
|
26
|
-
import { existsSync } from 'fs';
|
|
21
|
+
import { spawn } from 'node:child_process';
|
|
22
|
+
import { createRequire } from 'node:module';
|
|
23
|
+
import { dirname, join } from 'node:path';
|
|
24
|
+
import { existsSync } from 'node:fs';
|
|
25
|
+
import { VERSION } from './version.js';
|
|
26
|
+
import { EXIT } from './exit-codes.js';
|
|
27
|
+
import { SUBCOMMANDS, completionScript, helpText, isCompletionShell, suggestCommand, tourText, COMPLETION_SHELLS, } from './commands.js';
|
|
27
28
|
const require = createRequire(import.meta.url);
|
|
28
|
-
const VERSION = '0.1.0';
|
|
29
|
-
/**
|
|
30
|
-
* Top-level subcommand routing table. Order = display order in help.
|
|
31
|
-
*/
|
|
32
|
-
const SUBCOMMANDS = {
|
|
33
|
-
// Auth shortcuts at top level (gh-style: `almyty login` not `almyty auth login`)
|
|
34
|
-
login: { pkg: '@almyty/auth', prefixArgs: ['login'], help: 'Browser-based login' },
|
|
35
|
-
logout: { pkg: '@almyty/auth', prefixArgs: ['logout'], help: 'Remove stored credentials' },
|
|
36
|
-
whoami: { pkg: '@almyty/auth', prefixArgs: ['whoami'], help: 'Show the current identity' },
|
|
37
|
-
auth: { pkg: '@almyty/auth', help: 'Auth subcommands (login/logout/whoami)' },
|
|
38
|
-
// Domain CLIs
|
|
39
|
-
agents: { pkg: '@almyty/agents', help: 'List, run, and inspect agents' },
|
|
40
|
-
chat: { pkg: '@almyty/chat', help: 'Interactive chat REPL with an agent' },
|
|
41
|
-
skills: { pkg: '@almyty/skills', help: 'Install API skills into AI coding agents' },
|
|
42
|
-
mcp: { pkg: '@almyty/mcp-server', help: 'Run the MCP server proxy' },
|
|
43
|
-
acp: { pkg: '@almyty/acp-server', help: 'Run the ACP agent server' },
|
|
44
|
-
};
|
|
45
|
-
function printHelp() {
|
|
46
|
-
console.log(`
|
|
47
|
-
almyty CLI v${VERSION}
|
|
48
|
-
|
|
49
|
-
Usage:
|
|
50
|
-
almyty <command> [args]
|
|
51
|
-
|
|
52
|
-
Auth:
|
|
53
|
-
login Browser-based login (writes ~/.almyty/credentials.json)
|
|
54
|
-
logout Remove stored credentials
|
|
55
|
-
whoami Show the currently logged-in identity
|
|
56
|
-
auth <subcommand> Pass-through to @almyty/auth
|
|
57
|
-
|
|
58
|
-
Agents:
|
|
59
|
-
agents list List agents in your organization
|
|
60
|
-
agents get <ref> Show details for one agent
|
|
61
|
-
agents run <ref> [--input ...] Invoke / start a run
|
|
62
|
-
agents runs <ref> List recent runs
|
|
63
|
-
agents cancel <ref> <runId> Cancel an in-flight run
|
|
64
|
-
|
|
65
|
-
Chat:
|
|
66
|
-
chat Interactive REPL — pick an agent from a menu
|
|
67
|
-
chat <ref> Start chatting with that agent
|
|
68
|
-
|
|
69
|
-
Skills:
|
|
70
|
-
skills install <ref> Install skills into local AI coding agents
|
|
71
|
-
skills list [ref] List available skills
|
|
72
|
-
skills daemon Sync skills on a schedule
|
|
73
|
-
skills run <ref> Execute a skill once
|
|
74
|
-
|
|
75
|
-
MCP:
|
|
76
|
-
mcp <args> Run the MCP server proxy
|
|
77
|
-
|
|
78
|
-
Other:
|
|
79
|
-
help, --help Show this help
|
|
80
|
-
version, --version Show version
|
|
81
|
-
|
|
82
|
-
Each subcommand maps to a standalone npm package. You can invoke any
|
|
83
|
-
of them directly with npx:
|
|
84
|
-
|
|
85
|
-
npx @almyty/auth login
|
|
86
|
-
npx @almyty/agents list
|
|
87
|
-
npx @almyty/chat my-research-bot
|
|
88
|
-
npx @almyty/skills install @org/gateway
|
|
89
|
-
`);
|
|
90
|
-
}
|
|
91
29
|
function resolveBinPath(packageName) {
|
|
92
30
|
// Resolve the package's package.json to find its installation root,
|
|
93
31
|
// then read the "bin" entry to find the actual script path.
|
|
@@ -128,8 +66,8 @@ function delegate(packageName, args) {
|
|
|
128
66
|
if (!binPath) {
|
|
129
67
|
console.error(`Error: package ${packageName} is not installed.`);
|
|
130
68
|
console.error(` Install it with: npm install -g ${packageName}`);
|
|
131
|
-
console.error(` Or use:
|
|
132
|
-
return Promise.resolve(
|
|
69
|
+
console.error(` Or use: npx ${packageName} ${args.join(' ')}`);
|
|
70
|
+
return Promise.resolve(EXIT.ERROR);
|
|
133
71
|
}
|
|
134
72
|
return new Promise((resolve) => {
|
|
135
73
|
const child = spawn(process.execPath, [binPath, ...args], {
|
|
@@ -157,30 +95,49 @@ function delegate(packageName, args) {
|
|
|
157
95
|
process.kill(process.pid, signal);
|
|
158
96
|
return;
|
|
159
97
|
}
|
|
160
|
-
resolve(code ??
|
|
98
|
+
resolve(code ?? EXIT.OK);
|
|
161
99
|
});
|
|
162
100
|
child.on('error', (err) => {
|
|
163
101
|
console.error(`Failed to launch ${packageName}: ${err.message}`);
|
|
164
|
-
resolve(
|
|
102
|
+
resolve(EXIT.ERROR);
|
|
165
103
|
});
|
|
166
104
|
});
|
|
167
105
|
}
|
|
168
106
|
async function main() {
|
|
169
107
|
const argv = process.argv.slice(2);
|
|
170
|
-
|
|
171
|
-
|
|
108
|
+
// Bare `almyty` shows a short tour, not the full reference.
|
|
109
|
+
if (argv.length === 0) {
|
|
110
|
+
console.log(tourText(VERSION));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (argv[0] === '--help' || argv[0] === '-h' || argv[0] === 'help') {
|
|
114
|
+
console.log(helpText(VERSION));
|
|
172
115
|
return;
|
|
173
116
|
}
|
|
174
117
|
if (argv[0] === '--version' || argv[0] === '-v' || argv[0] === 'version') {
|
|
175
118
|
console.log(VERSION);
|
|
176
119
|
return;
|
|
177
120
|
}
|
|
121
|
+
if (argv[0] === 'completion') {
|
|
122
|
+
const shell = argv[1];
|
|
123
|
+
if (!shell || !isCompletionShell(shell)) {
|
|
124
|
+
console.error(`Usage: almyty completion <${COMPLETION_SHELLS.join('|')}>`);
|
|
125
|
+
process.exit(EXIT.USAGE);
|
|
126
|
+
}
|
|
127
|
+
console.log(completionScript(shell));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
178
130
|
const cmd = argv[0];
|
|
179
131
|
const sub = SUBCOMMANDS[cmd];
|
|
180
132
|
if (!sub) {
|
|
181
133
|
console.error(`Unknown command: ${cmd}`);
|
|
182
|
-
|
|
183
|
-
|
|
134
|
+
const suggestion = suggestCommand(cmd);
|
|
135
|
+
if (suggestion)
|
|
136
|
+
console.error(`Did you mean \`almyty ${suggestion}\`?`);
|
|
137
|
+
console.error('Run `almyty help` for the list of commands.');
|
|
138
|
+
// Usage error, not a generic failure: a script can tell a typo
|
|
139
|
+
// apart from a command that ran and failed.
|
|
140
|
+
process.exit(EXIT.USAGE);
|
|
184
141
|
}
|
|
185
142
|
const passthroughArgs = [...(sub.prefixArgs ?? []), ...argv.slice(1)];
|
|
186
143
|
const code = await delegate(sub.pkg, passthroughArgs);
|
|
@@ -188,5 +145,5 @@ async function main() {
|
|
|
188
145
|
}
|
|
189
146
|
main().catch((err) => {
|
|
190
147
|
console.error(`Error: ${err.message}`);
|
|
191
|
-
process.exit(
|
|
148
|
+
process.exit(EXIT.ERROR);
|
|
192
149
|
});
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CLI's own version, read from its package.json at startup.
|
|
3
|
+
*
|
|
4
|
+
* It used to be a hardcoded string, which drifted: `--version`
|
|
5
|
+
* answered 0.1.0 while the published package was 1.2.0, so a bug
|
|
6
|
+
* report never identified the build it came from. Both `dist/index.js`
|
|
7
|
+
* and `src/index.ts` sit one directory below the package root, so the
|
|
8
|
+
* same relative path resolves for the built bin and for `tsx src/index.ts`.
|
|
9
|
+
*/
|
|
10
|
+
import { readFileSync } from 'node:fs';
|
|
11
|
+
export function readVersion(fallback = '0.0.0') {
|
|
12
|
+
try {
|
|
13
|
+
const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
|
|
14
|
+
return typeof pkg.version === 'string' && pkg.version.length > 0
|
|
15
|
+
? pkg.version
|
|
16
|
+
: fallback;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return fallback;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export const VERSION = readVersion();
|
package/package.json
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@almyty/cli",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "The almyty CLI — one login for agents, chat, skills, an MCP server, and a machine runner. Part of almyty, the full-stack platform for AI agents.",
|
|
5
8
|
"type": "module",
|
|
6
9
|
"main": "dist/index.js",
|
|
7
10
|
"bin": {
|
|
@@ -26,19 +29,37 @@
|
|
|
26
29
|
"mcp"
|
|
27
30
|
],
|
|
28
31
|
"author": "almyty",
|
|
29
|
-
"license": "
|
|
32
|
+
"license": "Apache-2.0",
|
|
30
33
|
"dependencies": {
|
|
31
|
-
"@almyty/auth": "^
|
|
32
|
-
"@almyty/agents": "^
|
|
33
|
-
"@almyty/chat": "^
|
|
34
|
-
"@almyty/skills": "^1.0
|
|
35
|
-
"@almyty/
|
|
36
|
-
"@almyty/
|
|
34
|
+
"@almyty/auth": "^1.2.0",
|
|
35
|
+
"@almyty/agents": "^1.2.0",
|
|
36
|
+
"@almyty/chat": "^1.2.0",
|
|
37
|
+
"@almyty/skills": "^1.2.0",
|
|
38
|
+
"@almyty/models": "^1.2.0",
|
|
39
|
+
"@almyty/connections": "^1.2.0",
|
|
40
|
+
"@almyty/mcp-server": "^1.2.0",
|
|
41
|
+
"@almyty/acp-server": "^1.2.0",
|
|
42
|
+
"@almyty/runner": "^1.2.0"
|
|
37
43
|
},
|
|
38
44
|
"devDependencies": {
|
|
39
45
|
"@types/node": "^25.4.0",
|
|
40
46
|
"tsx": "^4.7.0",
|
|
41
47
|
"typescript": "^5.3.0",
|
|
42
48
|
"vitest": "^4.1.0"
|
|
49
|
+
},
|
|
50
|
+
"overrides": {
|
|
51
|
+
"@hono/node-server": "^2.0.5",
|
|
52
|
+
"fast-uri": "^3.1.5",
|
|
53
|
+
"ip-address": "^10.4.0",
|
|
54
|
+
"postcss": "^8.5.23"
|
|
55
|
+
},
|
|
56
|
+
"homepage": "https://almyty.com",
|
|
57
|
+
"repository": {
|
|
58
|
+
"type": "git",
|
|
59
|
+
"url": "git+https://github.com/almyty-inc/almyty.git",
|
|
60
|
+
"directory": "packages/almyty-cli"
|
|
61
|
+
},
|
|
62
|
+
"bugs": {
|
|
63
|
+
"url": "https://github.com/almyty-inc/almyty/issues"
|
|
43
64
|
}
|
|
44
65
|
}
|