@colony2/c2j
v0.0.23
Published
c2j job system
Maintainers
Readme
c2j
c2j is the local job-oriented CLI for submitting and running recipe jobs through an SWF runtime.
Use it when you want to:
- submit a recipe job from a named recipe or a local recipe file
- run or continue an existing job
- use the embedded local runtime for fast iteration
- inspect the current cell configuration used for job targeting
- list jobs for a cell
Examples below assume you are running from the repo root.
Command Summary
c2j self
c2j cells
c2j init
c2j submit
c2j exec
c2j list
c2j testUse go run ./cmd/c2j --help or c2j --help to see the full command tree.
Quick Start
1. Check current-cell resolution
submit targets the current cell by default. That usually comes from .c2j/config.yaml, but supported project types can also be auto-detected.
Inspect the resolved config:
c2j selfList allowed dependent cells:
c2j cellsGenerate a starter config if needed:
c2j init --stdoutIf the current directory does not resolve as a cell, either:
- create
.c2j/config.yaml, or - pass
--cell <repo-or-path>explicitly tosubmitorlist
2. Submit and run a local recipe file
For local authoring, this is the default loop:
c2j submit \
--recipe-file ./recipes/my-recipe.yaml \
--run \
--embedThat does all of the following:
- loads the local YAML file
- embeds that recipe into the submitted job
- starts an embedded SWF runtime
- submits the job
- immediately executes it
3. Continue or inspect a job later
Find recent jobs for the current cell:
c2j list --self --embedContinue a submitted job:
c2j exec --job-id <job-id> --embedCurrent Cell Commands
c2j self
Shows how c2j resolves the current cell from .c2j/config.yaml or supported auto-detection.
c2j self
c2j self --jsonFields include:
short_namereporefroot_reporoot_refpattern
c2j cells
Lists dependent cells allowed by the current config.
c2j cells
c2j cells --jsonThis is mainly useful when you want to target another cell by short name and need to verify how config expands it.
c2j init
Writes a commented .c2j/config.yaml template.
c2j init
c2j init --stdout
c2j init --forceThe generated template can derive values from the Go module in the current repo when base: go is appropriate.
Submitting Jobs
Basic forms
Submit a named recipe:
c2j submit --recipe default --embed--recipe accepts a recipe name or git selector. For local files, prefer --recipe-file.
Submit a local recipe file:
c2j submit --recipe-file ./recipes/my-recipe.yaml --embedSubmit and run immediately:
c2j submit --recipe-file ./recipes/my-recipe.yaml --run --embedBy default, if neither --recipe nor --recipe-file is set, c2j submits the recipe named default.
Passing inputs
Inline JSON:
c2j submit \
--recipe-file ./recipes/my-recipe.yaml \
--inputs-json '{"message":"hello"}' \
--run \
--embedInputs file in JSON or YAML:
c2j submit \
--recipe-file ./recipes/my-recipe.yaml \
--inputs-file ./recipes/test-inputs.yaml \
--run \
--embedPositional prompt shortcut:
c2j submit "Summarize the repo" --recipe my-prompt-recipe --embedThe positional argument is merged as inputs.prompt.
Rules:
--inputs-jsonand--inputs-fileare mutually exclusive- the positional prompt cannot also be provided as
inputs.prompt
Attaching files
Attach local files as job artifacts with repeatable --artifact flags:
c2j submit \
--recipe-file ./recipes/review-docs.yaml \
--artifact ./docs/brief.md \
--artifact requirements=./docs/requirements.md \
--run \
--embed--artifact <path> uses the file basename as the artifact name.
--artifact <name>=<path> sets an explicit artifact name.
Recipes bind submitted artifacts into an op inbox explicitly:
sequence:
- id: inspect
op: command_execution
artifacts:
brief.md: '${{ context.artifacts["brief.md"] }}'
inputs:
run: 'cat "${{ context.environment.op.inbox }}/brief.md"'Choosing the target cell
Use the current cell:
c2j submit --recipe-file ./recipes/my-recipe.yaml --self --embedUse another cell explicitly:
c2j submit \
--recipe-file ./recipes/my-recipe.yaml \
--cell github.com/colony-2/root \
--embed--cell accepts:
- a canonical repo string
- a clone URL
- a local repository path
- a configured short name when
.c2j/config.yamldefines a pattern
Rules:
--selfand--cellare mutually exclusive- if no
--cellis given,c2jbehaves as if you targeted--self
Getting machine-readable output
If you only want the submitted job identity:
c2j submit \
--recipe-file ./recipes/my-recipe.yaml \
--json \
--embedThis emits:
{
"tenant_id": "0",
"job_id": "job-...",
"recipe": "my_recipe_id"
}Note:
--jsonand--runare mutually exclusive
Testing Recipes
c2j test compiles, validates, and runs recipe test suites locally. It does not call the old Colony2 API.
Compile a suite to canonical IR:
c2j test compile \
--recipe-file ./recipes/my-recipe.yaml \
--file ./recipes/my-recipe.test.yaml \
--out ./tmp/compiled-test.jsonRun a local suite:
c2j test run \
--recipe-file ./recipes/my-recipe.yaml \
--file ./recipes/my-recipe.test.yaml \
--artifact-mode inlineRun one case:
c2j test case run \
--recipe-file ./recipes/my-recipe.yaml \
--file ./recipes/my-recipe.test.yaml \
--case-id smokeUseful flags:
--recipe <name-or-git-selector>targets a current-cell recipe or explicit git selector--recipe-file <path>uses a local inline recipe file--case <id>filters suite mode to selected cases--parallelism <n>controls local case concurrency--out-dir <dir>defaults to.c2j/test-results/<timestamp>/- passthrough cases use a disposable embedded runtime root automatically; use
--runtime-rootand--keep-runtimeonly for debugging
Running Jobs
c2j exec executes or continues an existing job and prints live story progress to stdout.
Basic usage:
c2j exec --job-id <job-id> --embedCommon variants:
c2j exec --job-id <job-id> --wait-timeout 30m --embed
c2j exec --job-id <job-id> --input-mode fail --embed
c2j exec --job-id <job-id> --ci --embedImportant behavior:
- completed jobs return successfully
- failed jobs return a non-zero exit code
- suspended jobs may wait, prompt, or fail depending on flags
- when input is pending, interactive terminals default to prompting
- in CI or non-terminal mode, input handling defaults to
ops
Input handling
--input-mode controls what happens when a job is blocked on user input:
promptPrompt on stdin/stdout and submit the responseopsEmit machine-readableinput_requiredJSON and exit non-zerofailExit immediately when input is required
--ci enables machine-readable input-required behavior without prompting.
Not-ready handling
--on-not-ready controls how exec reacts when a job is not runnable yet:
waitfailfail-on-leasefail-on-pending-jobsfail-on-futurefail-on-missing-capability
With the default wait, exec will print waiting: ... lines and poll until the job becomes runnable or the wait timeout is reached.
Exit codes
c2j exec uses distinct exit codes:
1: general failure or job failure2: wait timeout3: input required4: job not runnable under the selected policy5: invalid job identity or invalid exec arguments
Listing Jobs
List jobs for the current cell:
c2j list --self --embedList as JSON:
c2j list --self --json --embedFilter by status:
c2j list --self --status pending_jobs --status active --embedList jobs for another cell:
c2j list --cell github.com/colony-2/root --embedUseful filters:
--job-id--job-type--status--waiting-for--created-after--created-before--page-size--page-token--all
Embedded Runtime
--embed is shorthand for:
--swf-url embed:///Use it when you want a local self-contained runtime instead of an external SWF server.
Behavior:
- starts embedded Postgres and Strata as needed
- uses a persistent runtime root on disk
- works well for local recipe authoring and debugging
Defaults:
- runtime URL:
embed:/// - runtime root:
~/.c2j/embed/default
You can override the root with:
export C2J_EMBED_ROOT=/absolute/path/to/embed-rootNotes:
C2J_EMBED_ROOTmust be an absolute path- only one
c2jprocess can own a given embedded runtime root at a time - if you need parallel embedded runtimes, give each process a different
C2J_EMBED_ROOT
Runtime and Tenant Defaults
c2j reads these environment variables:
C2J_SWF_URLC2J_TENANT_IDC2J_EMBED_ROOT
Built-in defaults:
C2J_SWF_URL:http://localhost:9047C2J_TENANT_ID:0
Examples:
export C2J_SWF_URL=http://localhost:9047
export C2J_TENANT_ID=123When --embed is present, it overrides C2J_SWF_URL for that command.
Common Workflows
Local recipe authoring loop
c2j self
c2j submit --recipe-file ./recipes/my-recipe.yaml --run --embedDetached submit, then later run
c2j submit --recipe-file ./recipes/my-recipe.yaml --json --embed
c2j exec --job-id <job-id> --embedRun against a remote runtime instead of embed
c2j submit \
--recipe-file ./recipes/my-recipe.yaml \
--swf-url http://localhost:9047 \
--runTarget another cell explicitly
c2j submit \
--recipe-file ./recipes/my-recipe.yaml \
--cell github.com/colony-2/root \
--run \
--embedGotchas
--recipeand--recipe-fileare mutually exclusive--jsonand--runare mutually exclusive onsubmit--inputs-jsonand--inputs-fileare mutually exclusive--selfand--cellare mutually exclusive--artifactnames must be unique relative paths; directories are not supported yetself,cells, and implicit current-cell submission depend on config or supported auto-detection succeeding- short cell names require a config pattern; without config, use an explicit repo or path
--recipe-fileis clearer than passing a local file path through--recipe
Related Files
- command entrypoint: main.go
- embedded runtime notes: embed-swf-mode-spec.md
- recipe authoring docs: RECIPE_AUTHORING_GUIDE.md
