kanibako-cli 1.6.0.dev36__tar.gz → 1.7.0__tar.gz
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.
- {kanibako_cli-1.6.0.dev36/src/kanibako_cli.egg-info → kanibako_cli-1.7.0}/PKG-INFO +1 -1
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/README.md +134 -50
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/pyproject.toml +9 -1
- kanibako_cli-1.7.0/src/kanibako/__init__.py +25 -0
- kanibako_cli-1.7.0/src/kanibako/agent_config.py +146 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/agent_defaults.py +61 -4
- kanibako_cli-1.7.0/src/kanibako/agent_ref.py +185 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/agent_representation.py +86 -9
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/box_identity.py +73 -49
- kanibako_cli-1.7.0/src/kanibako/box_lifecycle.py +285 -0
- kanibako_cli-1.7.0/src/kanibako/box_resolve.py +335 -0
- kanibako_cli-1.7.0/src/kanibako/box_supervisor.py +1172 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/channels.py +13 -13
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/cli.py +81 -37
- kanibako_cli-1.7.0/src/kanibako/commands/agent_cmd.py +666 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/archive.py +21 -10
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/box/__init__.py +7 -3
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/box/_duplicate.py +90 -29
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/box/_lifecycle.py +256 -99
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/box/_parser.py +532 -105
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/clean.py +30 -21
- kanibako_cli-1.7.0/src/kanibako/commands/code_cmd.py +725 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/diagnose.py +258 -14
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/flags.py +4 -1
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/install.py +16 -15
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/setup_cmd.py +117 -2
- kanibako_cli-1.7.0/src/kanibako/commands/start.py +5292 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/stop.py +31 -6
- kanibako_cli-1.7.0/src/kanibako/commands/system_cmd.py +428 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/workset_cmd.py +235 -144
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/config.py +289 -259
- kanibako_cli-1.7.0/src/kanibako/config_interface.py +2926 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/config_io.py +1 -1
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/container.py +178 -15
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/core_defaults.py +85 -4
- kanibako_cli-1.7.0/src/kanibako/creds_watcher.py +386 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/data/core-defaults.yaml +90 -3
- kanibako_cli-1.7.0/src/kanibako/data/global/rom/playbook/kanibako/directives/KANIBAKO.md +81 -0
- kanibako_cli-1.7.0/src/kanibako/data/global/rom/playbook/kanibako/scripts/clear.py +20 -0
- kanibako_cli-1.7.0/src/kanibako/data/global/rom/playbook/kanibako/scripts/import-directives.py +307 -0
- kanibako_cli-1.7.0/src/kanibako/data/global/rom/playbook/kanibako/scripts/start.py +50 -0
- kanibako_cli-1.7.0/src/kanibako/data/global/template/playbook/CONTENTS.md +11 -0
- kanibako_cli-1.7.0/src/kanibako/data/global/template/playbook/agents/directives/AGENTS.md +4 -0
- kanibako_cli-1.7.0/src/kanibako/data/global/template/playbook/box/directives/BOX.md +16 -0
- kanibako_cli-1.7.0/src/kanibako/data/global/template/playbook/general/directives/GENERAL.md +12 -0
- kanibako_cli-1.7.0/src/kanibako/data/global/template/playbook/general/directives/rules/INTERACTION.md +20 -0
- kanibako_cli-1.7.0/src/kanibako/data/global/template/playbook/general/directives/rules/WORKPOLICY.md +17 -0
- kanibako_cli-1.7.0/src/kanibako/data/global/template/playbook/workset/directives/WORKSET.md +4 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/helper_listener.py +36 -13
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/helpers.py +2 -2
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/hygiene.py +116 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/image_sharing.py +2 -1
- kanibako_cli-1.7.0/src/kanibako/import_reconcile.py +299 -0
- kanibako_cli-1.7.0/src/kanibako/journal.py +201 -0
- kanibako_cli-1.7.0/src/kanibako/kuid.py +118 -0
- kanibako_cli-1.7.0/src/kanibako/names.py +336 -0
- kanibako_cli-1.7.0/src/kanibako/paths.py +2676 -0
- kanibako_cli-1.7.0/src/kanibako/registry_store.py +194 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/rig_registry.py +9 -7
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/scripts/kanibako-entry +4 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/settings_assemble.py +164 -31
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/settings_categories.py +113 -257
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/settings_configset.py +149 -125
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/settings_expand.py +124 -10
- kanibako_cli-1.7.0/src/kanibako/settings_launch.py +1706 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/settings_merge.py +39 -105
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/settings_resolve.py +28 -2
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/settings_store.py +13 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/settings_views.py +106 -6
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/shells.py +6 -4
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/targets/__init__.py +4 -4
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/targets/assembly.py +41 -11
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/targets/base.py +54 -5
- kanibako_cli-1.7.0/src/kanibako/targets/credsync.py +452 -0
- kanibako_cli-1.7.0/src/kanibako/templates.py +443 -0
- kanibako_cli-1.7.0/src/kanibako/vscode_config.py +971 -0
- kanibako_cli-1.7.0/src/kanibako/vscode_remote.py +705 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/workset.py +263 -212
- kanibako_cli-1.7.0/src/kanibako/workset_registry.py +201 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0/src/kanibako_cli.egg-info}/PKG-INFO +1 -1
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako_cli.egg-info/SOURCES.txt +42 -4
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_agent_config.py +63 -0
- kanibako_cli-1.7.0/tests/test_agent_ref.py +242 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_agent_representation.py +172 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_agent_resolution.py +114 -17
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_box_identity.py +87 -56
- kanibako_cli-1.7.0/tests/test_box_lifecycle.py +304 -0
- kanibako_cli-1.7.0/tests/test_box_resolve.py +344 -0
- kanibako_cli-1.7.0/tests/test_box_supervisor.py +1372 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_channels.py +44 -2
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_cli.py +495 -49
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_cli_exitcodes.py +37 -15
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_comms.py +15 -17
- kanibako_cli-1.7.0/tests/test_config.py +906 -0
- kanibako_cli-1.7.0/tests/test_config_interface.py +3644 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_container.py +248 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_container_extended.py +7 -1
- kanibako_cli-1.7.0/tests/test_create_recovery.py +649 -0
- kanibako_cli-1.7.0/tests/test_creds_watcher.py +281 -0
- kanibako_cli-1.7.0/tests/test_delivery_manifest.py +327 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_env_cmd.py +6 -6
- kanibako_cli-1.7.0/tests/test_explicit_create.py +204 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_fork.py +14 -10
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_helper_cmd.py +1 -1
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_helper_listener.py +18 -8
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_hygiene.py +152 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_image_sharing.py +3 -3
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_import.py +91 -109
- kanibako_cli-1.7.0/tests/test_import_directives.py +205 -0
- kanibako_cli-1.7.0/tests/test_import_recovery.py +604 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_init_cmd.py +194 -57
- kanibako_cli-1.7.0/tests/test_instructions_bind.py +183 -0
- kanibako_cli-1.7.0/tests/test_journal.py +212 -0
- kanibako_cli-1.7.0/tests/test_kuid.py +208 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_lifecycle_integration.py +11 -3
- kanibako_cli-1.7.0/tests/test_meta_pin.py +84 -0
- kanibako_cli-1.7.0/tests/test_names.py +793 -0
- kanibako_cli-1.7.0/tests/test_paths.py +1881 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_paths_extended.py +8 -1
- kanibako_cli-1.7.0/tests/test_persona_config_set.py +400 -0
- kanibako_cli-1.7.0/tests/test_playbook_delivery.py +126 -0
- kanibako_cli-1.7.0/tests/test_registry_store.py +294 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_resolve_box_target.py +73 -19
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_resource_scoping.py +173 -57
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_rig_registry.py +1 -1
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_safety_invariants.py +20 -14
- kanibako_cli-1.7.0/tests/test_settings_assemble.py +846 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_settings_categories.py +320 -52
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_settings_configset.py +274 -58
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_settings_expand.py +167 -0
- kanibako_cli-1.7.0/tests/test_settings_launch.py +1694 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_settings_launch_equivalence.py +142 -72
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_settings_merge.py +50 -102
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_settings_views.py +1 -4
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_setup_cmd.py +127 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_shells.py +7 -1
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_standalone_paths.py +201 -6
- kanibako_cli-1.7.0/tests/test_system_paths.py +689 -0
- kanibako_cli-1.7.0/tests/test_templates.py +612 -0
- kanibako_cli-1.7.0/tests/test_vscode_remote.py +440 -0
- kanibako_cli-1.7.0/tests/test_vscode_remote_dispatch.py +205 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_workset.py +224 -140
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_workset_paths.py +0 -79
- kanibako_cli-1.7.0/tests/test_workset_registry.py +280 -0
- kanibako_cli-1.6.0.dev36/src/kanibako/__init__.py +0 -11
- kanibako_cli-1.6.0.dev36/src/kanibako/agent_config.py +0 -101
- kanibako_cli-1.6.0.dev36/src/kanibako/box_seed.py +0 -84
- kanibako_cli-1.6.0.dev36/src/kanibako/commands/agent_cmd.py +0 -481
- kanibako_cli-1.6.0.dev36/src/kanibako/commands/start.py +0 -2830
- kanibako_cli-1.6.0.dev36/src/kanibako/commands/system_cmd.py +0 -248
- kanibako_cli-1.6.0.dev36/src/kanibako/config_interface.py +0 -1033
- kanibako_cli-1.6.0.dev36/src/kanibako/data/templates/base/INSTRUCTIONS.md +0 -67
- kanibako_cli-1.6.0.dev36/src/kanibako/import_reconcile.py +0 -312
- kanibako_cli-1.6.0.dev36/src/kanibako/names.py +0 -250
- kanibako_cli-1.6.0.dev36/src/kanibako/paths.py +0 -1889
- kanibako_cli-1.6.0.dev36/src/kanibako/registry_store.py +0 -285
- kanibako_cli-1.6.0.dev36/src/kanibako/settings_launch.py +0 -734
- kanibako_cli-1.6.0.dev36/src/kanibako/targets/credsync.py +0 -208
- kanibako_cli-1.6.0.dev36/src/kanibako/templates.py +0 -222
- kanibako_cli-1.6.0.dev36/tests/test_box_seed.py +0 -137
- kanibako_cli-1.6.0.dev36/tests/test_config.py +0 -912
- kanibako_cli-1.6.0.dev36/tests/test_config_interface.py +0 -1009
- kanibako_cli-1.6.0.dev36/tests/test_names.py +0 -652
- kanibako_cli-1.6.0.dev36/tests/test_paths.py +0 -1084
- kanibako_cli-1.6.0.dev36/tests/test_registry_store.py +0 -238
- kanibako_cli-1.6.0.dev36/tests/test_settings_assemble.py +0 -511
- kanibako_cli-1.6.0.dev36/tests/test_settings_launch.py +0 -354
- kanibako_cli-1.6.0.dev36/tests/test_system_paths.py +0 -492
- kanibako_cli-1.6.0.dev36/tests/test_templates.py +0 -327
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/LICENSE.md +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/setup.cfg +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/__main__.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/_atomic.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/auth_browser.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/auth_parser.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/baseline.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/browser_sidecar.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/browser_state.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/bun_sea.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/__init__.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/baseline_cmd.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/fork_cmd.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/helper_cmd.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/image.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/restore.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/upgrade.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/commands/vault_cmd.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/containerfiles.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/containers/Containerfile.template-android +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/containers/Containerfile.template-dotnet +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/containers/Containerfile.template-js +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/containers/Containerfile.template-jvm +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/containers/Containerfile.template-systems +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/containers/__init__.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/containers/tmux.conf +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/data/__init__.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/data/image-baseline.yaml +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/deprecation.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/errors.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/freshness.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/git.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/helper_client.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/install_method.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/log.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/plugins/__init__.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/py.typed +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/registry.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/rig_bundle.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/rig_meta.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/rig_resolve.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/rig_source.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/scripts/__init__.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/scripts/helper-init.sh +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/shellenv.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/snapshots.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/targets/no_agent.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/templates_image.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/tweakcc.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/tweakcc_cache.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako/utils.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako_cli.egg-info/dependency_links.txt +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako_cli.egg-info/entry_points.txt +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako_cli.egg-info/requires.txt +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/src/kanibako_cli.egg-info/top_level.txt +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_archive_restore_integration.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_atomic.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_auth_browser.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_auth_parser.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_baseline.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_browser_sidecar.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_browser_state.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_bun_sea.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_container_integration.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_containerfiles.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_credentials.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_defaults_golden.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_deprecations.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_error_messages.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_freshness.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_git.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_helper_client.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_helpers.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_install_integration.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_log.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_registry.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_rig_bundle.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_rig_meta.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_rig_resolve.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_rig_source.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_settings_resolve.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_settings_store.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_shellenv.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_snapshots.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_start_integration.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_status.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_templates_image.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_tweakcc.py +0 -0
- {kanibako_cli-1.6.0.dev36 → kanibako_cli-1.7.0}/tests/test_utils.py +0 -0
|
@@ -13,6 +13,9 @@ agent sessions that survive reboots and SSH disconnects.
|
|
|
13
13
|
|
|
14
14
|
CRAB: **C**ontained **R**untime **A**gent in a **B**ox.
|
|
15
15
|
|
|
16
|
+
New here? Start with [GETTING_STARTED.md](GETTING_STARTED.md) for a five-minute
|
|
17
|
+
walkthrough from install to your first agent session.
|
|
18
|
+
|
|
16
19
|
No Docker or Podman experience required. Just `cd` into a project and run
|
|
17
20
|
`kanibako`. Setup, rig pulls, credential syncing, and teardown are automatic.
|
|
18
21
|
Claude Code, Codex, and Goose ship as first-class agent plugins (all installed
|
|
@@ -39,12 +42,12 @@ by the `kanibako` meta-package); other agents can be added as plugins.
|
|
|
39
42
|
- **Vault snapshots** -- per-box read-only and read-write shared
|
|
40
43
|
directories with smart snapshot strategy detection (reflink, hardlink,
|
|
41
44
|
or tar.xz depending on filesystem)
|
|
42
|
-
- **Shell customization** -- per-box environment variables (`box
|
|
45
|
+
- **Shell customization** -- per-box environment variables (`box set
|
|
43
46
|
env.*`), drop-in init scripts (`shell.d/`), and layered seed-once home
|
|
44
47
|
templates
|
|
45
48
|
- **Agent configuration** -- per-agent YAML config with default args, state
|
|
46
49
|
knobs, env vars, and shared caches; per-box setting overrides via
|
|
47
|
-
`box
|
|
50
|
+
`box set`
|
|
48
51
|
- **Shared caches** -- global download caches (pip, cargo, npm, etc.)
|
|
49
52
|
shared across boxes; agent-level caches via the agent config
|
|
50
53
|
- **Plugin system** -- agent-agnostic core (`kanibako-cli`); Claude/Codex/Goose
|
|
@@ -60,21 +63,26 @@ by the `kanibako` meta-package); other agents can be added as plugins.
|
|
|
60
63
|
## Prerequisites
|
|
61
64
|
|
|
62
65
|
- Python 3.11+
|
|
63
|
-
- [Podman](https://podman.io/) (recommended) or Docker -- just needs to be
|
|
66
|
+
- [Podman](https://podman.io/) 4.3+ (recommended) or Docker -- just needs to be
|
|
64
67
|
installed; Kanibako manages all container operations automatically
|
|
65
68
|
- An AI coding agent installed on the host (e.g.
|
|
66
69
|
[Claude Code](https://docs.anthropic.com/en/docs/claude-code))
|
|
67
70
|
|
|
68
71
|
## Installation
|
|
69
72
|
|
|
73
|
+
> **Pre-release:** the current line (`1.7.0`) is still in release candidates, so
|
|
74
|
+
> add `--pre` (pip/pipx) or `--prerelease allow` (uv) to get the newest rc. Plain
|
|
75
|
+
> `pip install kanibako` gets the last *stable* release (`1.6.0`). Once `1.7.0`
|
|
76
|
+
> ships, drop the flag.
|
|
77
|
+
|
|
70
78
|
```bash
|
|
71
|
-
# Standard install (cli + Claude, Codex, and Goose plugins)
|
|
72
|
-
uv tool install kanibako
|
|
79
|
+
# Standard install (cli + Claude, Codex, and Goose plugins) -- current rc
|
|
80
|
+
uv tool install --prerelease allow kanibako
|
|
73
81
|
# -- or --
|
|
74
|
-
pip install kanibako
|
|
82
|
+
pip install --pre kanibako
|
|
75
83
|
|
|
76
84
|
# Base only (no agent plugins -- agent-agnostic shell mode)
|
|
77
|
-
pip install kanibako-cli
|
|
85
|
+
pip install --pre kanibako-cli
|
|
78
86
|
|
|
79
87
|
# Development install
|
|
80
88
|
git clone https://github.com/doctorjei/kanibako.git
|
|
@@ -92,8 +100,11 @@ it is used automatically. See [Agent Selection](#agent-selection).
|
|
|
92
100
|
## Quick Start
|
|
93
101
|
|
|
94
102
|
```bash
|
|
95
|
-
#
|
|
103
|
+
# Create a box for the current directory (a deliberate, one-time step)
|
|
96
104
|
cd ~/my-project
|
|
105
|
+
kanibako create
|
|
106
|
+
|
|
107
|
+
# Start an agent session (shortcut for `kanibako start`)
|
|
97
108
|
kanibako
|
|
98
109
|
|
|
99
110
|
# Start with a specific rig
|
|
@@ -109,10 +120,11 @@ kanibako shell -- echo hello
|
|
|
109
120
|
kanibako -N
|
|
110
121
|
```
|
|
111
122
|
|
|
112
|
-
That's it -- no `docker run`, no volume flags, no Containerfile.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
123
|
+
That's it -- no `docker run`, no volume flags, no Containerfile. Creating a box
|
|
124
|
+
is an explicit step (`kanibako create`); a launch (`kanibako` / `start` / `code` /
|
|
125
|
+
`shell`) never invents a box, so a typo'd project or wrong directory can't
|
|
126
|
+
silently make one. On the first launch of a box, Kanibako pulls the container
|
|
127
|
+
rig and syncs your credentials; subsequent runs pick up where you left off.
|
|
116
128
|
|
|
117
129
|
## Example: Python Project
|
|
118
130
|
|
|
@@ -121,21 +133,24 @@ gh, nano, jq, ripgrep, tmux, Podman, and common dev tools. This is enough for
|
|
|
121
133
|
most Python, JavaScript, and general scripting work.
|
|
122
134
|
|
|
123
135
|
```bash
|
|
124
|
-
# 1. Install kanibako
|
|
125
|
-
pip install kanibako
|
|
136
|
+
# 1. Install kanibako (--pre while 1.7.0 is in rc; see Installation)
|
|
137
|
+
pip install --pre kanibako
|
|
126
138
|
|
|
127
139
|
# 2. Create or clone a project
|
|
128
140
|
mkdir ~/my-flask-app && cd ~/my-flask-app
|
|
129
141
|
git init
|
|
130
142
|
# (or: git clone https://github.com/you/my-flask-app.git && cd my-flask-app)
|
|
131
143
|
|
|
132
|
-
# 3.
|
|
144
|
+
# 3. Create the box for this project (explicit, one-time)
|
|
145
|
+
kanibako create
|
|
146
|
+
|
|
147
|
+
# 4. Launch -- that's it
|
|
133
148
|
kanibako
|
|
134
149
|
```
|
|
135
150
|
|
|
136
|
-
|
|
151
|
+
`kanibako create` sets up an isolated environment for this project. On the
|
|
152
|
+
first launch, Kanibako will:
|
|
137
153
|
- Pull the base container rig (once, cached afterwards)
|
|
138
|
-
- Create an isolated environment for this project
|
|
139
154
|
- Copy your agent credentials into the sandbox
|
|
140
155
|
- Drop you into an agent session inside the container
|
|
141
156
|
|
|
@@ -161,20 +176,23 @@ toolchains you need:
|
|
|
161
176
|
kanibako rig prep systems
|
|
162
177
|
# (or build one interactively with: kanibako rig extend my-systems --from kanibako-oci)
|
|
163
178
|
|
|
164
|
-
# 2.
|
|
179
|
+
# 2. Create the box for your project, pinned to that rig (explicit, one-time)
|
|
165
180
|
cd ~/my-rust-project
|
|
166
|
-
kanibako --image kanibako-template-systems
|
|
181
|
+
kanibako create --image kanibako-template-systems
|
|
182
|
+
|
|
183
|
+
# 3. Launch
|
|
184
|
+
kanibako
|
|
167
185
|
```
|
|
168
186
|
|
|
169
|
-
|
|
170
|
-
|
|
187
|
+
`kanibako create` pins the rig choice for this project, so you can just run
|
|
188
|
+
`kanibako` next time.
|
|
171
189
|
|
|
172
190
|
See [Container Rigs](#container-rigs) for the base rigs and custom rig
|
|
173
191
|
creation.
|
|
174
192
|
|
|
175
193
|
## Commands
|
|
176
194
|
|
|
177
|
-
Kanibako organizes commands into four management groups plus
|
|
195
|
+
Kanibako organizes commands into four management groups plus eight top-level
|
|
178
196
|
shortcuts for common operations:
|
|
179
197
|
|
|
180
198
|
### Top-Level Shortcuts
|
|
@@ -188,6 +206,7 @@ shortcuts for common operations:
|
|
|
188
206
|
| `kanibako ps [-a] [-q]` | `box ps` | List active (running) boxes |
|
|
189
207
|
| `kanibako create [path]` | `box create` | Create a new project |
|
|
190
208
|
| `kanibako rm <project>` | `box rm` | Remove a project |
|
|
209
|
+
| `kanibako code [project]` | *(top-level only)* | Open VS Code attached to the box (see [VS Code Integration](#vs-code-integration)) |
|
|
191
210
|
|
|
192
211
|
### Management Commands
|
|
193
212
|
|
|
@@ -220,7 +239,7 @@ shortcuts for common operations:
|
|
|
220
239
|
| `box list` / `box ls` | List projects (`--all`, `--orphan`, `-q`) |
|
|
221
240
|
| `box info` / `box inspect` | Project details (mode, paths, lock, rig) |
|
|
222
241
|
| `box rm` / `box delete` | Remove project (`--purge` deletes metadata, `--force` skips confirm) |
|
|
223
|
-
| `box
|
|
242
|
+
| `box set` / `box get` / `box show` / `box reset` | View or modify project configuration |
|
|
224
243
|
| `box diagnose [project]` | Check project box health |
|
|
225
244
|
|
|
226
245
|
**Relocation & conversion:**
|
|
@@ -265,7 +284,7 @@ shortcuts for common operations:
|
|
|
265
284
|
| `workset list` / `workset ls` | List working sets (`-q`) |
|
|
266
285
|
| `workset info` / `workset inspect` | Working set details |
|
|
267
286
|
| `workset rm` / `workset delete` | Remove working set (`--purge`, `--force`) |
|
|
268
|
-
| `workset
|
|
287
|
+
| `workset set` / `workset get` / `workset show` / `workset reset` | View or modify workset configuration (use `workset set default <key>=<value>` for default-workset defaults) |
|
|
269
288
|
| `workset connect <workset> [source]` | Add project to working set (`--name`) |
|
|
270
289
|
| `workset disconnect <workset> <project>` | Remove project from working set (`--force`) |
|
|
271
290
|
|
|
@@ -275,7 +294,7 @@ shortcuts for common operations:
|
|
|
275
294
|
|------------|-------------|
|
|
276
295
|
| `agent list` / `agent ls` | List configured agents (`-q`) |
|
|
277
296
|
| `agent info` / `agent inspect` | Agent configuration details |
|
|
278
|
-
| `agent
|
|
297
|
+
| `agent set` / `agent get` / `agent show` / `agent reset` | View or modify agent configuration |
|
|
279
298
|
| `agent reauth [project]` | Refresh credentials |
|
|
280
299
|
|
|
281
300
|
### `box helper` / `box fork` Subcommands
|
|
@@ -300,10 +319,74 @@ The runtime helper and fork verbs (formerly under `crab`) now live under `box`:
|
|
|
300
319
|
| Subcommand | Description |
|
|
301
320
|
|------------|-------------|
|
|
302
321
|
| `system info` / `system inspect` | System details (version, runtime, paths) |
|
|
303
|
-
| `system
|
|
322
|
+
| `system set` / `system get` / `system show` / `system reset` | View or modify global configuration |
|
|
304
323
|
| `system upgrade` | Self-update (`--check` for dry run) |
|
|
305
324
|
| `system diagnose` | Check system health (runtime, images, agents, storage) |
|
|
306
325
|
|
|
326
|
+
## VS Code Integration
|
|
327
|
+
|
|
328
|
+
> **⚠ Experimental.** VS Code integration is **experimental** in this release.
|
|
329
|
+
> The commands below work, but multi-surface behavior is still hardening — in
|
|
330
|
+
> particular, kanibako does **not yet enforce a single active agent per box**.
|
|
331
|
+
> Running the agent **panel** and a **CLI agent** on the *same box at the same
|
|
332
|
+
> time* silently **forks the session**: both write the same agent history and
|
|
333
|
+
> one surface's turns can be lost with no warning. **Use one agent surface per
|
|
334
|
+
> box at a time** until single-writer enforcement lands.
|
|
335
|
+
|
|
336
|
+
`kanibako code [project]` opens your **host** VS Code attached to the box
|
|
337
|
+
(Dev Containers "Attach to Running Container"), at the box's `~/workspace`.
|
|
338
|
+
The box is auto-started detached if it isn't running, and it stays up when
|
|
339
|
+
you close the window. The box agent's editor extension is installed into the
|
|
340
|
+
attached window automatically.
|
|
341
|
+
|
|
342
|
+
Requirements: the `code` CLI on your PATH, the Dev Containers extension
|
|
343
|
+
(`ms-vscode-remote.remote-containers`), and
|
|
344
|
+
`"dev.containers.dockerPath": "podman"` in your VS Code user settings.
|
|
345
|
+
`kanibako system diagnose` checks all three.
|
|
346
|
+
|
|
347
|
+
### Remote boxes
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
kanibako code --remote <host> <project>
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
attaches your **local** VS Code to a box on a **remote** kanibako host —
|
|
354
|
+
no relay service, no VS Code on the remote host. `<host>` is an opaque SSH
|
|
355
|
+
destination resolved by your own `~/.ssh/config`. kanibako runs the box
|
|
356
|
+
lifecycle on the remote host over plain SSH, and the container-engine leg
|
|
357
|
+
rides a kanibako-owned SSH tunnel: one OpenSSH `ControlPersist` master
|
|
358
|
+
forwards the remote rootless podman socket to a local unix socket, and local
|
|
359
|
+
podman dials that socket. podman's own golang `ssh:` transport is **not**
|
|
360
|
+
used, so no `ssh-agent` is required, your `~/.ssh/config` is fully honored
|
|
361
|
+
(aliases, ProxyJump, ports, `IdentityFile`), and per-call SSH handshake
|
|
362
|
+
overhead is gone once the first call warms the tunnel.
|
|
363
|
+
|
|
364
|
+
Requirements:
|
|
365
|
+
|
|
366
|
+
- the same kanibako **version** on both hosts, plus a local `code` CLI and
|
|
367
|
+
local `podman` (the `--remote` client);
|
|
368
|
+
- the rootless podman API socket on the remote host:
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
systemctl --user enable --now podman.socket
|
|
372
|
+
loginctl enable-linger "$USER"
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
On first `--remote` use, kanibako asks to point
|
|
376
|
+
`dev.containers.dockerPath` at its dispatch wrapper (local attaches are
|
|
377
|
+
unaffected — the wrapper is a pass-through to `podman` except for remote
|
|
378
|
+
attach windows).
|
|
379
|
+
|
|
380
|
+
If a remote attach fails, check the dispatch log at
|
|
381
|
+
`~/.local/state/kanibako/vscode-remote/dispatch.log` (or under
|
|
382
|
+
`$XDG_STATE_HOME`) — one line per engine call showing the resolved route and
|
|
383
|
+
context.
|
|
384
|
+
|
|
385
|
+
> **First attach:** the first time VS Code attaches to a given container it
|
|
386
|
+
> shows a workspace-trust dialog you must click through. In headless or
|
|
387
|
+
> automated setups this can look like a silent hang — bring the VS Code
|
|
388
|
+
> window forward and confirm the trust prompt to proceed.
|
|
389
|
+
|
|
307
390
|
## Common Flags
|
|
308
391
|
|
|
309
392
|
### Agent Flags (on `start`)
|
|
@@ -349,7 +432,7 @@ error, not a silent no-op).
|
|
|
349
432
|
#### `--box`: operate on any box
|
|
350
433
|
|
|
351
434
|
`--box` substitutes for being in the box's directory: `kanibako stop --box myproj`,
|
|
352
|
-
`kanibako box
|
|
435
|
+
`kanibako box set --box myproj model=opus`. The value is a **box name (resolved
|
|
353
436
|
first) or a path**. It is the *subject* the command acts on, and stays orthogonal to
|
|
354
437
|
the `move`/`convert` *destination* group, so they coexist:
|
|
355
438
|
|
|
@@ -408,7 +491,7 @@ confirm. Non-TTY runs (CI / headless) skip the prompt gracefully.
|
|
|
408
491
|
nudge to run `setup` if it has never been run, then proceed.
|
|
409
492
|
|
|
410
493
|
Because `system.*` keys are **file-only** (see [Configuration](#configuration)),
|
|
411
|
-
the default agent is *not* settable via `kanibako system
|
|
494
|
+
the default agent is *not* settable via `kanibako system set` -- use `setup` or
|
|
412
495
|
edit `global/settings.yaml` directly.
|
|
413
496
|
|
|
414
497
|
## Project Modes
|
|
@@ -431,11 +514,11 @@ and run `kanibako`, and the box joins the primary workset.
|
|
|
431
514
|
|
|
432
515
|
The primary workset is addressable through the same `workset` commands as named
|
|
433
516
|
worksets (workset name token `__PRIMARY__`), so primary-workset settings use the
|
|
434
|
-
ordinary `workset
|
|
517
|
+
ordinary `workset set default` mechanism (see [Configuration](#configuration)):
|
|
435
518
|
|
|
436
519
|
```bash
|
|
437
|
-
kanibako workset
|
|
438
|
-
kanibako workset
|
|
520
|
+
kanibako workset set default model=opus # default for ALL primary-mode boxes
|
|
521
|
+
kanibako workset set default group_auth=false # distinct credentials by default
|
|
439
522
|
```
|
|
440
523
|
|
|
441
524
|
The names `__PRIMARY__` / `__STANDALONE__` (and legacy `default`) are reserved
|
|
@@ -629,9 +712,9 @@ container:
|
|
|
629
712
|
|
|
630
713
|
```bash
|
|
631
714
|
# Persistent (stored in project config)
|
|
632
|
-
kanibako box
|
|
633
|
-
kanibako system
|
|
634
|
-
kanibako box
|
|
715
|
+
kanibako box set env.EDITOR=vim # project-level
|
|
716
|
+
kanibako system set env.EDITOR=nano # global (all projects)
|
|
717
|
+
kanibako box get env.EDITOR # show one value
|
|
635
718
|
|
|
636
719
|
# Per-run (not persisted)
|
|
637
720
|
kanibako start -e EDITOR=vim -e DEBUG=1
|
|
@@ -644,7 +727,7 @@ Project env vars override global ones.
|
|
|
644
727
|
The shell prompt is controlled by the `KANIBAKO_PS1` environment variable:
|
|
645
728
|
|
|
646
729
|
```bash
|
|
647
|
-
kanibako box
|
|
730
|
+
kanibako box set env.KANIBAKO_PS1="(myproject) \u:\w\$ "
|
|
648
731
|
```
|
|
649
732
|
|
|
650
733
|
### Init scripts
|
|
@@ -702,8 +785,8 @@ Manage agent settings via the CLI:
|
|
|
702
785
|
|
|
703
786
|
```bash
|
|
704
787
|
kanibako agent list # list configured agents
|
|
705
|
-
kanibako agent
|
|
706
|
-
kanibako agent
|
|
788
|
+
kanibako agent get claude model # show the agent's model
|
|
789
|
+
kanibako agent set claude model=sonnet # set agent-level default
|
|
707
790
|
```
|
|
708
791
|
|
|
709
792
|
## Home Templates
|
|
@@ -822,7 +905,7 @@ guide.
|
|
|
822
905
|
pip install kanibako-target-myagent
|
|
823
906
|
|
|
824
907
|
# Use a specific target
|
|
825
|
-
kanibako box
|
|
908
|
+
kanibako box set box.agent=myagent
|
|
826
909
|
kanibako start
|
|
827
910
|
|
|
828
911
|
# (`crab_name` is gone -- select the agent via box.agent)
|
|
@@ -846,29 +929,30 @@ CLI flag > settings_required > box > workset > agent.<agent> > system > settings
|
|
|
846
929
|
**file-only** -- the CLI reads and shows them but refuses to set them (edit the
|
|
847
930
|
file directly); `setup` and programmatic writers still write them.
|
|
848
931
|
|
|
849
|
-
All settings levels share
|
|
932
|
+
All settings levels share the same four verbs -- `set` / `get` / `show` /
|
|
933
|
+
`reset`:
|
|
850
934
|
|
|
851
935
|
```bash
|
|
852
936
|
# Box level
|
|
853
|
-
kanibako box
|
|
854
|
-
kanibako box
|
|
855
|
-
kanibako box
|
|
856
|
-
kanibako box
|
|
857
|
-
kanibako box
|
|
937
|
+
kanibako box show # show box overrides
|
|
938
|
+
kanibako box show --effective # show resolved values (inherited + overrides)
|
|
939
|
+
kanibako box get model # get one key
|
|
940
|
+
kanibako box set model=sonnet # set one key
|
|
941
|
+
kanibako box reset model # remove override, back to default
|
|
858
942
|
|
|
859
943
|
# Workset level (group defaults inherited by member boxes)
|
|
860
|
-
kanibako workset
|
|
861
|
-
kanibako workset
|
|
944
|
+
kanibako workset set <workset> model=opus
|
|
945
|
+
kanibako workset set default model=opus # primary-workset default
|
|
862
946
|
|
|
863
947
|
# Agent level (defaults for all boxes using this agent)
|
|
864
|
-
kanibako agent
|
|
948
|
+
kanibako agent set claude model=opus
|
|
865
949
|
|
|
866
950
|
# System level (global settings defaults)
|
|
867
|
-
kanibako system
|
|
868
|
-
kanibako system
|
|
951
|
+
kanibako system set model=opus
|
|
952
|
+
kanibako system reset --all # reset all global settings
|
|
869
953
|
```
|
|
870
954
|
|
|
871
|
-
`kanibako system
|
|
955
|
+
`kanibako system set` sets **non-`system.`** settings only. `system.*`-prefixed
|
|
872
956
|
keys (layout paths AND `system.default_agent`) are **file-only**: the CLI shows them
|
|
873
957
|
but refuses to set/reset them, pointing you at the config file. Set the default agent
|
|
874
958
|
with `kanibako setup`; edit structural paths in `~/.config/kanibako.yaml` directly.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "kanibako-cli"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.7.0"
|
|
8
8
|
description = "Run AI coding agents in rootless containers with per-project isolation"
|
|
9
9
|
requires-python = ">=3.11"
|
|
10
10
|
dependencies = ["argcomplete>=3.0", "PyYAML>=6.0", "packaging>=20.0"]
|
|
@@ -30,11 +30,16 @@ where = ["src"]
|
|
|
30
30
|
"templates/**/*", "templates/**/.*",
|
|
31
31
|
"templates/.*/**/*", "templates/.*/*",
|
|
32
32
|
"templates/**/.*/**/*", "templates/**/.*/*",
|
|
33
|
+
"global/*", "global/**/*",
|
|
33
34
|
]
|
|
34
35
|
|
|
35
36
|
[tool.ruff]
|
|
36
37
|
target-version = "py311"
|
|
37
38
|
line-length = 99
|
|
39
|
+
# ``salvage/`` holds frozen, non-shipping reference snapshots (retired code kept
|
|
40
|
+
# for a possible future ``system recover``); it is not live code and is not
|
|
41
|
+
# linted. It is also outside ``src/`` so the wheel build never includes it.
|
|
42
|
+
extend-exclude = ["salvage"]
|
|
38
43
|
|
|
39
44
|
[tool.ruff.lint.per-file-ignores]
|
|
40
45
|
"tests/conftest.py" = ["E402"]
|
|
@@ -48,6 +53,9 @@ line-length = 99
|
|
|
48
53
|
# mypy at every src base and enable explicit package bases.
|
|
49
54
|
namespace_packages = true
|
|
50
55
|
explicit_package_bases = true
|
|
56
|
+
# ``salvage/`` is a frozen non-shipping reference snapshot (see [tool.ruff]); it
|
|
57
|
+
# is not type-checked and is not on any src base.
|
|
58
|
+
exclude = ['^salvage/']
|
|
51
59
|
mypy_path = "$MYPY_CONFIG_FILE_DIR/src:$MYPY_CONFIG_FILE_DIR/packages/agent-claude/src:$MYPY_CONFIG_FILE_DIR/packages/agent-goose/src:$MYPY_CONFIG_FILE_DIR/packages/agent-codex/src"
|
|
52
60
|
|
|
53
61
|
[[tool.mypy.overrides]]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""kanibako: Run AI coding agents in rootless containers with per-project isolation."""
|
|
2
|
+
|
|
3
|
+
__version__ = "1.7.0"
|
|
4
|
+
|
|
5
|
+
# Two-tier setup/config compatibility constants for the 5-band setup-completion
|
|
6
|
+
# gate (design: ``plans/2026-06-23-setup-version-tiers-NEXT.md``). Both are
|
|
7
|
+
# compared against the recorded ``system.setup_completed`` marker by BASE version
|
|
8
|
+
# (PEP 440 via ``packaging.version``), so a dev/rc build of the same base reads
|
|
9
|
+
# as the released base, not "from the future".
|
|
10
|
+
#
|
|
11
|
+
# * ``SETUP_BCV`` — backward-compatible version: the OLDEST setup/config version
|
|
12
|
+
# this build can function with AT ALL. Below it, the build can no longer
|
|
13
|
+
# auto-fill the gaps → the gate ERRORS (rc1) and the user must re-run setup.
|
|
14
|
+
# Bump only when a setup change can no longer be auto-filled.
|
|
15
|
+
# * ``SETUP_FCV`` — forward-compatible version: the oldest version whose setup is
|
|
16
|
+
# COMPLETELY compatible (nothing new since). At or above it (but below the
|
|
17
|
+
# running build) the gate SILENTLY bumps the marker forward. Between BCV and
|
|
18
|
+
# FCV the gate NUDGES (non-blocking) to re-run setup. Bump whenever setup adds
|
|
19
|
+
# a new feature/case.
|
|
20
|
+
#
|
|
21
|
+
# Invariant: ``SETUP_BCV <= SETUP_FCV <= __version__`` (base versions). Most
|
|
22
|
+
# releases change setup in no way → bump NEITHER → existing configs land
|
|
23
|
+
# ``>= FCV`` → silent.
|
|
24
|
+
SETUP_BCV = "1.6.0"
|
|
25
|
+
SETUP_FCV = "1.7.0"
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""Agent YAML configuration: load, write, and resolve per-agent settings."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from kanibako.config_io import dump_doc, load_doc
|
|
9
|
+
|
|
10
|
+
# Keys that live directly in the [agent] section as agent identity (not state).
|
|
11
|
+
IDENTITY_KEYS = frozenset({"name", "run_args"})
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class AgentConfig:
|
|
16
|
+
"""Per-agent configuration loaded from an agent YAML file.
|
|
17
|
+
|
|
18
|
+
Sections:
|
|
19
|
+
agent — identity (name, run_args) plus agent-state knobs
|
|
20
|
+
(model, auto_approve, allow_helpers, endpoint, …). The
|
|
21
|
+
per-node DISCRIMINATED sub-table ``agent.<node>.secret_path``
|
|
22
|
+
also lives here (see *secret_path* below).
|
|
23
|
+
env — raw env vars injected into container (VAR -> value)
|
|
24
|
+
secret_path — the SECRET category (spec §2a, 2026-07-06; RENAMED from the
|
|
25
|
+
rc0-rc2 ``env_file``): VAR -> host PATH pointer to secret
|
|
26
|
+
material (e.g. a 0600 bearer-token file). Stored DISCRIMINATED
|
|
27
|
+
under ``agent.<node>.secret_path.<VAR>`` (the SAME first-class
|
|
28
|
+
category shape ``config set agent.<node>.secret_path.<VAR>``
|
|
29
|
+
writes and ``_agent_partial`` reads into the launch cascade),
|
|
30
|
+
so it resolves through ``system → workset → box → agent``
|
|
31
|
+
precedence. The value is a PATH only — at launch it is ro-bind-
|
|
32
|
+
mounted arm's-length + exported IN-BOX; kanibako NEVER reads the
|
|
33
|
+
secret VALUE (never in the snapshot/keystore/logs/argv).
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
name: str = ""
|
|
37
|
+
run_args: list[str] = field(default_factory=list)
|
|
38
|
+
state: dict[str, str] = field(default_factory=dict)
|
|
39
|
+
env: dict[str, str] = field(default_factory=dict)
|
|
40
|
+
secret_path: dict[str, str] = field(default_factory=dict)
|
|
41
|
+
tweakcc: dict = field(default_factory=dict)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def agents_dir(data_path: Path, paths_agents: str = "agents") -> Path:
|
|
45
|
+
"""Return the agents directory under *data_path*."""
|
|
46
|
+
return data_path / (paths_agents or "agents")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def agent_settings_path(agents_root: Path, agent_id: str) -> Path:
|
|
50
|
+
"""Return ``@meta.agent.<agent>.settings`` for *agent_id*.
|
|
51
|
+
|
|
52
|
+
The per-agent SETTINGS cascade file lives INSIDE the per-agent store dir
|
|
53
|
+
(``@meta.agent.<agent>.path`` = ``agents/<agent>/``) as ``settings.yaml``
|
|
54
|
+
— NOT the old sibling ``agents/<agent>.yaml`` file (D-2026-06-22). This
|
|
55
|
+
parallels the per-agent template dir ``agents/<agent>/template`` and the
|
|
56
|
+
Part-3 ``agents/<agent>/{plugins,cache}`` stores.
|
|
57
|
+
"""
|
|
58
|
+
return agents_root / agent_id / "settings.yaml"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def agent_config_path(
|
|
62
|
+
data_path: Path, agent_id: str, paths_agents: str = "agents",
|
|
63
|
+
) -> Path:
|
|
64
|
+
"""Return the path to an agent's config (settings) file.
|
|
65
|
+
|
|
66
|
+
Convenience wrapper for callers that hold a *data_path* rather than the
|
|
67
|
+
resolved agents root; delegates to :func:`agent_settings_path`.
|
|
68
|
+
"""
|
|
69
|
+
return agent_settings_path(agents_dir(data_path, paths_agents), agent_id)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def load_agent_config(path: Path) -> AgentConfig:
|
|
73
|
+
"""Read an agent config file and return an AgentConfig.
|
|
74
|
+
|
|
75
|
+
Returns defaults if the file does not exist.
|
|
76
|
+
"""
|
|
77
|
+
cfg = AgentConfig()
|
|
78
|
+
if not path.exists():
|
|
79
|
+
return cfg
|
|
80
|
+
|
|
81
|
+
data = load_doc(path)
|
|
82
|
+
|
|
83
|
+
# The node is the per-agent store dir name (agents/<node>/settings.yaml), which
|
|
84
|
+
# IS the cascade discriminator ``_agent_partial`` reads (agent_name == node). The
|
|
85
|
+
# DISCRIMINATED ``agent.<node>.secret_path`` sub-table (first-class category)
|
|
86
|
+
# lives under the same ``agent:`` table as the flat state — read it by node.
|
|
87
|
+
node = path.parent.name
|
|
88
|
+
|
|
89
|
+
agent_sec = data.get("agent", {})
|
|
90
|
+
if not isinstance(agent_sec, dict):
|
|
91
|
+
agent_sec = {}
|
|
92
|
+
cfg.name = str(agent_sec.get("name", ""))
|
|
93
|
+
raw_args = agent_sec.get("run_args", [])
|
|
94
|
+
cfg.run_args = [str(a) for a in raw_args] if isinstance(raw_args, list) else []
|
|
95
|
+
|
|
96
|
+
# Flat state = the SCALAR agent-state knobs. Exclude identity keys AND any
|
|
97
|
+
# dict-valued entry: the discriminated ``<node>:`` sub-table (secret_path, node
|
|
98
|
+
# binds) is a dict and is NOT flat state — it rides ``_agent_partial``, not the
|
|
99
|
+
# ``_agent_state_partial`` state channel.
|
|
100
|
+
cfg.state = {
|
|
101
|
+
k: str(v)
|
|
102
|
+
for k, v in agent_sec.items()
|
|
103
|
+
if k not in IDENTITY_KEYS and not isinstance(v, dict)
|
|
104
|
+
}
|
|
105
|
+
cfg.env = {k: str(v) for k, v in data.get("env", {}).items()}
|
|
106
|
+
# secret_path: VAR -> host PATH pointer, read from the DISCRIMINATED
|
|
107
|
+
# ``agent.<node>.secret_path`` sub-table (spec §2a SECRET category). Stored as a
|
|
108
|
+
# plain string path; the file's CONTENTS (the secret) are never persisted here
|
|
109
|
+
# nor read — they are ro-mounted + exported IN-BOX only at launch.
|
|
110
|
+
node_sub = agent_sec.get(node, {})
|
|
111
|
+
secret_sub = node_sub.get("secret_path", {}) if isinstance(node_sub, dict) else {}
|
|
112
|
+
cfg.secret_path = {
|
|
113
|
+
k: str(v) for k, v in secret_sub.items()
|
|
114
|
+
} if isinstance(secret_sub, dict) else {}
|
|
115
|
+
cfg.tweakcc = dict(data.get("tweakcc", {}))
|
|
116
|
+
|
|
117
|
+
return cfg
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def write_agent_config(path: Path, cfg: AgentConfig) -> None:
|
|
121
|
+
"""Write an AgentConfig to a YAML file."""
|
|
122
|
+
node = path.parent.name
|
|
123
|
+
agent_sec: dict = {
|
|
124
|
+
"name": cfg.name,
|
|
125
|
+
"run_args": list(cfg.run_args),
|
|
126
|
+
}
|
|
127
|
+
for k, v in cfg.state.items():
|
|
128
|
+
agent_sec[k] = v
|
|
129
|
+
# secret_path (spec §2a SECRET category) is stored DISCRIMINATED under the
|
|
130
|
+
# ``agent.<node>.secret_path`` sub-table — the SAME first-class category location
|
|
131
|
+
# ``config set agent.<node>.secret_path.<VAR>`` writes and ``_agent_partial``
|
|
132
|
+
# reads into the launch cascade — so the persona-adopted token pointer resolves
|
|
133
|
+
# through the cascade like any other agent-tier category. Only materialized when
|
|
134
|
+
# non-empty (sparse). NO ``env_file`` section (RENAMED, clean break — rc0-rc2 only).
|
|
135
|
+
if cfg.secret_path:
|
|
136
|
+
agent_sec[node] = {"secret_path": dict(cfg.secret_path)}
|
|
137
|
+
|
|
138
|
+
data: dict = {
|
|
139
|
+
"agent": agent_sec,
|
|
140
|
+
"env": dict(cfg.env),
|
|
141
|
+
"tweakcc": dict(cfg.tweakcc),
|
|
142
|
+
}
|
|
143
|
+
# The settings file lives inside the per-agent store dir
|
|
144
|
+
# (agents/<agent>/settings.yaml); ensure that dir exists.
|
|
145
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
146
|
+
dump_doc(path, data)
|