@almyty/cli 0.1.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 ADDED
@@ -0,0 +1,43 @@
1
+ # @almyty/cli
2
+
3
+ Umbrella CLI for almyty. One install, every command.
4
+
5
+ ## Quick start
6
+
7
+ ```bash
8
+ $ npm install -g @almyty/cli
9
+ $ almyty login
10
+ $ almyty agents list
11
+ ```
12
+
13
+ ## Commands
14
+
15
+ | Command | Delegates to | Description |
16
+ |---------|-------------|-------------|
17
+ | `almyty login` | `@almyty/auth` | Browser-based login |
18
+ | `almyty logout` | `@almyty/auth` | Remove stored credentials |
19
+ | `almyty whoami` | `@almyty/auth` | Show current identity |
20
+ | `almyty agents <cmd>` | `@almyty/agents` | List, run, inspect agents |
21
+ | `almyty chat [name\|id]` | `@almyty/chat` | Interactive chat REPL |
22
+ | `almyty skills <cmd>` | `@almyty/skills` | Install and manage skills |
23
+ | `almyty mcp <args>` | `@almyty/mcp-server` | Start MCP server |
24
+
25
+ ## Standalone packages
26
+
27
+ Every subcommand is also available as a standalone package via `npx`:
28
+
29
+ ```bash
30
+ $ npx @almyty/agents list
31
+ $ npx @almyty/chat my-bot
32
+ $ npx @almyty/skills install @org/gateway
33
+ ```
34
+
35
+ All packages share the same credentials file (`~/.almyty/credentials.json`), so logging in once works everywhere.
36
+
37
+ ## Docs
38
+
39
+ https://almyty.com/docs
40
+
41
+ ## License
42
+
43
+ BSL-1.1
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @almyty/cli — single installable almyty CLI.
4
+ *
5
+ * npm install -g @almyty/cli
6
+ * almyty login
7
+ * almyty agents list
8
+ * almyty chat my-research-bot
9
+ * almyty skills install @org/gateway
10
+ * almyty mcp <args>
11
+ *
12
+ * The umbrella delegates each subcommand to a standalone @almyty/<thing>
13
+ * package by spawning its bin. Each package can ALSO be invoked directly:
14
+ *
15
+ * npx @almyty/auth login
16
+ * npx @almyty/agents list
17
+ * npx @almyty/chat my-research-bot
18
+ * …
19
+ *
20
+ * The standalone packages and the umbrella stay in sync because they
21
+ * share the same on-disk credentials store at ~/.almyty/credentials.json.
22
+ */
23
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,191 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @almyty/cli — single installable almyty CLI.
4
+ *
5
+ * npm install -g @almyty/cli
6
+ * almyty login
7
+ * almyty agents list
8
+ * almyty chat my-research-bot
9
+ * almyty skills install @org/gateway
10
+ * almyty mcp <args>
11
+ *
12
+ * The umbrella delegates each subcommand to a standalone @almyty/<thing>
13
+ * package by spawning its bin. Each package can ALSO be invoked directly:
14
+ *
15
+ * npx @almyty/auth login
16
+ * npx @almyty/agents list
17
+ * npx @almyty/chat my-research-bot
18
+ * …
19
+ *
20
+ * The standalone packages and the umbrella stay in sync because they
21
+ * share the same on-disk credentials store at ~/.almyty/credentials.json.
22
+ */
23
+ import { spawn } from 'child_process';
24
+ import { createRequire } from 'module';
25
+ import { dirname, join } from 'path';
26
+ import { existsSync } from 'fs';
27
+ 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
+ };
44
+ function printHelp() {
45
+ console.log(`
46
+ almyty CLI v${VERSION}
47
+
48
+ Usage:
49
+ almyty <command> [args]
50
+
51
+ Auth:
52
+ login Browser-based login (writes ~/.almyty/credentials.json)
53
+ logout Remove stored credentials
54
+ whoami Show the currently logged-in identity
55
+ auth <subcommand> Pass-through to @almyty/auth
56
+
57
+ Agents:
58
+ agents list List agents in your organization
59
+ agents get <ref> Show details for one agent
60
+ agents run <ref> [--input ...] Invoke / start a run
61
+ agents runs <ref> List recent runs
62
+ agents cancel <ref> <runId> Cancel an in-flight run
63
+
64
+ Chat:
65
+ chat Interactive REPL — pick an agent from a menu
66
+ chat <ref> Start chatting with that agent
67
+
68
+ Skills:
69
+ skills install <ref> Install skills into local AI coding agents
70
+ skills list [ref] List available skills
71
+ skills daemon Sync skills on a schedule
72
+ skills run <ref> Execute a skill once
73
+
74
+ MCP:
75
+ mcp <args> Run the MCP server proxy
76
+
77
+ Other:
78
+ help, --help Show this help
79
+ version, --version Show version
80
+
81
+ Each subcommand maps to a standalone npm package. You can invoke any
82
+ of them directly with npx:
83
+
84
+ npx @almyty/auth login
85
+ npx @almyty/agents list
86
+ npx @almyty/chat my-research-bot
87
+ npx @almyty/skills install @org/gateway
88
+ `);
89
+ }
90
+ function resolveBinPath(packageName) {
91
+ // Resolve the package's package.json to find its installation root,
92
+ // then read the "bin" entry to find the actual script path.
93
+ let pkgJsonPath;
94
+ try {
95
+ pkgJsonPath = require.resolve(`${packageName}/package.json`);
96
+ }
97
+ catch {
98
+ return null;
99
+ }
100
+ const pkgRoot = dirname(pkgJsonPath);
101
+ let pkg;
102
+ try {
103
+ pkg = require(pkgJsonPath);
104
+ }
105
+ catch {
106
+ return null;
107
+ }
108
+ // bin can be a string or { name: path }
109
+ let binRel;
110
+ if (typeof pkg.bin === 'string') {
111
+ binRel = pkg.bin;
112
+ }
113
+ else if (pkg.bin && typeof pkg.bin === 'object') {
114
+ // Take the first entry (or one matching the package name).
115
+ const keys = Object.keys(pkg.bin);
116
+ binRel = pkg.bin[keys[0]];
117
+ }
118
+ if (!binRel) {
119
+ // Fall back to dist/index.js convention used by all almyty packages.
120
+ binRel = pkg.main || 'dist/index.js';
121
+ }
122
+ const binAbs = join(pkgRoot, binRel);
123
+ return existsSync(binAbs) ? binAbs : null;
124
+ }
125
+ function delegate(packageName, args) {
126
+ const binPath = resolveBinPath(packageName);
127
+ if (!binPath) {
128
+ console.error(`Error: package ${packageName} is not installed.`);
129
+ console.error(` Install it with: npm install -g ${packageName}`);
130
+ console.error(` Or use: npx ${packageName} ${args.join(' ')}`);
131
+ return Promise.resolve(1);
132
+ }
133
+ return new Promise((resolve) => {
134
+ const child = spawn(process.execPath, [binPath, ...args], {
135
+ stdio: 'inherit',
136
+ });
137
+ // Forward Ctrl-C / Ctrl-\ so the child can clean up properly.
138
+ const forward = (sig) => {
139
+ try {
140
+ if (!child.killed)
141
+ child.kill(sig);
142
+ }
143
+ catch {
144
+ // best effort
145
+ }
146
+ };
147
+ process.on('SIGINT', forward);
148
+ process.on('SIGTERM', forward);
149
+ process.on('SIGHUP', forward);
150
+ child.on('exit', (code, signal) => {
151
+ process.removeListener('SIGINT', forward);
152
+ process.removeListener('SIGTERM', forward);
153
+ process.removeListener('SIGHUP', forward);
154
+ if (signal) {
155
+ // Re-raise the signal so our exit code reflects it.
156
+ process.kill(process.pid, signal);
157
+ return;
158
+ }
159
+ resolve(code ?? 0);
160
+ });
161
+ child.on('error', (err) => {
162
+ console.error(`Failed to launch ${packageName}: ${err.message}`);
163
+ resolve(1);
164
+ });
165
+ });
166
+ }
167
+ async function main() {
168
+ const argv = process.argv.slice(2);
169
+ if (argv.length === 0 || argv[0] === '--help' || argv[0] === '-h' || argv[0] === 'help') {
170
+ printHelp();
171
+ return;
172
+ }
173
+ if (argv[0] === '--version' || argv[0] === '-v' || argv[0] === 'version') {
174
+ console.log(VERSION);
175
+ return;
176
+ }
177
+ const cmd = argv[0];
178
+ const sub = SUBCOMMANDS[cmd];
179
+ if (!sub) {
180
+ console.error(`Unknown command: ${cmd}`);
181
+ console.error(`Run \`almyty help\` for the list of commands.`);
182
+ process.exit(1);
183
+ }
184
+ const passthroughArgs = [...(sub.prefixArgs ?? []), ...argv.slice(1)];
185
+ const code = await delegate(sub.pkg, passthroughArgs);
186
+ process.exit(code);
187
+ }
188
+ main().catch((err) => {
189
+ console.error(`Error: ${err.message}`);
190
+ process.exit(1);
191
+ });
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@almyty/cli",
3
+ "version": "0.1.0",
4
+ "description": "Single installable almyty CLI — login, agents, chat, skills, mcp under one binary",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "almyty": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "dev": "tsx src/index.ts",
16
+ "test": "vitest run",
17
+ "test:watch": "vitest",
18
+ "prepublishOnly": "npm run build"
19
+ },
20
+ "keywords": [
21
+ "almyty",
22
+ "cli",
23
+ "agents",
24
+ "chat",
25
+ "skills",
26
+ "mcp"
27
+ ],
28
+ "author": "almyty",
29
+ "license": "BSL-1.1",
30
+ "dependencies": {
31
+ "@almyty/auth": "^0.1.0",
32
+ "@almyty/agents": "^0.1.0",
33
+ "@almyty/chat": "^0.1.0",
34
+ "@almyty/skills": "^1.0.2",
35
+ "@almyty/mcp-server": "^1.0.0"
36
+ },
37
+ "devDependencies": {
38
+ "@types/node": "^25.4.0",
39
+ "tsx": "^4.7.0",
40
+ "typescript": "^5.3.0",
41
+ "vitest": "^4.1.0"
42
+ }
43
+ }