Continue the existing source
Read the project’s source before choosing a route:source inspect reads local checkout and sanitized remote information without signing in or uploading files. source status requests the authenticated project’s full binding. In MCP, use source_get with include_binding: true before using source connection or generation guards; REST uses GET /v1/projects/{project_id}/source?include_binding=true. Default GitHub reads retain the existing status view; managed reads always include their full binding. The saved binding takes precedence over a local Git remote. A Git directory alone does not imply GitHub.
For an unbound checkout, an explicit source choice already answers the question. Otherwise use its selected GitHub repository, or ask once whether to keep versions with ohmyho.st or set up GitHub. A new application developed entirely in a connected chat uses managed source. Keep the selected account, project, region, framework and data mode when continuing work.
Use GitHub setup for a GitHub source. Commit and push changes there before planning their full commit SHA. Managed source needs no GitHub account or GitHub push.
Save current local files
Run the CLI setup andohmyhost init --dry-run --json first. Resolve framework blockers and include the actual ohmyhost.yaml and lockfile. source publish captures current files, including uncommitted and new files, as one managed version. It does not import local Git history or deploy the app.
For a project with no source and no pending initialization, use initialize. Its expected source generation is 0; omit the source connection and commit flags:
SAVE_REQUEST_KEY for each new save and retain it with that request for retries. The capture honors root and nested ignore rules, excludes credentials, local link records, dependencies and build output, and rejects symlinks or files changing during capture. Review the intended files; keep private values in runtime secrets.
For later local saves, read source status for the binding’s source_connection_id and source_generation. Use commit with those values:
--expected-commit when this directory has a confirmed base from a successful local source publish/source publish complete: the CLI uses that directory’s own last confirmed commit. A template initialization alone does not establish that base. If another chat has saved newer files, first read and merge them into the checkout. Supply an explicit --expected-commit only after that reconciliation. Using a newly fetched remote head with stale local files can overwrite work.
Finish a pending save
A save returnsoperation.id. A committed upload receipt has state: "committed" and commit_sha; that exact SHA identifies your saved version. snapshot.sha256 is the snapshot checksum, not the commit. An accepted response or wait timeout does not mean the version is ready.
source publish complete checks once and can return status: "pending"; follow the operation and call it again. Only a succeeded operation and committed receipt confirm the persisted version and finish the local binding. Completion uploads no files and records your operation’s commit even if another chat has since advanced the source. With --wait, a successful source publish performs this completion itself.
After an interruption, source inspect lists safe pending_publications IDs. Observe that saved operation and receipt before retrying. If it is still staging, repeat source publish with the unchanged files, original arguments and original key to finish uploading. Preserve that attempt after an uncertain response; do not start another upload when the receipt is sealed or committed. An expired or failed upload needs its reported cause resolved before a new attempt.
Develop in a connected chat
Use the remote OAuth connection and its approved project grants. The remote server edits saved files directly; it does not read a directory on your computer. Read its actualtools/list schema, since the local and remote catalogs differ.
For a new managed app, remote project_create accepts source_provider: "managed" and template: "vite-react" or "empty". Use the basic Vite template for a blank web app, or an empty source for an explicitly selected supported stack. Follow operation_get, then source_get with include_binding: true until the source is ready with a persisted commit. Project creation can finish before source initialization. Do not issue a duplicate source_initialize while it is pending. A returned initialization_operation_id identifies the child operation; initialization_error_code explains a failed initialization.
For an existing unbound project without pending initialization, source_initialize creates the chosen template under the current generation and a saved idempotency key. Local CLI equivalents are listed below.
Read the current manifest with source_files. On remote MCP, add path to read one file; on local MCP use source_file. Text reads default to format: "text" and return content_text with encoding: "utf8". Binary files return content_base64; request format: "base64" for exact binary bytes.
For example, pass this argument object to source_changes, replacing the IDs, generation and commit with the values you read:
content_text for UTF-8, content_base64 for binary, or content_base64: null to delete a file. Preserve an existing file’s executable flag. Follow the accepted operation, then read source_get with include_binding: true before planning its resulting commit. Keep application passwords and model keys out of file content, chat and tool arguments; use the private secret input flow.
Save a complete tree in chat
Use the files actually available to the connected client. Remote upload tools accept file contents, not a path to a directory on your computer. If the chat cannot read or transfer the complete intended tree, arrange that file context before saving or switching source.- Read
source_getwithinclude_binding: true, then callsource_upload_prepareonce. Keep itsoperation.id, original guards andidempotency_key.initializeuses an unbound source, generation0and null connection/commit;commituses the managed connection, generation and reconciled parent commit;switchuses the original GitHub connection/generation and a null parent commit. - Call
source_blob_putfor every intended file, including unchanged files that should remain. Supply the same project/upload operation, a relativepath, itsexecutableflag, a saved per-file key and exactly onecontent_textorcontent_base64. The server computes SHA-256 and byte length from the validated bytes. Retain each returned{path, sha256, byte_length, executable}receipt exactly; do not calculate or invent hashes in chat. - Pass the complete
filesmanifest built from receipts of this upload tosource_upload_commitfor initialize/commit, retaining the original generation and a saved finalize key. Usesource_switchfor switch mode. Every staged file must appear exactly; an incomplete or altered manifest is rejected. An unstaged, previously saved file omitted from the next full snapshot is deleted. A staged path’s contents and executable flag cannot be changed within that upload. - Follow the same
operation_getandsource_upload. The version is saved only when the operation succeeds and the receipt iscommitted. Asealedreceipt can name an unpushed candidate and is not confirmation. Use this operation’s own committedcommit_sha, even if another chat later advances the source.
source_upload reports state and commit, not a file inventory. Recover a lost file receipt by repeating the identical source_blob_put arguments and key. Retain the original manifest and step keys; do not restage sealed or committed work. Resolve a reported failure or conflict before a deliberate new attempt. Saving a tree starts no deployment.
Resolve concurrent changes
source_generation changes when a source binding is initialized or switched. A commit or restore of a ready managed source also requires the exact parent expected_commit_sha. A source conflict means another change or binding has won; repeating stale guards cannot resolve it.
Read the current source and affected files, compare the versions, then merge the intended edits. Submit the reconciled change with the new guards and a new key. For local files, reconcile the checkout before changing its explicit base. After an uncertain response, observe or replay the original request first so the same work is not saved twice. Follow the returned error’s code and suggested_action.
Read history and restore files
next_commit_sha; pass it as --before SHA for the next page. source diff reports added, modified and deleted paths and their before/after hashes and executable flags.
To restore an earlier file tree, read the current generation and commit, then use:
Initialize or switch source
If an unbound project needs a template rather than local files:empty for an explicitly chosen supported stack. Wait for the accepted operation and read source status before editing. Initializing a template does not copy template files into a local checkout or confirm a local base. Before its first local commit, read and reconcile the saved template with the local files, then supply that commit explicitly with --expected-commit.
Switch a GitHub-bound project to managed source only when requested. Read its full source binding for the current connection and generation, review the complete replacement tree, then run:
mode: "switch". Stage the actual intended files, then call source_switch with their receipts, the original upload_operation_id, GitHub connection/generation and a saved key. Use the same project; source_upload_commit cannot finalize a switch.
The old binding remains active until the switch succeeds. This keeps the same project ID, environment URLs, secrets, domains and database/data mode, and disables this project’s GitHub auto-deploy. It replaces the source with the selected current files; it does not import GitHub history, delete the GitHub repository, edit its remotes or publish the app. Observe the original operation and committed upload, then reread source_get before planning the exact resulting commit.
File and request bounds
Managed source accepts at most 2,000 files, 2 MiB decoded per file or change batch, and 8 MiB decoded for the complete tree. These are server limits; a connected chat can have a smaller transfer capacity. Use a local publisher when that client cannot transfer the intended files. Use relative, archive-compatible ASCII paths, at most 240 characters. Paths cannot contain traversal, empty segments, backslashes, control characters or reserved credential directories. Private.env contents, keys, credentials, local link records, caches and dependency/build output are not application source. Preserve safe .env.example placeholders without real values. The local publisher filters the excluded files, honors ignore rules and refuses symbolic links; review its selected file inventory before saving.
Keep runtime values in private secret input. Source generation and parent-commit guards, saved idempotency keys and observed upload receipts remain required within these bounds.