[{"data":1,"prerenderedAt":1363},["ShallowReactive",2],{"docs-page:en:\u002Fdocs\u002Ftooling\u002Fcli":3,"docs-navigation:en":1263},{"id":4,"title":5,"body":6,"description":1256,"extension":1257,"meta":1258,"navigation":595,"path":1259,"seo":1260,"stem":1261,"__hash__":1262},"docs_en\u002Fen\u002Fdocs\u002Ftooling\u002Fcli.md","CLI",{"type":7,"value":8,"toc":1237},"minimark",[9,17,20,25,39,89,93,96,110,113,117,120,143,146,157,160,164,171,174,194,198,201,204,344,350,364,368,371,456,470,474,477,480,514,517,521,524,527,621,624,705,711,722,726,729,736,743,746,749,760,763,767,778,784,787,830,833,837,840,991,997,1001,1004,1042,1047,1051,1098,1102,1105,1125,1141,1144,1158,1161,1165,1168,1171,1174,1185,1189,1192,1195,1203,1206,1210,1213,1230,1233],[10,11,12,16],"p",{},[13,14,15],"code",{},"@otalan\u002Fcli"," is the release automation companion for the Otalan control-plane workflow.",[10,18,19],{},"The dashboard is the right place to learn the model, inspect state, and operate the platform. The CLI is the right place to make packaging and publishing repeatable from a repository or CI pipeline.",[21,22,24],"h2",{"id":23},"package","Package",[26,27,28],"ul",{},[29,30,31],"li",{},[32,33,37],"a",{"href":34,"rel":35},"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@otalan\u002Fcli",[36],"nofollow",[13,38,15],{},[40,41,46],"pre",{"className":42,"code":43,"language":44,"meta":45,"style":45},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# Install the Otalan CLI globally with Bun.\nbun add -g @otalan\u002Fcli\n# Verify that the otalan command is available.\notalan version\n","bash","",[13,47,48,57,74,80],{"__ignoreMap":45},[49,50,53],"span",{"class":51,"line":52},"line",1,[49,54,56],{"class":55},"sHwdD","# Install the Otalan CLI globally with Bun.\n",[49,58,60,64,68,71],{"class":51,"line":59},2,[49,61,63],{"class":62},"sBMFI","bun",[49,65,67],{"class":66},"sfazB"," add",[49,69,70],{"class":66}," -g",[49,72,73],{"class":66}," @otalan\u002Fcli\n",[49,75,77],{"class":51,"line":76},3,[49,78,79],{"class":55},"# Verify that the otalan command is available.\n",[49,81,83,86],{"class":51,"line":82},4,[49,84,85],{"class":62},"otalan",[49,87,88],{"class":66}," version\n",[21,90,92],{"id":91},"what-the-cli-is-for","What the CLI is for",[10,94,95],{},"Use the CLI when you want:",[26,97,98,101,104,107],{},[29,99,100],{},"repeatable local release commands",[29,102,103],{},"CI-driven packaging and publish steps",[29,105,106],{},"repository-aware export and bundle preparation",[29,108,109],{},"a release workflow that can fail fast and clearly in automation",[10,111,112],{},"The CLI is especially useful once your team has already validated the tuple model and no longer wants release engineers to build ZIP files by hand.",[21,114,116],{"id":115},"what-the-cli-does","What the CLI does",[10,118,119],{},"At a high level, the CLI covers the release side of the workflow:",[26,121,122,125,128,131,134,137,140],{},[29,123,124],{},"authenticate against Otalan using an OTA Publish Key",[29,126,127],{},"link the repository to an Otalan app",[29,129,130],{},"prepare a bundle artifact",[29,132,133],{},"publish the release through the same validated publish flow the dashboard uses",[29,135,136],{},"inspect bundle history and active state",[29,138,139],{},"trigger rollback operations",[29,141,142],{},"pause or resume delivery of the currently active bundle",[10,144,145],{},"Rollback targets must already be registered in Otalan. If a version is not listed in bundle history for the tuple, the CLI cannot roll back to it.",[10,147,148,149,152,153,156],{},"Release automation clients can call ",[13,150,151],{},"GET \u002Fv1\u002Freleases\u002Fchannels",", optionally with ",[13,154,155],{},"appId",", to discover existing project channels and the active apps using each one.",[10,158,159],{},"The critical design point is that the CLI does not bypass the platform. It still publishes through the validated Otalan release flow.",[21,161,163],{"id":162},"supported-targets-and-runtime","Supported targets and runtime",[10,165,166,167,170],{},"The package ships a Bun entrypoint, not standalone native binaries. Bun ",[13,168,169],{},">= 1.3.11"," must be installed wherever the command runs.",[10,172,173],{},"Current package support is:",[26,175,176,179,182,188],{},[29,177,178],{},"macOS and Linux with Bun installed",[29,180,181],{},"Windows is experimental until the release flow is validated there",[29,183,184,185],{},"Capacitor 7 and 8 with ",[13,186,187],{},"--target capacitor",[29,189,190,191],{},"Expo SDK 54, 55, and 56 with ",[13,192,193],{},"--target expo",[21,195,197],{"id":196},"release-environment-variables","Release environment variables",[10,199,200],{},"Use CI secrets for publish credentials. Keep app runtime variables separate from release automation variables.",[10,202,203],{},"Typical CI variables:",[205,206,207,223],"table",{},[208,209,210],"thead",{},[211,212,213,217,220],"tr",{},[214,215,216],"th",{},"Variable",[214,218,219],{},"Used by",[214,221,222],{},"Purpose",[224,225,226,246,260,285,305,329],"tbody",{},[211,227,228,234,240],{},[229,230,231],"td",{},[13,232,233],{},"OTALAN_API_URL",[229,235,236,239],{},[13,237,238],{},"otalan login"," or CI script",[229,241,242,243],{},"Public Otalan API URL, such as ",[13,244,245],{},"https:\u002F\u002Fapi.otalan.com",[211,247,248,253,257],{},[229,249,250],{},[13,251,252],{},"OTALAN_API_KEY",[229,254,255,239],{},[13,256,238],{},[229,258,259],{},"OTA Publish Key created in the dashboard",[211,261,262,267,279],{},[229,263,264],{},[13,265,266],{},"OTALAN_APP_ID",[229,268,269,272,273,272,276],{},[13,270,271],{},"otalan init",", ",[13,274,275],{},"otalan bundle",[13,277,278],{},"otalan publish",[229,280,281,282],{},"Registered mobile app ID, such as ",[13,283,284],{},"com.example.app",[211,286,287,292,295],{},[229,288,289],{},[13,290,291],{},"OTALAN_PLATFORM",[229,293,294],{},"CI script",[229,296,297,300,301,304],{},[13,298,299],{},"ios"," or ",[13,302,303],{},"android"," release lane",[211,306,307,312,316],{},[229,308,309],{},[13,310,311],{},"OTALAN_CHANNEL",[229,313,314],{},[13,315,278],{},[229,317,318,319,272,322,325,326],{},"Release channel, such as ",[13,320,321],{},"production",[13,323,324],{},"beta",", or ",[13,327,328],{},"internal",[211,330,331,336,341],{},[229,332,333],{},[13,334,335],{},"OTALAN_RUNTIME_VERSION",[229,337,338,340],{},[13,339,275],{}," and publish metadata",[229,342,343],{},"Native compatibility line for the installed app",[10,345,346,347,349],{},"Do not use the OTA App Key for CLI publishing. Do not put ",[13,348,252],{}," in frontend, mobile, Expo public, or Vite public env variables.",[10,351,352,353,355,356,359,360,363],{},"The variable is named ",[13,354,252],{}," because the CLI sends it as API auth, but the value must be an OTA Publish Key. OTA Publish Keys use the ",[13,357,358],{},"otalan_ci_"," prefix. OTA App Keys use the ",[13,361,362],{},"otalan_ota_"," prefix and belong only in the installed app runtime.",[21,365,367],{"id":366},"command-map","Command map",[10,369,370],{},"The package-level command surface currently includes:",[26,372,373,382,388,393,399,407,418,423,429,435,441,447],{},[29,374,375,378,379],{},[13,376,377],{},"otalan help"," and ",[13,380,381],{},"otalan version",[29,383,384,387],{},[13,385,386],{},"otalan keygen"," for local OTA Publish Key or OTA App Key material generation",[29,389,390,392],{},[13,391,238],{}," for saving the OTA Publish Key and API URL",[29,394,395,398],{},[13,396,397],{},"otalan doctor"," for checking API connectivity and resolved project context",[29,400,401,403,404],{},[13,402,271],{}," for writing ",[13,405,406],{},"otalan.config.json",[29,408,409,411,412,378,415],{},[13,410,275],{}," for creating ",[13,413,414],{},".otalan\u002Fbundle\u002Fbundle-\u003Cbundle-id>.zip",[13,416,417],{},".otalan\u002Fbundle\u002Fmanifest.json",[29,419,420,422],{},[13,421,278],{}," for upload, validation polling, and activation",[29,424,425,428],{},[13,426,427],{},"otalan channels"," for listing release channels in the authenticated project",[29,430,431,434],{},[13,432,433],{},"otalan bundles"," for listing published bundles for a tuple",[29,436,437,440],{},[13,438,439],{},"otalan status"," for showing the active bundle",[29,442,443,446],{},[13,444,445],{},"otalan rollback"," for reactivating an older bundle in the same tuple",[29,448,449,378,452,455],{},[13,450,451],{},"otalan pause",[13,453,454],{},"otalan resume"," for pausing or resuming the active bundle rollout",[10,457,458,459,462,463,466,467,469],{},"The ",[13,460,461],{},".otalan\u002F"," folder is generated output. Add it to ",[13,464,465],{},".gitignore","; ",[13,468,278],{}," reads the generated ZIP and manifest from the current local or CI workspace.",[21,471,473],{"id":472},"capacitor-workflow","Capacitor workflow",[10,475,476],{},"For Capacitor apps, the CLI typically packages the built web output already produced by your application.",[10,478,479],{},"That means:",[26,481,482,485,488,502,508,511],{},[29,483,484],{},"your normal frontend build still runs first",[29,486,487],{},"the CLI packages the generated files",[29,489,490,491,494,495,498,499],{},"without ",[13,492,493],{},"--input-dir",", the CLI checks ",[13,496,497],{},"dist\u002F"," first and then ",[13,500,501],{},"www\u002F",[29,503,504,507],{},[13,505,506],{},"--input-dir \u003Cpath>"," points the CLI at a custom web output folder",[29,509,510],{},"the CLI uploads the archive through the Otalan publish flow",[29,512,513],{},"the CLI waits for validation to complete",[10,515,516],{},"The CLI makes the packaging step consistent, but it does not try to replace your application build command.",[21,518,520],{"id":519},"typical-capacitor-release-loop","Typical Capacitor release loop",[10,522,523],{},"For a Capacitor project, the local release flow is usually:",[10,525,526],{},"Run setup before the first local publish:",[40,528,530],{"className":42,"code":529,"language":44,"meta":45,"style":45},"# Save your OTA Publish Key and API URL.\notalan login --api-key \"$OTALAN_API_KEY\" --api-url \"${OTALAN_API_URL:-https:\u002F\u002Fapi.otalan.com}\"\n\n# Link this repository to the Otalan app.\notalan init --app-id \"$OTALAN_APP_ID\"\n",[13,531,532,537,591,597,602],{"__ignoreMap":45},[49,533,534],{"class":51,"line":52},[49,535,536],{"class":55},"# Save your OTA Publish Key and API URL.\n",[49,538,539,541,544,547,551,555,558,561,564,566,569,572,575,578,581,583,585,588],{"class":51,"line":59},[49,540,85],{"class":62},[49,542,543],{"class":66}," login",[49,545,546],{"class":66}," --api-key",[49,548,550],{"class":549},"sMK4o"," \"",[49,552,554],{"class":553},"sTEyZ","$OTALAN_API_KEY",[49,556,557],{"class":549},"\"",[49,559,560],{"class":66}," --api-url",[49,562,563],{"class":549}," \"${",[49,565,233],{"class":553},[49,567,568],{"class":549},":-",[49,570,571],{"class":553},"https",[49,573,574],{"class":549},":\u002F\u002F",[49,576,577],{"class":553},"api",[49,579,580],{"class":66},".",[49,582,85],{"class":553},[49,584,580],{"class":66},[49,586,587],{"class":553},"com",[49,589,590],{"class":549},"}\"\n",[49,592,593],{"class":51,"line":76},[49,594,596],{"emptyLinePlaceholder":595},true,"\n",[49,598,599],{"class":51,"line":82},[49,600,601],{"class":55},"# Link this repository to the Otalan app.\n",[49,603,605,607,610,613,615,618],{"class":51,"line":604},5,[49,606,85],{"class":62},[49,608,609],{"class":66}," init",[49,611,612],{"class":66}," --app-id",[49,614,550],{"class":549},[49,616,617],{"class":553},"$OTALAN_APP_ID",[49,619,620],{"class":549},"\"\n",[10,622,623],{},"Run for each new web release:",[40,625,627],{"className":42,"code":626,"language":44,"meta":45,"style":45},"# Build the Capacitor web assets.\nbun run build\n# Package the generated assets for one platform\u002Fruntime line.\notalan bundle --target capacitor --platform \"$OTALAN_PLATFORM\" --runtime-version \"$OTALAN_RUNTIME_VERSION\"\n# Upload, validate, and activate the bundle on one channel.\notalan publish --channel \"$OTALAN_CHANNEL\"\n",[13,628,629,634,644,649,682,687],{"__ignoreMap":45},[49,630,631],{"class":51,"line":52},[49,632,633],{"class":55},"# Build the Capacitor web assets.\n",[49,635,636,638,641],{"class":51,"line":59},[49,637,63],{"class":62},[49,639,640],{"class":66}," run",[49,642,643],{"class":66}," build\n",[49,645,646],{"class":51,"line":76},[49,647,648],{"class":55},"# Package the generated assets for one platform\u002Fruntime line.\n",[49,650,651,653,656,659,662,665,667,670,672,675,677,680],{"class":51,"line":82},[49,652,85],{"class":62},[49,654,655],{"class":66}," bundle",[49,657,658],{"class":66}," --target",[49,660,661],{"class":66}," capacitor",[49,663,664],{"class":66}," --platform",[49,666,550],{"class":549},[49,668,669],{"class":553},"$OTALAN_PLATFORM",[49,671,557],{"class":549},[49,673,674],{"class":66}," --runtime-version",[49,676,550],{"class":549},[49,678,679],{"class":553},"$OTALAN_RUNTIME_VERSION",[49,681,620],{"class":549},[49,683,684],{"class":51,"line":604},[49,685,686],{"class":55},"# Upload, validate, and activate the bundle on one channel.\n",[49,688,690,692,695,698,700,703],{"class":51,"line":689},6,[49,691,85],{"class":62},[49,693,694],{"class":66}," publish",[49,696,697],{"class":66}," --channel",[49,699,550],{"class":549},[49,701,702],{"class":553},"$OTALAN_CHANNEL",[49,704,620],{"class":549},[10,706,707,708,580],{},"Use your project's actual build command if it is not ",[13,709,710],{},"bun run build",[10,712,713,715,716,718,719,721],{},[13,714,275],{}," packages the generated web output linked by ",[13,717,271],{},". ",[13,720,278],{}," uploads the ZIP and waits for Otalan to validate and activate it.",[21,723,725],{"id":724},"expo-workflow","Expo workflow",[10,727,728],{},"Expo is where the CLI becomes especially valuable.",[10,730,731,732,735],{},"For Expo apps using ",[13,733,734],{},"expo-updates",", the CLI can run the export flow, package the exported assets, and generate the Otalan manifest required by the publish request.",[10,737,738,739,742],{},"For Expo, ",[13,740,741],{},"otalan bundle --target expo"," runs the Expo export and writes the generated Otalan manifest expected by publish.",[10,744,745],{},"The published ZIP is still retained as the release archive. Otalan also extracts and stores the Expo launch asset and listed assets, so dashboard storage for Expo releases is archive storage plus Expo asset storage.",[10,747,748],{},"That makes it a better long-term option than a purely manual dashboard flow when your team wants:",[26,750,751,754,757],{},[29,752,753],{},"repeatable exports",[29,755,756],{},"CI-friendly release automation",[29,758,759],{},"less room for human error in packaging",[10,761,762],{},"Otalan does not block older runtime versions by version number. Other runtimes and older Expo or Capacitor versions might work or might not, but they are not supported for the moment.",[21,764,766],{"id":765},"publish-options-that-matter-in-ci","Publish options that matter in CI",[10,768,769,771,772,300,775,580],{},[13,770,278],{}," reads the current bundle output, uploads the ZIP, and polls until validation reaches ",[13,773,774],{},"ready",[13,776,777],{},"failed",[10,779,780,781,783],{},"Use a current CLI version for CI publishing. ",[13,782,278],{}," applies the upload details returned by Otalan automatically, so oversized ZIP uploads can be rejected early.",[10,785,786],{},"Common release options:",[26,788,789,794,799,804,809,815,821],{},[29,790,791],{},[13,792,793],{},"--channel production",[29,795,796],{},[13,797,798],{},"--rollout-percent 25",[29,800,801],{},[13,802,803],{},"--optional",[29,805,806],{},[13,807,808],{},"--release-notes \"Fix startup crash\"",[29,810,811,814],{},[13,812,813],{},"--output-dir \u003Cpath>"," when publishing from a non-default bundle folder",[29,816,817,820],{},[13,818,819],{},"--bundle-id 1.0.5"," when generating a customer-facing release ID",[29,822,823,826,827],{},[13,824,825],{},"--bundle-from-package"," when the bundle ID should come from ",[13,828,829],{},"package.json",[10,831,832],{},"Release metadata is bounded before Otalan records release state. Keep app IDs and bundle IDs under 255 characters, channels and runtime versions under 128 characters, release notes under 4,000 characters, file names under 255 characters, content types under 128 characters, and generated Expo manifests under 256 KB.",[21,834,836],{"id":835},"ci-example","CI example",[10,838,839],{},"Use one job per app\u002Fplatform\u002Fruntime lane. Keep the publish key in the CI secret store.",[40,841,843],{"className":42,"code":842,"language":44,"meta":45,"style":45},"bun install --frozen-lockfile\nbun add -g @otalan\u002Fcli\notalan login --api-url \"$OTALAN_API_URL\" --api-key \"$OTALAN_API_KEY\"\notalan init --app-id \"$OTALAN_APP_ID\"\nbun run build\notalan bundle \\\n  --target capacitor \\\n  --platform \"$OTALAN_PLATFORM\" \\\n  --runtime-version \"$OTALAN_RUNTIME_VERSION\"\notalan publish \\\n  --channel \"$OTALAN_CHANNEL\" \\\n  --release-notes \"$GIT_COMMIT\"\n",[13,844,845,855,865,888,902,910,919,929,943,955,964,978],{"__ignoreMap":45},[49,846,847,849,852],{"class":51,"line":52},[49,848,63],{"class":62},[49,850,851],{"class":66}," install",[49,853,854],{"class":66}," --frozen-lockfile\n",[49,856,857,859,861,863],{"class":51,"line":59},[49,858,63],{"class":62},[49,860,67],{"class":66},[49,862,70],{"class":66},[49,864,73],{"class":66},[49,866,867,869,871,873,875,878,880,882,884,886],{"class":51,"line":76},[49,868,85],{"class":62},[49,870,543],{"class":66},[49,872,560],{"class":66},[49,874,550],{"class":549},[49,876,877],{"class":553},"$OTALAN_API_URL",[49,879,557],{"class":549},[49,881,546],{"class":66},[49,883,550],{"class":549},[49,885,554],{"class":553},[49,887,620],{"class":549},[49,889,890,892,894,896,898,900],{"class":51,"line":82},[49,891,85],{"class":62},[49,893,609],{"class":66},[49,895,612],{"class":66},[49,897,550],{"class":549},[49,899,617],{"class":553},[49,901,620],{"class":549},[49,903,904,906,908],{"class":51,"line":604},[49,905,63],{"class":62},[49,907,640],{"class":66},[49,909,643],{"class":66},[49,911,912,914,916],{"class":51,"line":689},[49,913,85],{"class":62},[49,915,655],{"class":66},[49,917,918],{"class":553}," \\\n",[49,920,922,925,927],{"class":51,"line":921},7,[49,923,924],{"class":66},"  --target",[49,926,661],{"class":66},[49,928,918],{"class":553},[49,930,932,935,937,939,941],{"class":51,"line":931},8,[49,933,934],{"class":66},"  --platform",[49,936,550],{"class":549},[49,938,669],{"class":553},[49,940,557],{"class":549},[49,942,918],{"class":553},[49,944,946,949,951,953],{"class":51,"line":945},9,[49,947,948],{"class":66},"  --runtime-version",[49,950,550],{"class":549},[49,952,679],{"class":553},[49,954,620],{"class":549},[49,956,958,960,962],{"class":51,"line":957},10,[49,959,85],{"class":62},[49,961,694],{"class":66},[49,963,918],{"class":553},[49,965,967,970,972,974,976],{"class":51,"line":966},11,[49,968,969],{"class":66},"  --channel",[49,971,550],{"class":549},[49,973,702],{"class":553},[49,975,557],{"class":549},[49,977,918],{"class":553},[49,979,981,984,986,989],{"class":51,"line":980},12,[49,982,983],{"class":66},"  --release-notes",[49,985,550],{"class":549},[49,987,988],{"class":553},"$GIT_COMMIT",[49,990,620],{"class":549},[10,992,993,994,996],{},"For Expo, use ",[13,995,193],{}," and run separate jobs for iOS and Android if their generated exports differ.",[21,998,1000],{"id":999},"rollback-flow","Rollback flow",[10,1002,1003],{},"Rollback is intentionally narrow:",[1005,1006,1007,1018,1033,1039],"ol",{},[29,1008,1009,1010,1012,1013,1017],{},"List the tuple with ",[13,1011,433],{}," or the dashboard ",[1014,1015,1016],"strong",{},"Bundles"," page.",[29,1019,1020,1021,272,1023,272,1026,1029,1030,580],{},"Choose a previous bundle that is already registered for the same ",[13,1022,155],{},[13,1024,1025],{},"platform",[13,1027,1028],{},"channel",", and ",[13,1031,1032],{},"runtimeVersion",[29,1034,1035,1036,1038],{},"Run ",[13,1037,445],{}," or use the dashboard rollback action.",[29,1040,1041],{},"Re-check the app and confirm it receives the restored bundle.",[10,1043,1044,1045,580],{},"Rollback does not change the native binary. If the problem requires a native plugin, permission, entitlement, or runtime-version change, ship a store update and publish future OTA bundles on a new ",[13,1046,1032],{},[21,1048,1050],{"id":1049},"common-failure-modes","Common failure modes",[26,1052,1053,1056,1061,1064,1073,1078,1083,1086,1092,1095],{},[29,1054,1055],{},"the CI job uses an OTA App Key instead of an OTA Publish Key",[29,1057,1058,1060],{},[13,1059,266],{}," does not match a registered app in the selected project",[29,1062,1063],{},"the selected app is archived or inactive",[29,1065,1066,272,1068,325,1070,1072],{},[13,1067,1025],{},[13,1069,1028],{},[13,1071,1032],{}," differs from the installed app",[29,1074,1075,1076],{},"Capacitor output was not built before ",[13,1077,275],{},[29,1079,1080,1081],{},"Expo publish omitted the generated ",[13,1082,417],{},[29,1084,1085],{},"Expo config uploaded by the generated manifest contains fields that should have stayed out of release metadata",[29,1087,1088,1089,1091],{},"CI uses stale or custom upload tooling instead of the current ",[13,1090,278],{}," flow",[29,1093,1094],{},"release notes or generated manifest metadata exceed API limits",[29,1096,1097],{},"a rollback target is not present in bundle history for the exact tuple",[21,1099,1101],{"id":1100},"dashboard-versus-cli","Dashboard versus CLI",[10,1103,1104],{},"Use the dashboard when you need:",[26,1106,1107,1110,1113,1116,1119,1122],{},[29,1108,1109],{},"a first publish path",[29,1111,1112],{},"operational visibility",[29,1114,1115],{},"bundle history inspection",[29,1117,1118],{},"manual rollout changes",[29,1120,1121],{},"manual rollback",[29,1123,1124],{},"workspace, billing, and credential administration",[10,1126,1127,1128,1130,1131,1133,1134,1137,1138,1140],{},"Manual dashboard publishing still uses a CLI-generated artifact. Run ",[13,1129,275],{}," in the app repository, then upload ",[13,1132,414],{}," on the ",[1014,1135,1136],{},"Publish"," page. For Expo releases, use ",[13,1139,417],{}," in the Expo manifest field too.",[10,1142,1143],{},"Use the CLI when you need:",[26,1145,1146,1149,1152,1155],{},[29,1147,1148],{},"automation",[29,1150,1151],{},"repeatability",[29,1153,1154],{},"repository-aware packaging",[29,1156,1157],{},"CI integration",[10,1159,1160],{},"The two tools are complementary. Most teams should start with the dashboard, then move the publish step into the CLI when the process stabilizes.",[21,1162,1164],{"id":1163},"credentials-and-keys","Credentials and keys",[10,1166,1167],{},"The CLI should use an OTA Publish Key, not an OTA App Key.",[10,1169,1170],{},"Create that OTA Publish Key in the dashboard, either by letting Otalan generate it or by registering a locally generated suffix for the OTA Publish Key type.",[10,1172,1173],{},"That separation matters because:",[26,1175,1176,1179,1182],{},[29,1177,1178],{},"OTA App Keys belong inside supported app runtime flows",[29,1180,1181],{},"OTA Publish Keys belong in the CLI and release automation",[29,1183,1184],{},"operator actions remain easier to reason about when credentials are scoped correctly",[21,1186,1188],{"id":1187},"exit-behavior-and-release-confidence","Exit behavior and release confidence",[10,1190,1191],{},"One of the most useful properties of the CLI is that publish automation can treat the final exit result as meaningful.",[10,1193,1194],{},"In the intended workflow:",[26,1196,1197,1200],{},[29,1198,1199],{},"success means validation completed and the release reached a ready state",[29,1201,1202],{},"failure means validation or activation did not complete successfully",[10,1204,1205],{},"That gives CI a reliable contract instead of a fire-and-forget upload.",[21,1207,1209],{"id":1208},"documentation-boundary","Documentation boundary",[10,1211,1212],{},"These docs explain how the CLI fits into the product model. The dedicated package documentation should still own:",[26,1214,1215,1218,1221,1224,1227],{},[29,1216,1217],{},"installation steps",[29,1219,1220],{},"exact command syntax",[29,1222,1223],{},"repository configuration",[29,1225,1226],{},"CI examples",[29,1228,1229],{},"troubleshooting for package-level behavior",[10,1231,1232],{},"That split keeps the control-plane docs focused and prevents duplication of package-specific reference material.",[1234,1235,1236],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}",{"title":45,"searchDepth":76,"depth":76,"links":1238},[1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250,1251,1252,1253,1254,1255],{"id":23,"depth":59,"text":24},{"id":91,"depth":59,"text":92},{"id":115,"depth":59,"text":116},{"id":162,"depth":59,"text":163},{"id":196,"depth":59,"text":197},{"id":366,"depth":59,"text":367},{"id":472,"depth":59,"text":473},{"id":519,"depth":59,"text":520},{"id":724,"depth":59,"text":725},{"id":765,"depth":59,"text":766},{"id":835,"depth":59,"text":836},{"id":999,"depth":59,"text":1000},{"id":1049,"depth":59,"text":1050},{"id":1100,"depth":59,"text":1101},{"id":1163,"depth":59,"text":1164},{"id":1187,"depth":59,"text":1188},{"id":1208,"depth":59,"text":1209},"Learn when to use the Otalan CLI, what workflows it covers, and how it complements the dashboard instead of replacing the platform model.","md",{},"\u002Fen\u002Fdocs\u002Ftooling\u002Fcli",{"title":5,"description":1256},"en\u002Fdocs\u002Ftooling\u002Fcli","R0B6vhds8Pn3BZGu0DvdAoUcXdwyylx-zdwz7ZlGxA8",[1264],{"title":1265,"path":1266,"stem":1267,"children":1268,"page":1286},"En","\u002Fen","en",[1269],{"title":1270,"path":1271,"stem":1272,"children":1273,"description":1275},"Introduction","\u002Fen\u002Fdocs","en\u002Fdocs\u002Findex",[1274,1276,1287,1297,1307,1317,1337,1353],{"title":1270,"path":1271,"stem":1272,"description":1275},"Understand what Otalan is, when to use it, and how the first safe OTA release flow works for Capacitor and Expo apps.",{"title":1277,"path":1278,"stem":1279,"children":1280,"page":1286},"About","\u002Fen\u002Fdocs\u002Fabout","en\u002Fdocs\u002Fabout",[1281],{"title":1282,"path":1283,"stem":1284,"description":1285},"Security and trust","\u002Fen\u002Fdocs\u002Fabout\u002Fsecurity-trust","en\u002Fdocs\u002Fabout\u002Fsecurity-trust","How Otalan keeps OTA releases controlled: scoped keys, bundle validation, exact matching, rollout controls, rollback, deletion behavior, and support contact.",false,{"title":1288,"path":1289,"stem":1290,"children":1291,"page":1286},"Build","\u002Fen\u002Fdocs\u002Fbuild","en\u002Fdocs\u002Fbuild",[1292],{"title":1293,"path":1294,"stem":1295,"description":1296},"Generate a bundle","\u002Fen\u002Fdocs\u002Fbuild\u002Fgenerate-bundle","en\u002Fdocs\u002Fbuild\u002Fgenerate-bundle","Prepare a release artifact that will pass Otalan's validation pipeline, including the extra considerations required for Expo-based publish flows.",{"title":1298,"path":1299,"stem":1300,"children":1301,"page":1286},"Deploy","\u002Fen\u002Fdocs\u002Fdeploy","en\u002Fdocs\u002Fdeploy",[1302],{"title":1303,"path":1304,"stem":1305,"description":1306},"Publish a release","\u002Fen\u002Fdocs\u002Fdeploy\u002Fpublish-release","en\u002Fdocs\u002Fdeploy\u002Fpublish-release","Submit a release through the dashboard, understand each field in the publish form, and operate the validation lifecycle with confidence.",{"title":1308,"path":1309,"stem":1310,"children":1311,"page":1286},"Integration","\u002Fen\u002Fdocs\u002Fintegration","en\u002Fdocs\u002Fintegration",[1312],{"title":1313,"path":1314,"stem":1315,"description":1316},"Migrate from App Center CodePush","\u002Fen\u002Fdocs\u002Fintegration\u002Fapp-center-codepush","en\u002Fdocs\u002Fintegration\u002Fapp-center-codepush","Plan a migration from Microsoft App Center CodePush to Otalan, with mapping notes, rollout guidance, and common failure modes.",{"title":1318,"path":1319,"stem":1320,"children":1321,"page":1286},"Quick Start","\u002Fen\u002Fdocs\u002Fquick-start","en\u002Fdocs\u002Fquick-start",[1322,1327,1332],{"title":1323,"path":1324,"stem":1325,"description":1326},"Capacitor quick start","\u002Fen\u002Fdocs\u002Fquick-start\u002Fcapacitor","en\u002Fdocs\u002Fquick-start\u002Fcapacitor","Wire the Otalan Capacitor runtime into an installed app so it can check for OTA updates, install compatible bundles, and confirm successful launches.",{"title":1328,"path":1329,"stem":1330,"description":1331},"Expo quick start","\u002Fen\u002Fdocs\u002Fquick-start\u002Fexpo","en\u002Fdocs\u002Fquick-start\u002Fexpo","Configure expo-updates with Otalan, add the Otalan Expo helper, and make the installed app ready to receive compatible OTA bundles.",{"title":1333,"path":1334,"stem":1335,"description":1336},"Publish in 5 minutes","\u002Fen\u002Fdocs\u002Fquick-start\u002Fquick-start","en\u002Fdocs\u002Fquick-start\u002Fquick-start","Create the first Otalan release path, publish a baseline bundle, verify one update, and prove rollback before widening rollout.",{"title":1338,"path":1339,"stem":1340,"children":1341,"page":1286},"Tooling","\u002Fen\u002Fdocs\u002Ftooling","en\u002Fdocs\u002Ftooling",[1342,1347,1348],{"title":1343,"path":1344,"stem":1345,"description":1346},"AI skill","\u002Fen\u002Fdocs\u002Ftooling\u002Fai-skill","en\u002Fdocs\u002Ftooling\u002Fai-skill","Copy a compact assistant skill for Otalan SDK setup, CLI publishing, and safe credential boundaries.",{"title":5,"path":1259,"stem":1261,"description":1256},{"title":1349,"path":1350,"stem":1351,"description":1352},"SDKs","\u002Fen\u002Fdocs\u002Ftooling\u002Fsdk","en\u002Fdocs\u002Ftooling\u002Fsdk","Understand the difference between the Capacitor and Expo integrations, and choose the runtime package that matches the way your mobile app actually updates.",{"title":1354,"path":1355,"stem":1356,"children":1357,"page":1286},"Versions","\u002Fen\u002Fdocs\u002Fversions","en\u002Fdocs\u002Fversions",[1358],{"title":1359,"path":1360,"stem":1361,"description":1362},"v1","\u002Fen\u002Fdocs\u002Fversions\u002Fv1","en\u002Fdocs\u002Fversions\u002Fv1","Supported runtimes, public limits, and post-v1 candidates for Otalan v1.",1780287526992]