@cogover/dev-cli
v0.21.0
Published
Develop and publish Node.js and TypeScript applications with Cogover
Maintainers
Readme
Cogover Dev CLI
Cogover Dev CLI connects a local Node.js or TypeScript application that uses
@cogover/sdk to its Cogover project, publishes versions, and activates them.
publish and activate support both Custom Backend and Custom Frontend Projects.
Local development with login / run uses the backend Project key workflow.
secrets, inbound, and jobs manage secrets, inbound webhook access, and
background jobs of a Custom Backend Project. git connects a backend or
frontend Project directory to its repository on the Workspace Git server.
Requirements
- Node.js 20 or newer.
- Git, for the
gitcommands.git setupusesgit init --initial-branchwhen available; the credential helper needs Git 2.26 or newer. - Optional but recommended: an operating-system credential service:
- macOS Keychain;
- Windows Credential Manager;
- Linux Secret Service/libsecret with a running secrets service.
The optional native keytar dependency connects the CLI to the operating-system
credential store. If it or the operating-system service is unavailable,
cogover-dev login automatically uses a profile-specific entry in the .env
file next to the nearest cogover.json. The CLI creates or updates .env, sets
restrictive file permissions where supported, preserves unrelated entries, and
adds /.env to the project's .gitignore before storing the key.
Installation
npm install --global @cogover/dev-cli --allow-scripts=keytarnpm 12 and newer run the install script of a dependency only when it is allowed.
--allow-scripts=keytar lets the optional keytar dependency install its
native binding, which connects the CLI to the operating-system credential store;
older npm versions ignore the flag. Without it the CLI still works, but keeps
Workspace API keys in the project .env and cannot store Git access tokens, so
git setup stops. cogover-dev doctor reports whether the credential store is
available.
Confirm the installation:
cogover-dev --version
cogover-dev --helpQuick start
Create a non-secret cogover.json file at the root of your application:
{
"version": 1,
"runtimeUrl": "https://your-workspace.cogover.net",
"projectId": "project-order-processor",
"projectSlug": "order-processor"
}Ask your Cogover workspace administrator for a project key, then save it in a local profile:
cogover-dev login --profile order-devThe CLI prompts for the key without echoing it. Passing a raw key on the command
line is not supported. Native credential storage is preferred. On a headless or
minimal system without it, login reports a warning and uses the project-local
.env fallback; therefore login must run inside a project containing
cogover.json.
Run your application through Cogover:
cogover-dev run -- npm run startThe CLI searches upward from the current directory for the nearest
cogover.json. The projectId selects a matching credential profile; the
optional projectSlug is a human-readable project name. The file contains no
credentials and is safe to commit.
Publish the src/ directory as a new version and activate the version reported
by the command:
cogover-dev publish
cogover-dev activate <version-id>Commands
Log in
cogover-dev login --profile <name>The runtime URL is selected in this order:
--runtime <url>COGOVER_RUNTIME_URL- the nearest
cogover.json https://typescript-runtime.cogover.net
For local development, HTTP is accepted only for loopback addresses. Remote runtime URLs must use HTTPS. The verification response does not replace this client-selected URL; the CLI stores and continues using the resolved URL so each workspace can use its own hostname.
Manage profiles
List non-secret profile metadata:
cogover-dev profiles listRemove a profile and its stored credential:
cogover-dev logout --profile <name>Run logout inside the project when its key may be stored in the project-local
.env fallback, so the CLI can remove that entry as well as the profile metadata.
If several profiles belong to the same project, link the current checkout to one profile. This mapping stays on your computer and is not written to the project:
cogover-dev link --profile <name>Profile selection uses an explicit --profile first, then the local checkout
link, then a unique project ID match.
Run a local application
cogover-dev run [--profile <name>] [--allow-writes[=true|false]] [--no-enforce-limits] -- <command...>Write access is enabled by default. Use a read-only session when the application must not change Cogover data:
cogover-dev run --allow-writes=false -- npm run startA writable session performs real side effects: besides record, state and lock
writes, push messages, notifications (notifications.send) and email
(email.send) reach real people of the Workspace or outside it, and
processes.start and agents.start start real Process instances and AI Agent
runs. A read-only session rejects all of them.
onComplete of processes.start and onResult of agents.start are refused
with NOT_SUPPORTED: their background job runs only in a published version of
the Project. Test the start without them and read the outcome with
processes.get or agents.get, then publish the Project to test the job.
--allow-writes, --allow-writes=true, and --allow-writes=false are valid.
When specifying a value, use =; --allow-writes false is rejected so that
false cannot be mistaken for part of the application command.
Global flags must appear before the -- separator. Everything after the
separator is passed unchanged to the application:
cogover-dev --verbose run -- npm run start
cogover-dev run -- npm --versionA Development session is short-lived and has a call budget. cogover-dev run
renews it automatically, shortly before it expires or when its budget is used up,
so a long-running application keeps working without restarting the command.
The development context reaches every Node.js process the command starts,
including processes started through launchers such as cross-env, dotenv-cli
or concurrently, and child processes created with child_process.fork or
cluster. On Windows, commands such as npm, npx and pnpm (.cmd files) are
started through cmd.exe with each argument quoted, so
cogover-dev run -- npm run start works as on macOS and Linux.
If COGOVER_LOCAL_PORT is set, the CLI waits up to 30 seconds for the application
to listen on that port. It reports LOCAL_SERVER_PORT_IN_USE when the port is
already occupied and LOCAL_SERVER_START_TIMEOUT when startup times out. In
either failure case, it stops the application process tree.
Per-invocation limits
In Cogover, every execution of a route, record trigger, background job, or
Custom Module Action has its own budgets, which differ by lane (HTTP route,
before-change trigger, after-change trigger, background job; an action has the
budgets of an HTTP route). cogover-dev run applies the same
budgets to your code while it runs locally, so a handler that would go over a
budget in Cogover fails the same way on your computer. The CLI uses the values
published by your Cogover environment, or the default values when the
environment does not provide them.
This requires @cogover/sdk 0.14.0 or later in the project. Each handler
invocation then gets its own counters:
- Capability calls (
capabilityCalls): every call to records, schema, state, locks, push, notifications, email, jobs, secrets,fetch, processes, or agents, and everyorgread withwithDisplay: true. - Local calls (
localCalls):cryptocalls andorgreads withoutwithDisplay. - Records read (
recordsRead): the records returned byrecords.get,records.getMany, andrecords.list. A read is refused before it is sent when it could go over the budget (records.getcounts 1,records.getManythe number of IDs,records.listitslimit, 20 by default).records.aggregatedoes not count. - Records written (
recordsWritten): 1 forcreate,update, andupsertByUniqueField, the number of records forbatchInsertandbatchUpdate, and the number of IDs fordeleteMany, counted when the call is sent. - Process and AI Agent starts: at most 20
processes.startand 5agents.startcalls per invocation, besides their capability calls. A start that Cogover refuses before counting it, for example because the Project policy does not allow it, does not use one. Going over fails withRATE_LIMITEDwithoutdetails.budget, as in Cogover.
A call over a budget is not sent: the SDK throws RateLimitError with
code: "RATE_LIMITED", and details.budget, details.limit, details.used
(and details.requested for records) describe it, as in Cogover.
limits.usage() reports the counters of the current invocation.
Local runs differ from Cogover in a few ways:
- Linked records read by
expandLookupsare not counted locally. - The time limit is reported by
limits.usage()but not enforced. - Code that calls the SDK outside a handler invocation, or a project using an SDK older than 0.14.0, is not limited locally.
- The Development session keeps its own call budget, independent of these per-invocation budgets.
To see how much a handler uses without having calls refused, add
--no-enforce-limits: every call is still counted in limits.usage(), but
none is refused because of a per-invocation budget.
cogover-dev run --no-enforce-limits -- npm run startPublish a Project version
cogover-dev publish [zip-file]The nearest cogover.json selects the Project. Its optional projectType must
be backend or frontend; omitting it defaults to backend, preserving
existing projects. Invalid values are rejected, not inferred from directories.
With no argument, the CLI creates a temporary ZIP containing src/ for backend
or dist/ for frontend, uploads it
as a private file, publishes a version, waits for READY or FAILED, and then
removes the temporary ZIP. Backend requires src/main.ts; frontend requires
dist/index.html. The CLI does not build frontend code: run your application's
build command first and ensure its output is in dist/. Files outside the
selected directory are not included. Generated frontend archives reject
symlinks, special files, unsafe paths, and paths differing only by case.
The CLI checks the same size limits as the server before uploading:
| Project type | ZIP file | ZIP entries | Total extracted | Per file | |---|---|---|---|---| | backend | 20 MiB | 512 | 20 MiB | 5 MiB | | frontend | 80 MiB | 2048 | 80 MiB | 20 MiB |
A generated archive that breaks a limit fails with SOURCE_ARCHIVE_TOO_LARGE,
SOURCE_ARCHIVE_FILE_TOO_LARGE, or SOURCE_ARCHIVE_TOO_MANY_FILES, naming the
file or directory and the limit. A supplied ZIP is checked for its size only;
the server validates its content and reports a failed build with the same kind
of message. Backend code is also limited when it is compiled: see the Custom
Backend Module API reference.
The ZIP is uploaded as a file of the Files field of the Contract object, so the
Workspace also applies that field's maximum file size, which can be lower than
the limits above. When it does, the command fails with
WORKSPACE_UPLOAD_TOO_LARGE; make the archive smaller or ask a Workspace
administrator to raise that field's maximum file size.
If a ZIP path is supplied, the CLI uploads that file and never removes it. The
archive must contain src/main.ts for backend or dist/index.html for frontend
with the containing directory preserved; supplied ZIP contents are validated by
the server. The configured type still selects the API, even with an explicit ZIP.
For a frontend Project, configure cogover.json as follows:
{
"version": 1,
"runtimeUrl": "https://your-workspace.cogover.net",
"projectId": "FEPXXXXXXXXXXXX",
"projectSlug": "sales_dashboard",
"projectType": "frontend"
}Then run:
npm run build
cogover-dev publish
cogover-dev activate FEVXXXXXXXXXXXXReplace the placeholders with your frontend Project ID, slug, Workspace URL,
and the actual version ID returned by publish. Publishing does not activate
the version automatically. Frontend management uses the /api/v1/ts-projects/frontend/
API; backend management keeps using /api/v1/ts-projects/ without that segment.
No backend Project key login is required to publish or activate a frontend.
Publishing uses a Workspace API key, which is separate from the Project key
used by login and run. The CLI checks COGOVER_API_KEY in the
Project .env first, then the operating-system credential store, and securely
prompts when neither contains a key. A prompted key is saved to native storage
when available, otherwise to the Project .env. The resulting Workspace
session used by publishing is short-lived, held only in memory, and never displayed.
If the Workspace rejects a stored key (for example, it was revoked or replaced),
the CLI says where the rejected key is stored and prompts once for a new one.
The accepted replacement overwrites the rejected key in the same place. Without
an interactive terminal, or when the replacement is also rejected, the command
fails with WORKSPACE_API_KEY_REJECTED and leaves the stored key unchanged. Use
cogover-dev auth logout to remove a stored key without replacing it.
The command prints the READY version ID and the exact activate command to run.
Use --json for machine-readable output.
Activate a Project version
cogover-dev activate <version-id>The version must belong to the Project in the nearest cogover.json and have
status READY. Activation uses the same Workspace API key resolution as
publish. Use --json for machine-readable output.
projectType selects the same API as publish, defaulting to backend when
omitted. Frontend Project/version IDs use FEP/FEV; backend uses TSP/TSV.
IDs belonging to the opposite type are rejected rather than switching the
configured type automatically. A version from another Project is also rejected.
Manage secrets
cogover-dev secrets set <name> [--kind opaque|bearer|basic|header] [--header-name <name>] \
[--allowed-host <host>]... [--description <text>] [--value-stdin | --value-file <path>]
cogover-dev secrets list
cogover-dev secrets delete <name> [--yes]Secrets belong to the backend Project in the nearest cogover.json and are
managed with the same Workspace API key resolution and short-lived Workspace
session as publish. A frontend Project is rejected. Names match
[A-Za-z][A-Za-z0-9_]{0,63}.
secrets set creates the secret or, when a secret with that name already
exists, updates its value. The value is never accepted as a command-line
argument. Supply it with --value-stdin (the whole standard input),
--value-file <path>, or, in an interactive terminal, the hidden prompt shown
when neither option is given. One trailing line break is removed from stdin and
file input, so echo and editor-created files work as expected.
--kind selects how the secret is used:
opaque(default for new secrets): read by scripts throughsecrets.get.bearer,basic,header: attached to outgoingfetchcalls as a credential. These kinds require at least one--allowed-host(an exact host or*.suffix, optionally followed by:port), andheaderalso requires--header-name. An entry without a port only allows port 443; useerp.example.com:9899for an HTTPS origin on another port, which the Project's identity policy must also approve. Credential values must be a single line.
When updating an existing secret, omitted options keep their current settings;
only the value and the options you pass change. The command prints metadata
only: ID, name, kind, status, and the new value version. --json emits
{ "ok": true, "action": "created" | "updated", "secret": { ... } }; the
secret value is never part of any output, log, or error message.
printf '%s' "$STRIPE_KEY" | cogover-dev secrets set stripe_key \
--kind bearer --allowed-host api.stripe.com --value-stdin
cogover-dev secrets set signing_key --value-file ./signing-key.pem
cogover-dev secrets list --json
cogover-dev secrets delete stripe_key --yessecrets delete asks for confirmation in an interactive terminal; pass --yes
in scripts. Declining the confirmation exits with OPERATION_CANCELLED.
Manage inbound access
cogover-dev inbound create <name> [--mode key|hmac] [--route-prefix <path>] [--expires-at <iso-8601>] \
[--hmac-header <name>] [--hmac-encoding hex|base64] [--hmac-prefix <text>] \
[--hmac-timestamp-header <name>] [--hmac-tolerance <seconds>] \
[--hmac-secret-stdin | --hmac-secret-file <path>]
cogover-dev inbound list
cogover-dev inbound rotate <inbound-id>
cogover-dev inbound revoke <inbound-id> [--yes]An inbound lets an external system call the backend Project's webhook routes.
inbound create prints the webhook URL returned by Cogover. --route-prefix
restricts the inbound to routes below /hooks, for example /hooks/stripe;
the default /hooks allows every route. --expires-at sets an ISO-8601 expiry
in the future.
In key mode (the default) Cogover issues an inbound key. The raw key is
printed exactly once, followed by a warning on stderr; store it immediately
because it cannot be retrieved later. With --json, the key is included as
inboundKey. The caller sends it as Authorization: Bearer <inbound-key> or in
the X-Cogover-Inbound-Key header. inbound rotate issues a replacement key,
again printed once, and invalidates the previous key immediately.
In hmac mode the external system signs each request with a shared secret.
Provide the signature header with --hmac-header and, optionally, the encoding,
a prefix such as sha256=, and a timestamp header with the allowed skew for
replay protection. The shared secret is read from --hmac-secret-stdin,
--hmac-secret-file, or the hidden prompt, and is never printed.
cogover-dev inbound create stripe --route-prefix /hooks/stripe
printf '%s' "$GITHUB_WEBHOOK_SECRET" | cogover-dev inbound create github --mode hmac \
--hmac-header X-Hub-Signature-256 --hmac-prefix sha256= --hmac-secret-stdin
cogover-dev inbound list
cogover-dev inbound revoke TSIXXXXXXXXXXXX --yesinbound list shows metadata only. inbound revoke is permanent and asks for
confirmation unless --yes is supplied.
Inspect background jobs
cogover-dev jobs runs [--job <key>] [--status PENDING|RUNNING|SUCCEEDED|FAILED] [--page <n>] [--page-size <n>]
cogover-dev jobs run <run-id>
cogover-dev jobs enqueue <key> [--payload-file <path>] [--delay-ms <n>] [--idempotency-key <key>]
cogover-dev jobs schedulesjobs runs lists runs of the backend Project newest first with paging
metadata; jobs run shows one run including attempts, timing, and the last
error. Both show the duration of the last attempt and what it used of its
budgets: capability and local calls, records read and written (durationMs
and usage with --json). They are empty (-, or null in JSON) when no
attempt has finished yet, when the attempt did not reach its handler, and for
runs recorded before Cogover kept them. Payloads are never returned, only their size. jobs enqueue creates a
run of a job defined by the active version, optionally with a JSON payload file
(at most 64 KiB), a delay in milliseconds, and an idempotency key; when the key
matches an existing run, the command reports that run with duplicate: true.
jobs schedules lists the cron schedules of the active version with their
next and last run times.
cogover-dev jobs runs --job recalc_totals --status FAILED
cogover-dev jobs enqueue recalc_totals --payload-file ./payload.json --idempotency-key order-42
cogover-dev jobs run TSJXXXXXXXXXXXX --jsonUse the Workspace Git repository
cogover-dev git setup [--remote <name>] [--no-remote] [--no-create]
cogover-dev git token create [--name <name>] [--print-token]
cogover-dev git token list [--account <account-id>]
cogover-dev git token delete <id> [--account <account-id>] [--yes]
cogover-dev git credential <get|store|erase>Each Workspace has a Git server at https://<workspace-domain>/git/, and each
backend or frontend Project can have one repository there. Git over HTTPS signs
in with your Git username and an access token. git setup and git token use
the Workspace in the nearest cogover.json and the same Workspace API key
resolution and short-lived Workspace session as publish; managing tokens and
repositories currently requires SuperAdmin.
Run git setup once in the Project directory:
cogover-dev git setup
git add . && git commit -m "Initial commit"
git push -u origin maingit setup:
Reads the Project repository and creates it when the Project has none (
--no-createfails withGIT_REPOSITORY_MISSINGinstead). A Workspace without Git fails withGIT_DISABLED.Creates your Git account when you have none.
Creates an access token named
cogover-dev@<computer>(with a number appended when that name is taken) and stores it in the operating-system credential store, unless the token stored for this Workspace still exists.Runs
git initwith branchmainwhen the directory is not in a Git repository, and writes to the repository configuration (not the global one):[credential "https://<workspace-domain>/git"] helper = helper = !cogover-dev git credential username = <your Git username>The empty
helperresets credential helpers configured globally, so Git asks onlycogover-devfor this Workspace. Settings that are already correct are left alone.Keeps a remote that already points to the repository, otherwise adds
origin, orcogoverwhenoriginpoints elsewhere (for example GitHub).--remote <name>chooses the name; an existing remote with that name must already point to the repository.--no-remoteadds none.
The command never commits, pushes, or changes history; it prints the next
commands instead. It warns when .env exists but is not ignored by Git, and
when cogover-dev is not on PATH: Git runs the helper by that name, so
install the CLI globally. --json emits the repository, Git username, token
metadata, credential context, remote, and next commands.
git token create creates a token of your Git account and stores it for the
Workspace, replacing the token stored there before; the replaced token keeps
working until you revoke it with git token delete. When the operating-system
credential store is unavailable, the command fails before creating a token;
there is no .env fallback for Git access tokens. --print-token also prints
the token value alone on one line of standard output, for another tool, with
the metadata and a warning on standard error; it cannot be combined with
--json. git token list shows ID, name, the last eight characters, scopes,
and which token is stored on this computer. git token delete revokes a token
after confirmation (--yes in scripts) and removes the stored copy when it is
your stored token. --account lists or revokes another user's tokens.
git credential is the credential helper that Git runs; you do not run it
yourself. For get with protocol https and the host of a Workspace with a
stored token, it answers the Git username and token; otherwise it answers
nothing, so Git uses its other credentials. erase removes the stored token
when Git reports that the Workspace rejected it; run git setup again to
create a new one. It needs no cogover.json and makes no network request.
Export a Workspace session for curl
Run inside a project containing cogover.json (or one of its subdirectories):
cogover-dev auth session
cogover-dev auth session --format curl --output .cogover-session.curlUses the same Workspace API key lookup as publish: project .env
COGOVER_API_KEY, native storage (cogover.api-key, workspace host), then a
hidden prompt. This is a Workspace API key, not a Project key. A successful
prompted key is saved using the same native-storage / .env fallback, and a
stored key the Workspace rejects is replaced the same way as in publish.
The default JSON contains workspaceUrl, workspaceId, workspaceDomain,
httpSessionExpiresAt, authTokenExpiresAt, expiresAt (the earlier expiry),
cookies, and headers. All expiry timestamps are Unix seconds. Both JSON and
curl config contain all three cookies (HttpSessionId, XSRF-TOKEN, AuthToken)
and matching x-csrf-token / x-xsrf-token headers. The Workspace API key is
never exported. Sessions expiring within 30 seconds are rejected.
Remove a stored Workspace API key
Run inside the project whose cogover.json names the Workspace:
cogover-dev auth logoutRemoves the Workspace API key stored for that Workspace from the
operating-system credential store and from the project .env COGOVER_API_KEY
entry, so the next publish, activate, or auth session prompts for a new
key. Other entries in .env are kept. The command succeeds when no key is
stored, and warns when the operating-system credential store cannot be reached.
Project keys stored by login are not affected; remove those with
cogover-dev logout --profile <name>.
For an API that requires reverse-proxy routing, supply the documented service
value for that endpoint yourself (replace both placeholders below). TypeScript
Project APIs (/api/v1/ts-projects/...) use x-req-type: 9: the response is the
Runtime's own HTTP status, headers, and body, without an envelope, and an error
generated by the proxy itself has the header x-proxy-error: 1:
curl --config .cogover-session.curl \
--header 'x-req-type: 9' \
--header 'x-req-service: <service-for-this-endpoint>' \
'https://<workspace-domain>/api/v1/ts-projects/<endpoint>'Other reverse-proxied Workspace APIs still use x-req-type: 6, which wraps the
result in {"serviceVersion", "service", "id", "type", "body"}.
Routing headers are deliberately not part of the export. Use the method, body,
and content type documented for the API. Send these credentials only to the
workspace that created them; the curl config does not constrain the target URL.
Endpoints under /bapi use Workspace API key Bearer authentication instead.
Without --output, stdout contains only the selected payload, suitable for
piping; notices including expiry go to stderr. With --output, stdout is empty
and the CLI writes a new file with mode 0600 (on POSIX systems), adding an
exact rule to .gitignore beside it. Paths are relative to your current working
directory; missing parent directories are created. Existing files, symlinks,
and Git-tracked output paths are refused. Remove expired credential files or
choose a new filename before generating another export. Do not share the files.
Shell redirection (> file) does not provide these permission/ignore protections.
The CLI reports the earlier expiry on stderr; rerun the command before that time
or if the session is revoked. It does not refresh exported credentials automatically.
--json is compatible with the default format but conflicts with --format curl.
Diagnose the environment
cogover-dev doctor
cogover-dev doctor --profile <name>doctor checks Node.js, native or project-local .env credential storage,
project configuration, profile matching, Cogover connectivity, and whether a
Git access token is stored for the project's Workspace. A usable
.env fallback is reported as a warning rather than an error. It does not open
a development session or read project records.
Generate shell completion
cogover-dev completion bash
cogover-dev completion zsh
cogover-dev completion fish
cogover-dev completion powershellThe command writes the completion script to standard output. Follow your shell's instructions to load or save it.
Output and diagnostics
--json provides machine-readable output for login, profiles list,
logout, link, publish, activate, auth logout, secrets, inbound, jobs,
git setup, git token, and doctor. auth session defaults to JSON.
cogover-dev profiles list --json
cogover-dev doctor --profile order-dev --jsonUse --verbose for redacted progress messages or --debug for redacted
diagnostic stack traces. ANSI color is enabled only in interactive terminals.
Use --no-color or the standard NO_COLOR environment variable to disable it;
use --color to force it.
Environment variables
| Variable | Purpose |
| --- | --- |
| COGOVER_RUNTIME_URL | Overrides the runtime URL when --runtime is not supplied. |
| COGOVER_LOCAL_PORT | Makes cogover-dev run wait for the local application port. |
| COGOVER_API_KEY | Project .env Workspace API key used by publish, activate, secrets, inbound, jobs, and auth session; removed by auth logout. |
| COGOVER_CONFIG_DIR | Overrides the operating-system-specific Cogover config directory. |
| NO_COLOR | Disables ANSI color output. |
Security and privacy
- Project keys are stored in the operating-system credential store when it is
available. Otherwise the CLI stores profile-specific entries in the project
root
.env; it never stores a key incogover.jsonor profile metadata files. - Workspace API keys are resolved separately from Project keys. A project-local
COGOVER_API_KEYtakes precedence over the native Workspace API key for that Workspace. A stored key is only overwritten after the Workspace has accepted its replacement, andauth logoutremoves it from both locations. GeneratedHttpSessionId,XSRF-TOKEN, andAuthTokenvalues are held only in memory, except when explicitly exported usingauth session. That command deliberately emits session secrets to stdout or a private, Git-ignored output file; diagnostic messages do not include them. - Secret values and HMAC shared secrets are read only from standard input, a file, or a hidden prompt, never from arguments. They are sent to Cogover once and never appear in command output, metadata, verbose or debug messages, or error text.
- An inbound key is shown exactly once, by
inbound createandinbound rotate(asinboundKeywith--json). It cannot be retrieved afterwards; rotate to replace it and revoke to disable it. - Git access tokens are kept only in the operating-system credential store
(
cogover.git-token, Workspace host), as{username, token, id, name}. They are never written to Git configuration,.env, command output, JSON, logs, or error text; onlygit token create --print-tokenand thegit credential getanswer to Git contain the value. The helper answers only HTTPS requests for the stored Workspace host and Git username. - The CLI adds
/.envto.gitignorebefore writing a fallback key. Verify that.envremains untracked and never commit or share it. - Project keys and short-lived session credentials are not added to the
application command line or process environment by the CLI. Application tools
that load
.envthemselves can read fallback entries, so native credential storage remains the preferred option. - Profile and checkout-link files contain non-secret metadata and use restrictive file permissions on operating systems that support POSIX modes.
- Remote connections require HTTPS. HTTP is accepted only for loopback addresses, and redirects are rejected.
- Read-only mode is enforced by Cogover when
--allow-writes=falseis used. - The CLI does not automatically retry record writes. The only exception is a call that Cogover refused before running it because the Development session had expired or used up its budget: it runs once on the renewed session.
Running an SDK application without cogover-dev run does not provide a Cogover
development context, so SDK operations fail with CAPABILITY_UNAVAILABLE.
License
MIT
