{"id":50138772,"url":"https://github.com/tdupont750/clause","last_synced_at":"2026-05-24T00:02:47.238Z","repository":{"id":352986331,"uuid":"1217363116","full_name":"tdupont750/clause","owner":"tdupont750","description":"Run Claude CLI in a lightweight container using only Bash.","archived":false,"fork":false,"pushed_at":"2026-05-18T23:28:12.000Z","size":1578,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-19T01:39:15.291Z","etag":null,"topics":["bash","bash-script","claude","claude-code","container","docker","podman"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tdupont750.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-21T20:10:48.000Z","updated_at":"2026-05-18T23:28:16.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tdupont750/clause","commit_stats":null,"previous_names":["tdupont750/clause"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tdupont750/clause","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tdupont750%2Fclause","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tdupont750%2Fclause/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tdupont750%2Fclause/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tdupont750%2Fclause/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tdupont750","download_url":"https://codeload.github.com/tdupont750/clause/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tdupont750%2Fclause/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33416315,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T22:14:44.296Z","status":"ssl_error","status_checked_at":"2026-05-23T22:14:43.778Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bash","bash-script","claude","claude-code","container","docker","podman"],"created_at":"2026-05-24T00:02:45.794Z","updated_at":"2026-05-24T00:02:47.230Z","avatar_url":"https://github.com/tdupont750.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Clause\n\nMeet Claude’s safety-conscious friend, Clause!\n\nClause mounts your working directory into a tiny container with its own copy of [Claude Code](https://claude.ai/code). Inside that container, Claude can do whatever it wants however it wants, while your host machine and all of its secrets stay safe. Clause supports persistent settings and credentials in named profiles that can use custom container images.\n\n![Clause](images/clause_small.png)\n\n## Why use Clause?\n\n1. You should be running your agents inside a container. Stop raw-dogging the internet. You're going to catch something.\n\n2. Clause is just a single Bash script. No frameworks, packages, runtimes, installs, or opinionated code. Change anything you like.\n\n## Requirements\n\n- [Podman](https://podman.io/) or [Docker](https://www.docker.com/)\n\n`clause` auto-detects whichever is on your `PATH`, preferring Podman. To override:\n\n```bash\nclause --runtime-set docker\n```\n\n## Getting Started\n\n```bash\n# 1. Make the script executable:\nchmod +x clause\n\n# 2. Add the shell alias** so you can run `clause` from any directory:\n./clause --alias-create\n\n# 3. Then reload your shell (`source ~/.bashrc` or open a new terminal).\nsource ~/.bashrc\n\n# 4. Build the container image:**\nclause -b\n\n# 5. Start Claude in your project:\ncd ~/your-project\nclause\n```\n\nThat's it. Claude Code runs inside the container with your project mounted at `/workspace`.\n\n## Usage\n\n```\nusage: clause [-h] [profile] [options]\n\narguments:\n  profile                 Profile to use (default: 'default')\n\nsession options:\n  -a, --args \u003cvalue\u003e      One-shot claude args (overrides clause-args files)\n  -t, --terminal          Launch bash instead of claude\n  -w, --workspace \u003cpath\u003e  Workspace directory (default: $PWD)\n\nprompt options:\n  -y, --yes               Auto-answer yes to all prompts\n  -n, --no                Auto-answer no to all prompts\n\nmapping (then exit):\n  -m, --map               Add workspace→profile mapping\n  -u, --unmap             Remove workspace→profile mapping\n  -l, --list              Show current mapping and list all profiles\n  -L, --list-all          List all workspace→profile mappings\n\nprofile management (then exit):\n  -C, --create-profile        Create a new profile (Containerfile + clause-args seeded)\n  -D, --delete-profile        Delete a profile and remove its mappings\n  -R, --reset-containerfile   Overwrite profile Containerfile with default\n  -S, --suggest-updates       Suggest Containerfile updates from sudo log\n\narguments (then exit):\n  -A, --args-view                 Print effective claude args + source\n      --args-set \u003cvalue\u003e          Write workspace .clause-args (this directory)\n      --args-set-profile \u003cvalue\u003e  Write profile clause-args\n                                  Default: --effort max --dangerously-skip-permissions\n\nalias management (then exit):\n  --alias-create          Add clause alias to .bashrc and/or .zshrc\n  --alias-delete          Remove clause alias from .bashrc and/or .zshrc\n\nruntime management (then exit):\n  --runtime-set \u003cvalue\u003e   Set container runtime override (podman or docker)\n  --runtime-remove        Remove container runtime override\n\nother:\n  -b, --build             Build the container image\n  -h, --help              Print this help\n```\n\nRunning `clause` launches Claude Code inside the container with your current directory mounted at `/workspace`.\n\n## Profiles\n\nProfiles isolate Claude settings, credentials, history, and plugins. Each profile is a directory under `~/.clause/profiles/` with its own `.claude/`, `.claude.json`, `Containerfile`, and `clause-args`. The `default` profile is created automatically on first run.\n\n```bash\n# Create a profile (also adds a workspace→profile mapping)\nclause work -C\n\n# Use a profile\nclause work\n\n# Show current mapping and list all profiles\nclause -l\n\n# Delete a profile (also removes its workspace mappings and image)\nclause work -D\n```\n\n### Per-profile Container Images\n\nEvery profile gets its own `Containerfile` (copied from `defaults/Containerfile` when the profile is created) and builds to a profile-specific image `clause-\u003cprofile\u003e`.\n\n```bash\n# Edit ~/.clause/profiles/work/Containerfile as needed, then build\nclause work -b\n\n# Overwrite a profile's Containerfile with the default again\nclause work -R\n```\n\n- `-b` / `--build` is profile-aware: it builds `clause-\u003cprofile\u003e` from the profile's `Containerfile`. If a profile has no `Containerfile` (legacy profiles created before this change), it falls back to building the base `clause` image from the repo's default.\n- `-R` / `--reset-containerfile` overwrites the profile's `Containerfile` with the current default.\n\n### Claude args\n\nThe args appended to `claude` at launch come from one of three places, in this precedence:\n\n1. **`-a, --args \u003cstring\u003e`** — one-shot CLI override for this launch only.\n2. **`$WORKSPACE/.clause-args`** — workspace-local override. Present (even empty) wins over the profile file. Manage with `--args-set \u003cstring\u003e`.\n3. **`$PROFILE_DIR/clause-args`** — profile default at `~/.clause/profiles/\u003cprofile\u003e/clause-args`, seeded on profile creation. Manage with `--args-set-profile \u003cstring\u003e`.\n\nThe seeded default content is:\n\n```\n--effort max --dangerously-skip-permissions\n```\n\n```bash\n# One-shot override for this launch\nclause work -a '--effort high'\n\n# Print what would actually be used (and from where)\nclause work -A\n\n# Write workspace-local override\nclause --args-set '--effort low'\n\n# Write profile-wide default\nclause work --args-set-profile '--effort max --dangerously-skip-permissions'\n```\n\nArgs are ignored under `-t/--terminal` (bash mode passes no args). An empty `.clause-args` file means \"no args\" — the workspace explicitly opts out.\n\n## Workspace Mappings\n\n`clause` remembers which profile to use for each workspace directory in `clause.conf`. On first use from a directory, you'll be prompted to save the mapping.\n\n```\nNo mapping found. Save /home/tom/projects/myapp → work? [y/n/q]\n```\n\n- `y` — save mapping and continue\n- `n` — continue without saving\n- `q` — exit\n\nIf a mapping already exists but you specify a different profile, you'll be prompted to override it.\n\n```bash\n# Explicitly add a mapping without starting a session\nclause work -m\n\n# Show the current mapping (plus all profiles)\nclause -l\n\n# Remove the current mapping\nclause -u\n\n# List all mappings\nclause -L\n\n# Skip prompts in scripts\nclause work -y\n```\n\n## Shell Alias\n\nAdd a `clause` alias to your shell so you can run it from any directory without specifying the full path:\n\n```bash\nclause --alias-create\n```\n\nThis checks for `~/.bashrc` and `~/.zshrc` and prompts to append the alias to each file found. If the alias already exists in a file, it is skipped. To remove it:\n\n\u003e **Note:** Only aliases created by `--alias-create` are detected (they contain a `# clause-alias` marker). Manually created `alias clause=...` entries without this marker will not be detected and may result in duplicates.\n\n```bash\nclause --alias-delete\n```\n\n## Persistence\n\nEach profile's data is stored under `~/.clause/profiles/\u003cname\u003e/` and bind-mounted into the container:\n\n| What | Host path | Container path |\n|------|-----------|----------------|\n| Credentials, history, plugins, cache | `~/.clause/profiles/\u003cname\u003e/.claude/` | `/home/claude/.claude/` |\n| Settings, first-run state | `~/.clause/profiles/\u003cname\u003e/.claude.json` | `/home/claude/.claude.json` |\n| Git configuration | `~/.clause/profiles/\u003cname\u003e/.gitconfig` | `/home/claude/.gitconfig` |\n| Containerfile (per profile) | `~/.clause/profiles/\u003cname\u003e/Containerfile` | — (build input) |\n| Claude args (profile) | `~/.clause/profiles/\u003cname\u003e/clause-args` | — (read by `clause` on launch) |\n| Claude args (workspace override) | `\u003cworkspace\u003e/.clause-args` | — (read by `clause` on launch) |\n| sudo activity log | `~/.clause/profiles/\u003cname\u003e/.claude/clause-sudo.log` | `/home/claude/.claude/clause-sudo.log` |\n| Workspace mappings | `~/.clause/clause.conf` | — |\n| Workspace | `$PWD` (or `-w path`) | `/workspace/` |\n\nAll runtime state lives in `~/.clause/` and is created automatically on first run. Nothing in the clause repo needs to be gitignored for runtime data.\n\n## Rebuilding\n\nAfter changes to `Containerfile`:\n\n```bash\nclause -b\n```\n\n`--build` is profile-aware: if the specified profile has its own `Containerfile` under `~/.clause/profiles/\u003cprofile\u003e/`, it builds the `clause-\u003cprofile\u003e` image from that file; otherwise it builds the base `clause` image from the repo `Containerfile`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftdupont750%2Fclause","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftdupont750%2Fclause","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftdupont750%2Fclause/lists"}