ccx-native 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +240 -4
  3. package/bin/ccx +55 -2
  4. package/ccx/__init__.py +167 -0
  5. package/ccx/__main__.py +28 -0
  6. package/ccx/claude/__init__.py +0 -0
  7. package/ccx/claude/analytics.py +466 -0
  8. package/ccx/claude/attach.py +807 -0
  9. package/ccx/claude/context.py +465 -0
  10. package/ccx/claude/delivery.py +806 -0
  11. package/ccx/claude/external.py +253 -0
  12. package/ccx/claude/host/__init__.py +0 -0
  13. package/ccx/claude/host/events.py +297 -0
  14. package/ccx/claude/host/hooks.py +438 -0
  15. package/ccx/claude/host/pty.py +269 -0
  16. package/ccx/claude/host/session.py +5244 -0
  17. package/ccx/claude/host/subagents.py +169 -0
  18. package/ccx/claude/host/successor.py +267 -0
  19. package/ccx/claude/managed_turns.py +240 -0
  20. package/ccx/claude/oauth.py +176 -0
  21. package/ccx/claude/settings.py +339 -0
  22. package/ccx/claude/spawn.py +557 -0
  23. package/ccx/claude/tasks.py +72 -0
  24. package/ccx/claude/telemetry.py +282 -0
  25. package/ccx/claude/transcript.py +2535 -0
  26. package/ccx/claude/usage.py +796 -0
  27. package/ccx/claude/usage_control.py +204 -0
  28. package/ccx/cli/__init__.py +0 -0
  29. package/ccx/cli/codex.py +1009 -0
  30. package/ccx/cli/commands/__init__.py +0 -0
  31. package/ccx/cli/commands/_common.py +407 -0
  32. package/ccx/cli/commands/control.py +161 -0
  33. package/ccx/cli/commands/create.py +669 -0
  34. package/ccx/cli/commands/models.py +53 -0
  35. package/ccx/cli/commands/read.py +1104 -0
  36. package/ccx/cli/commands/turns.py +1081 -0
  37. package/ccx/cli/controller.py +757 -0
  38. package/ccx/cli/main.py +302 -0
  39. package/ccx/cli/parser.py +1439 -0
  40. package/ccx/cli/skills.py +215 -0
  41. package/ccx/cli/statusline.py +160 -0
  42. package/ccx/client.py +1904 -0
  43. package/ccx/codex/__init__.py +0 -0
  44. package/ccx/codex/attach_tty.py +267 -0
  45. package/ccx/codex/client.py +738 -0
  46. package/ccx/codex/completion.py +121 -0
  47. package/ccx/codex/control.py +288 -0
  48. package/ccx/codex/daemon/__init__.py +0 -0
  49. package/ccx/codex/daemon/__main__.py +4 -0
  50. package/ccx/codex/daemon/daemon.py +1558 -0
  51. package/ccx/codex/daemon/models.py +140 -0
  52. package/ccx/codex/daemon/native.py +1590 -0
  53. package/ccx/codex/daemon/release.py +367 -0
  54. package/ccx/codex/daemon/worker.py +2424 -0
  55. package/ccx/codex/delivery.py +758 -0
  56. package/ccx/codex/delivery_recovery.py +232 -0
  57. package/ccx/codex/evidence.py +827 -0
  58. package/ccx/codex/history.py +158 -0
  59. package/ccx/codex/history_store.py +131 -0
  60. package/ccx/codex/notify_history.py +140 -0
  61. package/ccx/codex/ops.py +666 -0
  62. package/ccx/codex/paths.py +70 -0
  63. package/ccx/codex/protocol.py +805 -0
  64. package/ccx/codex/provenance.py +105 -0
  65. package/ccx/codex/read.py +29 -0
  66. package/ccx/codex/records.py +51 -0
  67. package/ccx/codex/reports.py +177 -0
  68. package/ccx/codex/runtime.py +1454 -0
  69. package/ccx/codex/settle.py +363 -0
  70. package/ccx/codex/telemetry.py +792 -0
  71. package/ccx/codex/types.py +659 -0
  72. package/ccx/codex/worker_environment.py +25 -0
  73. package/ccx/constants.py +288 -0
  74. package/ccx/controllers/__init__.py +0 -0
  75. package/ccx/controllers/controller.py +1449 -0
  76. package/ccx/controllers/live_vars.py +1706 -0
  77. package/ccx/controllers/live_vars_runner.py +216 -0
  78. package/ccx/controllers/notify.py +213 -0
  79. package/ccx/controllers/orchestrator.py +193 -0
  80. package/ccx/controllers/policy.py +57 -0
  81. package/ccx/controllers/store.py +681 -0
  82. package/ccx/errors.py +634 -0
  83. package/ccx/models.py +225 -0
  84. package/ccx/notify/__init__.py +0 -0
  85. package/ccx/notify/__main__.py +5 -0
  86. package/ccx/notify/client.py +116 -0
  87. package/ccx/notify/daemon.py +480 -0
  88. package/ccx/notify/deliver.py +304 -0
  89. package/ccx/notify/paths.py +51 -0
  90. package/ccx/notify/registry.py +649 -0
  91. package/ccx/notify/select.py +750 -0
  92. package/ccx/notify/settle.py +684 -0
  93. package/ccx/ops/__init__.py +0 -0
  94. package/ccx/ops/background.py +115 -0
  95. package/ccx/ops/cancel.py +296 -0
  96. package/ccx/ops/codex_import.py +96 -0
  97. package/ccx/ops/common.py +397 -0
  98. package/ccx/ops/compact.py +337 -0
  99. package/ccx/ops/compact_ops.py +550 -0
  100. package/ccx/ops/context_events.py +48 -0
  101. package/ccx/ops/conversation.py +1593 -0
  102. package/ccx/ops/conversation_paging.py +1339 -0
  103. package/ccx/ops/create.py +56 -0
  104. package/ccx/ops/creation.py +952 -0
  105. package/ccx/ops/creation_steps.py +575 -0
  106. package/ccx/ops/event_feed.py +710 -0
  107. package/ccx/ops/forking.py +711 -0
  108. package/ccx/ops/history.py +1041 -0
  109. package/ccx/ops/input.py +556 -0
  110. package/ccx/ops/maintenance.py +295 -0
  111. package/ccx/ops/report.py +773 -0
  112. package/ccx/ops/semantics.py +490 -0
  113. package/ccx/ops/send.py +961 -0
  114. package/ccx/ops/steer_ops.py +867 -0
  115. package/ccx/ops/terminate.py +383 -0
  116. package/ccx/ops/turn_reports.py +348 -0
  117. package/ccx/ops/wait.py +762 -0
  118. package/ccx/ops/worker_events.py +640 -0
  119. package/ccx/rpc/__init__.py +0 -0
  120. package/ccx/rpc/local_rpc.py +1602 -0
  121. package/ccx/rpc/rpc.py +559 -0
  122. package/ccx/rpc/serve.py +374 -0
  123. package/ccx/rpc/transport.py +409 -0
  124. package/ccx/rpc/view.py +125 -0
  125. package/ccx/store/__init__.py +0 -0
  126. package/ccx/store/discovery.py +170 -0
  127. package/ccx/store/identity.py +105 -0
  128. package/ccx/store/journal_io.py +79 -0
  129. package/ccx/store/liveness.py +194 -0
  130. package/ccx/store/paths.py +250 -0
  131. package/ccx/store/record_cache.py +40 -0
  132. package/ccx/store/records.py +309 -0
  133. package/ccx/store/root.py +789 -0
  134. package/ccx/store/runtime_presence.py +137 -0
  135. package/ccx/store/store.py +2332 -0
  136. package/ccx/store/worker_state.py +86 -0
  137. package/ccx/system/__init__.py +0 -0
  138. package/ccx/system/bounded.py +296 -0
  139. package/ccx/system/cwd_paths.py +25 -0
  140. package/ccx/system/engine_binary.py +59 -0
  141. package/ccx/system/executable.py +50 -0
  142. package/ccx/system/oslayer.py +667 -0
  143. package/ccx/system/pipes.py +46 -0
  144. package/ccx/system/private_json.py +54 -0
  145. package/ccx/system/sanitize.py +43 -0
  146. package/ccx/types.py +809 -0
  147. package/ccx/version.py +29 -0
  148. package/ccx/workers.py +2093 -0
  149. package/ccx.py +9 -0
  150. package/package.json +39 -7
  151. package/pyproject.toml +87 -0
  152. package/skills/ccx/SKILL.md +166 -0
  153. package/skills/ccx/references/controllers.md +244 -0
  154. package/skills/ccx/references/history.md +50 -0
  155. package/skills/ccx/references/troubleshooting.md +94 -0
  156. package/skills/ccx/references/variables.md +62 -0
@@ -0,0 +1,94 @@
1
+ # ccx troubleshooting
2
+
3
+ ## Delivery and steering
4
+
5
+ `send` and `steer` have delivery ids (`--json`, or supply `--delivery-id`).
6
+ Retry the same message with the same id to avoid duplicate delivery.
7
+ `ccx reconcile TARGET --delivery-id ID` checks without sending; Codex also
8
+ accepts `--turn-id`.
9
+
10
+ If a `new` reply was lost, `ccx list` may find the worker. For retryable
11
+ creation, choose a UUIDv4 first and reuse it with `--worker-id`; bare `new`
12
+ always creates another worker.
13
+
14
+ A Claude `steer` watches for where the message landed:
15
+
16
+ | Status | Meaning |
17
+ |---|---|
18
+ | `consumed-current-turn` | the running turn took it |
19
+ | `started-next-turn` | it runs as the next turn |
20
+ | `accepted-pending` | ccx holds it; placement is unproven. Wait or reconcile; don't resend. |
21
+ | `unknown` | reconcile before retrying |
22
+
23
+ Pending Claude steering blocks other sends and steers; the refusal names its
24
+ delivery id. Codex steering accepts or rejects at once.
25
+
26
+ ## Stopped, failed and revived workers
27
+
28
+ Idle workers stop after `--idle-timeout`. Stopped or failed workers revive on
29
+ `send`, keeping their history. Interrupted turns aren't resumed or resent:
30
+ check `report`, then send what remains.
31
+
32
+ `ccx resume TARGET` reloads without starting a turn. `ccx shutdown` stops
33
+ runtimes, preserving histories; `--engine` limits it to one engine.
34
+
35
+ ## Workers waiting on background work
36
+
37
+ A Claude worker can finish a turn while a background task or monitor keeps
38
+ running, then wake for another turn. `peek` and `report` show background tasks.
39
+
40
+ To follow finite work the worker is waiting on (tests or a build):
41
+
42
+ - Claude or a person: `ccx wait TARGET --next-turn`
43
+ - Codex: `ccx notify TARGET --next-turn`
44
+
45
+ A server or watcher left running doesn't mean the work is unfinished.
46
+
47
+ ## Input requests
48
+
49
+ `ccx peek TARGET` shows pending input and its request id.
50
+
51
+ - **Question (Claude):** `ccx answer TARGET "Option label"`; see help for
52
+ multiple questions or selections.
53
+ - **Permission:** `ccx approve TARGET` or `ccx reject TARGET`.
54
+ - **MCP server form (Claude):** `ccx respond TARGET --accept --field
55
+ name=value`, `--decline` or `--cancel`.
56
+
57
+ To follow the resumed turn, Claude/human parents add `--wait` where supported;
58
+ Codex parents use `--notify-parent`.
59
+
60
+ ## Context and compaction
61
+
62
+ Right after compaction, `ccx context TARGET --json` may show `tokens_used: null`
63
+ until the next reading; `reason` explains why.
64
+
65
+ Claude compaction revives stopped workers; Codex compaction needs an idle
66
+ worker. `ccx notify TARGET` follows a compaction already running.
67
+
68
+ `ccx set TARGET --model M --effort E` needs an idle or stopped worker. Codex
69
+ uses the settings next turn. For a running, idle Claude worker, add `--restart`
70
+ to stop its runtime; the next send revives it with the new settings. A stopped
71
+ Claude worker uses them on revival. Let compaction settle before `set`.
72
+
73
+ ## Usage caps
74
+
75
+ Caps stop a turn at the given account usage percentage (exit 7). Check
76
+ `ccx usage` first. Caps apply only to that message; later sends need their own.
77
+ If usage can't be read, the turn keeps running.
78
+
79
+ ## Deeper inspection
80
+
81
+ - `ccx peek TARGET --full`: untruncated messages and tool errors.
82
+ - `ccx logs TARGET --full`: conversation JSON without tool-result truncation,
83
+ including stopped workers. Claude's `--jsonl` gives the raw transcript.
84
+ - `ccx events TARGET --follow`: lifecycle events for diagnostics.
85
+ - `ccx import ID`: bring an idle Claude session into ccx, or fork a Codex
86
+ thread whose latest turn completed.
87
+
88
+ ## Engine differences
89
+
90
+ - `answer`, `respond`, `--cap-opus`, `--next-turn` and `logs --jsonl` are
91
+ Claude-only. `--settle` (also wait for workers a Codex worker started) and
92
+ `reconcile --turn-id` are Codex-only.
93
+ - Codex workers share one ccx-managed Codex daemon. `kill` unloads a single
94
+ worker and leaves the others running.
@@ -0,0 +1,62 @@
1
+ # ccx variables
2
+
3
+ Variables are named JSON values attached to a worker. Inside the worker,
4
+ plain `python3` (or `python`) sees them as ordinary Python variables; changes
5
+ are saved and visible to every worker sharing the same state.
6
+
7
+ ## Attach, update, read
8
+
9
+ ```bash
10
+ W=$(ccx new --engine codex --cwd ~/repo --var 'result={"done": false, "issues": []}' \
11
+ "List the TODOs in src/. With python3, append each to result['issues'], then set result['done'] = True last.")
12
+ ccx wait "$W"
13
+ ccx vars "$W" result --json # the value
14
+ ccx vars "$W" --json # names and metadata only
15
+ ```
16
+
17
+ - `--var NAME=JSON` works on `new`, `send` and `fork`, and is repeatable. On
18
+ `send` it attaches or replaces that variable.
19
+ - ccx tells the worker which names are available; you don't need to explain
20
+ the mechanism, just say what to put where.
21
+ - Inside the worker, mutating a value or rebinding the name both write back;
22
+ `del NAME` removes it.
23
+ - Start with a sentinel (`done: false`) and ask the worker to set it last, so an
24
+ untouched value can't pass as an empty result.
25
+
26
+ ## Sharing between workers
27
+
28
+ `--vars-from TARGET` gives a new worker (or a `send`) the same state as
29
+ `TARGET`, across Claude and Codex. Both see each other's changes at once, and
30
+ ccx runs their Python calls one at a time.
31
+
32
+ ```bash
33
+ B=$(ccx new --engine claude --cwd ~/repo --vars-from "$W" \
34
+ "With python3, replace each string in result['issues'] with a dict: text holds the string, priority is high or low.")
35
+ ```
36
+
37
+ `--var` and `--vars-from` can't be combined in one command. A `fork` doesn't
38
+ copy the source's variables (pass `--vars-from SOURCE` to share them), and
39
+ workers a worker starts never inherit its variables.
40
+
41
+ ## Rules
42
+
43
+ - Variables need full permissions (the default).
44
+ - Values attached from the CLI are JSON. A controller can attach live Python
45
+ objects instead; see [controllers.md](controllers.md).
46
+ - Only direct `python`/`python3` sees them. `command python3`, `env python3`,
47
+ a full interpreter path and scripts run through a shebang get normal Python.
48
+ In Codex workers, nested bash and zsh keep them; in Claude workers, call
49
+ `python3` directly from the tool shell.
50
+ - Keep values small and structured: verdicts, lists, paths, handles.
51
+
52
+ ## When python3 doesn't see them
53
+
54
+ Check the worker's exact command and its selected Python with
55
+ `command -v python3` and `command python3 --version`. Leading interpreter flags
56
+ such as `python3 -u` bypass variables. On stock macOS, a non-login shell can
57
+ find Apple's older `/usr/bin/python3`, which can't run them.
58
+
59
+ Live controller objects require Python to match the controller's version and
60
+ platform; otherwise ccx runs ordinary Python with a warning. Saved JSON has no
61
+ matching-version check, but needs Python capable of running ccx's variable
62
+ support. See [variable troubleshooting](https://github.com/ccx-native/ccx/blob/main/docs/variables/troubleshooting.md).