Codex does not follow instructions correctly, goes off on tangent modifying files when not asked to do so based on assumptions without reading the files

Resolved 💬 2 comments Opened Apr 30, 2026 by mikeNickaloff Closed Apr 30, 2026

What version of Codex CLI is running?

0.125.0

What subscription do you have?

Pro

Which model were you using?

gpt-5.5 high

What platform is your computer?

x86_64 linux kubuntu 25

What terminal emulator and version are you using (if applicable)?

konsole

What issue are you seeing?

Codex has a weird tendency to just randomly start doing things now that were not requested after reading unrelated skill instructions when specified in AGENTS.md, it will incorrectly apply the skill and take the instructions from the skill and treat them as global instructions even though the global instructions say only a specific situation to use a specific skill, it will treat that skill's instructions as to be used everywhere, even outside of the stated situation.

As a result, codex displays strange behavior (may be partially model related as well).

Example:

When asked to create a q-factory QHTML element that supports this:

q-component mycomponent { 
div,span { text { hello world } }
}
q-factory myfactory { 
 mycomponent { } 
}
q-array instances { }

 button { onclick { var instance = myfactory.create(); instances.push(instance);  } text { click here to create } }

The way it created a q-factory shoould have been

q-component q-factory {
slot { main-slot }
function create() { var elem = document.createElement(this.component.slot("main-slot").qdom().tagName); return elem; }
}

But instead it returned this:

     1 +q-component q-factory {
      2 +  q-property target: ""
      3 +  q-property lastUuid: ""
      4 +  q-property count: 0
      5 +
      6 +  q-signal created(instance, qdomNode, uuid)
      7 +
      8 +  function getRootHost() {
      9 +    if (this.qhtml && this.qhtml.nodeType === 1) {
     10 +      return this.qhtml;
     11 +    }
     12 +    if (typeof this.closest === "function") {
     13 +      return this.closest("q-html");
     14 +    }
     15 +    return null;
     16 +  }
     17 +
     18 +  function getRootQDom() {
     19 +    var host = this.getRootHost();
     20 +    return host && typeof host.qdom === "function" ? host.qdom() : null;
     21 +  }
     22 +
     23 +  function getTemplateSlot() {
     24 +    var self = typeof this.qdom === "function" ? this.qdom() : null;
     25 +    return self && typeof self.slot === "function" ? self.slot("default") : null;
     26 +  }
     27 +
     28 +  function templateQHTML() {
     29 +    var slot = this.getTemplateSlot();
     30 +    if (!slot) {
     31 +      return "";
     32 +    }
     33 +    if (typeof slot.listChildren === "function") {
     34 +      var children = slot.listChildren();
     35 +      if (children && typeof children.qhtml === "function") {
     36 +        return String(children.qhtml({ preserveOriginal: false }) || "").trim();
     37 +      }
     38 +    }
     39 +    if (slot.children && typeof slot.children.qhtml === "function") {
     40 +      return String(slot.children.qhtml({ preserveOriginal: false }) || "").trim();
     41 +    }
     42 +    if (typeof slot.qhtml === "function") {
     43 +      return String(slot.qhtml({ preserveOriginal: false }) || "").trim();
     44 +    }
     45 +    return "";
     46 +  }
     47 +
     48 +  function resolveTargetQDom(root, targetOverride) {
     49 +    var rootQdom = root || this.getRootQDom();
     50 +    if (!rootQdom) {
     51 +      return null;
     52 +    }
     53 +    var targetValue = typeof targetOverride === "string" && targetOverride.trim()
     54 +      ? targetOverride
     55 +      : String(this.target || "").trim();
     56 +    if (!targetValue) {
     57 +      return rootQdom;
     58 +    }
     59 +    if (targetOverride && typeof targetOverride === "object") {
     60 +      if (typeof targetOverride.qdom === "function") {
     61 +        return targetOverride.qdom();
     62 +      }
     63 +      if (typeof targetOverride.appendNode === "function") {
     64 +        return targetOverride;
     65 +      }
     66 +    }
     67 +    if (typeof rootQdom.find === "function") {
     68 +      var found = rootQdom.find(targetValue);
     69 +      if (found && typeof found.appendNode === "function") {
     70 +        return found;
     71 +      }
     72 +    }
     73 +    return rootQdom;
     74 +  }
     75 +
     76 +  function normalizeCreatedNode(created) {
     77 +    if (!created) {
     78 +      return null;
     79 +    }
     80 +    if (Array.isArray(created)) {
     81 +      return created.length > 0 ? created[0] : null;
     82 +    }
     83 +    if (created.toArray && typeof created.toArray === "function") {
     84 +      var arr = created.toArray();
     85 +      return arr && arr.length > 0 ? arr[0] : null;
     86 +    }
     87 +    return created;
     88 +  }
     89 +
     90 +  function resolveCreatedElement(host, qdomNode) {
     91 +    if (!host || !qdomNode) {
     92 +      return null;
     93 +    }
     94 +    var uuid = String(qdomNode.UUID || (qdomNode.meta && qdomNode.meta.uuid) || "").trim();
     95 +    if (!uuid) {
     96 +      return null;
     97 +    }
     98 +    if (typeof host.elementForUuid === "function") {
     99 +      var byUuid = host.elementForUuid(uuid);
    100 +      if (byUuid) {
    101 +        return byUuid;
    102 +      }
    103 +    }
    104 +    if (host.querySelectorAll) {
    105 +      var all = host.querySelectorAll("[qdom-uuid='" + uuid + "'],[data-qdom-uuid='" + uuid + "']");
    106 +      if (all && all.length > 0) {
    107 +        return all[0];
    108 +      }
    109 +    }
    110 +    return null;
    111 +  }
    112 +
    113 +  function create(options) {
    114 +    var opts = options && typeof options === "object" ? options : {};
    115 +    var host = this.getRootHost();
    116 +    var root = host && typeof host.qdom === "function" ? host.qdom() : null;
    117 +    if (!host || !root || typeof root.createInstanceFromQHTML !== "function") {
    118 +      return null;
    119 +    }
    120 +
    121 +    var source = String(opts.source || this.templateQHTML() || "").trim();
    122 +    if (!source) {
    123 +      return null;
    124 +    }
    125 +
    126 +    var target = this.resolveTargetQDom(root, opts.target || "");
    127 +    if (!target || typeof target.appendNode !== "function") {
    128 +      return null;
    129 +    }
    130 +
    131 +    var created = root.createInstanceFromQHTML(source);
    132 +    var appended = target.appendNode(created);
    133 +    var createdNode = this.normalizeCreatedNode(appended) || this.normalizeCreatedNode(created);
    134 +    if (!createdNode) {
    135 +      return null;
    136 +    }
    137 +
    138 +    var targetUuid = String((target && target.UUID) || "").trim();
    139 +    if (typeof host.update === "function") {
    140 +      if (targetUuid) {
    141 +        host.update(targetUuid);
    142 +      } else {
    143 +        host.update();
    144 +      }
    145 +    }
    146 +
    147 +    var uuid = String(createdNode.UUID || (createdNode.meta && createdNode.meta.uuid) || "").trim();
    148 +    this.lastUuid = uuid;
    149 +    this.count = Number(this.count || 0) + 1;
    150 +
    151 +    var instance = this.resolveCreatedElement(host, createdNode);
    152 +    if (typeof this.created === "function") {
    153 +      this.created(instance, createdNode, uuid);
    154 +    }
    155 +    return instance || createdNode;
    156 +  }
    157 +
    158 +  div.q-factory-template {
    159 +    style { display: none; }
    160 +    slot { default }
    161 +  }
    162 +}

Its like going off on insane tangents instead of just doing the thing needed to implement the request and doesnt follow instructions in the AGENTS.md which state that it should not include type checking and null reference checks on functions since qhtml is declarative so it does not need procedural checking as everything is already declared by the time it reaches the javascript parsing which is after the qhtml is already fully parsed and instantiated.

But it just keeps on doing
if (!target || typeof target.appendNode !== "function") {

on every single line..

I think it doesn't really have the ability to understand what 'declarative' means and it only thinks from the point of view of javascript.

What steps can reproduce the bug?

clone qhtml6 repo https://github.com/qhtml/qhtml6 and then start new codex session and ask it to create some q-component with some functionality - you will see it spew out garbage trying to figure how to do that and it wont even read the README file or the docs folder and start just jamming out broken nonsensical code.

Try this prompt

"Create a qhtml-only animated square and ball that each animate separately by growing and shrinking based on a fixed timer."

Easily done using

q-painter mypainter {
   q-property scaleSquare: 1.0
   q-property scaleBall: 1.0
   onpaint { drawRect(10 * scaleSquare, ... );  drawCircle(10 * scaleCircle) }
}
q-timer { 
ontimeout { mypainter.scaleSquare = mypainter.scaleSquare + 0.1  or something }
}

You will see an implementation that is like 800 lines and it will likely modify multiple unrelated files and still not produce a valid output because its not doing its due diligence and researching before coding - it just jumps right in and starts making stuff up.

What is the expected behavior?

10 line solution fulfilling prompt request easily made after doing quick research in the repo

Additional information

Instead of trying to make it more token efficient, why dont you make it use some of those tokens to actually figure out what its doing before it does it so it doesn't become a huge mess.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗