@heyamiko/amiko-cli 0.4.0 → 0.4.7
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/PLAN.md +113 -0
- package/bun.lock +596 -0
- package/dist/agent/piAgent.js +239 -0
- package/dist/agent/tools.js +149 -0
- package/dist/app.js +355 -0
- package/dist/cli.js +77 -0
- package/dist/commands.js +22 -0
- package/dist/components/ModelPicker.js +63 -0
- package/dist/config.js +26 -0
- package/dist/configFile.js +23 -0
- package/dist/memory/qmd.js +87 -0
- package/dist/prompt.js +43 -0
- package/dist/session.js +26 -0
- package/dist/types.js +1 -0
- package/dist/workspace.js +42 -0
- package/package.json +16 -27
- package/src/agent/piAgent.ts +266 -0
- package/src/agent/tools.ts +153 -0
- package/src/app.tsx +448 -0
- package/src/cli.tsx +95 -0
- package/src/commands.ts +39 -0
- package/src/components/ModelPicker.tsx +107 -0
- package/src/config.ts +31 -0
- package/src/configFile.ts +33 -0
- package/src/memory/qmd.ts +111 -0
- package/src/prompt.ts +55 -0
- package/src/session.ts +35 -0
- package/src/types.ts +40 -0
- package/src/workspace.ts +58 -0
- package/tsconfig.json +16 -0
- package/README.md +0 -222
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -67563
package/src/config.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { AppConfig } from "./types.js";
|
|
5
|
+
|
|
6
|
+
function defaultWorkspacePath() {
|
|
7
|
+
return path.join(os.homedir(), ".amiko");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function newSessionId() {
|
|
11
|
+
return randomUUID().split("-")[0];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function loadConfig(): AppConfig {
|
|
15
|
+
const workspacePath = process.env.AMIKO_WORKSPACE || defaultWorkspacePath();
|
|
16
|
+
const sessionId = process.env.AMIKO_SESSION_ID || newSessionId();
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
workspacePath,
|
|
20
|
+
sessionId,
|
|
21
|
+
qmdBin: process.env.AMIKO_QMD_BIN || "qmd",
|
|
22
|
+
qmdLimit: Number(process.env.AMIKO_QMD_LIMIT || 5),
|
|
23
|
+
qmdEnabled: process.env.AMIKO_QMD_ENABLED !== "0",
|
|
24
|
+
qmdCollection: process.env.AMIKO_QMD_COLLECTION || undefined,
|
|
25
|
+
qmdFull: process.env.AMIKO_QMD_FULL === "1",
|
|
26
|
+
model: process.env.AMIKO_MODEL || undefined,
|
|
27
|
+
modelProvider: process.env.AMIKO_MODEL_PROVIDER || undefined,
|
|
28
|
+
modelId: process.env.AMIKO_MODEL_ID || undefined,
|
|
29
|
+
thinkingLevel: (process.env.AMIKO_THINKING_LEVEL as any) || undefined
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import { AppConfig } from "./types.js";
|
|
5
|
+
|
|
6
|
+
export type PersistedConfig = {
|
|
7
|
+
model?: string;
|
|
8
|
+
modelProvider?: string;
|
|
9
|
+
modelId?: string;
|
|
10
|
+
thinkingLevel?: AppConfig["thinkingLevel"];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function getConfigFilePath(workspacePath: string) {
|
|
14
|
+
const base = workspacePath || path.join(os.homedir(), ".amiko");
|
|
15
|
+
return path.join(base, "config.json");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function loadConfigFile(workspacePath: string): Promise<PersistedConfig> {
|
|
19
|
+
const filePath = getConfigFilePath(workspacePath);
|
|
20
|
+
try {
|
|
21
|
+
const raw = await fs.readFile(filePath, "utf8");
|
|
22
|
+
const parsed = JSON.parse(raw) as PersistedConfig;
|
|
23
|
+
return parsed || {};
|
|
24
|
+
} catch {
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function saveConfigFile(workspacePath: string, config: PersistedConfig): Promise<void> {
|
|
30
|
+
const filePath = getConfigFilePath(workspacePath);
|
|
31
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
32
|
+
await fs.writeFile(filePath, JSON.stringify(config, null, 2) + "\n", "utf8");
|
|
33
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
import { MemoryHit } from "../types.js";
|
|
4
|
+
|
|
5
|
+
const execFileAsync = promisify(execFile);
|
|
6
|
+
|
|
7
|
+
function parseJsonLines(text: string) {
|
|
8
|
+
const lines = text.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
9
|
+
const results: any[] = [];
|
|
10
|
+
for (const line of lines) {
|
|
11
|
+
try {
|
|
12
|
+
results.push(JSON.parse(line));
|
|
13
|
+
} catch {
|
|
14
|
+
// ignore
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return results;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function qmdSearch(options: {
|
|
21
|
+
qmdBin: string;
|
|
22
|
+
query: string;
|
|
23
|
+
limit: number;
|
|
24
|
+
collection?: string;
|
|
25
|
+
}): Promise<MemoryHit[]> {
|
|
26
|
+
const { qmdBin, query, limit, collection } = options;
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const args = ["query", "--json", "-n", String(limit)];
|
|
30
|
+
if (collection) {
|
|
31
|
+
args.push("-c", collection);
|
|
32
|
+
}
|
|
33
|
+
args.push(query);
|
|
34
|
+
|
|
35
|
+
const { stdout } = await execFileAsync(qmdBin, [
|
|
36
|
+
...args
|
|
37
|
+
]);
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const parsed = JSON.parse(stdout);
|
|
41
|
+
if (Array.isArray(parsed)) {
|
|
42
|
+
return parsed.map(normalizeHit);
|
|
43
|
+
}
|
|
44
|
+
} catch {
|
|
45
|
+
// fall through to JSONL parsing
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return parseJsonLines(stdout).map(normalizeHit);
|
|
49
|
+
} catch {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function qmdGet(options: {
|
|
55
|
+
qmdBin: string;
|
|
56
|
+
docId: string;
|
|
57
|
+
full?: boolean;
|
|
58
|
+
}): Promise<string | null> {
|
|
59
|
+
const { qmdBin, docId, full } = options;
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
const args = ["get", docId];
|
|
63
|
+
if (full) args.push("--full");
|
|
64
|
+
|
|
65
|
+
const { stdout } = await execFileAsync(qmdBin, args);
|
|
66
|
+
return stdout.trim();
|
|
67
|
+
} catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function qmdCollectionAdd(options: {
|
|
73
|
+
qmdBin: string;
|
|
74
|
+
name: string;
|
|
75
|
+
path: string;
|
|
76
|
+
}): Promise<boolean> {
|
|
77
|
+
const { qmdBin, name, path } = options;
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
await execFileAsync(qmdBin, ["collection", "add", path, "--name", name]);
|
|
81
|
+
return true;
|
|
82
|
+
} catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export async function qmdEmbed(options: {
|
|
88
|
+
qmdBin: string;
|
|
89
|
+
collection?: string;
|
|
90
|
+
}): Promise<boolean> {
|
|
91
|
+
const { qmdBin, collection } = options;
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
const args = ["embed"];
|
|
95
|
+
if (collection) args.push("-c", collection);
|
|
96
|
+
await execFileAsync(qmdBin, args);
|
|
97
|
+
return true;
|
|
98
|
+
} catch {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function normalizeHit(hit: any): MemoryHit {
|
|
104
|
+
return {
|
|
105
|
+
id: String(hit.id ?? hit.docId ?? hit.path ?? "unknown"),
|
|
106
|
+
score: typeof hit.score === "number" ? hit.score : undefined,
|
|
107
|
+
title: hit.title ?? hit.name,
|
|
108
|
+
snippet: hit.snippet ?? hit.text,
|
|
109
|
+
path: hit.path
|
|
110
|
+
};
|
|
111
|
+
}
|
package/src/prompt.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import { MemoryHit } from "./types.js";
|
|
3
|
+
|
|
4
|
+
export function buildPrompt(options: {
|
|
5
|
+
identity: string;
|
|
6
|
+
personality: string;
|
|
7
|
+
memory: string;
|
|
8
|
+
hits: MemoryHit[];
|
|
9
|
+
}) {
|
|
10
|
+
const { identity, personality, memory, hits } = options;
|
|
11
|
+
const hitText = hits
|
|
12
|
+
.map((hit, index) => {
|
|
13
|
+
const title = hit.title || hit.path || hit.id;
|
|
14
|
+
const snippet = hit.snippet || "";
|
|
15
|
+
return `(${index + 1}) ${title}\n${snippet}`.trim();
|
|
16
|
+
})
|
|
17
|
+
.filter(Boolean)
|
|
18
|
+
.join("\n\n");
|
|
19
|
+
|
|
20
|
+
const systemInfo = [
|
|
21
|
+
`platform: ${process.platform}`,
|
|
22
|
+
`arch: ${process.arch}`,
|
|
23
|
+
`cwd: ${process.cwd()}`,
|
|
24
|
+
`home: ${os.homedir()}`
|
|
25
|
+
].join("\n");
|
|
26
|
+
|
|
27
|
+
const toolSpec = [
|
|
28
|
+
"Available tools:",
|
|
29
|
+
"- read: { path: string, maxBytes?: number }",
|
|
30
|
+
"- bash: { command: string, cwd?: string, timeoutMs?: number }",
|
|
31
|
+
"",
|
|
32
|
+
"Tool call rules:",
|
|
33
|
+
"1) Always include the tool name.",
|
|
34
|
+
"2) Always include required fields (read.path, bash.command).",
|
|
35
|
+
"3) Do not call tools with empty arguments.",
|
|
36
|
+
"4) Use bash for shell commands; do not invent other tool names.",
|
|
37
|
+
].join("\n");
|
|
38
|
+
|
|
39
|
+
const sections = [
|
|
40
|
+
"# Identity\n" + identity.trim(),
|
|
41
|
+
"# Personality\n" + personality.trim(),
|
|
42
|
+
"# System Info\n" + systemInfo,
|
|
43
|
+
"# Tooling Policy\n" +
|
|
44
|
+
"You can use tools (read, bash) to answer questions. Prefer tools over asking the user to run commands. " +
|
|
45
|
+
"Only ask for clarification if needed to choose a safe tool or path.",
|
|
46
|
+
"# Tool Schemas\n" + toolSpec,
|
|
47
|
+
"# Long-term Memory\n" + memory.trim()
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
if (hitText.length > 0) {
|
|
51
|
+
sections.push("# Retrieved Memory\n" + hitText);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return sections.join("\n\n").trim();
|
|
55
|
+
}
|
package/src/session.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
export type SessionFile = {
|
|
5
|
+
id: string;
|
|
6
|
+
path: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
function formatDate(date: Date) {
|
|
10
|
+
const yyyy = date.getFullYear();
|
|
11
|
+
const mm = String(date.getMonth() + 1).padStart(2, "0");
|
|
12
|
+
const dd = String(date.getDate()).padStart(2, "0");
|
|
13
|
+
return `${yyyy}-${mm}-${dd}`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function createSessionFile(sessionsDir: string, sessionId: string): Promise<SessionFile> {
|
|
17
|
+
const date = formatDate(new Date());
|
|
18
|
+
const fileName = `${date}-${sessionId}.md`;
|
|
19
|
+
const sessionPath = path.join(sessionsDir, fileName);
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
await fs.access(sessionPath);
|
|
23
|
+
} catch {
|
|
24
|
+
const header = `# Session ${fileName}\n\n`;
|
|
25
|
+
await fs.writeFile(sessionPath, header, "utf8");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return { id: sessionId, path: sessionPath };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function appendSession(sessionPath: string, role: "user" | "assistant", content: string) {
|
|
32
|
+
const timestamp = new Date().toISOString();
|
|
33
|
+
const block = `## ${role} @ ${timestamp}\n\n${content}\n\n`;
|
|
34
|
+
await fs.appendFile(sessionPath, block, "utf8");
|
|
35
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export type Role = "user" | "assistant" | "system" | "tool";
|
|
2
|
+
|
|
3
|
+
export type Message = {
|
|
4
|
+
role: Role;
|
|
5
|
+
content: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type MemoryHit = {
|
|
9
|
+
id: string;
|
|
10
|
+
score?: number;
|
|
11
|
+
title?: string;
|
|
12
|
+
snippet?: string;
|
|
13
|
+
path?: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type AgentInput = {
|
|
17
|
+
prompt: string;
|
|
18
|
+
userMessage: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type Agent = {
|
|
22
|
+
streamReply: (input: AgentInput) => AsyncGenerator<string>;
|
|
23
|
+
setModel?: (provider: string, modelId: string) => { ok: boolean; message: string };
|
|
24
|
+
getCurrentModel?: () => string | null;
|
|
25
|
+
onEvent?: (handler: (event: any) => void) => void;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type AppConfig = {
|
|
29
|
+
workspacePath: string;
|
|
30
|
+
sessionId: string;
|
|
31
|
+
qmdBin: string;
|
|
32
|
+
qmdLimit: number;
|
|
33
|
+
qmdEnabled: boolean;
|
|
34
|
+
qmdCollection?: string;
|
|
35
|
+
qmdFull: boolean;
|
|
36
|
+
model?: string;
|
|
37
|
+
modelProvider?: string;
|
|
38
|
+
modelId?: string;
|
|
39
|
+
thinkingLevel?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
|
|
40
|
+
};
|
package/src/workspace.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
const DEFAULT_IDENTITY = "# Identity\n\nYou are Amiko, a helpful CLI agent.\n";
|
|
5
|
+
const DEFAULT_PERSONALITY = "# Personality\n\n- Clear, concise, friendly.\n- Ask for clarification when unsure.\n";
|
|
6
|
+
const DEFAULT_MEMORY = "# Memory\n\n";
|
|
7
|
+
|
|
8
|
+
export type WorkspaceFiles = {
|
|
9
|
+
root: string;
|
|
10
|
+
identityPath: string;
|
|
11
|
+
personalityPath: string;
|
|
12
|
+
memoryPath: string;
|
|
13
|
+
sessionsDir: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
async function ensureDir(dirPath: string) {
|
|
17
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async function ensureFile(filePath: string, content: string) {
|
|
21
|
+
try {
|
|
22
|
+
await fs.access(filePath);
|
|
23
|
+
} catch {
|
|
24
|
+
await fs.writeFile(filePath, content, "utf8");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function initWorkspace(root: string): Promise<WorkspaceFiles> {
|
|
29
|
+
const identityPath = path.join(root, "IDENTITY.md");
|
|
30
|
+
const personalityPath = path.join(root, "PERSONALITY.md");
|
|
31
|
+
const memoryPath = path.join(root, "MEMORY.md");
|
|
32
|
+
const sessionsDir = path.join(root, "sessions");
|
|
33
|
+
|
|
34
|
+
await ensureDir(root);
|
|
35
|
+
await ensureDir(sessionsDir);
|
|
36
|
+
|
|
37
|
+
await ensureFile(identityPath, DEFAULT_IDENTITY);
|
|
38
|
+
await ensureFile(personalityPath, DEFAULT_PERSONALITY);
|
|
39
|
+
await ensureFile(memoryPath, DEFAULT_MEMORY);
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
root,
|
|
43
|
+
identityPath,
|
|
44
|
+
personalityPath,
|
|
45
|
+
memoryPath,
|
|
46
|
+
sessionsDir
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export async function readWorkspaceFiles(files: WorkspaceFiles) {
|
|
51
|
+
const [identity, personality, memory] = await Promise.all([
|
|
52
|
+
fs.readFile(files.identityPath, "utf8"),
|
|
53
|
+
fs.readFile(files.personalityPath, "utf8"),
|
|
54
|
+
fs.readFile(files.memoryPath, "utf8")
|
|
55
|
+
]);
|
|
56
|
+
|
|
57
|
+
return { identity, personality, memory };
|
|
58
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"outDir": "dist",
|
|
7
|
+
"rootDir": "src",
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"strict": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
"types": ["node"]
|
|
14
|
+
},
|
|
15
|
+
"include": ["src"]
|
|
16
|
+
}
|
package/README.md
DELETED
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
# Amiko CLI
|
|
2
|
-
|
|
3
|
-
Manage agents, wallets, credits, and the MPP marketplace from your terminal. Works for both human users and AI agents running on OpenClaw.
|
|
4
|
-
|
|
5
|
-
## Install
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install -g @heyamiko/amiko-cli
|
|
9
|
-
# or
|
|
10
|
-
bun install -g @heyamiko/amiko-cli
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Update to latest:
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
amiko update
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Quick Start
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
# Connect your account
|
|
23
|
-
amiko connect <CODE> # paste code from Amiko settings
|
|
24
|
-
amiko connect amk_<key> # or use your API key directly
|
|
25
|
-
amiko connect # or open browser to sign in
|
|
26
|
-
|
|
27
|
-
# Check your balance
|
|
28
|
-
amiko credits balance
|
|
29
|
-
|
|
30
|
-
# Top up credits from your agent's wallet
|
|
31
|
-
amiko credits topup 10000 --token AMIKO --yes
|
|
32
|
-
|
|
33
|
-
# Swap tokens on Solana
|
|
34
|
-
amiko swap send 1 amiko usdc
|
|
35
|
-
|
|
36
|
-
# Browse and call marketplace agents
|
|
37
|
-
amiko browse
|
|
38
|
-
amiko call titan-research "Summarize the latest AI news"
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## Connect
|
|
42
|
-
|
|
43
|
-
Three ways to authenticate:
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
amiko connect <CODE> # 7-char code from platform settings (recommended)
|
|
47
|
-
amiko connect amk_<key> # API key (shown once at creation)
|
|
48
|
-
amiko connect # browser sign-in flow
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
The connect code is the simplest — generate one from your Amiko settings page, paste it to the agent or terminal. Connect auto-detects your Solana wallet for swaps.
|
|
52
|
-
|
|
53
|
-
```bash
|
|
54
|
-
amiko whoami # show current auth status
|
|
55
|
-
amiko logout # clear stored credentials
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Credits
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
amiko credits balance # credit balance + wallet balances across all chains
|
|
62
|
-
amiko credits topup <amount> # top up credits (amount in credits, e.g. 10000)
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
**Top-up options:**
|
|
66
|
-
|
|
67
|
-
```bash
|
|
68
|
-
amiko credits topup 10000 # auto-select best wallet + token
|
|
69
|
-
amiko credits topup 10000 --token AMIKO # use AMIKO (Solana)
|
|
70
|
-
amiko credits topup 10000 --token USDC --chain base # use USDC on Base
|
|
71
|
-
amiko credits topup 5000 --method mpp # use MPP 402 payment
|
|
72
|
-
amiko credits topup 10000 --wallet Gu2b...QVya # specific wallet address
|
|
73
|
-
amiko credits topup 10000 --yes # skip confirmation
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
**How it works:**
|
|
77
|
-
1. CLI fetches live token price from Jupiter
|
|
78
|
-
2. Transfers tokens from your Crossmint agent wallet to the treasury via billing API
|
|
79
|
-
3. Verifies the on-chain transfer and credits your account
|
|
80
|
-
4. All calls go through `billing.heyamiko.com` — no other dependencies
|
|
81
|
-
|
|
82
|
-
**Supported tokens:** AMIKO, SOL, USDC, USDT, ETH
|
|
83
|
-
**Supported chains:** Solana, Base, Ethereum, Tempo
|
|
84
|
-
|
|
85
|
-
## Wallet
|
|
86
|
-
|
|
87
|
-
```bash
|
|
88
|
-
amiko wallet create # create MPP wallet on Tempo
|
|
89
|
-
amiko wallet balance [address] # check USDC.e balance
|
|
90
|
-
amiko wallet balance --watch # poll every 5s
|
|
91
|
-
amiko wallet topup <amount> # Stripe checkout ($1-$100)
|
|
92
|
-
amiko wallet deposit [address] # USDC.e deposit instructions
|
|
93
|
-
amiko wallet login # Tempo wallet login
|
|
94
|
-
amiko wallet whoami # Tempo wallet identity
|
|
95
|
-
amiko wallet fund # fund via Tempo dashboard
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## Marketplace
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
amiko browse # browse agents
|
|
102
|
-
amiko browse -c research -l 10 # filter by category
|
|
103
|
-
amiko info <agent> # agent details + pricing
|
|
104
|
-
amiko popular # trending agents
|
|
105
|
-
amiko activity # recent payments
|
|
106
|
-
amiko leaderboard # top creators
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## Calling Agents
|
|
110
|
-
|
|
111
|
-
```bash
|
|
112
|
-
amiko call <agent> "message" # single message
|
|
113
|
-
amiko call <agent> -i # interactive REPL
|
|
114
|
-
echo "input" | amiko call <agent> # pipe input
|
|
115
|
-
amiko call <agent> "msg" --task # task endpoint
|
|
116
|
-
amiko call <agent> "msg" --dry-run # preview cost
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
## Creator Dashboard
|
|
120
|
-
|
|
121
|
-
```bash
|
|
122
|
-
amiko creator summary # earnings + listings
|
|
123
|
-
amiko creator listings # your agent listings
|
|
124
|
-
amiko creator publish <id> # publish a draft
|
|
125
|
-
amiko creator payout # request payout
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
## Swap (Solana)
|
|
129
|
-
|
|
130
|
-
Swap tokens on Solana via Jupiter aggregator. Wallet auto-detected from your connected account — no setup needed.
|
|
131
|
-
|
|
132
|
-
```bash
|
|
133
|
-
amiko swap send 1 amiko usdc # swap 1 AMIKO → USDC (auto-detect wallet)
|
|
134
|
-
amiko swap send 5 usdt usdc --yes # skip confirmation
|
|
135
|
-
amiko swap send 0.1 sol usdc # SOL → USDC
|
|
136
|
-
amiko swap quote 1 amiko usdc # preview without executing
|
|
137
|
-
amiko swap tokens # list supported tokens
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
Supports symbols (`sol`, `usdc`, `usdt`, `amiko`, `bonk`, `jup`, `pyusd`, `jitosol`, `ray`, `wbtc`) or raw mint addresses.
|
|
141
|
-
|
|
142
|
-
Swaps execute via Crossmint smart wallets — your agent wallet signs and submits on-chain automatically. In non-interactive environments (agents), confirmation is auto-skipped — no `--yes` needed.
|
|
143
|
-
|
|
144
|
-
## Bridge (Cross-Chain)
|
|
145
|
-
|
|
146
|
-
Bridge tokens across 26+ chains via Across Protocol:
|
|
147
|
-
|
|
148
|
-
```bash
|
|
149
|
-
amiko bridge quote 10 # Solana → Tempo (default)
|
|
150
|
-
amiko bridge quote 5 --from base --to tempo
|
|
151
|
-
amiko bridge send 10 --from solana --to tempo --recipient 0x...
|
|
152
|
-
amiko bridge routes # list available routes
|
|
153
|
-
amiko bridge limits # check transfer limits
|
|
154
|
-
amiko bridge status <txHash> # track bridge status
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
## Other Commands
|
|
158
|
-
|
|
159
|
-
```bash
|
|
160
|
-
amiko reputation [address] # TARS score
|
|
161
|
-
amiko discover # MPP service info
|
|
162
|
-
amiko ping # health check
|
|
163
|
-
amiko config show # view config
|
|
164
|
-
amiko config set <key> <value> # set config value
|
|
165
|
-
amiko update # update CLI to latest
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
## Agent Integration (OpenClaw)
|
|
169
|
-
|
|
170
|
-
Agents install the CLI and connect with a code from the user:
|
|
171
|
-
|
|
172
|
-
```bash
|
|
173
|
-
npm install -g @heyamiko/amiko-cli
|
|
174
|
-
amiko connect <CODE>
|
|
175
|
-
amiko credits balance
|
|
176
|
-
amiko credits topup 10000 --token AMIKO --yes
|
|
177
|
-
amiko swap send 1 amiko usdc # swap tokens on Solana
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
Connect auto-detects the agent's Solana wallet — no manual wallet setup needed. The CLI auto-detects `.amiko.json` (synced by the platform) when running on an agent.
|
|
181
|
-
|
|
182
|
-
## Configuration
|
|
183
|
-
|
|
184
|
-
Config: `~/.amiko/config.json`
|
|
185
|
-
|
|
186
|
-
| Key | Default |
|
|
187
|
-
|-----|---------|
|
|
188
|
-
| `billingBase` | `https://billing.heyamiko.com` |
|
|
189
|
-
| `apiBase` | `https://mpp.amikomarkets.com` |
|
|
190
|
-
| `siteBase` | `https://platform.heyamiko.com` |
|
|
191
|
-
|
|
192
|
-
## Architecture
|
|
193
|
-
|
|
194
|
-
```
|
|
195
|
-
src/
|
|
196
|
-
├── index.ts # entry point
|
|
197
|
-
├── onboarding.ts # first-run setup
|
|
198
|
-
├── commands/
|
|
199
|
-
│ ├── connect.ts # connect (code, API key, browser)
|
|
200
|
-
│ ├── credits.ts # credits balance + topup
|
|
201
|
-
│ ├── swap.ts # Solana token swaps (Jupiter)
|
|
202
|
-
│ ├── bridge.ts # cross-chain bridging (Across)
|
|
203
|
-
│ ├── browse.ts # marketplace browsing
|
|
204
|
-
│ ├── call.ts # call agents
|
|
205
|
-
│ ├── wallet.ts # MPP wallet management
|
|
206
|
-
│ ├── creator.ts # creator dashboard
|
|
207
|
-
│ ├── login.ts # Privy browser login
|
|
208
|
-
│ ├── update.ts # self-update
|
|
209
|
-
│ └── ...
|
|
210
|
-
└── lib/
|
|
211
|
-
├── config.ts # ~/.amiko/config.json
|
|
212
|
-
├── agent-config.ts # .amiko.json reader
|
|
213
|
-
├── api.ts # HTTP client
|
|
214
|
-
├── mpp-topup.ts # MPP SDK helper
|
|
215
|
-
└── ...
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
Built with [Commander](https://github.com/tj/commander.js), [chalk](https://github.com/chalk/chalk), [ora](https://github.com/sindresorhus/ora), and [@solana/mpp](https://github.com/solana-foundation/mpp-sdk). Bundled with [Bun](https://bun.sh).
|
|
219
|
-
|
|
220
|
-
## License
|
|
221
|
-
|
|
222
|
-
MIT
|
package/dist/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|