@easysociable/cli 0.1.7 → 0.1.9

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.
Files changed (93) hide show
  1. package/README.md +29 -9
  2. package/dist/easysociable.js +111 -100
  3. package/dist/easysociable.js.map +1 -1
  4. package/package.json +2 -2
  5. package/scripts/engine/migrate-split-vault.py +75 -0
  6. package/skills/ONBOARDING.md +19 -4
  7. package/skills/easysociable-content/SKILL.md +25 -9
  8. package/content-engine/scripts/fixture.test.mjs +0 -24
  9. package/content-engine/scripts/starter.mjs +0 -58
  10. package/content-engine/scripts/validate.test.mjs +0 -101
  11. package/content-engine/scripts/workbench.mjs +0 -140
  12. package/content-engine/starter/CLAUDE.md +0 -908
  13. package/content-engine/starter/accounts/README.md +0 -9
  14. package/content-engine/starter/accounts/_index.md +0 -31
  15. package/content-engine/starter/accounts/overrides/README.md +0 -3
  16. package/content-engine/starter/engine.json +0 -23
  17. package/content-engine/starter/exports/README.md +0 -28
  18. package/content-engine/starter/hits/README.md +0 -5
  19. package/content-engine/starter/hits/_index.md +0 -30
  20. package/content-engine/starter/hits/_template.md +0 -46
  21. package/content-engine/starter/hits/entries/README.md +0 -3
  22. package/content-engine/starter/inbox/README.md +0 -9
  23. package/content-engine/starter/inbox/_index.md +0 -24
  24. package/content-engine/starter/inbox/entries/README.md +0 -3
  25. package/content-engine/starter/needs/README.md +0 -38
  26. package/content-engine/starter/needs/_index.md +0 -31
  27. package/content-engine/starter/needs/_template.md +0 -24
  28. package/content-engine/starter/needs/entries/README.md +0 -5
  29. package/content-engine/starter/platforms/README.md +0 -19
  30. package/content-engine/starter/platforms/ig.md +0 -69
  31. package/content-engine/starter/platforms/instagram.md +0 -5
  32. package/content-engine/starter/platforms/linkedin.md +0 -72
  33. package/content-engine/starter/platforms/threads.md +0 -69
  34. package/content-engine/starter/platforms/tiktok.md +0 -71
  35. package/content-engine/starter/platforms/x.md +0 -78
  36. package/content-engine/starter/platforms/xiaohongshu.md +0 -19
  37. package/content-engine/starter/products/README.md +0 -38
  38. package/content-engine/starter/products/_index.md +0 -25
  39. package/content-engine/starter/products/_template.md +0 -56
  40. package/content-engine/starter/products/entries/P-001-easysociable.md +0 -150
  41. package/content-engine/starter/products/entries/P-002-content-engine.md +0 -136
  42. package/content-engine/starter/profiles/_index.md +0 -16
  43. package/content-engine/starter/profiles/default/README.md +0 -17
  44. package/content-engine/starter/profiles/default/audience.md +0 -38
  45. package/content-engine/starter/profiles/default/boundaries.md +0 -14
  46. package/content-engine/starter/profiles/default/expression.md +0 -18
  47. package/content-engine/starter/profiles/default/handles.md +0 -8
  48. package/content-engine/starter/profiles/default/keywords.md +0 -31
  49. package/content-engine/starter/profiles/default/lanes.md +0 -12
  50. package/content-engine/starter/profiles/default/pillars.md +0 -33
  51. package/content-engine/starter/profiles/default/stories.md +0 -15
  52. package/content-engine/starter/profiles/default/voice.md +0 -38
  53. package/content-engine/starter/published/_index.md +0 -20
  54. package/content-engine/starter/raw/README.md +0 -4
  55. package/content-engine/starter/raw/_index.md +0 -12
  56. package/content-engine/starter/recommendations/README.md +0 -21
  57. package/content-engine/starter/recommendations/_index.md +0 -21
  58. package/content-engine/starter/recommendations/_template.md +0 -44
  59. package/content-engine/starter/runs/README.md +0 -22
  60. package/content-engine/starter/runs/_index.md +0 -41
  61. package/content-engine/starter/runs/_template/brief.md +0 -76
  62. package/content-engine/starter/runs/_template/draft.md +0 -11
  63. package/content-engine/starter/runs/_template/editor.md +0 -18
  64. package/content-engine/starter/runs/_template/feedback.md +0 -15
  65. package/content-engine/starter/runs/_template/idea.md +0 -27
  66. package/content-engine/starter/runs/_template/pack.md +0 -55
  67. package/content-engine/starter/runs/_template/packet.md +0 -31
  68. package/content-engine/starter/runs/_template/rubric.md +0 -19
  69. package/content-engine/starter/swipe/_index.md +0 -27
  70. package/content-engine/starter/swipe/_template.md +0 -36
  71. package/content-engine/starter/topics/README.md +0 -21
  72. package/content-engine/starter/topics/_index.md +0 -51
  73. package/content-engine/starter/topics/_template-item.md +0 -106
  74. package/content-engine/starter/topics/items/README.md +0 -4
  75. package/content-engine/starter/topics/scoring.md +0 -255
  76. package/content-engine/starter/wiki/README.md +0 -13
  77. package/content-engine/starter/wiki/atoms/_index.md +0 -23
  78. package/content-engine/starter/wiki/atoms/_template.md +0 -31
  79. package/content-engine/starter/wiki/claims/_index.md +0 -26
  80. package/content-engine/starter/wiki/claims/_template.md +0 -38
  81. package/content-engine/starter/workbench/README.md +0 -17
  82. package/content-engine/workbench/__pycache__/build.cpython-310.pyc +0 -0
  83. package/content-engine/workbench/build.py +0 -1467
  84. package/content-engine/workbench/serve.py +0 -53
  85. package/content-engine/workbench/template.html +0 -2686
  86. /package/{content-engine/scripts → scripts/engine}/contracts.mjs +0 -0
  87. /package/{content-engine/scripts → scripts/engine}/export-contracts.mjs +0 -0
  88. /package/{content-engine → scripts/engine}/fixtures/golden-run-en/draft.md +0 -0
  89. /package/{content-engine → scripts/engine}/fixtures/golden-run-en/idea.md +0 -0
  90. /package/{content-engine → scripts/engine}/fixtures/golden-run-en/pack-tiktok.json +0 -0
  91. /package/{content-engine/scripts → scripts/engine}/validate-export.mjs +0 -0
  92. /package/{content-engine/scripts → scripts/engine}/validate-pack.mjs +0 -0
  93. /package/{content-engine/scripts → scripts/engine}/validate-run.mjs +0 -0
@@ -1,9 +0,0 @@
1
- # accounts/
2
-
3
- | File | Role |
4
- |------|------|
5
- | `_index.md` | **Source of truth** for handle → profile, platforms, voice, overrides path |
6
- | `overrides/<handle>.md` | **Optional** — only when account-only deltas exist; path listed in `_index.overrides` |
7
-
8
- Do **not** keep a full `accounts/<handle>.md` for every account.
9
- Pillars/audience bodies stay under `profiles/<id>/`.
@@ -1,31 +0,0 @@
1
- # Accounts index
2
-
3
- Each handle points at a **profile** + platforms.
4
- Full pillars/audience/voice live under `profiles/<id>/` (unless voice overridden).
5
-
6
- Replace the starter handle before the first run.
7
-
8
- | handle | profile_id | voice | platforms | default_platform | overrides | status |
9
- |--------|------------|-------|-----------|------------------|-----------|--------|
10
- | your-handle | default | profile | x | x | | active |
11
-
12
- ## Columns
13
-
14
- | Column | Meaning |
15
- |--------|---------|
16
- | `handle` | Social account id |
17
- | `profile_id` | Row in `profiles/_index.md` |
18
- | `voice` | `profile` → `profiles/<profile_id>/voice.md`; or explicit path to another voice file |
19
- | `platforms` | Platforms this account posts on |
20
- | `default_platform` | Watchlist / catalog filter when unset — **not** used to silent-default 开一单 |
21
- | `overrides` | Empty = none; else path e.g. `accounts/overrides/<handle>.md` |
22
- | `status` | active / planned / retired |
23
-
24
- ## Resolve path (Agent)
25
-
26
- 1. Read this table for the handle (default: first **active** row)
27
- 2. Load `profiles/<profile_id>/pillars.md` + `audience.md`
28
- 3. Voice: if `profile` or empty → `profiles/<profile_id>/voice.md`; else load the path in the cell
29
- 4. If `overrides` non-empty, read that file last
30
- 5. Load `platforms/<platform>.md` for craft (**required** when drafting that platform; map in `platforms/README.md`)
31
- 6. Filter swipe/atoms/claims by platform + profile (`*` = all)
@@ -1,3 +0,0 @@
1
- # Account overrides
2
-
3
- Optional per-handle deltas. Path must be listed in `accounts/_index.md` `overrides` column.
@@ -1,23 +0,0 @@
1
- {
2
- "schemaVersion": "content-engine.v1",
3
- "locale": "en",
4
- "root": "Content Engine",
5
- "paths": {
6
- "runs": "runs",
7
- "exports": "exports",
8
- "topics": "topics",
9
- "needs": "needs",
10
- "hits": "hits",
11
- "products": "products",
12
- "recommendations": "recommendations",
13
- "swipe": "swipe",
14
- "profiles": "profiles",
15
- "inbox": "inbox",
16
- "accounts": "accounts",
17
- "raw": "raw",
18
- "published": "published",
19
- "wiki": "wiki",
20
- "platforms": "platforms",
21
- "workbench": "workbench"
22
- }
23
- }
@@ -1,28 +0,0 @@
1
- # exports/
2
-
3
- **Rendered image packs only** (slideshow skill / Gateway). Not drafts.
4
-
5
- ## Layout
6
-
7
- One run = one platform, so the slug already scopes the platform. Optional `<platform>/` subfolder still OK.
8
-
9
- ```text
10
- exports/
11
- <run-folder-slug>/ # same name as runs/YYYY-MM-DD-slug[-platform]
12
- 01.png
13
- 02.png
14
- …
15
- manifest.json # optional: job_id, deck_hint, page_count
16
- ```
17
-
18
- Example: `exports/2026-08-26-angle-linkedin/01.png`
19
-
20
- ## Pointers
21
-
22
- - `runs/.../pack.md` → `export_path: exports/<slug>/`
23
- - `runs/_index` column `export`: `no` \| `yes`
24
- - **Do not** put binaries in `published/` — only URLs after ship
25
-
26
- ## Until slideshow skill is wired
27
-
28
- Folder may stay empty. Agent must not invent images; pack render status stays `not_requested` / `blocked`.
@@ -1,5 +0,0 @@
1
- # Hits
2
-
3
- Research triage board. Scan → stage here → route to Needs or Library (swipe/atom). Not a Topic queue.
4
-
5
- See engine `CLAUDE.md` **§ Hits**.
@@ -1,30 +0,0 @@
1
- # Hits index (research triage)
2
-
3
- **Role:** Staging board for research hits. Route to Needs or Library — **not** a Topic queue.
4
-
5
- Newest on top. Scan may write rows here (include source-post heat). Routing out still needs explicit confirm.
6
-
7
- | id | date | profile | platform | keyword_id | source | hit_kind | signal | status | excerpt | src_likes | src_replies | src_bookmarks | src_views | engagement_at | file |
8
- |----|------|---------|----------|------------|--------|----------|--------|--------|---------|-----------|-------------|---------------|-----------|---------------|------|
9
-
10
- ## Status
11
-
12
- | status | Meaning |
13
- |--------|---------|
14
- | `triage` | Waiting for route |
15
- | `routed_need` | Written to `needs/` |
16
- | `routed_library` | Capture + library ingest path |
17
- | `discarded` | Rejected |
18
-
19
- ## Columns
20
-
21
- | Column | Meaning |
22
- |--------|---------|
23
- | `keyword_id` | Primary recipe `K-xx` |
24
- | `src_*` | Source-post heat snapshot (not our results) |
25
-
26
- ## Agent rules
27
-
28
- - Exits: **need** \| **library** \| **discard**. Hits are not Topic inputs.
29
- - On scan: write `keyword_id` + engagement snapshot when known. Do not invent metrics.
30
- - Author hooks ≠ Needs. Zero starter rows — do not invent hits.
@@ -1,46 +0,0 @@
1
- ---
2
- id: H-YYYYMMDD-XX
3
- date: YYYY-MM-DD
4
- profile: default
5
- platform: x
6
- status: triage
7
- hit_kind: author_post | comment | thread
8
- signal: demand_language | structure | foil | mixed | noise
9
- source_keyword:
10
- keyword_id: K-XX
11
- source_handle:
12
- source_url:
13
- src_likes:
14
- src_replies:
15
- src_bookmarks:
16
- src_views:
17
- engagement_at:
18
- ---
19
-
20
- # H-YYYYMMDD-XX
21
-
22
- ## Excerpt
23
-
24
- > verbatim excerpt — do not rewrite
25
-
26
- ## Context
27
-
28
- Where this came from and why it was kept for triage.
29
-
30
- ## Engagement snapshot
31
-
32
- - likes:
33
- - replies:
34
- - bookmarks:
35
- - views:
36
- - snapshot_at:
37
-
38
- ## Suggested route
39
-
40
- need | library | discard | undecided
41
-
42
- ## Route log
43
-
44
- | date | action | result_ids |
45
- |------|--------|------------|
46
- | | | |
@@ -1,3 +0,0 @@
1
- # Hit entries
2
-
3
- One file per `H-YYYYMMDD-XX`. Create from `../_template.md`.
@@ -1,9 +0,0 @@
1
- # inbox/
2
-
3
- | Path | Role |
4
- |------|------|
5
- | `_index.md` | Capture registry (source of truth for list/status) |
6
- | `entries/C-YYYYMMDD-XX.md` | Working notes for one capture |
7
- | *(no capture.md)* | Deprecated stream file removed |
8
-
9
- Authoritative originals → `../raw/`.
@@ -1,24 +0,0 @@
1
- # Inbox index
2
-
3
- Registry of captures. **Source of truth for capture lifecycle**.
4
-
5
- Newest rows on top.
6
-
7
- | id | date | type | one_liner | platforms | profile | entry | raw | library | status |
8
- |----|------|------|-----------|-----------|---------|-------|-----|---------|--------|
9
-
10
- ## Columns
11
-
12
- | Column | Meaning |
13
- |--------|---------|
14
- | `entry` | Working notes file under `inbox/entries/` |
15
- | `raw` | Authoritative source file if any; else empty |
16
- | `library` | `none` or e.g. `swipe:S1` / `atom:A-…` / `claim:C-…` after user-approved ingest |
17
- | `profile` | Which content profile this capture is for |
18
- | `status` | `captured` \| `ingested` \| `archived` |
19
-
20
- ## Agent rules
21
-
22
- - Every capture: new row + new `entries/<id>.md`
23
- - raw file only when URL / structure / media / user says important → also row in `raw/_index.md`
24
- - Never silent-write swipe/atoms/claims; only update `library` after approval
@@ -1,3 +0,0 @@
1
- # inbox/entries/
2
-
3
- One file per capture (`C-YYYYMMDD-XX.md`). Registry: `../_index.md`.
@@ -1,38 +0,0 @@
1
- # needs/
2
-
3
- First-class **user-needs library**. Not an inbox type. Inbox stays structure / link / insight.
4
-
5
- | Path | Role |
6
- |------|------|
7
- | `_index.md` | Quote registry (source of truth for list/status) |
8
- | `entries/N-YYYYMMDD-XX.md` | One need: verbatim quote + sightings + optional gloss |
9
- | `_template.md` | Entry shape |
10
-
11
- ## Status machine (only these words)
12
-
13
- ```text
14
- captured → just written, or still captured after a synonym merge (frequency ≥ 1)
15
- promoted → and only when a T- exists whose need_ids contain this N-; topic_ids lists that T-
16
- retired → user discarded
17
- ```
18
-
19
- Do **not** use `clustered`. Merge is not a status.
20
-
21
- ## Do not
22
-
23
- - Invent quotes or FAQ template sentences
24
- - Treat a watchlist hook / viral title as a need
25
- - Put `N-` into a topic `capture_id` (`capture_id` is inbox `C-…` only)
26
- - Hosted clustering
27
-
28
- ## Quote shape (not product copy, not index rows)
29
-
30
- These lines are the **shape** of a creator's audience talking. They are **not** EasySociable features and must **not** be seeded as rows:
31
-
32
- - 我不知道自己适合做什么 AI 自媒体方向
33
- - 我每天用 AI 写稿,还是断更
34
- - 我账号有流量,但为什么没人咨询
35
- - 我想接广告,要多少粉丝才可以
36
- - 我不会出镜,能不能先做图文
37
-
38
- When a quote is reused as published copy, redact names / DMs / student details.
@@ -1,31 +0,0 @@
1
- # Needs index
2
-
3
- Registry of **audience quotes**. Source of truth for need lifecycle.
4
-
5
- Newest rows on top. **Zero starter rows** — do not invent quotes.
6
-
7
- | id | date | profile | source_type | quote | speaker | frequency | status | topic_ids | file |
8
- |----|------|---------|-------------|-------|---------|-----------|--------|-----------|------|
9
-
10
- ## Columns
11
-
12
- | Column | Meaning |
13
- |--------|---------|
14
- | `id` | `N-YYYYMMDD-XX`, increment per day (same shape as `C-` / `D-` / `T-`) |
15
- | `date` | First sighting date |
16
- | `profile` | Default current `profile_id` |
17
- | `source_type` | `comment` \| `dm` \| `consult` \| `faq` \| `student` \| `other` |
18
- | `quote` | **Verbatim.** Never put a gloss in this cell |
19
- | `speaker` | Optional; anonymous → `anon`. Do not invent names |
20
- | `frequency` | Integer, default 1. Same-meaning merge: `+1` on this row, append a sighting — do **not** create a second row |
21
- | `status` | `captured` \| `promoted` \| `retired` (**never** `clustered`) |
22
- | `topic_ids` | Cited `T-…`, comma-separated. Non-empty **iff** status=`promoted` |
23
- | `file` | `needs/entries/N-….md` |
24
-
25
- ## Agent rules
26
-
27
- - Every need: new row + new `entries/<id>.md`
28
- - Merge is not a new status. After a user-approved synonym merge, keep `captured`, bump `frequency`, append sighting
29
- - Do not mark `promoted` without a `T-` whose `need_ids` contain this `N-`
30
- - Scan-for-topics input set: `status=captured` (`topic_ids` empty). Max 5 `produce`
31
- - Quotes may include DMs / student info. Keep local. Redact PII if a quote is used in published copy
@@ -1,24 +0,0 @@
1
- ---
2
- id: N-YYYYMMDD-XX
3
- date: YYYY-MM-DD
4
- profile: default
5
- source_type: comment | dm | consult | faq | student | other
6
- frequency: 1
7
- status: captured
8
- ---
9
-
10
- # N-… — five-character-or-less need label (Agent-coined, not the quote)
11
-
12
- ## Quote
13
- > (verbatim, unedited)
14
-
15
- ## Sightings
16
- | date | source_type | where |
17
- |------|-------------|-------|
18
- | YYYY-MM-DD | comment | url or `pasted` |
19
-
20
- ## Our gloss(optional, separate from the quote)
21
- One line: what they are hiring us to solve.
22
-
23
- ## Status
24
- captured
@@ -1,5 +0,0 @@
1
- # needs/entries/
2
-
3
- One file per need (`N-YYYYMMDD-XX.md`). Registry: `../_index.md`.
4
-
5
- Do not pre-seed FAQ rows.
@@ -1,19 +0,0 @@
1
- # Platforms (craft only)
2
-
3
- One file per network. **Required** whenever drafting that platform (especially § Open a run: brief → draft → editor → rubric → pack).
4
-
5
- Loaded as `platforms/<platform>.md` after account → profile resolve. Map:
6
-
7
- | Platform id | File |
8
- |-------------|------|
9
- | `x` | `x.md` |
10
- | `linkedin` | `linkedin.md` |
11
- | `ig` | `ig.md` |
12
- | `instagram` | `ig.md` (canonical; `instagram.md` is redirect stub) |
13
- | `tiktok` | `tiktok.md` |
14
- | `threads` | `threads.md` |
15
- | `xiaohongshu` / `xhs` | `xiaohongshu.md` |
16
-
17
- **Not here:** ICP, pillars, voice → `profiles/`. Pixels → EasySociable `PLATFORM_SPECS`.
18
- **Rule:** same Topic, different platforms → **N runs**, each **re-reads** its craft file (no paste-across).
19
- **Missing file:** do not invent craft; stop and tell the user.
@@ -1,69 +0,0 @@
1
- # Platform: Instagram
2
-
3
- **Scope:** How to *write* for Instagram — caption, carousel norms, job-of-format.
4
- **Not in this file:** Who you are, product story, pillars, voice, audience.
5
- **Pixels / canvas:** EasySociable `PLATFORM_SPECS` — feed carousel default **4:5 @ 1080×1350** (or `1:1` if user wants max compatibility).
6
-
7
- Agent: platform id in this vault is often `ig` (also accept `instagram` → this file).
8
-
9
- ---
10
-
11
- ## Defaults
12
-
13
- - Language: English (unless user asks otherwise)
14
- - Default unit for easysociable-builder: **feed carousel** (save/depth job) — **not** Reels unless the user explicitly asks for Reels
15
- - Assume thumb stop on **cover slide**; caption supports the cover, does not replace it
16
- - Pack: **yes** for carousel runs
17
-
18
- ## Length & shape
19
-
20
- | Form | Guidance |
21
- |------|----------|
22
- | Carousel | **7–9 slides** common; keep one aspect for all slides. One tip/step per slide. Big type; few words. |
23
- | Caption | 1–3 short lines: hook + what they’ll get by swiping. Optional soft CTA (“Save for your next brand kit”). |
24
- | Reels | Only if user asks. Different job: discovery/reach. Do not silently turn a carousel brief into a Reel script. |
25
- | Single image | Rare for system topics; prefer carousel when teaching steps. |
26
-
27
- ## Hooks (mechanics only)
28
-
29
- Cover slide should:
30
-
31
- - Stop the scroll with a **bold, specific promise or mistake**
32
- - Signal “worth saving” (checklist, steps, before/after), not “watch me talk”
33
-
34
- Caption line 1 mirrors the cover; no LinkedIn-length essay above the fold.
35
-
36
- ## Craft rules
37
-
38
- 1. **Visual first.** If the slides don’t work with sound off and skim-reading, rewrite.
39
- 2. Optimize carousel for **saves** and return visits — reference content, not dunks.
40
- 3. One idea per slide; max clarity over clever wordplay.
41
- 4. Keep brand kit / template consistency visible (this is where EasySociable proof belongs).
42
- 5. CTA: save / share to a teammate / soft follow — not comment-gate lead magnets.
43
- 6. Hashtags: light or none; never a block of 30.
44
- 7. Do not paste X thread text onto slides.
45
-
46
- ## Anti-slop (Instagram)
47
-
48
- Do **not** default to:
49
-
50
- - Wall-of-text slides
51
- - Engagement bait (“Comment SAVE”) as the whole strategy
52
- - Faceless “viral in 60 seconds” energy as the brand voice
53
- - Using Reels trends/audio as required for every post
54
- - Treating IG as a dump of LinkedIn PDF screenshots with tiny type
55
-
56
- ## Quality self-check
57
-
58
- - [ ] Cover stops a visual scroll without reading the caption?
59
- - [ ] Would someone save this to reuse next week?
60
- - [ ] Words per slide low enough for mobile?
61
- - [ ] Same aspect across the deck?
62
- - [ ] Job clear: save/authority (carousel) vs reach (Reel) — and format matches?
63
- - [ ] No invented metrics; EasySociable only if earned?
64
-
65
- ## Out of scope here
66
-
67
- - Reels editing / trending audio tactics
68
- - Pixel export → EasySociable skills + `PLATFORM_SPECS`
69
- - Other networks → sibling `platforms/*.md`
@@ -1,5 +0,0 @@
1
- # Platform: Instagram (alias)
2
-
3
- Vault platform id is often **`ig`**. Product/catalog enum may say **`instagram`**.
4
-
5
- **→ Follow [`ig.md`](./ig.md) in full.** Do not maintain a second craft body here.
@@ -1,72 +0,0 @@
1
- # Platform: LinkedIn
2
-
3
- **Scope:** How to *write* for LinkedIn — length, rhythm, quality bars, document/carousel norms.
4
- **Not in this file:** Who you are, product story, pillars, voice, audience.
5
- Those live under `profiles/<id>/` (via account → profile resolve).
6
- **Pixels / canvas:** EasySociable `PLATFORM_SPECS` (LinkedIn page templates; PDF document pages often `4:5` or `1:1`).
7
-
8
- Agent: before drafting any LinkedIn post, read this file for craft.
9
-
10
- ---
11
-
12
- ## Defaults
13
-
14
- - Language: English (unless user asks otherwise)
15
- - Default unit: **document carousel (PDF pages) + short post text** — not a pure text hot take
16
- - Assume professional feed skim: **cover slide + first line of caption** do most of the work
17
- - Pack: **almost always yes** for easysociable-builder runs (visual production proof)
18
-
19
- ## Length & shape
20
-
21
- | Form | Guidance |
22
- |------|----------|
23
- | Caption | Hook in line 1 (above the fold). 3–8 short lines total. One clear promise. Put outbound links in the **first comment**, not the post body when possible. |
24
- | Document carousel | **7–10 pages** sweet spot (acceptable band ~5–15). One idea per page. Headlines scannable alone. Body under ~30 words/page when present. |
25
- | Aspect (pack) | Prefer **4:5 (1080×1350)** mobile-first, or **1:1 (1080×1080)** for safe desktop+mobile. Same size every page. |
26
- | Text-only | Allowed as a light mid-week post; do not make it the default for system/framework topics. |
27
-
28
- ## Hooks (mechanics only)
29
-
30
- Cover slide **and** caption line 1 should each do one of:
31
-
32
- - Name a **specific agency / operator pain** (revisions, brand feedback, blank prompt)
33
- - Promise a **numbered framework** or checklist the reader can steal
34
- - Lead with a **concrete claim or contrast** (not “My thoughts on AI”)
35
-
36
- Avoid vague covers: “Leadership lessons”, “What I learned this week”.
37
-
38
- ## Craft rules
39
-
40
- 1. Write like a **saveable mini-deck**, not like an X dunk.
41
- 2. One idea per slide; if it needs a paragraph, split across two slides.
42
- 3. Prefer frameworks, steps, before/after production loops, cost-of-revision angles.
43
- 4. Soft CTA on the last slide (invite / question / “save for your next client kickoff”) — not “Buy now”.
44
- 5. EasySociable only as **visual production layer** proof after the framework lands.
45
- 6. Tone: calm, specific, peer-to-peer operator — not hype, not meme war.
46
- 7. Hashtags: 0–3 max, optional; never a wall.
47
-
48
- ## Anti-slop (LinkedIn)
49
-
50
- Do **not** default to:
51
-
52
- - Inspiration-poster fluff with no procedure
53
- - Hard sell on slide 1 or slide N
54
- - Crypto flex / “I made $X in 30 days” unless user supplies a real number for that draft
55
- - Pasting an X-style contrarian one-liner as the whole post
56
- - External link in the post body as the main content
57
- - Dense slides that require pinch-zoom
58
-
59
- ## Quality self-check
60
-
61
- - [ ] Cover works as a standalone headline in under 3 seconds?
62
- - [ ] Would an agency lead save this for a teammate?
63
- - [ ] Each page one idea; captions not essays?
64
- - [ ] Soft CTA, not a pitch deck close?
65
- - [ ] Matches pillars; no invented metrics/customers?
66
- - [ ] Pack page count and aspect sensible for LI document post?
67
-
68
- ## Out of scope here
69
-
70
- - Exact render pipeline → run `pack.md` + EasySociable slideshow/template skills
71
- - Profile ICP emphasis → `profiles/.../audience.md`
72
- - Other networks → sibling `platforms/*.md`
@@ -1,69 +0,0 @@
1
- # Platform: Threads
2
-
3
- **Scope:** How to *write* for Meta Threads — length, tone, conversation norms.
4
- **Not in this file:** Who you are, product story, pillars, voice, audience.
5
- **Pixels / canvas:** Optional; if images, follow EasySociable `PLATFORM_SPECS` for **threads** (often shared with IG **4:5 @ 1080×1350**).
6
-
7
- Agent: before drafting any Threads post, read this file for craft.
8
-
9
- ---
10
-
11
- ## Defaults
12
-
13
- - Language: English (unless user asks otherwise)
14
- - Default unit: **1 conversational short post** (≤500 characters available — use only what you need)
15
- - Assume calmer, Instagram-adjacent feed: **invitation > combat**
16
- - Pack: **optional**. Prefer text (+ one image) unless the user wants a mini carousel
17
- - Role for easysociable-builder: **secondary** surface — warm process / questions; not the main agency acquisition channel (X / LinkedIn lead)
18
-
19
- ## Length & shape
20
-
21
- | Form | Guidance |
22
- |------|----------|
23
- | Single post | 1–5 short sentences. Room for one nuance line X might cut. End with a **real question** when you want replies. |
24
- | Reply | Add substance or a precise follow-up. Same ban on empty praise as X. |
25
- | Media | Images help; don’t rely on a 10-slide deck as the default Threads unit. |
26
- | Cross-post from X | **Rewrite.** Do not paste X dunks unchanged. |
27
-
28
- ## Hooks (mechanics only)
29
-
30
- A strong open usually:
31
-
32
- - Shares a **process observation** (“We stopped letting the agent pick templates silently…”)
33
- - Offers a **small, stealable rule**
34
- - Asks an **answerable** ICP question
35
-
36
- Avoid opening with maximum contrarian heat meant for X ratio.
37
-
38
- ## Craft rules
39
-
40
- 1. Tone: warmer, more human, less debate-club than X.
41
- 2. Optimize for **replies and positive conversation**, not quote-dunk chains.
42
- 3. Good fits: behind-the-scenes, experiment notes, “what’s your bottleneck?”, light system tips.
43
- 4. Bad fits as primary: hard category warfare, political newsjacking, long frameworks (send those to LinkedIn).
44
- 5. EasySociable: mention lightly as visual production layer when relevant — no install sermon.
45
- 6. One topic tag max if used; no hashtag walls.
46
-
47
- ## Anti-slop (Threads)
48
-
49
- Do **not** default to:
50
-
51
- - Raw paste of an X banger
52
- - Corporate LinkedIn voice
53
- - Engagement bait with no point
54
- - Fake vulnerability / engagement-pod energy
55
- - Treating Threads as the only growth channel for AI-native agencies
56
-
57
- ## Quality self-check
58
-
59
- - [ ] Would this feel natural in a calm group chat, not a town-hall fight?
60
- - [ ] If there’s a question, can a busy operator answer in one sentence?
61
- - [ ] Rewritten for Threads — not an X clone?
62
- - [ ] Media optional and not a tiny-type PDF dump?
63
- - [ ] No invented metrics?
64
-
65
- ## Out of scope here
66
-
67
- - Meta ads / Instagram cross-post mechanics
68
- - Full carousel systems → prefer `ig.md` / `linkedin.md` / `tiktok.md`
69
- - Other networks → sibling `platforms/*.md`
@@ -1,71 +0,0 @@
1
- # Platform: TikTok
2
-
3
- **Scope:** How to *write* for TikTok — especially **Photo Mode / slideshow** craft.
4
- **Not in this file:** Who you are, product story, pillars, voice, audience.
5
- **Pixels / canvas:** EasySociable `PLATFORM_SPECS` — default **9:16 @ 1080×1920** for Photo Mode; keep text out of UI chrome safe zones.
6
-
7
- Agent: before drafting any TikTok slideshow/post, read this file for craft.
8
-
9
- ---
10
-
11
- ## Defaults
12
-
13
- - Language: English (unless user asks otherwise)
14
- - Default unit for easysociable-builder: **photo slideshow (carousel)** competing in For You next to video
15
- - Assume: if slide 1 fails, slides 2–N never exist
16
- - Pack: **yes**; design for **completion / swipe-through**, not desktop reading
17
-
18
- ## Length & shape
19
-
20
- | Form | Guidance |
21
- |------|----------|
22
- | Slideshow | **6–10 slides** sweet spot (platform allows more; completion pressure rises). One line per slide when possible. |
23
- | Slide 1 | Hook only — open loop, specific pain, or numbered promise. Not a course title. |
24
- | Middle | One tip / mistake / step each. Max ~15 words/slide; hook slide often ≤10 words, huge type. |
25
- | Last | Explicit save/share CTA is OK on TikTok (more direct than LinkedIn). |
26
- | On-video / talking head | Only if user asks; not the default for EasySociable PNG runs. |
27
-
28
- ## Hooks (mechanics only)
29
-
30
- Slide 1 usually does one of:
31
-
32
- - Specific cringe / cost (“You redesign the carousel every Wednesday”)
33
- - Numbered open loop (“7 production leaks agencies ignore”)
34
- - Sharp contrast / “stop doing X”
35
-
36
- Avoid textbook titles: “Content Systems Explained”.
37
-
38
- ## Craft rules
39
-
40
- 1. Write for a **video-trained thumb**: bigger type, fewer words, higher contrast than IG if needed.
41
- 2. Each slide must **earn the next swipe**; cut any slide that only restates.
42
- 3. Prefer listicle / mistakes / stack / steps formats.
43
- 4. Tone: spoken, direct, slightly punchy — not LinkedIn deck voice.
44
- 5. Agency worldview is OK if compressed into swipeable bites; deep theory → X or LinkedIn instead.
45
- 6. EasySociable as quick proof of visual production — not a feature tour.
46
- 7. Same aspect every slide; default 9:16 unless user overrides.
47
-
48
- ## Anti-slop (TikTok)
49
-
50
- Do **not** default to:
51
-
52
- - Soft corporate captions on slide 1
53
- - Dense paragraphs or LI-style frameworks with 40 words/slide
54
- - “Follow for part 2” without delivering value in-post
55
- - Watermarked or letterboxed 4:5 content that looks like a wrong-platform export
56
- - Comment-gate playbooks as the primary CTA for this brand
57
-
58
- ## Quality self-check
59
-
60
- - [ ] Slide 1 works as a For You interrupt?
61
- - [ ] Would a stranger swipe to slide 3 without loving you already?
62
- - [ ] Word count low; type large; chrome-safe?
63
- - [ ] Completion-friendly length (not a 20-slide essay)?
64
- - [ ] 9:16 (or user-agreed alt) consistent across pack?
65
- - [ ] No invented metrics?
66
-
67
- ## Out of scope here
68
-
69
- - TikTok Shop / live / music licensing
70
- - Native video editing
71
- - Exact render → EasySociable slideshow skill + `PLATFORM_SPECS`