Fountain
Fountain Labs Ltd v1.22.0
Publisher description
From the marketplace listing
Fountain helps podcast teams find clip moments, prepare social posts, manage podcast episodes, and review performance. Users can search public podcasts and transcripts, manage project preferences, upload media, publish or schedule content, and send report emails.
Language: English · Automatically detected from descriptions.
Files & skills
File archives
Skill instructions
fountain-clip-finder6 KB
--- name: fountain-clip-finder description: Find the strongest clip moments in a show, write the post copy, and open a draft post for each channel. --- ## Overview This skill searches a show's transcripts for the moments that could become a strong clip. Four modules process the moments in order. Module **discovery** scores the moments. Module **media** resolves the file that each moment is cut from. Module **boundaries** sets the span, and module **copy** writes the words around it. For a video that Fountain does not hold, module **external-source** replaces the search. Each clip becomes a draft post, so the user decides which clips are posted. ## Input One of these: - A topic, or the terms to search for. - A kind of moment, for example funny, angry, or surprising. - An episode, with an optional quote or approximate time. - A person, to find the moments of one guest or host. - One or more videos that the show never published as an episode, each a URL or a file on this machine, with an optional topic or quote. Optional: - `clip_count` - the maximum number of clips to return. The show's archive may hold fewer. - `min_duration_seconds` and `max_duration_seconds` - the length range of a clip. - A link that every post MUST contain, for example the landing page of a campaign. - Trend context with its sources, when the clip must answer a news story. This skill does not search the news, so the caller gives the sources. ## Output One draft `SocialPost` for each clip on each connected `SocialChannel`. The posts are ranked by the clip score of module **boundaries**. A post targets one channel, and the platform of that channel sets the style of the text. Thus one clip on two channels gives two posts, each with its own text. This skill MUST write `source` when `media` is a URL. A later renderer cuts the clip from `source`. Module **copy** writes `meta.label`, `content.title`, `content.text`, and `context`. Module **media** and module **boundaries** build `source` between them. A Fountain episode source names its episode and show in `ids`. A YouTube match for that episode adds its YouTube video id. A standalone YouTube source names only its YouTube video id. Another external URL uses empty `ids`. Module **external-source** builds the last two forms. A raw local path is not a URL, so its post holds no `source`. Thus the render MUST happen in the same session. The posts with `source` then wait in the Social API. This skill does not start the next stage. Skill **fountain-clip-producer** works from `source` and attaches the video to the post. Skill **fountain-clip-producer** receives a raw local source directly in the same session. ## Housekeeping You MUST read HOUSEKEEPING.md if you haven't already. ## Requirements - Fountain API. - A web search tool, for episodes that have no video on Fountain. - Python 3.11 or later, yt-dlp for a video URL, and ffmpeg with whisper for a local video that has no subtitle file. Module **external-source** needs all three. A machine without them can run every other input. - Skill **fountain-onboarding**. ## Process Make the calls that do not need each other's answers at the same time. A run loses time between its actions, and not inside them. 1. Resolve the show, and list the connected `SocialChannel` with the Social API. Run skill **fountain-onboarding** when the show has no channel. A clip becomes a draft post on a channel, and there is no other place to keep the work. Continue only when the user asks for the clips without a channel. 2. Run module **discovery** to search the transcripts, score each moment, and drop the weak ones. For a video that is not an episode, run module **external-source** first. Give its segments to module **discovery** as the passages to score. 3. Run module **media** to resolve the file that each moment is cut from, and the clock of that file. Drop a moment when its episode has no video to cut from. Skip this module for a video that is not an episode, because module **external-source** already named the file. 4. Run module **boundaries** to make each moment into a clip, and to drop the clips that fail a gate. 5. Run module **copy** to write `meta.label`, `content.title`, `content.text`, and `context`. 6. Create one draft `SocialPost` for each clip on each channel with the Social API. Give it the copy, and the complete `SocialPostMediaSource` when `media` is a URL. The clips do not depend on each other, so create them in batches of 4 to 6 at the same time. 7. Present each clip as one clip card of `assets/clip-card.md`, in rank order. End with the drafts link of the card. The card shows the score, the reason, and each flag, so do not put them in a summary above the cards. Give each raw local source to the renderer in this session. Say that these posts cannot be rendered from a later session. ## Additional notes Each module removes work from the next one, so you MUST run them in the order above. Inside a module, the order is less strict. Where a step repeats one API call for many items, the items do not depend on each other. Ask for them together, and not one at a time. A clip from a video that is not an episode is about something that the audience cannot find on the feed. Thus the words contain the link that the request gives, and the user approves the words and the link together. An episode that is not published yet is the other case. The clip is posted before the episode is published. Thus the words MUST NOT say that the audience can hear the rest of the episode today. `ts_start` and `ts_end` are always in the clock of the transcript. A YouTube cut of an episode runs to its own clock, and skill **fountain-clip-producer** translates the span into it at render time. A video that is not an episode is its own transcript. Thus the two clocks are the same, and nothing translates the span. This skill never makes a video file. It finds the moment, sets the span, and writes the words, and `source` holds all of that. Give a few strong clips, and not many weak clips. Say clearly when the show holds no strong clip.
Referenced files: 8
fountain-clip-producer11.1 KB
---
name: fountain-clip-producer
description: Render a clip post into a finished, platform-ready video with framing, captions, and overlays.
---
## Overview
This skill turns the clip that a post carries into a video file.
It does not choose the moment or the span.
The caller chooses both before this skill runs.
Module **media** cuts the landscape master.
Every module after it works from that one file.
The other modules crop the picture and put the captions and the layers on it.
The skill delivers nothing until one report passes.
## Input
- The `SocialPostMediaSource` of a `SocialPost`, which names the file and the span.
The file can have no video.
Most files of a podcast catalogue have no video.
Empty `ids` and a YouTube video id both name sources that Fountain does not hold as episodes.
- Or an external source for a raw local video, which carries the media path and span for this session.
Its post carries no `source`, because a raw local path is not a valid `media` URL.
- The word timings of that span, which this skill makes from the clip's own audio.
Module **shots** also needs the speaker of each word.
No input supplies it.
- A delivery tier, which the words of the request imply.
- Or a queue run.
Module **queue** reads the drafts that wait for media, and derives the inputs above from them.
Optional:
- A target shape, which is vertical, square, or landscape.
- The name of a caption preset, or the text of an overlay.
## Output
- The finished work: a landscape master, and one export for each shape that the request asks for.
The master is finished work, and not one of the workings.
The user keeps it and cuts from it again.
- A `SocialPostUpload` on `content.uploads` of the post, unless the user asked you not to attach it.
- Workings: a clip manifest, a crop plan, a caption plan, an overlay plan, a QA report, and a removal
report when module **trims** cut the clip.
## Housekeeping
You MUST read HOUSEKEEPING.md if you haven't already.
## Requirements
- Fountain API.
- Python 3.11 or later.
- OpenCV 4.8 or later, importable from that same Python, for the face detection of module **framing**.
Its model, and the fonts that the presets name, ship in `assets`, so no machine installs either.
- ffmpeg and ffprobe, built with libass, drawtext, fontconfig and whisper.
Without them, the skill cannot burn a caption or time a word.
A stock build often has none of them.
On macOS, the Homebrew `ffmpeg-full` formula has them.
- A whisper.cpp model file.
The whisper filter takes the path of this file, and does nothing without it.
This skill looks first for `ggml-base.en.bin` in `~/.cache/whisper`.
That file is 141 MB, so the skill does not ship it.
The machine installs it one time.
- ImageMagick, to measure the width of caption text.
- yt-dlp, for a source that ffmpeg cannot seek directly.
Keep it current, because YouTube changes what a client must send.
A build a few weeks old gets a 403 error on every download, while the captions still download.
- A web search tool, and a way to read a page, for the reference sources of module **brand**.
- Skill **fountain-onboarding**, which installs a tool that module **preflight** finds missing.
## Process
1. Read the delivery tier from the request.
Do the least work that the tier asks for.
2. Run module **preflight** to check the machine before the first render.
One report serves every clip of a run, because the machine does not change between clips.
3. Run module **media** to cut the landscape master from `media`, between `ts_start` and `ts_end`.
Cut all the clips of the run together, then transcribe them all together.
No clip waits for another one.
Then transcribe the master with whisper to get the word timings of the clip.
Rebase the timings so that the first word starts at zero.
Use the binary and the model that module **preflight** names, with `max_len=1`.
Put `model=` last in the filter string, or the filter loses the option after it.
Write the output as SRT, and give it to `scripts/align-word-timings.py`.
Give the script the `transcript` of the source as the reference, and the clip's start in that SRT as
the offset.
The script keeps the words of the transcript and the timings of whisper.
So a name or a number that whisper misheard is spelled correctly.
The script writes the words JSON that module **captions** reads.
Before you caption, read the words that the script lists as unheard.
A number in digits, or a word that differs from the audio, is where a caption goes wrong.
The words that the script lists as past the end are not in this clip, so check the offset and the duration.
When the script matches less than 80% of the transcript, the transcript does not describe this clip.
Then check the span and the offset before you caption.
These timings are measured from the audio of the cut, so they are the only timings that describe this
file.
4. Run module **trims** to survey the pauses and the filler, and report what it found.
Cut only when the user asks, because a cut moves every time stamp after it.
5. Run module **framing** to crop the master to each shape that the request asks for.
Run module **shots** with it when one shot holds two people and the crop must follow who speaks.
Skip both for a source with no video.
Such a source has no picture to crop and no face to follow.
6. Run module **brand** to load the look of the show, for a clean final or a publish final.
7. Send the user to the clip styling page when the request names no caption style and module
**brand** holds none.
The choice that the page records comes back as a brand kit.
Do not stop the run to wait for an answer.
Produce the clip with the default style, and tell the user which style that was.
8. Run module **captions** on every portrait export, and on another shape when the request asks for it.
Run module **fonts** with it.
9. Run module **overlays** when the request asks for a layer, and always for a source with no video.
For a source with no video, the overlay is not polish.
There, an audiogram package is the whole picture.
Without one, the clip is captions on an empty frame.
Load the artwork of the show from `info.image`, and give it to the package.
Every audiogram package needs the artwork.
10. Run module **qa** as the blocking gate.
Deliver nothing until it reports a pass.
11. Use the render, and never the transcript, to confirm two things.
The quote that the copy uses is in the clip.
The person that the copy credits is the person who says the quote.
The caller wrote the quote and the credit without seeing the clip.
The transcript holds sentences and names no speaker.
Find the speaker from the camera, and from a cutaway that shows a closed mouth.
Repair what is wrong with the Social API, and tell the user what you changed.
Move `ts_start` or `ts_end` when the clip opens or closes inside a word, or when the quote is outside
the span.
Then write the new words into `transcript`, so that the two agree.
Correct the label, the title, the text and the context when the credit is wrong.
A moved edge makes the render out of date, so go back to step 3 with the new span.
The words, the captions and the gate all describe the old cut.
Only the gate can say that the new cut is finished.
Move an edge only to repair a fault that you can prove, or to make a change that the user asked for.
Never move an edge to improve the clip, because choosing the moment is the caller's job.
12. Attach the video with the Uploads API and the Social API, unless the user asked you not to.
13. Present each finished clip on the clip card of skill **fountain-clip-finder**, with one added
line saying the render result and where the video is attached.
## Additional notes
A run with more than one clip does the same work on each clip.
Move all the clips through one stage, then move them all through the next stage.
Most of the time of a render goes between the actions, and not inside them.
A render of one clip spends a third of its time in the tools.
There are three delivery tiers, and each tier adds to the one before it.
The request implies which tier to use.
The user names the work that they want, and not the tier, so read the tier from their words:
- A rough cut is the landscape master alone, with no crop, no captions and no gate.
Read it from words about checking a span rather than making a clip.
- A clean final is publishable.
Its portrait export has captions, because people watch it with the sound off.
Read it from "produce this clip", when the request names neither captions nor packaging.
A clean final of a source with no video also has its audiogram package.
The reason is the same as for the captions on a portrait export.
Without the package, there is nothing to watch.
- A publish final adds the overlays and the packaging, and the request names one of them.
Ask the user when the words fit none of the three tiers.
You MUST NOT raise the tier on your own, because polish is requested work.
Captions on a portrait export do not raise the tier.
Make a square or a landscape export only when the request asks for it.
The word timings come from the clip, and never from the episode transcript.
That transcript holds sentences and no words.
It is the caller's evidence for the span, and not this skill's evidence for a caption.
The text of the words follows a different rule.
Whisper mishears a name or a number that the transcript has right.
So the words come from the transcript, and the timings come from whisper.
Never write your own alignment code in the run, because code written during a run fails in a new way each time.
Always cut from the tallest rendition.
A 9:16 crop keeps the whole height and about a third of the width.
Thus that height is the real resolution of the clip, and module **qa** fails a big upscale.
When the tallest rendition cannot reach the target, deliver the size that it can hold, and tell the user.
E.g., deliver 720x1280 from a 720p master.
A true smaller resolution passes the gate, and an upscale does not.
When a span seems wrong but you cannot prove it wrong, report it and do not repair it.
A letterbox is also requested work.
To change a clip that this skill already made, first read the manifest and the QA report.
Reuse what is still correct, and write each new output under a new name.
Change only the output of the module that changes.
A caption change MUST NOT force a new crop.
A post does not have to be approved before this skill runs, and rendering one approves nothing.
Never put an API key, a token, or a cookie into a command, a manifest, or a report.
These steps make one clip, and the clips of one run are independent of each other.
Module **queue** therefore shares the clips of a long queue between at most three workers.
Each worker has its own output folder.
A run is finished when the last clip is finished.
Three workers do not finish three times faster, because ffmpeg already uses every core of the machine.
A short queue uses one worker, because each new worker reads the skill again before it renders anything.
The purpose of this skill is a good clip, and not a full set of completed steps.
Readability, framing, and sync matter more than procedure.
Referenced files: 75
fountain-daily-growth5.38 KB
--- name: fountain-daily-growth description: Read yesterday's results and today's news, then brief fountain-clip-finder on the best trends. --- ## Overview This skill is the first step of the daily content chain. It runs two modules in order. Module **performance-review** reviews yesterday's posts. It turns the numbers of those posts into lessons in the preferences. Module **trend-discovery** reviews today's news. It scores the news and makes the best trends into briefs for skill **fountain-clip-finder**. The skill itself updates the narratives first, because both modules read them. ## Input - `show` - the show to run the loop for. - The Narratives and Editorial sections of the preferences. ## Output - One brief per advancing trend, handed to skill **fountain-clip-finder**. A brief is a completed trend of module **trend-discovery**. Each brief holds its share of the day's clip budget as `clip_count`. - One report for the day. It shows the posts that wait, then yesterday's numbers. With auto-render on, the report goes out when the videos exist, and it is the only mail of the day. - Updated preferences: the narratives, and the lessons of module **performance-review**. ## Housekeeping You MUST read HOUSEKEEPING.md if you haven't already. ## Requirements - An HTTP client, e.g. curl, for the Google News RSS route of module **trend-discovery**. - Optional: a web search tool, and a social trend search tool such as one for X, when the machine has them. - Fountain API. - Skill **fountain-clip-finder**. - Skill **fountain-reports**. - Skill **fountain-onboarding**. ## Process 1. Update the Narratives section, because both modules read it. 2. Run module **performance-review** to turn yesterday's posts and their numbers into lessons. Skip it when a render machine sends the report, because that machine runs it. 3. Run module **trend-discovery** to score today's trends and shape the strongest into briefs. 4. Hand each brief to skill **fountain-clip-finder**, and do not read its result. The chain continues without this skill. 5. List the day's drafts with the Social API, because step 4 hands the briefs on and never reads them back. Render them with skill **fountain-clip-producer**, under the rules of Rendering below. 6. Send the day's report one time, as the `review-posts` report of skill **fountain-reports**. The report shows the clips that wait, then the numbers of module **performance-review**. Ask skill **fountain-reports** to send the report and also to print the same report here. ## Additional notes Some steps repeat one API call over many items. Examples are the numbers of each post, the news of each subject, and the drafts of each clip. These items do not depend on each other, so ask for them all at the same time. This skill owns the two morning modules, and none of the work after them. Finding moments and writing the copy is the job of skill **fountain-clip-finder**. Rendering is the job of skill **fountain-clip-producer**, run here or on a render machine that picks the drafts up from the Social API. The rules for rendering come from the Automation section. Auto-render is on unless that section says otherwise. - With auto-render on, render the drafts here as a clean final. Then the user reviews the clip, and not a description of it. - With no confirmed kit under Brand, render the strongest clip first, as the style proof of skill **fountain-clip-producer**. Render the rest after the user confirms or corrects that clip. This is because a batch in the wrong look is rendered twice. - With a render machine named for this show, do not render here. The render machine renders the drafts and sends the report. Stop after step 5, unless no draft waits for a video. When no draft waits, the render machine renders nothing and sends nothing. - With auto-render off, something else has to render. Say which: the user's word in the chat, or a render machine that works this show. The thing that renders later sends a second mail to say that the renders are ready. That mail is the only other mail. When the user wants the day to finish without them, run skill **fountain-onboarding** to schedule that render. This is because a draft that nothing renders never becomes a clip. When auto-render is on, the report waits for the videos, so the reader reviews clips and not descriptions. When auto-render is off, the report goes at once, and its approve note says what renders a clip. Give the label of each source, and its publish date when known. For a source with an episode id, the label is the episode. For other sources, the label is the external video title from `context`. The printed report is all that the chat shows about the day's clips. It also covers the clips that this run did not make. This is because a day at budget still has clips that the user has not seen. A caller that has just rendered the day's drafts can ask for the report alone. Run steps 2 and 6 for that caller, and put the drafts that it gave up under warnings. Skip the report when the line that module **performance-review** writes in the Reporting section already has today's date. This makes sure that a second pass of the render machine never mails the day twice. An empty Editorial section does not stop the skill. Proceed, and tell the user plainly that the section is empty. Use this skill for the recurring daily cycle. For a one-off "find me a clip about X", use skill **fountain-clip-finder** directly.
Referenced files: 3
fountain-onboarding4.39 KB
---
name: fountain-onboarding
description: Set up Fountain. Trigger on first use, when asked, when preferences are empty, or when a skill is missing something.
---
## Overview
This skill ensures that the user can effectively use Fountain API and skills.
It makes sure that:
- Fountain API is reachable.
- Fountain skills are installed.
- Project preferences are recorded.
- Relevant software is installed.
- Any other blockers are resolved.
You MUST go through each outstanding item, even if the task does not require some of the above.
This way, you do not need to ask the user again later.
## Input
- None.
## Output
- Updated preferences.
- A scheduled run of skill **fountain-daily-growth**.
- A summary in the chat: what changed, what is still missing, and who must act on it.
- A next step: return to the task that triggered this skill, or offer a first run of skill **fountain-clip-finder**.
## Housekeeping
You MUST read HOUSEKEEPING.md if you haven't already.
## Process
1. Ensure you are in a fully capable agent environment, such as Claude Code or Codex.
Otherwise, suggest that the user uses such an environment to take full advantage of Fountain.
2. Ensure you have access to Fountain API by fetching the user's projects.
An empty array is fine, as long as the status is 200.
If you don't have access, install the plugin from https://github.com/fountain-fm/fountain-skills
3. Ensure you have access to Fountain skills: **fountain-clip-finder**, **fountain-clip-producer**,
**fountain-daily-growth**, and **fountain-reports**.
If you don't have access, install the plugin from https://github.com/fountain-fm/fountain-skills
4. Ensure that the user has at least one project.
Otherwise, link to https://fountain.fm/studio/onboarding?kind=PODCAST
5. Ensure that the project has at least one podcast.
Otherwise, link to https://fountain.fm/studio/{project_id}/onboarding?kind=PODCAST
6. If there are no connected social channels, suggest connecting YouTube, X, or Instagram via the Social API.
7. Ensure the project preferences specify the source of clip material, automation (auto-render, etc.),
email addresses to send the reports to, and any other relevant details.
8. When running locally, ensure all relevant software is installed: Python 3.11 or above, yt-dlp,
ffmpeg + ffprobe (the most complete version that includes libass, drawtext, fontconfig and whisper,
e.g. Homebrew `ffmpeg-full`), OpenCV 4.8 or later, ImageMagick, and a whisper.cpp model file
(`ggml-base.en.bin` in `~/.cache/whisper`).
If something is missing, attempt to install it yourself.
If you cannot install it, make it easy for the user to install it themselves, even if they are non-technical.
9. Research the look of the show: its artwork, its website, and its existing clips.
Write out brand guidelines from that research.
Choose the caption style (using skill **fountain-clip-producer**), color, and font.
Record the guidelines, and the logo URLs if available.
Don't include logos in the clip settings unless existing clips have them.
Present a mockup of what the clip will look like.
Offer to customize the style on the clip styling page.
10. Set up automatic daily growth using skill **fountain-daily-growth**.
Record its time and the machine that runs it under Automation.
## Additional notes
Record each preference with the Project API as soon as you or the user choose it.
Any preference that the agent asks to confirm MUST already be recorded in project preferences.
Therefore, if the user leaves the chat, the choices made so far are still recorded.
Onboarding must not feel overwhelming:
- Record the Fountain defaults below.
Then present them for the user to confirm, and offer customization as an option.
Do not present all options unless the user chooses to customize.
- Do not provide unnecessary information.
- When appropriate, make a decision yourself but offer customization.
Fountain defaults:
- Each report delivered as email, under Reporting.
- `performance` and `review-posts-simple` as two separate reports, under Reporting.
- Auto-render on, under Automation.
- 3 clips per day, under Automation.
When no user is present, e.g. in a scheduled run, do only the steps that need no answer from the user.
Report what is still missing, so that the user can complete it in the next chat.
When this skill is triggered as part of a specific task, explain to the user why they need to go through this skill.
Referenced files: 1
fountain-reports4.61 KB
--- name: fountain-reports description: Build the reports the user reads - compose components into a preset, then email or print it. --- ## Overview This skill owns how a report looks, so no caller invents its own format. A report is a preset, which is an ordered list of components. Each component is a markdown template that the data fills. The caller names the preset and gives the data. This skill composes the report. It delivers the report the way the Reporting section asks: email, printed, combined with a later report, or not at all. The user customizes a preset once, in the preferences, and every later report follows that customization. ## Input - The preset name. - The data that the preset's components need, from the caller. - Optional: the surface, when the user is present and asks to read the report here. - Report customizations from the Reporting section of the preferences, when the show has any. ## Output - The report, delivered as the Reporting section asks. Email is the default. ## Housekeeping You MUST read HOUSEKEEPING.md if you haven't already. ## Requirements - Fountain API. - Skill **fountain-onboarding**. ## Process 1. Read the report customizations from the Reporting section of the preferences. A customization can drop a component, reorder them, change a subject line, or change the delivery. 2. Read the preset from `assets/presets`, and apply the customization. 3. Fill each component template from `assets/components` with the caller's data. Drop a component whose data the caller did not give, and say so after the send. This rule never drops a component that needs no data, because that component is never missing data. Only a customization can drop it. 4. Deliver the report as the Reporting section asks: email via the Project API, printed in the chat, combined into a report sent later in the same run, or not at all. Email is the default, and goes to the addresses under Reporting. Run skill **fountain-onboarding** when the section holds no addresses. When the caller asks for both, send the report and also print it in the chat. When the user asked only to read it here, print it instead of sending it. A printed report has the same words as the sent report. So the reader never has to open the mail to learn what the chat left out. Say plainly when a report was composed but not sent. A send that returns success is not proof of delivery, so say which of the two you saw. ## Additional notes The presets: - `performance` - the numbers for a window: headline, channels overview, yesterday's clips, learnings, warnings. - `review-posts-simple` - the posts that wait for a decision, and nothing else. The reader reads the words in the dashboard, where the reader approves or deletes. So the mail says which posts exist, and sends the reader to the dashboard. The approve note says whether approving renders a clip or sends it. A second preset does not do this job. - `review-posts` - the whole day in one mail: the posts that wait for a decision, then the numbers. The user asks for it in place of the two presets above. The Reporting section records which of these forms the show wants. - `settings` - the current settings, each with its origin, and the tour of the headings. Sent when the user asks what their settings are. A preset is named for the state that it reports. It is never named for the occasion, or for the skill that sends it. So any skill that starts a chain can reuse it unchanged. The printed surface is for the review in the chat. There the user reads the same report that the email holds, so the two never disagree. A caller that prints and sends gives the reader one report in two places, and never two reports. Combining joins reports, and not machines. A report can wait only for a report that is sent later in the same run. This is because nothing holds a pending report between machines. A component is small and single-purpose. A new kind of email is a new preset made from the same components. A missing block is a new component, and never markdown that a caller writes by hand. This is because two callers that write the same block by hand soon write it in two different ways. Numbers come from the caller and go into the template unchanged. This skill formats the numbers. It MUST NOT recompute, round away, or soften what the caller measured. Send markdown, and never HTML. The Project API renders the markdown itself. It strips every attribute from the result, so styling that this skill sets does not reach the reader. The Project API styles the tables, and keeps the column alignment that the markdown sets. So markdown holds everything that a report needs.
Referenced files: 15
Package details
Publisher declarations from the archived package. These are separate from our research and the live service's terms.
- Package author
- Fountain Labs Ltd
Package observed Oct 10, 2026.
Technical details
- First seen
- Oct 10, 2026 · 12:00 UTC
- Last seen
- Oct 10, 2026 · 18:00 UTC
- Collection status
- Collected
plugin_asdk_app_6aa429bc4d1c819198ad6571766be52b
Download plugin data (JSON)Before you connect Fountain
How do I connect it?
Open the publisher's marketplace listing to check current availability and follow its connection instructions. This directory does not install plugins. Check the requested access and any account requirements before connecting.
Check marketplace availability ↗
Does it require paid access?
We have not established the pricing or subscription requirements for this plugin. An absent price does not mean free access.
Compare researched pricing and access models →
How can I evaluate it?
Check the declared skills and available files, then try a small task whose result you can verify. Our archived descriptions and instructions establish publisher claims, not tested runtime quality. Review sources and coverage limits.