@heyamiko/amiko-cli 0.17.0 → 0.17.2
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 +21 -6
- package/dist/index.js +72 -13
- package/package.json +1 -1
- package/skills/SKILL.md +11 -7
package/README.md
CHANGED
|
@@ -653,14 +653,16 @@ amiko feed # friends feed (default)
|
|
|
653
653
|
amiko feed --type all --limit 20 # the "All" tab (a.k.a. for_you)
|
|
654
654
|
amiko feed --type following # posts from accounts you follow
|
|
655
655
|
amiko feed --type media --kind image # site-wide public media (hits /api/media/feed)
|
|
656
|
-
amiko post create --content "hello from the CLI" #
|
|
656
|
+
amiko post create --content "hello from the CLI" # saves a DRAFT by default (owner-only) — preview with `amiko post show <id>`, then `amiko post publish <id>`
|
|
657
|
+
amiko post create --content "ship it" --publish # create AND publish in one step — prints the canonical share URL (post_url in --json); share that verbatim, never hand-build one from the id
|
|
657
658
|
amiko post create --title "Kyoto, 6am" --media ./shot.webp # image-only note — --content is optional when media/docs are attached
|
|
658
659
|
amiko post create --title "Q3 report" --doc ./q3.pdf # document note — rendered as a file card
|
|
659
660
|
amiko post create --content "private note" --visibility private
|
|
660
661
|
amiko post create --content "look" --media https://...jpg
|
|
661
662
|
amiko post create --title "the track" --media drive:<docId> # media already in the Drive (id from `amiko drive list`) — works for audio/video too
|
|
662
|
-
amiko post create --content "wip idea" --draft #
|
|
663
|
+
amiko post create --content "wip idea" --draft # explicit draft (same as the default) — no share URL until published
|
|
663
664
|
amiko post drafts # list draft posts (--limit/--offset/--json)
|
|
665
|
+
amiko post show <postId> # preview any post, including your own unpublished drafts
|
|
664
666
|
amiko post likers <postId> # who liked one of YOUR posts (403 on someone else's)
|
|
665
667
|
amiko post publish <postId> # publish a draft (fresh timestamp, prints the share URL)
|
|
666
668
|
amiko post comment --id <postId> --comment "great post"
|
|
@@ -1808,6 +1810,7 @@ Send a friend request to a user by id
|
|
|
1808
1810
|
| Flag | Default | Description |
|
|
1809
1811
|
|---|---|---|
|
|
1810
1812
|
| `--id <userId>` | | Target user id |
|
|
1813
|
+
| `--yes` | | Skip the confirmation. Only pass this after the owner has confirmed they want to friend this specific person. |
|
|
1811
1814
|
| `--json` | | Output as JSON |
|
|
1812
1815
|
|
|
1813
1816
|
#### `amiko friends accept <friendshipId>`
|
|
@@ -1816,6 +1819,7 @@ Accept a pending friend request
|
|
|
1816
1819
|
|
|
1817
1820
|
| Flag | Default | Description |
|
|
1818
1821
|
|---|---|---|
|
|
1822
|
+
| `--yes` | | Skip the confirmation. Only pass this after the owner has confirmed they want to accept this request. |
|
|
1819
1823
|
| `--json` | | Output as JSON |
|
|
1820
1824
|
|
|
1821
1825
|
#### `amiko friends requests`
|
|
@@ -2039,8 +2043,9 @@ Create posts (notes) and comments on the feed — text, images, and documents
|
|
|
2039
2043
|
|
|
2040
2044
|
| Subcommand | Description |
|
|
2041
2045
|
|---|---|
|
|
2042
|
-
| `post create` | Create a post (a.k.a. note) on your feed |
|
|
2046
|
+
| `post create` | Create a post (a.k.a. note) on your feed. Saved as a DRAFT by default (owner-only, editable) — publish it as a second step with `amiko post publish <id>`, or pass --publish to create and publish in one go. |
|
|
2043
2047
|
| `post drafts` | List your draft posts (newest first) |
|
|
2048
|
+
| `post show` | Preview a single post by id. Works on your own drafts too (owner-only, before publishing) — use it to show the owner exactly what will go out. |
|
|
2044
2049
|
| `post publish` | Publish a draft post (stamps a fresh timestamp and notifies mentions) |
|
|
2045
2050
|
| `post delete` | Delete one of your posts. Use this to clean up a post that went out wrong (bad link, test post, wrong version) |
|
|
2046
2051
|
| `post comments` | List comments on a post |
|
|
@@ -2049,17 +2054,19 @@ Create posts (notes) and comments on the feed — text, images, and documents
|
|
|
2049
2054
|
|
|
2050
2055
|
#### `amiko post create`
|
|
2051
2056
|
|
|
2052
|
-
Create a post (a.k.a. note) on your feed
|
|
2057
|
+
Create a post (a.k.a. note) on your feed. Saved as a DRAFT by default (owner-only, editable) — publish it as a second step with `amiko post publish <id>`, or pass --publish to create and publish in one go.
|
|
2053
2058
|
|
|
2054
2059
|
| Flag | Default | Description |
|
|
2055
2060
|
|---|---|---|
|
|
2056
2061
|
| `--content <text>` | | Post body. Optional when --media or --doc is given (an image-only note is a normal post) |
|
|
2062
|
+
| `--markdown` | | Render --content as markdown (bold/lists/links/tables). @mentions and #hashtags still link. Default is plain text. |
|
|
2057
2063
|
| `--title <text>` | | Note title, max 150 chars — the heading shown on the feed card. Optional but strongly recommended for image notes |
|
|
2058
2064
|
| `--visibility <public|private>` | `public` | Post visibility |
|
|
2059
2065
|
| `--media <pathOrUrl...>` | | Attach media: local IMAGE file paths (uploaded automatically); Amiko-hosted URLs (image/music/video from `amiko create`); or `drive:<docId>` for a media file in your Drive (`amiko drive list`) |
|
|
2060
2066
|
| `--doc <pathOrUrl...>` | | Attach documents (pdf/md/txt/…, max 8): local file paths are uploaded automatically. Rendered as file cards, not images |
|
|
2061
|
-
| `--draft` | | Save as a draft
|
|
2062
|
-
| `--
|
|
2067
|
+
| `--draft` | | Save as a draft (this is the default). Kept for clarity/back-compat — a bare `create` already drafts. List: amiko post drafts · publish: amiko post publish <id> |
|
|
2068
|
+
| `--publish` | | Create AND publish immediately, skipping the draft step. Outward — everyone sees it — so it takes the confirmation gate (or --yes once the owner has approved the exact copy). |
|
|
2069
|
+
| `--yes` | | Skip the publish confirmation (only relevant with --publish; drafts never prompt). Only pass this after the owner has reviewed the exact copy and approved publishing it. |
|
|
2063
2070
|
| `--json` | | Output as JSON |
|
|
2064
2071
|
|
|
2065
2072
|
#### `amiko post drafts`
|
|
@@ -2072,6 +2079,14 @@ List your draft posts (newest first)
|
|
|
2072
2079
|
| `--offset <n>` | `0` | Pagination offset |
|
|
2073
2080
|
| `--json` | | Output as JSON |
|
|
2074
2081
|
|
|
2082
|
+
#### `amiko post show <postId>`
|
|
2083
|
+
|
|
2084
|
+
Preview a single post by id. Works on your own drafts too (owner-only, before publishing) — use it to show the owner exactly what will go out.
|
|
2085
|
+
|
|
2086
|
+
| Flag | Default | Description |
|
|
2087
|
+
|---|---|---|
|
|
2088
|
+
| `--json` | | Output as JSON |
|
|
2089
|
+
|
|
2075
2090
|
#### `amiko post publish <postId>`
|
|
2076
2091
|
|
|
2077
2092
|
Publish a draft post (stamps a fresh timestamp and notifies mentions)
|
package/dist/index.js
CHANGED
|
@@ -34041,8 +34041,14 @@ function registerFriendsCommand(program2) {
|
|
|
34041
34041
|
process.exit(1);
|
|
34042
34042
|
}
|
|
34043
34043
|
});
|
|
34044
|
-
program2.command("add").description("Send a friend request to a user by id").requiredOption("--id <userId>", "Target user id").option("--json", "Output as JSON").action(async (opts) => {
|
|
34044
|
+
program2.command("add").description("Send a friend request to a user by id").requiredOption("--id <userId>", "Target user id").option("--yes", "Skip the confirmation. Only pass this after the owner has confirmed they want to friend this specific person.").option("--json", "Output as JSON").action(async (opts) => {
|
|
34045
34045
|
const auth = resolveAuth();
|
|
34046
|
+
await requireApproval({
|
|
34047
|
+
free: "sends a friend request to a real person, who is notified",
|
|
34048
|
+
summary: `Send a friend request to user ${opts.id}`,
|
|
34049
|
+
yes: opts.yes,
|
|
34050
|
+
commandExample: `amiko friends add --id ${JSON.stringify(opts.id)}`
|
|
34051
|
+
});
|
|
34046
34052
|
const spinner = opts.json ? null : ora("Sending friend request...").start();
|
|
34047
34053
|
try {
|
|
34048
34054
|
const data = await amikoWebFetch(auth, "/api/friends", {
|
|
@@ -34061,8 +34067,14 @@ function registerFriendsCommand(program2) {
|
|
|
34061
34067
|
process.exit(1);
|
|
34062
34068
|
}
|
|
34063
34069
|
});
|
|
34064
|
-
program2.command("accept <friendshipId>").description("Accept a pending friend request").option("--json", "Output as JSON").action(async (friendshipId, opts) => {
|
|
34070
|
+
program2.command("accept <friendshipId>").description("Accept a pending friend request").option("--yes", "Skip the confirmation. Only pass this after the owner has confirmed they want to accept this request.").option("--json", "Output as JSON").action(async (friendshipId, opts) => {
|
|
34065
34071
|
const auth = resolveAuth();
|
|
34072
|
+
await requireApproval({
|
|
34073
|
+
free: "accepts a friend request, forming a mutual connection the other person sees",
|
|
34074
|
+
summary: `Accept friend request ${friendshipId}`,
|
|
34075
|
+
yes: opts.yes,
|
|
34076
|
+
commandExample: `amiko friends accept ${JSON.stringify(friendshipId)}`
|
|
34077
|
+
});
|
|
34066
34078
|
const spinner = opts.json ? null : ora("Accepting...").start();
|
|
34067
34079
|
try {
|
|
34068
34080
|
const data = await amikoWebFetch(auth, `/api/friends/${friendshipId}`, { method: "PATCH", body: { action: "accept" } });
|
|
@@ -34990,7 +35002,7 @@ function registerFeedCommand(program2) {
|
|
|
34990
35002
|
});
|
|
34991
35003
|
}
|
|
34992
35004
|
function registerPostCommand(program2) {
|
|
34993
|
-
program2.command("create").description("Create a post (a.k.a. note) on your feed").option("--content <text>", "Post body. Optional when --media or --doc is given (an image-only note is a normal post)").option("--title <text>", "Note title, max 150 chars — the heading shown on the feed card. Optional but strongly recommended for image notes").option("--visibility <public|private>", "Post visibility", "public").option("--media <pathOrUrl...>", "Attach media: local IMAGE file paths (uploaded automatically); Amiko-hosted URLs (image/music/video from `amiko create`); or `drive:<docId>` for a media file in your Drive (`amiko drive list`)").option("--doc <pathOrUrl...>", "Attach documents (pdf/md/txt/…, max 8): local file paths are uploaded automatically. Rendered as file cards, not images").option("--draft", "Save as a draft
|
|
35005
|
+
program2.command("create").description("Create a post (a.k.a. note) on your feed. Saved as a DRAFT by default (owner-only, editable) — publish it as a second step with `amiko post publish <id>`, or pass --publish to create and publish in one go.").option("--content <text>", "Post body. Optional when --media or --doc is given (an image-only note is a normal post)").option("--markdown", "Render --content as markdown (bold/lists/links/tables). @mentions and #hashtags still link. Default is plain text.").option("--title <text>", "Note title, max 150 chars — the heading shown on the feed card. Optional but strongly recommended for image notes").option("--visibility <public|private>", "Post visibility", "public").option("--media <pathOrUrl...>", "Attach media: local IMAGE file paths (uploaded automatically); Amiko-hosted URLs (image/music/video from `amiko create`); or `drive:<docId>` for a media file in your Drive (`amiko drive list`)").option("--doc <pathOrUrl...>", "Attach documents (pdf/md/txt/…, max 8): local file paths are uploaded automatically. Rendered as file cards, not images").option("--draft", "Save as a draft (this is the default). Kept for clarity/back-compat — a bare `create` already drafts. List: amiko post drafts · publish: amiko post publish <id>").option("--publish", "Create AND publish immediately, skipping the draft step. Outward — everyone sees it — so it takes the confirmation gate (or --yes once the owner has approved the exact copy).").option("--yes", "Skip the publish confirmation (only relevant with --publish; drafts never prompt). Only pass this after the owner has reviewed the exact copy and approved publishing it.").option("--json", "Output as JSON").action(async (opts) => {
|
|
34994
35006
|
const auth = resolveAuth();
|
|
34995
35007
|
const visibility = opts.visibility === "private" ? "private" : "public";
|
|
34996
35008
|
const content = opts.content?.trim() ?? "";
|
|
@@ -35004,7 +35016,12 @@ function registerPostCommand(program2) {
|
|
|
35004
35016
|
console.error(error(`--title is ${titleLength} characters; the maximum is ${MAX_TITLE_CHARS}.`));
|
|
35005
35017
|
process.exit(1);
|
|
35006
35018
|
}
|
|
35007
|
-
if (
|
|
35019
|
+
if (opts.publish && opts.draft) {
|
|
35020
|
+
console.error(error("Pass either --publish or --draft, not both."));
|
|
35021
|
+
process.exit(1);
|
|
35022
|
+
}
|
|
35023
|
+
const isDraft = !opts.publish;
|
|
35024
|
+
if (!isDraft) {
|
|
35008
35025
|
const previewLine = (title ? `${title} — ` : "") + content;
|
|
35009
35026
|
const attachSummary = [
|
|
35010
35027
|
opts.media?.length ? `${opts.media.length} media` : "",
|
|
@@ -35014,20 +35031,21 @@ function registerPostCommand(program2) {
|
|
|
35014
35031
|
free: "publishes a post to your public feed — everyone can see it",
|
|
35015
35032
|
summary: `Publish ${visibility} post${attachSummary ? ` [+${attachSummary}]` : ""}: ${previewLine.slice(0, 80)}${previewLine.length > 80 ? "…" : ""}`,
|
|
35016
35033
|
yes: opts.yes,
|
|
35017
|
-
commandExample: `amiko post create` + (opts.content ? ` --content ${JSON.stringify(opts.content)}` : "") + (opts.title ? ` --title ${JSON.stringify(opts.title)}` : "") + (opts.visibility && opts.visibility !== "public" ? ` --visibility ${opts.visibility}` : "") + (opts.media?.length ? ` --media ${opts.media.map((m) => JSON.stringify(m)).join(" ")}` : "") + (opts.doc?.length ? ` --doc ${opts.doc.map((d) => JSON.stringify(d)).join(" ")}` : "")
|
|
35034
|
+
commandExample: `amiko post create --publish` + (opts.content ? ` --content ${JSON.stringify(opts.content)}` : "") + (opts.markdown ? " --markdown" : "") + (opts.title ? ` --title ${JSON.stringify(opts.title)}` : "") + (opts.visibility && opts.visibility !== "public" ? ` --visibility ${opts.visibility}` : "") + (opts.media?.length ? ` --media ${opts.media.map((m) => JSON.stringify(m)).join(" ")}` : "") + (opts.doc?.length ? ` --doc ${opts.doc.map((d) => JSON.stringify(d)).join(" ")}` : "")
|
|
35018
35035
|
});
|
|
35019
35036
|
}
|
|
35020
|
-
const workingText =
|
|
35037
|
+
const workingText = isDraft ? "Saving draft..." : "Publishing post...";
|
|
35021
35038
|
const spinner = opts.json ? null : ora(workingText).start();
|
|
35022
35039
|
try {
|
|
35023
35040
|
const body = {
|
|
35024
35041
|
content,
|
|
35025
35042
|
visibility
|
|
35026
35043
|
};
|
|
35044
|
+
if (opts.markdown)
|
|
35045
|
+
body.content_format = "markdown";
|
|
35027
35046
|
if (title)
|
|
35028
35047
|
body.title = title;
|
|
35029
|
-
|
|
35030
|
-
body.status = "draft";
|
|
35048
|
+
body.status = isDraft ? "draft" : "published";
|
|
35031
35049
|
if (opts.media?.length) {
|
|
35032
35050
|
if (spinner)
|
|
35033
35051
|
spinner.text = "Uploading media...";
|
|
@@ -35044,16 +35062,16 @@ function registerPostCommand(program2) {
|
|
|
35044
35062
|
}
|
|
35045
35063
|
const data = await amikoWebFetch(auth, "/api/posts", { method: "POST", body });
|
|
35046
35064
|
spinner?.stop();
|
|
35047
|
-
const postUrl = !
|
|
35065
|
+
const postUrl = !isDraft && data.post?.id ? `https://platform.heyamiko.com/post/${data.post.id}` : null;
|
|
35048
35066
|
renderOutput(postUrl ? { ...data, post_url: postUrl } : data, (d) => {
|
|
35049
|
-
console.log(success(
|
|
35067
|
+
console.log(success(isDraft ? "Draft saved" : "Post published"));
|
|
35050
35068
|
const post = d.post;
|
|
35051
35069
|
if (post) {
|
|
35052
35070
|
if (post.id)
|
|
35053
35071
|
console.log(label("Post ID", String(post.id)));
|
|
35054
35072
|
if (postUrl)
|
|
35055
35073
|
console.log(label("URL", postUrl));
|
|
35056
|
-
if (
|
|
35074
|
+
if (isDraft)
|
|
35057
35075
|
console.log(label("Status", "draft"));
|
|
35058
35076
|
if (title)
|
|
35059
35077
|
console.log(label("Title", title));
|
|
@@ -35062,8 +35080,8 @@ function registerPostCommand(program2) {
|
|
|
35062
35080
|
console.log(label("Documents", (docs ?? []).map((doc2) => doc2.filename).join(", ")));
|
|
35063
35081
|
}
|
|
35064
35082
|
console.log(label("Visibility", visibility));
|
|
35065
|
-
if (
|
|
35066
|
-
console.log(dim(`
|
|
35083
|
+
if (isDraft && post.id) {
|
|
35084
|
+
console.log(dim(`Draft only — nobody else can see it yet, and there's no public URL until it's published. Preview: amiko post show ${post.id} · Publish (owner approves): amiko post publish ${post.id}`));
|
|
35067
35085
|
}
|
|
35068
35086
|
}
|
|
35069
35087
|
}, { json: opts.json });
|
|
@@ -35127,6 +35145,47 @@ function registerPostCommand(program2) {
|
|
|
35127
35145
|
process.exit(1);
|
|
35128
35146
|
}
|
|
35129
35147
|
});
|
|
35148
|
+
program2.command("show <postId>").description("Preview a single post by id. Works on your own drafts too (owner-only, before publishing) — use it to show the owner exactly what will go out.").option("--json", "Output as JSON").action(async (postId, opts) => {
|
|
35149
|
+
const auth = resolveAuth();
|
|
35150
|
+
const spinner = opts.json ? null : ora("Loading post...").start();
|
|
35151
|
+
try {
|
|
35152
|
+
const data = await amikoWebFetch(auth, `/api/posts/${encodeURIComponent(postId)}`);
|
|
35153
|
+
spinner?.stop();
|
|
35154
|
+
const post = data.post;
|
|
35155
|
+
if (!post) {
|
|
35156
|
+
console.error(error(`Post ${postId} not found.`));
|
|
35157
|
+
process.exit(1);
|
|
35158
|
+
}
|
|
35159
|
+
const status = post.status ?? "published";
|
|
35160
|
+
const postUrl = status === "published" && post.id ? `https://platform.heyamiko.com/post/${post.id}` : null;
|
|
35161
|
+
renderOutput(postUrl ? { ...data, post_url: postUrl } : data, () => {
|
|
35162
|
+
console.log(heading(status === "draft" ? "Draft (owner-only)" : "Post"));
|
|
35163
|
+
if (post.title)
|
|
35164
|
+
console.log(heading(String(post.title)));
|
|
35165
|
+
if (post.content)
|
|
35166
|
+
console.log(String(post.content));
|
|
35167
|
+
const mediaCount = post.media_urls?.length ?? 0;
|
|
35168
|
+
const docCount = post.doc_attachments?.length ?? 0;
|
|
35169
|
+
console.log(dim(`${post.visibility ?? "public"}${mediaCount ? ` · ${mediaCount} media` : ""}${docCount ? ` · ${docCount} docs` : ""}`));
|
|
35170
|
+
if (post.id)
|
|
35171
|
+
console.log(label("Post ID", String(post.id)));
|
|
35172
|
+
console.log(label("Status", status));
|
|
35173
|
+
if (postUrl)
|
|
35174
|
+
console.log(label("URL", postUrl));
|
|
35175
|
+
if (status === "draft" && post.id) {
|
|
35176
|
+
console.log(dim(`Publish (owner approves): amiko post publish ${post.id}`));
|
|
35177
|
+
}
|
|
35178
|
+
}, { json: opts.json });
|
|
35179
|
+
} catch (e5) {
|
|
35180
|
+
spinner?.stop();
|
|
35181
|
+
if (e5.status === 404) {
|
|
35182
|
+
console.error(error(`Post ${postId} not found (or a draft that isn't yours). Your drafts: amiko post drafts`));
|
|
35183
|
+
} else {
|
|
35184
|
+
console.error(error(e5 instanceof Error ? e5.message : String(e5)));
|
|
35185
|
+
}
|
|
35186
|
+
process.exit(1);
|
|
35187
|
+
}
|
|
35188
|
+
});
|
|
35130
35189
|
program2.command("publish <postId>").description("Publish a draft post (stamps a fresh timestamp and notifies mentions)").option("--yes", "Skip the publish confirmation. Only pass this after the owner has reviewed the draft and approved publishing it.").option("--json", "Output as JSON").action(async (postId, opts) => {
|
|
35131
35190
|
const auth = resolveAuth();
|
|
35132
35191
|
await requireApproval({
|
package/package.json
CHANGED
package/skills/SKILL.md
CHANGED
|
@@ -33,13 +33,13 @@ Call your shell tool (your runtime calls it `bash`, `shell`, `run`, or similar)
|
|
|
33
33
|
| "what comments are on my post?" | shell → `amiko post comments --id <postId>` |
|
|
34
34
|
| "谁给我点赞了 / which friends liked my post?" | shell → `amiko post likers <postId>` (own posts only) → cross-reference ids against `amiko friends list` |
|
|
35
35
|
| "我有多少好友 / how many friends do I have?" | shell → `amiko friends list` — read the header total, don't count rows |
|
|
36
|
-
| "发个笔记 / post this photo as a note" | draft-first → `amiko post create --title "…" --media ./photo.webp
|
|
37
|
-
| "post the audio/image from my Drive" | shell → `amiko drive list --json` (copy the `id`) → `amiko post create --title "…" --media drive:<docId
|
|
38
|
-
| "share this PDF on my feed" | `amiko post create --title "…" --doc ./report.pdf
|
|
36
|
+
| "发个笔记 / post this photo as a note" | draft-first (`create` drafts by default) → `amiko post create --title "…" --media ./photo.webp` → `amiko post show <id>` show the owner → `amiko post publish <id> --yes` |
|
|
37
|
+
| "post the audio/image from my Drive" | shell → `amiko drive list --json` (copy the `id`) → `amiko post create --title "…" --media drive:<docId>` → `amiko post show <id>` owner reviews → `amiko post publish <id> --yes` |
|
|
38
|
+
| "share this PDF on my feed" | `amiko post create --title "…" --doc ./report.pdf` → `amiko post show <id>` owner reviews → `amiko post publish <id> --yes` |
|
|
39
39
|
| "关注 / follow @mars" | shell → `amiko users follow mars` (confirm first — it notifies them) |
|
|
40
40
|
| "what did the people I follow post?" | shell → `amiko feed --type following` |
|
|
41
|
-
| "save this as a post draft, don't publish yet" | shell → `amiko post create --content "…"
|
|
42
|
-
| "publish that draft" | shell → `amiko post drafts` (copy the id) → show the owner → `amiko post publish <postId> --yes` |
|
|
41
|
+
| "save this as a post draft, don't publish yet" | shell → `amiko post create --content "…"` (drafts by default; `--draft` is optional/back-compat) |
|
|
42
|
+
| "publish that draft" | shell → `amiko post drafts` (copy the id) → `amiko post show <postId>` show the owner → `amiko post publish <postId> --yes` |
|
|
43
43
|
| "delete / 撤下 that post (it went out wrong)" | shell → `amiko post list` (copy the id) → confirm which one → `amiko post delete <postId> --yes` |
|
|
44
44
|
| "search memory for X" | shell → `amiko memory search "X"` |
|
|
45
45
|
| "share the group's invite link" (asked by an admin) | shell → `amiko chat group info "<group>"` (confirm they're admin) → `amiko chat group invite "<group>"` |
|
|
@@ -73,7 +73,7 @@ Discover everything via `amiko --help` (or `amiko <group> --help` / `amiko <grou
|
|
|
73
73
|
|
|
74
74
|
## Critical Rules
|
|
75
75
|
|
|
76
|
-
1. **Every paid / value-moving command is hard-gated on `--yes` in a non-interactive shell.** The CLI refuses to run `search *`, `markets *`, `create *`, `card mint`, `credits topup`, `wallets swap send`, `wallets bridge send`, `wallets transfer` unless `--yes` is passed. The refusal prints the cost and the re-run command. **Quote the cost, get explicit approval, THEN append `--yes`.** For `create *` there is a step before that — propose the model and settings and get the owner's sign-off on the *plan* first; see **Proposing, then quoting, before you generate**. The same `--yes` gate also covers **free outward social actions** — `chat send`, `chat pin` (the whole chat sees a pinned-message announcement), `chat group create`, `chat group add` (real people see them
|
|
76
|
+
1. **Every paid / value-moving command is hard-gated on `--yes` in a non-interactive shell.** The CLI refuses to run `search *`, `markets *`, `create *`, `card mint`, `credits topup`, `wallets swap send`, `wallets bridge send`, `wallets transfer` unless `--yes` is passed. The refusal prints the cost and the re-run command. **Quote the cost, get explicit approval, THEN append `--yes`.** For `create *` there is a step before that — propose the model and settings and get the owner's sign-off on the *plan* first; see **Proposing, then quoting, before you generate**. The same `--yes` gate also covers **free outward social actions** — `chat send`, `chat pin` (the whole chat sees a pinned-message announcement), `chat group create`, `chat group add`, `friends add` / `friends accept` (real people see them — a friended user is notified — so get the owner's explicit approval for the action itself) — and **destructive ops** like `chat unpin` (removes the pin for everyone), `chat mark-read --all` (irreversibly marks every conversation read — senders see read ticks), `chat group remove/leave/rename/promote/mention-all`, `chat lists create/rename/add/remove/delete` (private to the owner, but they reshape the owner's chat UI), `friends nickname set/remove` (private to the owner, but it changes how that friend is displayed everywhere in the owner's apps), `twin update --public`, `drive delete`, `drive share` / `drive folder share` (exposes the file — or the folder's ENTIRE subtree — to anyone with the link), `friends remove`, `friends reports request`, `avatar update`, `voice reset`, `review reject`. **For these free actions never mention cost, never say "the cost is 0", and never call it a paid operation** — ask for plain confirmation of the action itself (e.g. "Send "hi" to Mars — go ahead?").
|
|
77
77
|
2. **After every paid command, report the remaining balance.** The CLI prints a `Balance: N credits` line — include that figure in your reply.
|
|
78
78
|
3. **Never retry a failed command.** Report and stop. Every paid call costs tokens even on failure.
|
|
79
79
|
4. **Auth is automatic.** Never suggest `amiko login` / `amiko connect`. Run from the agent's workspace folder; if anything looks off, `amiko accounts` shows the resolved `userId` / `twinId`.
|
|
@@ -352,7 +352,9 @@ Two different relationships — pick the one the owner actually asked for:
|
|
|
352
352
|
|
|
353
353
|
**"Notes" and "posts" are the same thing.** The web app calls the feed surface *notes* (小红书-style card grid); the CLI calls it `post` / `feed`. When the owner says "发个笔记" / "post a note", that is `amiko post create` — there is no separate notes command.
|
|
354
354
|
|
|
355
|
-
> **⚠️ Draft-first, publish on the owner's word.** Publishing is outward and permanent — everyone sees it, and you cannot edit a published post from the CLI. Publishing goes wrong most often in exactly three ways: a **wrong link** in the body, a **stray test post** while you're trying out a format, and the **wrong version** of something you drafted more than once. So
|
|
355
|
+
> **⚠️ Draft-first, publish on the owner's word.** Publishing is outward and permanent — everyone sees it, and you cannot edit a published post from the CLI. Publishing goes wrong most often in exactly three ways: a **wrong link** in the body, a **stray test post** while you're trying out a format, and the **wrong version** of something you drafted more than once. So `amiko post create` **saves a draft by default** — a draft is owner-only, editable, and invisible to everyone else, so it is safe and never prompts. Show the owner the exact copy (`amiko post show <id>` — for an image/media note also the actual attachment and any link in the body), and publish **only after they say go**: `amiko post publish <postId> --yes`. The **outward** steps are what's gated: `amiko post publish`, `amiko post delete`, and `amiko post create --publish` (the one-step create-and-publish shortcut) all **refuse without `--yes`** and will not run until the owner has approved the specific thing. A bare `amiko post create` does NOT need `--yes` — it only makes a draft. `--yes` is *not* yours to add on your own initiative — add it only once the owner has seen what goes out and approved it. When in doubt, draft it and ask; do not publish to "check how it looks."
|
|
356
|
+
|
|
357
|
+
> **⏰ Schedule mode — publishing needs `--publish` (the job is the owner's pre-approval).** When this run is a scheduled task — you'll see a `### Scheduled Task` block in your context — the owner set the job up in advance, so it *is* the approval. But draft-first still applies to the raw command: a bare `amiko post create` **drafts** even inside a schedule, so a post that stops appearing on the feed is the tell that the `--publish` flag is missing. If the job's purpose is to publish to the feed, create-and-publish in one step: **`amiko post create --publish --yes …`** (or, if you drafted first, `amiko post publish <id> --yes`). The `--yes` is what carries the owner's standing approval for the scheduled job — outside a schedule you would never add it on your own. If the job only says "draft" (e.g. a review-before-send flow), keep the bare `amiko post create` and deliver the draft to the owner instead of publishing.
|
|
356
358
|
|
|
357
359
|
**A note is a card, so give it a `--title`.** `--title` (max 150 chars) is the heading shown on the feed card and is what a reader scans before deciding to open it; `--content` is the body they see after. For an image note, the title is doing nearly all the work — always pass one. Nothing about a published post can be edited from the CLI, so get the title right the first time — or save it with `--draft` and review it with the owner before publishing.
|
|
358
360
|
|
|
@@ -364,6 +366,8 @@ Two different relationships — pick the one the owner actually asked for:
|
|
|
364
366
|
|
|
365
367
|
**Attaching documents: `--doc`, not `--media`.** `--doc <pathOrUrl...>` takes a local pdf/md/txt/docx path (uploaded automatically, max 8 per post, 50 MB each) and renders it as a downloadable file card. `--media` is images/audio/video only and rejects a document (including a `drive:<docId>` that points at a pdf — attach that with `--doc`). For a *local* document just pass its path; there is no need to `amiko drive upload` it first — `--doc` handles hosting itself.
|
|
366
368
|
|
|
369
|
+
**Markdown in the body is opt-in: pass `--markdown`.** `--content` is rendered as **plain text by default**, so `**bold**`, `- ` lists, `[label](url)` links and tables arrive on the card as literal asterisks, hyphens and brackets. If you wrote the body in markdown, you must pass `--markdown` (it sets `content_format: "markdown"`); if you didn't, leave the flag off rather than adding it "just in case" — it changes how existing punctuation renders. `@[Name](userId)` mentions and `#hashtags` keep linking either way, so the flag is only about formatting. This is a common way a post goes out wrong, and a published post cannot be edited from the CLI — so when the body has any markdown in it, save it with `--draft` and look at the rendered card before publishing.
|
|
370
|
+
|
|
367
371
|
**@-mentions use `@[Name](userId)`, not `@handle`.** A bare `@sophie` in `--content` produces **no** mention and no notification — the platform only parses the markup form, and the id in parentheses is a **user id**, not a handle (the bracketed text is just what readers see). Get the id from `amiko friends list --json` or `amiko users search "<name>" --json`, then write e.g. `--content "thanks @[Sophie](cm1abc…) for the shots"`. The same rule applies to `amiko post comment`. (Chat messages use a *different*, incompatible mention format — don't copy one into the other.)
|
|
368
372
|
|
|
369
373
|
**Quoting another post: put its URL in the body.** There is no repost/quote flag; paste the canonical `https://platform.heyamiko.com/post/<id>` link into `--content` and the feed renders it as a quote card. Only ever use a URL the CLI printed — never compose one from an id.
|