ek9_write_file

Answers first: status (applied | ready | would-fail | conflicts), written, edits[{file, type:create|overwrite, bytesWritten}] and contentHash; a .ek9 write carries wouldBeDiagnostics from the verifying compile, any other file is written as-is.

Category: Editor · Compare: fs.writeFile / Write tool (Claude Code) / IDE write-back

When to use it

You are creating a file or replacing one whole - one call with path + content; a .ek9 path is compile-verified, any other file is written as-is. On create a .ek9 path gets the shebang / defines module / //EOF boilerplate when missing; a verified apply is rolled back on new errors.

When not to use it

Details

fileKind is inferred from the extension (.ek9 → ek9-source); pass it only to override. Boilerplate handling is create-only and idempotent on all three markers; on overwrite of ek9-source, missing markers attach warnings rather than mutating edited content. A .ek9 dry run scratch-compiles the would-be file (ready / would-fail); a .ek9 apply is verified by the post-write compile and rolled back on new diagnostics (would-fail + apply-rolled-back advisory, written:false) - wouldBeDiagnostics is present only on a verified write. Non-.ek9 targets are written without compile checking (non-ek9-file-not-compile-checked advisory). Writes are workspace-bounded and UTF-8; expectedContentHash (the contentHash ek9_read_file returned) guards overwrites against lost-update races; every applied write returns the new contentHash. An explicit module that diverges from the path-derived one attaches a module-name-mismatches-path warning — the write still succeeds.

Arguments

ArgumentTypeRequiredWhat it is
contentstringyesContent to write. For a .ek9 path on create, may be body-only — the writer prepends shebang + defines module and appends //EOF when missing.
createIntermediateDirsbooleanWhen true (default), missing parent directories are created automatically.
expectedContentHashstringThe contentHash ek9_read_file (or a prior write) returned for the file's CURRENT content; the write is refused when the file changed since (lost-update protection).
fileKindstring: text | ek9-source | env | configInferred from the extension (.ek9 → ek9-source, else text); pass it only to override. ek9-source: boilerplate injection on create + compile verification; env: KEY=VALUE; config: reserved.
modestring: auto | create-only | overwrite-onlyauto (default): create or overwrite; create-only: conflict if the file exists; overwrite-only: error if it doesn't.
modulestringFully-qualified EK9 module name for a .ek9 create. Optional — defaults to the path-derived module under the workspace source root; an explicit value that differs emits a 'module-name-mismatches-path' warning.
pathstringyesFile path: workspace-relative (preferred) or absolute inside the workspace. Created when absent (mode auto).

It also takes the arguments every tool takes.

Recorded calls

Real calls, recorded against small projects and checked on every build - a changed answer fails it. 3 of the 11 recorded are shown.

Write negated membership as sent

Request

{
  "content" : "#!ek9\ndefines module com.example.names\n\n  defines function\n\n    isNew() as pure\n      ->\n        name as String\n        names as List of String\n      <- rtn as Boolean: not name in names\n\n//EOF\n",
  "mode" : "create-only",
  "path" : "Names.ek9"
}

Response

{
  "conflicts" : [ ],
  "contentHash" : "sha256:109c174f2975113c5d175a4ad480666eecec1141e785453f2eda39fdc0dcbd7f",
  "edits" : [ {
    "boilerplateInjection" : {
      "eof" : "preserved",
      "module" : "preserved",
      "shebang" : "preserved"
    },
    "bytesWritten" : 194,
    "file" : "Names.ek9",
    "type" : "create"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 1,
    "lineCount" : 0,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
...

Cut short here: 6 more lines. The whole recorded call.

Write new ek9 file verified apply

Request

{
  "content" : "#!ek9\ndefines module com.example.greeter\n\n  defines function\n    greet()\n      stdout <- Stdout()\n      stdout.println(\"hello\")\n\n//EOF\n",
  "path" : "greeter.ek9"
}

Response

{
  "conflicts" : [ ],
  "contentHash" : "sha256:b39ae77c04a1126bb3aff9a756cf2e40155c298a86cc5381db1b449bb71b8ee0",
  "edits" : [ {
    "boilerplateInjection" : {
      "eof" : "preserved",
      "module" : "preserved",
      "shebang" : "preserved"
    },
    "bytesWritten" : 135,
    "file" : "greeter.ek9",
    "type" : "create"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 1,
    "lineCount" : 0,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
...

Cut short here: 6 more lines. The whole recorded call.

Write new text file apply

Request

{
  "content" : "Hello from probe.\n",
  "mode" : "create-only",
  "path" : "NOTES.txt"
}

Response

{
  "advisories" : [ {
    "kind" : "non-ek9-file-not-compile-checked",
    "message" : "Target is not an .ek9 source — written without compile verification."
  } ],
  "conflicts" : [ ],
  "contentHash" : "sha256:11c8e9f77d5df33f6a3b6e75f853c3bb151353b39bc07ec6c849186d5aaabc3b",
  "edits" : [ {
    "bytesWritten" : 18,
    "file" : "NOTES.txt",
    "type" : "create"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 1,
    "lineCount" : 0,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "applied",
...

Cut short here: 4 more lines. The whole recorded call.

See also