git init | first commit

This commit is contained in:
2026-07-12 18:06:43 +02:00
parent 8154f4bb29
commit a3a9b0e24b
11 changed files with 572 additions and 1 deletions

3
.env.example Normal file
View File

@@ -0,0 +1,3 @@
OPENCHAMBER_PORT=5200
UI_PASSWORD=
REPOSITORIES_PATH=./repositories

12
.gitignore vendored Normal file
View File

@@ -0,0 +1,12 @@
.DS_Store
.env
repositories/
opencode-cache/
opencode-data/
opencode-state/
openchamber-config/
opencode-config/agents
opencode-config/commands
opencode-config/skills
opencode-config/plugins
opencode-config/opencode.jsonc

43
Dockerfile Normal file
View File

@@ -0,0 +1,43 @@
FROM node:26-trixie-slim
USER root
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
curl \
bash \
ca-certificates \
coreutils \
findutils \
git \
grep \
openssh-client \
tar \
docker.io \
docker-compose \
python3 \
python3-pip \
pipx \
make \
g++ \
&& rm -rf /var/lib/apt/lists/*
USER node
ENV HOME=/home/node
ENV PATH="/home/node/.local/bin:/home/node/.opencode/bin:${PATH}"
RUN npm config set prefix ~/.local
WORKDIR /home/node
# Install OpenCode CLI
RUN curl -fsSL https://opencode.ai/install | bash
# Install OpenChamber (web + PWA)
RUN curl -fsSL https://raw.githubusercontent.com/openchamber/openchamber/main/scripts/install.sh | bash
# Install Graphifyy
RUN pipx install graphifyy && graphify install opencode
CMD ["sh", "-c", "rm -f /home/node/.config/openchamber/run/openchamber-*.pid /home/node/.config/openchamber/run/openchamber-*.json && exec openchamber serve --host 0.0.0.0 --port ${OPENCHAMBER_PORT:-5200} --foreground ${UI_PASSWORD:+--ui-password $UI_PASSWORD}"]

132
README.md
View File

@@ -1,2 +1,132 @@
# my-opencode-simple
# OpenCode Web
Dockerized [OpenCode](https://opencode.ai) with [OpenChamber](https://github.com/openchamber/openchamber) as the browser/PWA frontend.
## What it does
This project runs OpenChamber in the container and lets OpenChamber start and keep OpenCode available in the background.
The stack inside the container:
- **OpenCode CLI** — the AI coding assistant
- **OpenChamber** — web frontend that starts and presents OpenCode
- **Node 26** — runtime
- **Graphifyy** — knowledge-graph skill for codebase understanding (installed via pipx)
## OpenCode configuration
The `opencode-config/` directory contains a full custom OpenCode agent setup, mounted at `/home/node/.config/opencode` inside the container.
### Agents
| File | Mode | Purpose |
| --- | --- | --- |
| `agents/build.md` | primary | Default agent with full permission set for implementation work |
| `agents/explore.md` | subagent | Specialized codebase file/content search |
| `agents/general.md` | subagent | General-purpose multi-step research and execution |
| `agents/plan.md` | primary | Plan mode — architecture design and implementation plans (read-only) |
| `agent/executor.md` | subagent | Runs shell commands only, no editing or file-reading |
### Commands
| File | Description |
| --- | --- |
| `command/commit.md` | Create git commits with auto-generated conventional commit messages |
| `command/rapid.md` | Fast iteration mode — quick fixes without extensive planning |
| `commands/plan.md` | Creates detailed implementation plans |
| `commands/review.md` | Reviews code changes (commit, branch, PR, or uncommitted) |
### Plugins
| File | Description |
| --- | --- |
| `plugin/fail-fast.ts` | Converts denied permissions and missing shell utilities into explicit task failures so agents don't stall or retry blocked actions |
### Snippets
| File | Aliases | Description |
| --- | --- | --- |
| `snippet/commit-message.md` | `cm` | Generates a commit message from current changes |
| `snippet/create-plan.md` | `plan` | Creates an implementation plan from the current session |
### Permissions
Fine-grained tool permissions are defined in `opencode.jsonc` (auto-generated, gitignored). Each agent has a tailored permission set — for example, `explore` has broad read/search access with bash allowed, while `build` has write/edit access but denies bash for safety.
## Fail-fast plugin
The fail-fast plugin (`plugin/fail-fast.ts`) hooks into OpenCode's tool lifecycle to catch three conditions:
1. **Permission denied** — if a `permission.ask` results in `deny`, the plugin throws a `FAIL_FAST_PERMISSION_DENIED` error with the permission name and next-action guidance.
2. **Invalid command** — if bash is called without a command, it throws `FAIL_FAST_INVALID_COMMAND`.
3. **Missing utility** — after every bash execution, the plugin checks stderr/stdout for "command not found", "not found", "ENOENT" patterns. If found, it throws `FAIL_FAST_MISSING_UTILITY` with the utility name.
This prevents agents from silently retrying blocked operations or looping on missing dependencies.
## How to run
```bash
docker compose up -d
```
Open `http://localhost:5200` in your browser.
To run OpenChamber on a different port, set `OPENCHAMBER_PORT` in `.env` and restart the container:
```env
OPENCHAMBER_PORT=5300
```
The container uses host networking, so OpenChamber binds directly to `OPENCHAMBER_PORT`; there is no separate Docker port mapping to update.
To protect the UI, set `UI_PASSWORD` in `.env`.
User and group IDs can be set in `.env` to match the host user:
```env
UID=1000
GID=1000
```
## How to update
Rebuild the image to pull the latest versions of OpenCode and OpenChamber:
```bash
docker compose build --no-cache
docker compose up -d
```
## Managing repositories
Set `REPOSITORIES_PATH` in `.env` to the host directory that contains repositories OpenCode should work on:
```env
REPOSITORIES_PATH=./repositories
```
The directory is mounted at `/home/repositories` inside the container.
## Container details
| Aspect | Detail |
| --- | --- |
| Network | `host` mode — no port mapping needed |
| Docker access | `/var/run/docker.sock` mounted for in-container Docker usage |
| Container user | Runs as `${UID}:${GID}` (default 1000:1000) |
| OpenChamber | Configured to allow unauthenticated LAN access (`OPENCHAMBER_ALLOW_UNAUTHENTICATED_LAN=true`) |
## Persisted data (gitignored)
| Local path | Container mount point | Purpose |
| --- | --- | --- |
| `.config/opencode-data/` | `/home/node/.local/share/opencode` | Agent state and tool outputs |
| `.config/opencode-state/` | `/home/node/.local/state/opencode` | Session and runtime state |
| `.config/opencode-cache/` | `/home/node/.cache/opencode` | Model cache and temporary data |
| `.config/openchamber-config/` | `/home/node/.config/openchamber` | OpenChamber configuration and session data |
## Browser and PWA notifications
OpenChamber can send browser notifications for prompt completion, questions, errors, and subtasks.
To receive notifications, open OpenChamber in your browser or installed PWA and allow notifications for the site/app when prompted. If notifications were previously blocked, reset the site notification permission in your browser settings.

20
docker-compose.yml Normal file
View File

@@ -0,0 +1,20 @@
services:
my-opencode:
user: "${UID}:${GID}"
build:
context: .
volumes:
- "./opencode-config:/home/node/.config/opencode"
- ".config/opencode-data:/home/node/.local/share/opencode"
- ".config/opencode-state:/home/node/.local/state/opencode"
- ".config/opencode-cache:/home/node/.cache/opencode"
- ".config/openchamber-config:/home/node/.config/openchamber"
- "${REPOSITORIES_PATH:-./repositories}:/home/node/repositories"
- "/var/run/docker.sock:/var/run/docker.sock"
environment:
OPENCHAMBER_PORT: ${OPENCHAMBER_PORT:-5200}
OPENCODE_BINARY: /home/node/.opencode/bin/opencode
OPENCHAMBER_ALLOW_UNAUTHENTICATED_LAN: true
UI_PASSWORD: ${UI_PASSWORD:-}
restart: unless-stopped
network_mode: host

View File

@@ -0,0 +1,62 @@
---
description: Runs shell commands and returns command results. Use this instead
of the general agent whenever a task is only to execute commands.
mode: subagent
temperature: 0.1
tools:
write: false
edit: false
bash: true
permission:
doom_loop: ask
external_directory:
"*": ask
/home/.local/share/opencode/tool-output/*: allow
/tmp/opencode/*: allow
question: deny
plan_enter: deny
plan_exit: deny
read:
"*": deny
"*.env": ask
"*.env.*": ask
"*.env.example": allow
edit: deny
bash:
rm *: deny
git push*: deny
git reset --hard*: deny
glob: deny
grep: deny
list: deny
task: deny
todowrite: deny
webfetch: deny
websearch: deny
model: openai/gpt-5.4-mini
---
You are the executor agent.
Your only responsibility is to run shell commands requested by the caller and report the results. Do not inspect files with non-shell tools, edit files, research, plan, or perform general coding work.
## Fail-Fast Capability Check
Before running a command, check whether it requires a denied permission, destructive action, or unavailable shell utility. If a command fails because a utility is missing or permission is denied, do not retry variants blindly.
Stop immediately and report:
- `FAIL_FAST_CAPABILITY_MISSING`
- Missing utility, denied permission, or blocked command
- Why it is required
- The exact command attempted or requested
- Exact next action for the caller
For each requested command:
1. Run the command exactly as needed, using the shell tool.
2. Report whether it succeeded or failed.
3. Include the relevant stdout, stderr, and exit status when available.
4. Keep analysis minimal and limited to what the command output shows.
If the request is not primarily command execution, say that it should be handled by another agent.

View File

@@ -0,0 +1,74 @@
---
description: Create git commit with auto-generated conventional commit message
agent: build
model: opencode/deepseek-v4-flash-free
---
# Git Commit Command
Create a well-structured git commit by analyzing staged changes and generating a conventional commit message.
## Phase 1: Gather Context
Run these commands in parallel to understand the current state:
1. `git status` - See all staged and unstaged changes
2. `git diff --cached` - View the actual staged changes that will be committed
3. `git log --oneline -5` - Review recent commit message style for consistency
## Phase 2: Analyze Changes
Based on the staged diff, determine:
1. **Change Type** (use conventional commits):
- `feat`: New feature
- `fix`: Bug fix
- `refactor`: Code restructuring without behavior change
- `docs`: Documentation only
- `test`: Adding or updating tests
- `chore`: Maintenance tasks
- `style`: Formatting, whitespace
- `perf`: Performance improvement
- `ci`: CI/CD changes
2. **Scope** (optional): Affected module or component
3. **Description**: Concise summary focusing on WHY, not WHAT
## Phase 3: Generate Commit Message
Format: `type(scope): description`
Rules:
- Use imperative mood ("Add feature" not "Added feature")
- Keep first line under 72 characters
- Focus on the purpose and impact
- Add body for complex changes explaining reasoning
## Phase 4: Execute Commit
1. If there are unstaged changes that should be included, ask user first
2. Stage any additional files if requested
3. Execute the commit with the generated message
4. Run `git status` to verify success
## Output Format
```
Commit Analysis
---------------
Type: [type]
Scope: [scope or "none"]
Files: [number] files changed
Generated Message:
[commit message]
Commit Status: [success/failure]
```
## Safety Checks
- NEVER commit files that appear to contain secrets (.env, credentials, API keys)
- WARN if committing lock files or large binary files
- CONFIRM before committing if there are untracked files that might be forgotten

View File

@@ -0,0 +1,57 @@
---
description: Fast iteration mode - quick fixes without extensive planning
agent: build
subtask: false
---
# Rapid Mode - Fast Iteration
You are in **rapid mode**. Optimize for speed and iteration velocity. Skip extensive planning and get to implementation quickly.
## Your Mission
Execute the following task with minimal ceremony:
$ARGUMENTS
## Rapid Execution Protocol
1. **Understand** (30 seconds max)
- What exactly needs to change?
- What's the fastest path to working code?
2. **Execute** (immediately)
- Make the change directly
- Use existing patterns - don't reinvent
- Keep changes minimal and focused
3. **Verify** (quick check)
- Does it work? Test it.
- Any obvious issues? Fix them.
## Rapid Mode Rules
- **No extensive planning** - Act first, refine later
- **Minimal changes** - Touch only what's necessary
- **Use existing patterns** - Copy from similar code in the codebase
- **Skip documentation** - Unless explicitly requested
- **Iterate fast** - Ship something, then improve
- **Ask only if blocked** - Make reasonable assumptions otherwise
## What Rapid Mode is NOT
- Not for complex architectural changes (use `/architect`)
- Not for learning or understanding (use `/mentor`)
- Not for critical security code (use `/review`)
- Not for large refactors (use `/refactor`)
## Output Style
Keep responses concise:
```
Changed: [what was modified]
Verified: [how it was tested]
Note: [any caveats, if critical]
```
Do not explain decisions unless they're non-obvious. Just ship it.

View File

@@ -0,0 +1,156 @@
/**
* Fail Fast Plugin
* Converts denied permissions and missing shell utilities into explicit task
* failures so agents do not repeatedly retry or stall on unavailable actions.
*/
import type { Plugin } from "@opencode-ai/plugin"
const MISSING_UTILITY_PATTERNS = [
/(?:^|\n)(?:sh|bash|zsh|fish):\s*(?<command>[\w./-]+):\s*command not found\b/i,
/(?:^|\n)(?<command>[\w./-]+):\s*command not found\b/i,
/(?:^|\n)(?:sh|bash|zsh|fish):\s*(?<command>[\w./-]+):\s*not found\b/i,
/(?:^|\n)(?<command>[\w./-]+):\s*not found\b/i,
/(?:^|\n)env:\s*(?<command>[\w./-]+):\s*No such file or directory\b/i,
/(?:^|\n).*spawn\s+(?<command>[\w./-]+)\s+ENOENT\b/i,
]
const SHELL_BUILTINS = new Set([
"alias",
"break",
"cd",
"command",
"continue",
"dirs",
"echo",
"eval",
"exec",
"exit",
"export",
"false",
"fg",
"hash",
"jobs",
"popd",
"printf",
"pushd",
"pwd",
"read",
"return",
"set",
"shift",
"source",
"test",
"true",
"type",
"ulimit",
"unalias",
"unset",
])
function normalizeCommand(command: string): string {
return command.replace(/^['"]|['"]$/g, "").trim()
}
function findMissingUtility(output: string): string | undefined {
for (const pattern of MISSING_UTILITY_PATTERNS) {
const match = pattern.exec(output)
const command = match?.groups?.command
if (!command) {
continue
}
const normalized = normalizeCommand(command)
if (normalized && !SHELL_BUILTINS.has(normalized)) {
return normalized
}
}
return undefined
}
function getBashCommand(args: unknown): string | undefined {
if (!args || typeof args !== "object") {
return undefined
}
const record = args as Record<string, unknown>
const command = record.command ?? record.cmd ?? record.script
return typeof command === "string" ? command : undefined
}
function describePermission(input: {
type: string
pattern?: string | string[]
title: string
}): string {
const pattern = Array.isArray(input.pattern)
? input.pattern.join(", ")
: input.pattern
return [input.type, pattern].filter(Boolean).join(" ") || input.title
}
export const FailFastPlugin = (async () => {
return {
"permission.ask": async (input, output) => {
if (output.status !== "deny") {
return
}
throw new Error(
[
"FAIL_FAST_PERMISSION_DENIED: A required tool permission was denied.",
`Permission: ${describePermission(input)}`,
`Title: ${input.title}`,
"Next action: reroute to an agent with the required permission, request permission from the user, or fail the task explicitly.",
].join("\n")
)
},
"tool.execute.before": async (input, output) => {
if (input.tool !== "bash") {
return
}
const command = getBashCommand(output.args)
if (command === undefined || command.trim()) {
return
}
throw new Error(
"FAIL_FAST_INVALID_COMMAND: The bash tool was called without a command. Stop and report the missing command instead of retrying."
)
},
"tool.execute.after": async (input, output) => {
if (input.tool !== "bash") {
return
}
const missingUtility = findMissingUtility(output.output ?? "")
if (!missingUtility) {
return
}
const command = getBashCommand(input.args)
const commandLine = command ? `\nCommand: ${command}` : ""
throw new Error(
[
`FAIL_FAST_MISSING_UTILITY: Required shell utility "${missingUtility}" is not available in this environment.`,
commandLine.trim(),
"Next action: install or mount the missing utility, choose a different validation path, or fail the task explicitly.",
]
.filter(Boolean)
.join("\n")
)
},
}
}) satisfies Plugin

View File

@@ -0,0 +1,7 @@
---
aliases:
- cm
description: Creates a commit message
---
Based on only the current changes recommend me a commit message.

View File

@@ -0,0 +1,7 @@
---
aliases:
- plan
description: It creates and implementation plan from the previous interactions and chat
---
I want you to create an implementation plan based on our conversation in this session. It should contain a precise instructions so even someone with less knowledge of the system can implement the plan without going into the wrong direction.