Moonwalk
Write and publish live boards
- Category
- Productivity
- Primary Subcategory
- Business Data & Low-Code Apps
Integration details
Description
Moonwalk is where you write boards: pages that hold text alongside live tables, charts and interactive widgets, which you can keep private or publish as a public page. This plugin lets ChatGPT write and maintain those boards with you, and build the data and machinery behind them. What ChatGPT can do with it: - Boards: read, search and write pages, reorganize them, and publish a board as a public page. - Data for your boards: create tables, read and write rows, and run read-only SQL queries whose results show live on a board. - Widgets: build interactive screens (charts, forms, dashboards) that sit on a board, and see a picture of what it built. - Automations: create workflows in Python that keep a board's data current, running on a schedule, from a webhook or by hand, and read each run's results. - Files: browse, search, read and edit the files in your base, and upload new ones. - Connections: see which third-party accounts and keys your base holds, and ask you to add one. ChatGPT never sees or types a secret; you enter it in Moonwalk. Safe to hand to an agent: - Everything ChatGPT changes is recorded as yours, with ChatGPT noted as the agent. - Deleted boards, tables, widgets, automations and files go to a 30-day trash and can be restored. - Edits are versioned, and a batch of row changes can be undone in one step. Requires a Moonwalk account (sign up at moonwalk.now). You sign in and approve access on Moonwalk's own screen, and can revoke it at any time from Moonwalk's Agents page.
- Integration type
- Plugin
- Verification status
- Not applicable
- Platform
- ChatGPT
- Primary Subcategory
- Business Data & Low-Code Apps
- Secondary Subcategories
- None listed
- Brand
- Moonwalk
- Access
- Account required
- First tracked
- 2026-09-28
- Tool count
- 91
- Geography
- US
The Primary Subcategory used for this profile’s headline score.
Other Subcategories where the Integration is listed.
Get alerts for Moonwalk
Get updates when Moonwalk’s Discoverability Score or category rank changes.
ChatGPT Plugin Discovery Score
ChatGPT Plugin discovery is coming soon
ChatGPT can surface a Plugin when it matches a user's request.Your Plugin Discovery Score measures how often yours appears.
No spam. Unsubscribe any time.
What discovery looks like

Competing in ChatGPT Business Data & Low-Code Apps
View Category91 tools agents can invoke
Lock this exact version and allow it to fire. Needs steps — the version is always there, because every edit goes into one. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
activate_automation
Add a column to a table. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
add_column
Ask the person for a credential you must never see. Name the connection you want and why: `secret`, `basic` or `hmac` for a key they type, or `account` for a service they connect by clicking — then `provider` is the service's slug, like `gmail`. Never ask for an API key, password or token in the conversation, and never accept one there. In the chat panel a box asks them under your message, and their answer comes back to you as the next message: stop and wait for it. Anywhere else, show them the URL this answers and stop; then poll `get_connection_request`. The name is a proposal — bind steps to the name the answer gives, not the one you asked for. For a key, `how_to_get` is required: the path to it from where the person starts, as `site > page > button`, like `platform.openai.com > API keys > Create new secret key`. Add `how_to_get_url`, like `https://platform.openai.com/api-keys`, when you know the page. It shows in the box where they type the key, so write it for someone who has never done it. When you're not sure of the path, say so in it rather than inventing one. An account takes neither. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
request_connection
Bind a base connection to one declared key. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
bind_step_connection
Change a column's type. Refused, naming the rows that stopped it, when a value would not survive the cast. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
change_column_type
Drop one config value, back to the declared default. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
clear_step_config
Create a board, at the end of the list or after `after`. Every board is at the top level; one board links to another with a mention, never by holding it. It starts unpublished. The id is yours to mint. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
create_board
Add a step. The source is linted at save: it must define a top-level `run(...)` and, for a code step, a `ReturnType` model it returns. Say why in `change_description` — one line a person would understand: "Skips weekends". It is the line the automation's history shows, and code saved without one is refused (422 `change_description_required`). A positional parameter of `run(...)` is an input, filled from the step's `inputs` list in order. `{"step": "trigger", "path": [...]}` reads what fired the run; `{"step": "<hash>", "path": [...]}` reads an earlier step's output. def run(title, file) -> ReturnType: ... inputs=[{"step": "trigger", "path": ["title"]}, {"step": "trigger", "path": ["file"]}] A count that does not match, or the same names in a different order, is refused at save (422 `invalid_step`). A step reaches the base's own tables through the SDK — no connection needed, and tables and columns are named by id, never by name: from mw_sdk import BaseModel, Config, Annotated, Literal, Ge, Le, Gt, Lt, MinLen, MaxLen, MultipleOf, connection_type, SecretConnection, BasicConnection, HmacConnection, AccountConnection, tables, files import uuid class ReturnType(BaseModel): written: int def run() -> ReturnType: tables.write(table_id, [ {"op": "insert", "row": str(uuid.uuid4()), "values": {column_id: value}}, ]) return ReturnType(written=1) `tables.sql`, `tables.columns` and `tables.rows` read; `tables.write` writes, and every write a run makes lands in one transaction, the run's. Undo never takes it back; on each table it touches it is a version of its own. `discard_latest_version` takes it back while it is still the newest, `revert_version` to the version before it once something is on top. An `op` is one of insert, set, delete, restore; `row` is a UUID the caller mints; `values` is keyed by column id. A new row lands last; rows are in # order and cannot be placed. `tables.sql` is read-only Postgres over the base's views: a table is `"v_<hex>"` and a column `"c_<hex>"`, the uuid without its dashes, so a rename never breaks a step. `tables.columns(table_id)` is how a step gets from a name to an id at run time rather than pasting one in. A step reads and writes files under `/files`, its working directory, with plain `open`. Pass any file name that came from outside — a trigger's input, a cell — through `files.inside(folder, name)` before opening it: it answers the absolute path, `/files/<folder>/<name>`, and raises `ValueError` for a name that climbs out of `folder`. A file field (`"format": "file"` on a manual trigger) hands the step the path the file was saved at, `/files/Uploads/<name>`. To delete a file, `files.trash(path)`: it answers nothing, and the file waits in the base's trash for 30 days, so a mistake can be taken back. `os.remove` cannot be. A config (`Config[T]` on `run`) is a setting and never a credential. A key, password or token is a connection, asked for with `request_connection`. Each step gets 1 hour of wall time and 120 CPU-seconds, counted across every process it starts. Past either it is killed, and its step run's `error_type` says which: `wall_time` or `cpu_time`. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
create_step
Create a table and its columns. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
create_table
Create a widget from a declaration and a TypeScript screen. The screen is compiled on the way in; a refusal names every violation by line. Say why in `change_description` — one line, in words the person would use: "Shows the week's total above the chart". It is the line the widget's history shows for this version, and a source saved without one is refused (422 `change_description_required`). A screen imports react and @moonwalk/widget and nothing else, and exports its component as the default export: import { useFocus, useQuery, useRun, useRunResult, useScroll, useTheme } from '@moonwalk/widget' export default function Tasks() { const tasks = useQuery('tasks') // a key of declaration.data const move = useRun('move') // a key of declaration.runs const collect = useRunResult() // a run answered `strt`, asked again by its id const theme = useTheme() // 'light' or 'dark' const scroll = useScroll() // 0 → 1 as the page scrolls this block past const focus = useFocus() // false while the reader is in another window if (!tasks.rows) return <p>Loading…</p> return <ul>{tasks.rows.map((t) => <li key={t.id}>{String(t.title)}</li>)}</ul> } The `<Screen>` provider is mounted around it for you; a screen never renders one. `useQuery` gives `{rows, broken}` and nothing that writes. There is no `fetch`, no token and no storage — the broker is the only way in or out. `useRun` gives a function resolving to `{run_id, status, returncode, output}`. `status` is `fin` (it ended) or `strt` (still going past the server's 3-second wait — not a failure). `fin` does not mean it worked: check `status === 'fin' && returncode === 0`. `rej` never reaches a screen — a refused run rejects the promise instead. `output` is the JSON object the automation's last step returned — its `ReturnType` — so read the field you want: `run.output.message`. It is `null` while `strt` and when the last step failed, and past 16 KB it is `{"$over": <bytes>}`: a run answers, it does not hand over a dataset. `get_widget` reports each run's `output_schema`. A run answered `strt` can be collected later: `useRunResult()(run.run_id)` resolves the same shape. A run may take a **file**. A trigger property marked `{"type": "string", "format": "file"}` takes one, and a screen passes a `File` at the top level of `input` — `useRun('import')({ book: file, language: 'en' })`. It goes as bytes in the one request, is saved into `/files/Uploads/`, and the step is handed the path it was saved at. Nothing in the SDK is new for it: an `<input type="file">` and the `File` it yields. This is the one thing you cannot do yourself — `fire_automation` names a path because MCP carries no bytes, and the browser is the caller that sends them. A file past 100 MB is refused, 413 `too_large`. A declaration is `data` and `runs`. A widget **reads and runs, and does nothing else** — there is no way to write a row through a query, so a data entry has no `mode` and a declaration carrying one is refused. Each `declaration.data` entry is two fields: `sql` and `description`. The SQL is read-only Postgres over this base's views — `"v_<hex>"` for a table and `"c_<hex>"` for a column, both derived from ids, so a rename never breaks one. Alias every column to the key the screen reads, and select `id` when the screen needs a row to name in a run. The `description` is for the person, not for you: what the query asks, in the words someone would use to ask for it. The SQL is hex and nobody can read it, so this is the only readable record, and an entry without one is refused. Each `declaration.runs` entry is **the screen's name for it → the id of an automation** that already exists in this base. Its trigger must be `manual`: a cron or webhook trigger fills its own payload, so a screen has nothing to supply. `useRun('move')(input)` fires it with `input` as the trigger's output, so `input` has to fit that trigger's `output_schema` — read it back off `get_widget`, which reports each run as `{automation_id, automation_name, input_schema, output_schema}`, the last being what the run's `output` holds. Build the automation first, then bind it; there is no way to make one from here. **The box is fixed.** A screen draws into exactly `width` × `height` CSS pixels and nothing grows to fit it: anything taller scrolls inside the box, so design to the number. `size` is its own field beside the declaration — `{"width": 480, "ratio": "4:3"}` — and a resize is that alone. A new widget with a screen names its size (422 `size_required` without one); only a stub is given the smallest. The 16 boxes: 320 wide: 16:9 is 320×180, 4:3 is 320×240, 3:4 is 320×427, 2:3 is 320×480 480 wide: 16:9 is 480×270, 4:3 is 480×360, 3:4 is 480×640, 2:3 is 480×720 640 wide: 16:9 is 640×360, 4:3 is 640×480, 3:4 is 640×853, 2:3 is 640×960 960 wide: 16:9 is 960×540, 4:3 is 960×720, 3:4 is 960×1280, 2:3 is 960×1440 **Every save that changes the screen, the declaration or the size answers with a screenshot** of the widget as drawn, from its real rows, and four sizes: `clientWidth` and `clientHeight` are the box, `scrollWidth` and `scrollHeight` the content, the page's or a div's that fills the box and scrolls or clips, whichever is bigger. A `scrollHeight` above `clientHeight` means the content scrolls inside the box. `thrown` is every message the screen threw while it drew, word for word. While it draws, every run is refused — `not while previewing` — so a screenshot never writes to the base. `theme` picks `light` (the default) or `dark`. When it cannot be drawn the save still stands, and `screenshot` is `{"unavailable": <reason>}`. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
create_widget
Create an automation. The trigger's mode is set here and never again — a different mode is a different automation. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
create_automation
Stop it firing and unlock it for editing. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
deactivate_automation
Trash a board with everything on it. `restore_board` brings it back; `list_trash` with `board` shows it. While it is in the trash its address answers not-found. One with nothing in it that nothing but your own open sitting ever touched is deleted outright instead, and has no way back. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
delete_board
Drop a column. Never refused — every query naming it stops running and says so. `restore_column` takes it back, with its values — and so do `undo`, to the place it held, and reverting the table to a version from before the drop. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
delete_column
Delete a connection. Refused while a step is bound to it. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
delete_connection
Move a file, or a directory and everything in it, into the base's trash, where it waits 30 days. It leaves the tree — `list_trash` with `kind="file"` is where it is now, and `restore_file` takes the `id` from there and puts it back where it was. Never the root or `/files/Uploads`. Nothing you do deletes a file for good. Documented at https://docs.moonwalk.now/tools.html#files. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
delete_file
Delete a step and everything under it — an `if` takes both branches. Refused while a step left behind reads one that goes; rewire or delete that step first. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
delete_step
Trash a table. `restore_table` brings it back — unless the table held no rows and nothing but your own open sitting ever touched it, which is deleted outright and has no way back. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
delete_table
Trash a widget. `restore_widget` brings it back. Refused while a board still draws it, naming the blocks. One with no source that nothing but your own open sitting ever touched is deleted outright instead, and has no way back. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
delete_widget
Trash an automation. Its steps, runs, versions and files are kept and nothing fires it; `restore_automation` brings it back with its trigger live. Refused while a widget binds it, naming the widgets. One with no steps that nothing but your own open sitting ever touched is deleted outright instead, and has no way back. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
delete_automation
Throw away the newest version and put the resource back as the version before had it — yours, your person's or a run's. Appends nothing. Only you can do this: a person reverts instead. Refused when a run names the version (409 `version_has_runs`) and when it is the only one (409 `only_version`). This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
discard_latest_version
Apply a batch of block operations to one board — the only way to write, delete or reorder a block. One call is one transaction. A heading is a `heading` block: its text, and `level` 1, 2 or 3 in `props`. A `set` at `["type"]` turns a paragraph into a heading or back and keeps the block's id — send the level with it. A value box is a text chunk `{"value": {"sql": …, "description": …}}`: one cell of a query, drawn live inside a sentence. Always both fields, the description one line. Rows on a board are a widget's job: make one with `create_widget` and put a widget block on the board. A text chunk may instead be `{"mention": "<board id>"}`: a live board of this base, drawn as its current title. It stores no title, and anything else it names is refused with `mention_invalid`. A board is never a block of another board. Marks sit flat on a chunk: `bold`, `italic`, `underline`, `code`, `strike`, `link`, and `color` for the ink and `background` for a wash behind it. A colour is a name, never a hex — `grey`, `brown`, `orange`, `yellow`, `green`, `blue`, `purple`, `pink` or `red` — and the two are independent. An image block's props are exactly one of `{"path": "/files/…"}`, a picture in the base's files, or `{"url": "https://…"}`, one on the web. A path is copied into the block and shrunk to 4000 px, so moving or deleting the file later changes nothing; it is stored as `image`, `width` and `height`, and the answer's `stored` says so. A URL is drawn live and breaks when its site does. PNG, JPEG, GIF and WebP only. To put a local file on a board, `request_upload` it and name the path you get back. The description is for the person, not for you: what the query asks, in the words someone would use to ask for it — "Tasks still open, newest first". The SQL is physical names in hex and nobody can read it, so this is the only readable record of what the block draws, and a block saved without one is refused. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
edit_board
Replace `old` with `new` in a text file, leaving the rest of it byte for byte. `old` must appear exactly once — include enough of the lines around it to make it unique — unless `replace_all`. Nothing changes when the edit is refused, and the answer says why. To write a whole file, use `write_file`. Documented at https://docs.moonwalk.now/tools.html#files. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
edit_file
Find files and folders by a glob, without listing folders one by one. A pattern with no `/` matches a name at any depth (`*.md`); one with a `/` matches the path from `path`, `**` descending (`notes/**/*.md`), or from the root when it starts `/files/`. Dotfiles are included. At most 100 answers. Documented at https://docs.moonwalk.now/tools.html#files. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
search_files
Fire an automation by hand, whether it is on or off. Returns the run id at once — read the run to find out what happened. A file field (`"format": "file"`) takes the path of a file already in the base — `/files/Uploads/book.pdf`; `request_upload` is how a file from your own machine gets there. You are the one caller that names a path; every other sender of a run, a widget's screen included, sends the file itself. 422 `file_not_found` for a path that is not a file. Each step gets 1 hour of wall time and 120 CPU-seconds, counted across every process it starts. Past either it is killed, and its step run's `error_type` says which: `wall_time` or `cpu_time`. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
fire_automation
One board: its blocks, whether it is published, and its address. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
get_board
How an ask was answered: `pending` or `filled`, and — once filled — the connection that was actually made, which may not be the name you asked for. 404 `no_such_request` once the person declined it, `expired` once the hour is up. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
get_connection_request
One run: its status, its timings, what it received (`input`) and what it returned (`output`). Either is `{"$over": <bytes>}` past 16 KB. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
get_run
One row per executed step, in execution order — what you debug a run from. `cpu_ms` and `wall_ms` are what the CPU and wall-time limits count: every process it started, from the moment it was sent. Installing its dependencies comes first and is in neither, so a first run can take a minute and report a few hundred ms. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
get_run_steps
What a step declares as config, and the values saved against it. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
get_step_configs
What a step declares as connections, and which base connection is bound to each key. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
get_step_connections
The Python source of one step, as it is on disk. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
get_step_source
One table and every column on it, with each column's type. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
get_table
One version, and what it changed against the version before it. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
get_version
One widget: its declaration, its screen source and its build hash. An empty `source` is a stub someone made from the menu — a name waiting for you to write its screen with `update_widget`. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
get_widget
Run every data query a widget declares and return the rows. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
get_widget_data
One action of a linked account: its argument JSON Schema in `input_parameters`, plus its output shape and its scopes. Read it before writing the call rather than guessing at argument names. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
get_account_action
One automation: its step tree, its trigger and its state. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
get_automation
Get a one-time link for sending a file from your own machine into the base — MCP carries no bytes, so this is how one gets in. Run the `command` it answers with your file's path in place of the placeholder; the upload answers `{"path": "/files/Uploads/…"}`, which is what a file field in `fire_automation` takes. The link works once, for 5 minutes. If the upload cannot connect, do what the `note` says. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
request_upload
Where the person gets a webhook trigger's signing secret, never the secret itself. Show them the `url`: on that screen they press the eye on the trigger and copy the secret to paste upstream. `secret_set` is false while an upstream secret has not been pasted in. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
get_webhook_secret
Where the person pastes the upstream's signing secret, never the secret itself. Show them the `url`: on that screen they paste it into the trigger; never ask for it in the conversation. Refused (409 `system_generated`) when Moonwalk made the secret; that one is copied, with `get_webhook_secret`. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
set_webhook_secret
Rows of one table, by limit and offset. To filter, sort, group or join, write SQL — `run_sql`. The database screen's own filter is the UI's and adds nothing an agent holding SQL does not already have. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
list_rows
What went wrong with a widget, newest first, each with its `kind`: `undeclared_data` and `undeclared_run` for a read or run its declaration never named, `automation_gone` for a declared run whose automation has left, `render` for a screen that threw, `compile` for a save the compiler refused. A run's own failure is not here — `get_run` has it. `limit` is capped at 200. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
list_widget_errors
What a linked account can do: every action slug a step may call through it, narrowed by `search`. 409 `not_an_account` for a connection that was typed rather than clicked — only an account has a catalogue. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
list_account_actions
An automation's runs, newest first. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
list_runs
Every step of an automation, in tree order, with its inputs. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
list_steps
Every automation in the base, with its steps and trigger. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
list_automations
Every board of the base, in sidebar order, with whether each is published and its address. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
list_boards
Every ask in the base still waiting on the person — yours, another chat's, or one made over `/api/mcp` — with its name, kind, who asked, why, and when it runs out (`expires_at`). The list the Connections dot reads. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
list_connection_requests
Every connection the base holds. The fields never come back out. This is Moonwalk. `base_id` is an id from `list_bases`. The rules of a Moonwalk base that no single tool states are in `read_overview`.
list_connections
How do I improve a ChatGPT Plugin's discoverability?
The levers are the listing surface agents actually read: names, descriptions, keywords, tool metadata, and registry health. Which lever matters depends on where discovery breaks, which is what continuous measurement shows.
What are Moonwalk alternatives on ChatGPT?
As of 2026-09-28, Moonwalk competes with AnyDB, Dreambooth Studio, Exportlab, Jotform Apps, Ragic, xMatix in ChatGPT Business Data & Low-Code Apps, ranked by public Discoverability Score.
Where is this profile measured?
This profile uses the geography attached to the latest public registry snapshot: US. Locale tags are intentionally omitted.