Add to a graph you don't own
Add a result under a node you can read, find your fork, and decide who can see your addition.
You can add a child under any node you can read without joining its repository. Your addition goes into your fork: a repository the server creates for you on your first addition to that person's repository, then reuses for later additions to its graphs. The original node stays where it is and becomes your node's boundary parent, a parent in another repository. This is different from a branch, which creates a child node.
When you hold a named Editor or Admin grant on the parent, a node in your fork starts shared like the parent. Its named people can see your addition at the same roles, including members of the parent's repository. That repository's owner gets Admin on the new node, so they can change its sharing later. The parent's Public or Unlisted audience is copied too.
Otherwise your addition starts private unless you have added members to your fork. A Viewer grant, editing through a link, or reading a Public or Unlisted node does not qualify for the copy. Repository members' roles reach every node in their repository. Leave sharing unchanged unless you choose to change it.
If you hold a write role in the parent's repository, the server places your addition there instead. A node in the same repository as all its parents copies their common sharing once: with one parent, the same sharing; with several, the narrowest read visibility (Private, Unlisted or Public) and only the people named on every parent, each at their lowest role. Link write is copied only when every parent grants it. Public plus Unlisted with link write gives Unlisted without link write. The fork copy uses the same intersection when every parent is in the one upstream repository and you hold a named Editor or Admin grant on every parent. The upstream repository owner counts as Admin on every parent; a retained controller counts as Admin on the parent they control. You own the fork and are not copied. Roots and other nodes with boundary parents keep the repository default. Placement, ownership and commit author do not change. Later parent changes do not propagate to existing children, and adding a parent to an existing node leaves its sharing unchanged.
Choose where to work
- Already inside a local repository? Create and link the node there, then commit locally. The local workflow does not publish anything.
- Adding directly to a hosted graph? Use the CLI or an MCP agent and let the server choose the repository. Do not clone someone else's repository or ask for membership just to add a node.
- Want a local copy afterwards? Clone your fork, not their repository.
Web app
Open the parent node to read its content and graph. The canvas's Set as source action followed by a double-click on empty canvas creates a child when you can write the source. The current web branch action can refuse a read-only source with “This shared node is read-only. Branch this node to continue.” If you encounter that refusal, use the CLI or MCP steps below; you do not need repository membership.
After creating the child, open its node URL in the web app to edit it or use Share node to choose its audience. Sharing your addition below explains how to let the original graph's owner see it without sharing an entire repository.
CLI
Read the parent first:
flywheel hosted:node:get "<parent-node-id>" --format=jsoncan_write: false is expected for someone else's read-only node. Keep its
repository_id for the local alternative. owner_email is included only
when you own the node, hold a viewer/editor/admin role in its repository,
or have it shared with you by name. Public or Unlisted link access alone
does not include another account's email, even when you are signed in.
Create your addition without --repository-id:
flywheel hosted:node:create --parent "<parent-node-id>" --title "My result" --format=jsonUse --values-file node.json instead of --title for the full node content;
see hosted:node:create for the file format.
Alternatively, hosted:node:branch creates a child
that copies the parent's title:
flywheel hosted:node:branch "<parent-node-id>" --format=jsonBoth commands return node_id, repository_id, and placement. Report those
values from the answer, not by comparing repository IDs:
placement | Where the new node landed |
|---|---|
parent_repository | The parent's repository, where you hold a write role |
fork | Your fork of the parent's repository |
default_workspace | Your default workspace, for a root created with no parent |
The explicit --repository-id forms commit into that named repository; they
do not ask the server to choose a fork. Do not use them for this workflow.
Read the new node for its slug_name and actual visibility:
flywheel hosted:node:get "<new-node-id>" --format=jsonReport the node, repository, placement and visibility you read back, and read
nodes:sharing:get to report who can see it. Change sharing only when asked;
do not make the node public merely because its parent is public.
Find shared and public graphs
Unscoped node listings show your own nodes. Request other readable scopes
explicitly; --access_scopes accepts a comma-separated list of owned,
shared, and public:
flywheel hosted:node:list --access_scopes shared --format=table
flywheel hosted:node:list --access_scopes public --format=table
flywheel graph:get --access_scopes shared --format=json
flywheel graph:get --access_scopes public --filter include:visibility:public --format=jsonThe node table's owner column is empty for other people's public nodes
unless you also have a repository role or the node shared with you by name.
Follow node-list pagination and graph
next_cursor while has_more is true. A graph read anchored by
--node_id "<parent-node-id>" without an access-scope flag already reads every
scope you can read. Without a node ID, its default is your own nodes.
Visibility filters narrow the requested scopes; they do not add one.
graph:get --filter include:visibility:public alone does not discover other
people's public graphs: include --access_scopes public.
MCP agents
Ask your agent to add your result under the node's URL. The bundled skills use this sequence:
- Read the parent with
flywheel_get_node.can_write: falsedoes not prevent adding a child. - Call
flywheel_commit_new_nodewith the parent's ID inparent_ids, a caller-generatedlocal_temp_node_id, and the fullstaged_payload. Alternatively, callflywheel_branch_nodewith the parent's ID and its currentrevisionasexpected_revision. Neither request chooses a repository. - Report the answer's
node_id,repository_id, andplacement:parent_repositorymeans the parent's repository,forkmeans your fork, anddefault_workspacemeans your default workspace. In theflywheel_commit_new_nodeanswer,node_idis insidenodewhilerepository_idandplacementare top-level fields. Do not infer placement by comparing repository IDs. - Report the new node's
visibilityfrom the creation answer (node.visibilityforflywheel_commit_new_node). Read it withflywheel_get_nodefor itsslug_nameif needed. Leave sharing unchanged.
If a creation response is lost, retry with the same local_temp_node_id,
unchanged content and the same MCP session. The saved answer keeps the
original repository and placement.
Inside a local repository
Keep the selected local repository as your destination. Read the hosted parent
with hosted:node:get to obtain its repository_id. Inspect repo:status
first so your commit does not include unrelated staged work. Then create a
node here and link it to the parent there:
flywheel repo:node:create --repo "<repository-path>" --title "My result" --format=json
flywheel repo:lineage:add "<parent-node-id>" "<new-node-id>" --parent-repository-id "<parent-repository-id>" --repo "<repository-path>" --format=json
flywheel repo:diff --repo "<repository-path>" --staged --format=json
flywheel repo:commit --repo "<repository-path>" --message "Add result under readable parent" --format=jsonThe new node stays in your local repository. Its parent stays in the other
repository; repo:lineage:list shows the relationship
with boundary: true. A local commit publishes nothing, so it has no hosted
visibility or server-decided placement to report yet.
Push only when you want to publish. Agents first show the
repo:push --dry-run summary and wait for your approval.
Publication checks that you can still read the parent; it never redirects the
push into another repository.
Work an agent should not publish as it goes can stay in this local repository until it is reviewed and pushed. The server applies initial sharing on push: same-repository parents contribute their common sharing. A node in your fork also copies sharing when every parent is in the one upstream repository and you hold a named Editor or Admin grant on every parent. Other boundary-parent nodes keep their repository's default. The push preserves repository placement, ownership and commit author.
Clone your fork
After your first hosted addition, find your fork:
flywheel hosted:repository:list --format=tableChoose the row with kind: fork, your owner_email, and the parent's
repository as upstream_repository_id. Its repository_id is also the one
returned by creation. Other kinds are default_workspace for your new roots
and other for other repositories, including those owned by someone else.
flywheel repo:clone "<your-fork-repository-id>" "<repository-path>" --format=jsonReading a public node does not grant access to clone its whole repository. You can clone your fork because you own it.
Share your addition
Change sharing only when you choose to. First check who already has access:
the Editor/Admin copy already gives the upstream repository owner Admin.
To let someone who cannot yet read your addition see it, open the new child,
choose Share node, and add their email under Collaborators with the
Viewer role. If the parent read includes owner_email, you can use it;
otherwise ask that person for their email.
Keep the existing people and audience setting. You can instead choose
Unlisted for people with the URL or Public for discovery by anyone,
if that is what you intend.
An MCP agent must first call flywheel_get_node_sharing, preserve the current
sharing_mode unless you asked to change it, and use people.add to add the
requested person without replacing anyone else. Omitted collaborators keep
the existing people, including the copied Admin grant. Use people.remove
or people.set only for a requested removal or exact role, and confirm with
another sharing read.
The CLI's nodes:sharing:set follows the same rule: keep the current
--sharing_mode and use --people for the requested change. Omitting
--collaborators keeps existing people; an explicit list replaces them.
Sharing a node never makes anyone a repository member. It does not let them clone your fork or read your other private nodes. See Repositories for repository-wide membership and access.