Compare commits

...

19 Commits

Author SHA1 Message Date
Adam
06fefbec09 chore: cleanup 2026-02-09 12:16:26 -06:00
Adam
fbef8f2ef3 chore: cleanup 2026-02-09 11:28:18 -06:00
Adam
14b0cf3bea chore: cleanup 2026-02-09 11:28:06 -06:00
Adam
28e82016de chore: cleanup 2026-02-09 11:22:12 -06:00
Adam
f019164f1e chore: cleanup 2026-02-09 11:20:26 -06:00
Adam
a3cd70a081 chore: cleanup 2026-02-09 11:20:25 -06:00
Adam
fb0082c2d6 chore: cleanup 2026-02-09 11:20:25 -06:00
Adam
0bfd31770d wip(docs): i18n 2026-02-09 05:24:28 -06:00
Adam
5c447d751f wip(docs): i18n 2026-02-09 05:24:28 -06:00
Adam
16d92d6693 wip(docs): i18n 2026-02-09 05:24:28 -06:00
Adam
861aed0c6a chore: specs 2026-02-09 05:24:28 -06:00
Israel Araújo de Oliveira
93a11ddedf feat(desktop): add native Wayland toggle on Linux (#11971)
Co-authored-by: Brendan Allan <git@brendonovich.dev>
2026-02-09 17:00:35 +08:00
Brendan Allan
94feb811ca app: include sandboxes in project unseen/error notifs 2026-02-09 16:51:04 +08:00
OpeOginni
b0ceec9b19 feat(desktop): persist currentSidecarUrl in state when isSidecar prop is true (#12792) 2026-02-09 07:56:26 +00:00
opencode-agent[bot]
40b111d92c chore: generate 2026-02-09 07:36:24 +00:00
Brendan Allan
520110e864 desktop: track currentSidecarUrl 2026-02-09 15:34:52 +08:00
Silvio Ney
d4a68b0f4e feat: exclude devtools from production builds (#12290)
Co-authored-by: Brendan Allan <git@brendonovich.dev>
2026-02-09 07:30:15 +00:00
opencode-agent[bot]
019cfd4a52 chore: generate 2026-02-09 07:18:48 +00:00
OpeOginni
687210a55d feat(desktop): add isSidecar prop to AppInterface and logic to persist sidecar server urls (#12366)
Co-authored-by: Brendan Allan <git@brendonovich.dev>
2026-02-09 07:18:06 +00:00
657 changed files with 193041 additions and 532 deletions

82
.github/workflows/docs-locale-sync.yml vendored Normal file
View File

@@ -0,0 +1,82 @@
name: docs-locale-sync
on:
push:
branches:
- dev
paths:
- packages/web/src/content/docs/*.mdx
jobs:
sync-locales:
if: github.actor != 'opencode-agent[bot]'
runs-on: blacksmith-4vcpu-ubuntu-2404
permissions:
id-token: write
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Bun
uses: ./.github/actions/setup-bun
- name: Setup git committer
id: committer
uses: ./.github/actions/setup-git-committer
with:
opencode-app-id: ${{ vars.OPENCODE_APP_ID }}
opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }}
- name: Compute changed English docs
id: changes
run: |
FILES=$(git diff --name-only "${{ github.event.before }}" "${{ github.sha }}" -- 'packages/web/src/content/docs/*.mdx' || true)
if [ -z "$FILES" ]; then
echo "has_changes=false" >> "$GITHUB_OUTPUT"
echo "No English docs changed in push range"
exit 0
fi
echo "has_changes=true" >> "$GITHUB_OUTPUT"
{
echo "files<<EOF"
echo "$FILES"
echo "EOF"
} >> "$GITHUB_OUTPUT"
- name: Sync locale docs with OpenCode
if: steps.changes.outputs.has_changes == 'true'
uses: sst/opencode/github@latest
env:
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
with:
model: opencode/gpt-5.2
agent: docs
prompt: |
Update localized docs to match the latest English docs changes.
Changed English doc files:
<changed_english_docs>
${{ steps.changes.outputs.files }}
</changed_english_docs>
Requirements:
1. Update all relevant locale docs under packages/web/src/content/docs/<locale>/ so they reflect these English page changes.
2. Preserve frontmatter keys, internal links, code blocks, and existing locale-specific metadata unless the English change requires an update.
3. Keep locale docs structure aligned with their corresponding English pages.
4. Do not modify English source docs in packages/web/src/content/docs/*.mdx.
5. If no locale updates are needed, make no changes.
- name: Commit and push locale docs updates
if: steps.changes.outputs.has_changes == 'true'
run: |
if [ -z "$(git status --porcelain)" ]; then
echo "No locale docs changes to commit"
exit 0
fi
git add -A
git commit -m "docs(i18n): sync locale docs from english changes"
git pull --rebase --autostash origin "$GITHUB_REF_NAME"
git push origin HEAD:"$GITHUB_REF_NAME"

122
bun.lock
View File

@@ -470,7 +470,7 @@
"@astrojs/solid-js": "5.1.0",
"@astrojs/starlight": "0.34.3",
"@fontsource/ibm-plex-mono": "5.2.5",
"@shikijs/transformers": "3.4.2",
"@shikijs/transformers": "3.20.0",
"@types/luxon": "catalog:",
"ai": "catalog:",
"astro": "5.7.13",
@@ -485,8 +485,10 @@
"shiki": "catalog:",
"solid-js": "catalog:",
"toolbeam-docs-theme": "0.4.8",
"vscode-languageserver-types": "3.17.5",
},
"devDependencies": {
"@astrojs/check": "0.9.6",
"@types/node": "catalog:",
"opencode": "workspace:*",
"typescript": "catalog:",
@@ -617,12 +619,16 @@
"@anycable/core": ["@anycable/core@0.9.2", "", { "dependencies": { "nanoevents": "^7.0.1" } }, "sha512-x5ZXDcW/N4cxWl93CnbHs/u7qq4793jS2kNPWm+duPrXlrva+ml2ZGT7X9tuOBKzyIHf60zWCdIK7TUgMPAwXA=="],
"@astrojs/check": ["@astrojs/check@0.9.6", "", { "dependencies": { "@astrojs/language-server": "^2.16.1", "chokidar": "^4.0.1", "kleur": "^4.1.5", "yargs": "^17.7.2" }, "peerDependencies": { "typescript": "^5.0.0" }, "bin": { "astro-check": "bin/astro-check.js" } }, "sha512-jlaEu5SxvSgmfGIFfNgcn5/f+29H61NJzEMfAZ82Xopr4XBchXB1GVlcJsE+elUlsYSbXlptZLX+JMG3b/wZEA=="],
"@astrojs/cloudflare": ["@astrojs/cloudflare@12.6.3", "", { "dependencies": { "@astrojs/internal-helpers": "0.7.1", "@astrojs/underscore-redirects": "1.0.0", "@cloudflare/workers-types": "^4.20250507.0", "tinyglobby": "^0.2.13", "vite": "^6.3.5", "wrangler": "^4.14.1" }, "peerDependencies": { "astro": "^5.0.0" } }, "sha512-xhJptF5tU2k5eo70nIMyL1Udma0CqmUEnGSlGyFflLqSY82CRQI6nWZ/xZt0ZvmXuErUjIx0YYQNfZsz5CNjLQ=="],
"@astrojs/compiler": ["@astrojs/compiler@2.13.0", "", {}, "sha512-mqVORhUJViA28fwHYaWmsXSzLO9osbdZ5ImUfxBarqsYdMlPbqAqGJCxsNzvppp1BEzc1mJNjOVvQqeDN8Vspw=="],
"@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.7.1", "", {}, "sha512-7dwEVigz9vUWDw3nRwLQ/yH/xYovlUA0ZD86xoeKEBmkz9O6iELG1yri67PgAPW6VLL/xInA4t7H0CK6VmtkKQ=="],
"@astrojs/language-server": ["@astrojs/language-server@2.16.3", "", { "dependencies": { "@astrojs/compiler": "^2.13.0", "@astrojs/yaml2ts": "^0.2.2", "@jridgewell/sourcemap-codec": "^1.5.5", "@volar/kit": "~2.4.27", "@volar/language-core": "~2.4.27", "@volar/language-server": "~2.4.27", "@volar/language-service": "~2.4.27", "muggle-string": "^0.4.1", "tinyglobby": "^0.2.15", "volar-service-css": "0.0.68", "volar-service-emmet": "0.0.68", "volar-service-html": "0.0.68", "volar-service-prettier": "0.0.68", "volar-service-typescript": "0.0.68", "volar-service-typescript-twoslash-queries": "0.0.68", "volar-service-yaml": "0.0.68", "vscode-html-languageservice": "^5.6.1", "vscode-uri": "^3.1.0" }, "peerDependencies": { "prettier": "^3.0.0", "prettier-plugin-astro": ">=0.11.0" }, "optionalPeers": ["prettier", "prettier-plugin-astro"], "bin": { "astro-ls": "bin/nodeServer.js" } }, "sha512-yO5K7RYCMXUfeDlnU6UnmtnoXzpuQc0yhlaCNZ67k1C/MiwwwvMZz+LGa+H35c49w5QBfvtr4w4Zcf5PcH8uYA=="],
"@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.1", "", { "dependencies": { "@astrojs/internal-helpers": "0.6.1", "@astrojs/prism": "3.2.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.1.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.1", "remark-smartypants": "^3.0.2", "shiki": "^3.0.0", "smol-toml": "^1.3.1", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1", "vfile": "^6.0.3" } }, "sha512-c5F5gGrkczUaTVgmMW9g1YMJGzOtRvjjhw6IfGuxarM6ct09MpwysP10US729dy07gg8y+ofVifezvP3BNsWZg=="],
"@astrojs/mdx": ["@astrojs/mdx@4.3.13", "", { "dependencies": { "@astrojs/markdown-remark": "6.3.10", "@mdx-js/mdx": "^3.1.1", "acorn": "^8.15.0", "es-module-lexer": "^1.7.0", "estree-util-visit": "^2.0.0", "hast-util-to-html": "^9.0.5", "piccolore": "^0.1.3", "rehype-raw": "^7.0.0", "remark-gfm": "^4.0.1", "remark-smartypants": "^3.0.2", "source-map": "^0.7.6", "unist-util-visit": "^5.0.0", "vfile": "^6.0.3" }, "peerDependencies": { "astro": "^5.0.0" } }, "sha512-IHDHVKz0JfKBy3//52JSiyWv089b7GVSChIXLrlUOoTLWowG3wr2/8hkaEgEyd/vysvNQvGk+QhysXpJW5ve6Q=="],
@@ -639,6 +645,8 @@
"@astrojs/underscore-redirects": ["@astrojs/underscore-redirects@1.0.0", "", {}, "sha512-qZxHwVnmb5FXuvRsaIGaqWgnftjCuMY+GSbaVZdBmE4j8AfgPqKPxYp8SUERyJcjpKCEmO4wD6ybuGH8A2kVRQ=="],
"@astrojs/yaml2ts": ["@astrojs/yaml2ts@0.2.2", "", { "dependencies": { "yaml": "^2.5.0" } }, "sha512-GOfvSr5Nqy2z5XiwqTouBBpy5FyI6DEe+/g/Mk5am9SjILN1S5fOEvYK0GuWHg98yS/dobP4m8qyqw/URW35fQ=="],
"@aws-crypto/crc32": ["@aws-crypto/crc32@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg=="],
"@aws-crypto/crc32c": ["@aws-crypto/crc32c@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag=="],
@@ -849,6 +857,20 @@
"@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="],
"@emmetio/abbreviation": ["@emmetio/abbreviation@2.3.3", "", { "dependencies": { "@emmetio/scanner": "^1.0.4" } }, "sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA=="],
"@emmetio/css-abbreviation": ["@emmetio/css-abbreviation@2.1.8", "", { "dependencies": { "@emmetio/scanner": "^1.0.4" } }, "sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw=="],
"@emmetio/css-parser": ["@emmetio/css-parser@0.4.1", "", { "dependencies": { "@emmetio/stream-reader": "^2.2.0", "@emmetio/stream-reader-utils": "^0.1.0" } }, "sha512-2bC6m0MV/voF4CTZiAbG5MWKbq5EBmDPKu9Sb7s7nVcEzNQlrZP6mFFFlIaISM8X6514H9shWMme1fCm8cWAfQ=="],
"@emmetio/html-matcher": ["@emmetio/html-matcher@1.3.0", "", { "dependencies": { "@emmetio/scanner": "^1.0.0" } }, "sha512-NTbsvppE5eVyBMuyGfVu2CRrLvo7J4YHb6t9sBFLyY03WYhXET37qA4zOYUjBWFCRHO7pS1B9khERtY0f5JXPQ=="],
"@emmetio/scanner": ["@emmetio/scanner@1.0.4", "", {}, "sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA=="],
"@emmetio/stream-reader": ["@emmetio/stream-reader@2.2.0", "", {}, "sha512-fXVXEyFA5Yv3M3n8sUGT7+fvecGrZP4k6FnWWMSZVQf69kAq0LLpaBQLGcPR30m3zMmKYhECP4k/ZkzvhEW5kw=="],
"@emmetio/stream-reader-utils": ["@emmetio/stream-reader-utils@0.1.0", "", {}, "sha512-ZsZ2I9Vzso3Ho/pjZFsmmZ++FWeEd/txqybHTm4OgaZzdS8V9V/YYWQwg5TC38Z7uLWUV1vavpLLbjJtKubR1A=="],
"@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
"@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
@@ -1961,6 +1983,22 @@
"@vitest/utils": ["@vitest/utils@4.0.18", "", { "dependencies": { "@vitest/pretty-format": "4.0.18", "tinyrainbow": "^3.0.3" } }, "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA=="],
"@volar/kit": ["@volar/kit@2.4.28", "", { "dependencies": { "@volar/language-service": "2.4.28", "@volar/typescript": "2.4.28", "typesafe-path": "^0.2.2", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" }, "peerDependencies": { "typescript": "*" } }, "sha512-cKX4vK9dtZvDRaAzeoUdaAJEew6IdxHNCRrdp5Kvcl6zZOqb6jTOfk3kXkIkG3T7oTFXguEMt5+9ptyqYR84Pg=="],
"@volar/language-core": ["@volar/language-core@2.4.28", "", { "dependencies": { "@volar/source-map": "2.4.28" } }, "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ=="],
"@volar/language-server": ["@volar/language-server@2.4.28", "", { "dependencies": { "@volar/language-core": "2.4.28", "@volar/language-service": "2.4.28", "@volar/typescript": "2.4.28", "path-browserify": "^1.0.1", "request-light": "^0.7.0", "vscode-languageserver": "^9.0.1", "vscode-languageserver-protocol": "^3.17.5", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" } }, "sha512-NqcLnE5gERKuS4PUFwlhMxf6vqYo7hXtbMFbViXcbVkbZ905AIVWhnSo0ZNBC2V127H1/2zP7RvVOVnyITFfBw=="],
"@volar/language-service": ["@volar/language-service@2.4.28", "", { "dependencies": { "@volar/language-core": "2.4.28", "vscode-languageserver-protocol": "^3.17.5", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" } }, "sha512-Rh/wYCZJrI5vCwMk9xyw/Z+MsWxlJY1rmMZPsxUoJKfzIRjS/NF1NmnuEcrMbEVGja00aVpCsInJfixQTMdvLw=="],
"@volar/source-map": ["@volar/source-map@2.4.28", "", {}, "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ=="],
"@volar/typescript": ["@volar/typescript@2.4.28", "", { "dependencies": { "@volar/language-core": "2.4.28", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" } }, "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw=="],
"@vscode/emmet-helper": ["@vscode/emmet-helper@2.11.0", "", { "dependencies": { "emmet": "^2.4.3", "jsonc-parser": "^2.3.0", "vscode-languageserver-textdocument": "^1.0.1", "vscode-languageserver-types": "^3.15.1", "vscode-uri": "^3.0.8" } }, "sha512-QLxjQR3imPZPQltfbWRnHU6JecWTF1QSWhx3GAKQpslx7y3Dp6sIIXhKjiUJ/BR9FX8PVthjr9PD6pNwOJfAzw=="],
"@vscode/l10n": ["@vscode/l10n@0.0.18", "", {}, "sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ=="],
"@webgpu/types": ["@webgpu/types@0.1.54", "", {}, "sha512-81oaalC8LFrXjhsczomEQ0u3jG+TqE6V9QHLA8GNZq/Rnot0KDugu3LhSYSlie8tSdooAN1Hov05asrUUp9qgg=="],
"@zip.js/zip.js": ["@zip.js/zip.js@2.7.62", "", {}, "sha512-OaLvZ8j4gCkLn048ypkZu29KX30r8/OfFF2w4Jo5WXFr+J04J+lzJ5TKZBVgFXhlvSkqNFQdfnY1Q8TMTCyBVA=="],
@@ -1989,6 +2027,8 @@
"ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
"ajv-draft-04": ["ajv-draft-04@1.0.0", "", { "peerDependencies": { "ajv": "^8.5.0" }, "optionalPeers": ["ajv"] }, "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw=="],
"ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="],
"ansi-align": ["ansi-align@3.0.1", "", { "dependencies": { "string-width": "^4.1.0" } }, "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w=="],
@@ -2391,6 +2431,8 @@
"electron-to-chromium": ["electron-to-chromium@1.5.282", "", {}, "sha512-FCPkJtpst28UmFzd903iU7PdeVTfY0KAeJy+Lk0GLZRwgwYHn/irRcaCbQQOmr5Vytc/7rcavsYLvTM8RiHYhQ=="],
"emmet": ["emmet@2.4.11", "", { "dependencies": { "@emmetio/abbreviation": "^2.3.3", "@emmetio/css-abbreviation": "^2.1.8" } }, "sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ=="],
"emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
"emoji-regex-xs": ["emoji-regex-xs@1.0.0", "", {}, "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg=="],
@@ -3169,6 +3211,8 @@
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
"muggle-string": ["muggle-string@0.4.1", "", {}, "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ=="],
"multicast-dns": ["multicast-dns@7.2.5", "", { "dependencies": { "dns-packet": "^5.2.2", "thunky": "^1.0.2" }, "bin": { "multicast-dns": "cli.js" } }, "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg=="],
"mustache": ["mustache@4.2.0", "", { "bin": { "mustache": "bin/mustache" } }, "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ=="],
@@ -3321,6 +3365,8 @@
"pascal-case": ["pascal-case@3.1.2", "", { "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" } }, "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g=="],
"path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="],
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
@@ -3521,6 +3567,10 @@
"remeda": ["remeda@2.26.0", "", { "dependencies": { "type-fest": "^4.41.0" } }, "sha512-lmNNwtaC6Co4m0WTTNoZ/JlpjEqAjPZO0+czC9YVRQUpkbS4x8Hmh+Mn9HPfJfiXqUQ5IXXgSXSOB2pBKAytdA=="],
"request-light": ["request-light@0.7.0", "", {}, "sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q=="],
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
"require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
"reselect": ["reselect@4.1.8", "", {}, "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="],
@@ -3863,8 +3913,12 @@
"typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="],
"typesafe-path": ["typesafe-path@0.2.2", "", {}, "sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA=="],
"typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="],
"typescript-auto-import-cache": ["typescript-auto-import-cache@0.3.6", "", { "dependencies": { "semver": "^7.3.8" } }, "sha512-RpuHXrknHdVdK7wv/8ug3Fr0WNsNi5l5aB8MYYuXhq2UH5lnEB1htJ1smhtD5VeCsGr2p8mUDtd83LCQDFVgjQ=="],
"ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="],
"ulid": ["ulid@3.0.1", "", { "bin": { "ulid": "dist/cli.js" } }, "sha512-dPJyqPzx8preQhqq24bBG1YNkvigm87K8kVEHCD+ruZg24t6IFEFv00xMWfxcC4djmFtiTLdFuADn4+DOz6R7Q=="],
@@ -3961,10 +4015,40 @@
"vitest": ["vitest@4.0.18", "", { "dependencies": { "@vitest/expect": "4.0.18", "@vitest/mocker": "4.0.18", "@vitest/pretty-format": "4.0.18", "@vitest/runner": "4.0.18", "@vitest/snapshot": "4.0.18", "@vitest/spy": "4.0.18", "@vitest/utils": "4.0.18", "es-module-lexer": "^1.7.0", "expect-type": "^1.2.2", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^3.10.0", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", "vite": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.0.18", "@vitest/browser-preview": "4.0.18", "@vitest/browser-webdriverio": "4.0.18", "@vitest/ui": "4.0.18", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ=="],
"volar-service-css": ["volar-service-css@0.0.68", "", { "dependencies": { "vscode-css-languageservice": "^6.3.0", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-lJSMh6f3QzZ1tdLOZOzovLX0xzAadPhx8EKwraDLPxBndLCYfoTvnNuiFFV8FARrpAlW5C0WkH+TstPaCxr00Q=="],
"volar-service-emmet": ["volar-service-emmet@0.0.68", "", { "dependencies": { "@emmetio/css-parser": "^0.4.1", "@emmetio/html-matcher": "^1.3.0", "@vscode/emmet-helper": "^2.9.3", "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-nHvixrRQ83EzkQ4G/jFxu9Y4eSsXS/X2cltEPDM+K9qZmIv+Ey1w0tg1+6caSe8TU5Hgw4oSTwNMf/6cQb3LzQ=="],
"volar-service-html": ["volar-service-html@0.0.68", "", { "dependencies": { "vscode-html-languageservice": "^5.3.0", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-fru9gsLJxy33xAltXOh4TEdi312HP80hpuKhpYQD4O5hDnkNPEBdcQkpB+gcX0oK0VxRv1UOzcGQEUzWCVHLfA=="],
"volar-service-prettier": ["volar-service-prettier@0.0.68", "", { "dependencies": { "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0", "prettier": "^2.2 || ^3.0" }, "optionalPeers": ["@volar/language-service", "prettier"] }, "sha512-grUmWHkHlebMOd6V8vXs2eNQUw/bJGJMjekh/EPf/p2ZNTK0Uyz7hoBRngcvGfJHMsSXZH8w/dZTForIW/4ihw=="],
"volar-service-typescript": ["volar-service-typescript@0.0.68", "", { "dependencies": { "path-browserify": "^1.0.1", "semver": "^7.6.2", "typescript-auto-import-cache": "^0.3.5", "vscode-languageserver-textdocument": "^1.0.11", "vscode-nls": "^5.2.0", "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-z7B/7CnJ0+TWWFp/gh2r5/QwMObHNDiQiv4C9pTBNI2Wxuwymd4bjEORzrJ/hJ5Yd5+OzeYK+nFCKevoGEEeKw=="],
"volar-service-typescript-twoslash-queries": ["volar-service-typescript-twoslash-queries@0.0.68", "", { "dependencies": { "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-NugzXcM0iwuZFLCJg47vI93su5YhTIweQuLmZxvz5ZPTaman16JCvmDZexx2rd5T/75SNuvvZmrTOTNYUsfe5w=="],
"volar-service-yaml": ["volar-service-yaml@0.0.68", "", { "dependencies": { "vscode-uri": "^3.0.8", "yaml-language-server": "~1.19.2" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-84XgE02LV0OvTcwfqhcSwVg4of3MLNUWPMArO6Aj8YXqyEVnPu8xTEMY2btKSq37mVAPuaEVASI4e3ptObmqcA=="],
"vscode-css-languageservice": ["vscode-css-languageservice@6.3.9", "", { "dependencies": { "@vscode/l10n": "^0.0.18", "vscode-languageserver-textdocument": "^1.0.12", "vscode-languageserver-types": "3.17.5", "vscode-uri": "^3.1.0" } }, "sha512-1tLWfp+TDM5ZuVWht3jmaY5y7O6aZmpeXLoHl5bv1QtRsRKt4xYGRMmdJa5Pqx/FTkgRbsna9R+Gn2xE+evVuA=="],
"vscode-html-languageservice": ["vscode-html-languageservice@5.6.1", "", { "dependencies": { "@vscode/l10n": "^0.0.18", "vscode-languageserver-textdocument": "^1.0.12", "vscode-languageserver-types": "^3.17.5", "vscode-uri": "^3.1.0" } }, "sha512-5Mrqy5CLfFZUgkyhNZLA1Ye5g12Cb/v6VM7SxUzZUaRKWMDz4md+y26PrfRTSU0/eQAl3XpO9m2og+GGtDMuaA=="],
"vscode-json-languageservice": ["vscode-json-languageservice@4.1.8", "", { "dependencies": { "jsonc-parser": "^3.0.0", "vscode-languageserver-textdocument": "^1.0.1", "vscode-languageserver-types": "^3.16.0", "vscode-nls": "^5.0.0", "vscode-uri": "^3.0.2" } }, "sha512-0vSpg6Xd9hfV+eZAaYN63xVVMOTmJ4GgHxXnkLCh+9RsQBkWKIghzLhW2B9ebfG+LQQg8uLtsQ2aUKjTgE+QOg=="],
"vscode-jsonrpc": ["vscode-jsonrpc@8.2.1", "", {}, "sha512-kdjOSJ2lLIn7r1rtrMbbNCHjyMPfRnowdKjBQ+mGq6NAW5QY2bEZC/khaC5OR8svbbjvLEaIXkOq45e2X9BIbQ=="],
"vscode-languageserver": ["vscode-languageserver@9.0.1", "", { "dependencies": { "vscode-languageserver-protocol": "3.17.5" }, "bin": { "installServerIntoExtension": "bin/installServerIntoExtension" } }, "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g=="],
"vscode-languageserver-protocol": ["vscode-languageserver-protocol@3.17.5", "", { "dependencies": { "vscode-jsonrpc": "8.2.0", "vscode-languageserver-types": "3.17.5" } }, "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg=="],
"vscode-languageserver-textdocument": ["vscode-languageserver-textdocument@1.0.12", "", {}, "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA=="],
"vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="],
"vscode-nls": ["vscode-nls@5.2.0", "", {}, "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng=="],
"vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="],
"web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="],
"web-streams-polyfill": ["web-streams-polyfill@4.0.0-beta.3", "", {}, "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug=="],
@@ -4025,6 +4109,8 @@
"yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="],
"yaml-language-server": ["yaml-language-server@1.19.2", "", { "dependencies": { "@vscode/l10n": "^0.0.18", "ajv": "^8.17.1", "ajv-draft-04": "^1.0.0", "lodash": "4.17.21", "prettier": "^3.5.0", "request-light": "^0.5.7", "vscode-json-languageservice": "4.1.8", "vscode-languageserver": "^9.0.0", "vscode-languageserver-textdocument": "^1.0.1", "vscode-languageserver-types": "^3.16.0", "vscode-uri": "^3.0.2", "yaml": "2.7.1" }, "bin": { "yaml-language-server": "bin/yaml-language-server" } }, "sha512-9F3myNmJzUN/679jycdMxqtydPSDRAarSj3wPiF7pchEPnO9Dg07Oc+gIYLqXR4L+g+FSEVXXv2+mr54StLFOg=="],
"yargs": ["yargs@18.0.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg=="],
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
@@ -4097,6 +4183,8 @@
"@ai-sdk/xai/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@1.0.30", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-thubwhRtv9uicAxSWwNpinM7hiL/0CkhL/ymPaHuKvI494J7HIzn8KQZQ2ymRz284WTIZnI7VMyyejxW4RMM6w=="],
"@astrojs/check/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
"@astrojs/cloudflare/vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="],
"@astrojs/markdown-remark/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="],
@@ -4291,7 +4379,7 @@
"@opencode-ai/desktop/typescript": ["typescript@5.6.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw=="],
"@opencode-ai/web/@shikijs/transformers": ["@shikijs/transformers@3.4.2", "", { "dependencies": { "@shikijs/core": "3.4.2", "@shikijs/types": "3.4.2" } }, "sha512-I5baLVi/ynLEOZoWSAMlACHNnG+yw5HDmse0oe+GW6U1u+ULdEB3UHiVWaHoJSSONV7tlcVxuaMy74sREDkSvg=="],
"@opencode-ai/web/@shikijs/transformers": ["@shikijs/transformers@3.20.0", "", { "dependencies": { "@shikijs/core": "3.20.0", "@shikijs/types": "3.20.0" } }, "sha512-PrHHMRr3Q5W1qB/42kJW6laqFyWdhrPF2hNR9qjOm1xcSiAO3hAHo7HaVyHE6pMyevmy3i51O8kuGGXC78uK3g=="],
"@opentui/solid/@babel/core": ["@babel/core@7.28.0", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.0", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.27.3", "@babel/helpers": "^7.27.6", "@babel/parser": "^7.28.0", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.0", "@babel/types": "^7.28.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ=="],
@@ -4365,6 +4453,8 @@
"@tanstack/server-functions-plugin/@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="],
"@vscode/emmet-helper/jsonc-parser": ["jsonc-parser@2.3.1", "", {}, "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg=="],
"accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
"ai-gateway-provider/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.58", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-CkNW5L1Arv8gPtPlEmKd+yf/SG9ucJf0XQdpMG8OiYEtEMc2smuCA+tyCp8zI7IBVg/FE7nUfFHntQFaOjRwJQ=="],
@@ -4591,6 +4681,8 @@
"vitest/why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],
"vscode-languageserver-protocol/vscode-jsonrpc": ["vscode-jsonrpc@8.2.0", "", {}, "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="],
"which-builtin-type/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
"wrangler/esbuild": ["esbuild@0.25.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.4", "@esbuild/android-arm": "0.25.4", "@esbuild/android-arm64": "0.25.4", "@esbuild/android-x64": "0.25.4", "@esbuild/darwin-arm64": "0.25.4", "@esbuild/darwin-x64": "0.25.4", "@esbuild/freebsd-arm64": "0.25.4", "@esbuild/freebsd-x64": "0.25.4", "@esbuild/linux-arm": "0.25.4", "@esbuild/linux-arm64": "0.25.4", "@esbuild/linux-ia32": "0.25.4", "@esbuild/linux-loong64": "0.25.4", "@esbuild/linux-mips64el": "0.25.4", "@esbuild/linux-ppc64": "0.25.4", "@esbuild/linux-riscv64": "0.25.4", "@esbuild/linux-s390x": "0.25.4", "@esbuild/linux-x64": "0.25.4", "@esbuild/netbsd-arm64": "0.25.4", "@esbuild/netbsd-x64": "0.25.4", "@esbuild/openbsd-arm64": "0.25.4", "@esbuild/openbsd-x64": "0.25.4", "@esbuild/sunos-x64": "0.25.4", "@esbuild/win32-arm64": "0.25.4", "@esbuild/win32-ia32": "0.25.4", "@esbuild/win32-x64": "0.25.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q=="],
@@ -4601,6 +4693,12 @@
"wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"yaml-language-server/lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
"yaml-language-server/request-light": ["request-light@0.5.8", "", {}, "sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg=="],
"yaml-language-server/yaml": ["yaml@2.7.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ=="],
"yargs/yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="],
"zod-to-json-schema/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
@@ -4621,6 +4719,10 @@
"@ai-sdk/openai/@ai-sdk/provider-utils/zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="],
"@astrojs/check/yargs/cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
"@astrojs/check/yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"@astrojs/mdx/@astrojs/markdown-remark/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.7.5", "", {}, "sha512-vreGnYSSKhAjFJCWAwe/CNhONvoc5lokxtRoZims+0wa3KbHBdPHSSthJsKxPd8d/aic6lWKpRTYGY/hsgK6EA=="],
"@astrojs/mdx/@astrojs/markdown-remark/@astrojs/prism": ["@astrojs/prism@3.3.0", "", { "dependencies": { "prismjs": "^1.30.0" } }, "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ=="],
@@ -4865,9 +4967,9 @@
"@opencode-ai/desktop/@actions/artifact/@actions/http-client": ["@actions/http-client@2.2.3", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^5.25.4" } }, "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA=="],
"@opencode-ai/web/@shikijs/transformers/@shikijs/core": ["@shikijs/core@3.4.2", "", { "dependencies": { "@shikijs/types": "3.4.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-AG8vnSi1W2pbgR2B911EfGqtLE9c4hQBYkv/x7Z+Kt0VxhgQKcW7UNDVYsu9YxwV6u+OJrvdJrMq6DNWoBjihQ=="],
"@opencode-ai/web/@shikijs/transformers/@shikijs/core": ["@shikijs/core@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g=="],
"@opencode-ai/web/@shikijs/transformers/@shikijs/types": ["@shikijs/types@3.4.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-zHC1l7L+eQlDXLnxvM9R91Efh2V4+rN3oMVS2swCBssbj2U/FBwybD1eeLaq8yl/iwT+zih8iUbTBCgGZOYlVg=="],
"@opencode-ai/web/@shikijs/transformers/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="],
"@opentui/solid/@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
@@ -5111,6 +5213,14 @@
"@actions/github/@octokit/plugin-rest-endpoint-methods/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@20.0.0", "", {}, "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="],
"@astrojs/check/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"@astrojs/check/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
"@astrojs/check/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"@astrojs/check/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"@aws-crypto/sha1-browser/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
"@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
@@ -5251,6 +5361,10 @@
"tw-to-css/tailwindcss/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
"@astrojs/check/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"@astrojs/check/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/token-providers/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.782.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.775.0", "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", "@aws-sdk/middleware-user-agent": "3.782.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", "@aws-sdk/util-endpoints": "3.782.0", "@aws-sdk/util-user-agent-browser": "3.775.0", "@aws-sdk/util-user-agent-node": "3.782.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/fetch-http-handler": "^5.0.2", "@smithy/hash-node": "^4.0.2", "@smithy/invalid-dependency": "^4.0.2", "@smithy/middleware-content-length": "^4.0.2", "@smithy/middleware-endpoint": "^4.1.0", "@smithy/middleware-retry": "^4.1.0", "@smithy/middleware-serde": "^4.0.3", "@smithy/middleware-stack": "^4.0.2", "@smithy/node-config-provider": "^4.0.2", "@smithy/node-http-handler": "^4.0.4", "@smithy/protocol-http": "^5.1.0", "@smithy/smithy-client": "^4.2.0", "@smithy/types": "^4.2.0", "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", "@smithy/util-defaults-mode-browser": "^4.0.8", "@smithy/util-defaults-mode-node": "^4.0.8", "@smithy/util-endpoints": "^3.0.2", "@smithy/util-middleware": "^4.0.2", "@smithy/util-retry": "^4.0.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-QOYC8q7luzHFXrP0xYAqBctoPkynjfV0r9dqntFu4/IWMTyC1vlo1UTxFAjIPyclYw92XJyEkVCVg9v/nQnsUA=="],
"@jsx-email/cli/tailwindcss/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],

View File

@@ -84,7 +84,7 @@ function ServerKey(props: ParentProps) {
)
}
export function AppInterface(props: { defaultUrl?: string; children?: JSX.Element }) {
export function AppInterface(props: { defaultUrl?: string; children?: JSX.Element; isSidecar?: boolean }) {
const platform = usePlatform()
const stored = (() => {
@@ -106,7 +106,7 @@ export function AppInterface(props: { defaultUrl?: string; children?: JSX.Elemen
}
return (
<ServerProvider defaultUrl={defaultServerUrl()}>
<ServerProvider defaultUrl={defaultServerUrl()} isSidecar={props.isSidecar}>
<ServerKey>
<GlobalSDKProvider>
<GlobalSyncProvider>

View File

@@ -1,8 +1,10 @@
import { Component, createMemo, type JSX } from "solid-js"
import { Component, Show, createEffect, createMemo, createResource, type JSX } from "solid-js"
import { createStore } from "solid-js/store"
import { Button } from "@opencode-ai/ui/button"
import { Icon } from "@opencode-ai/ui/icon"
import { Select } from "@opencode-ai/ui/select"
import { Switch } from "@opencode-ai/ui/switch"
import { Tooltip } from "@opencode-ai/ui/tooltip"
import { useTheme, type ColorScheme } from "@opencode-ai/ui/theme"
import { showToast } from "@opencode-ai/ui/toast"
import { useLanguage } from "@/context/language"
@@ -40,6 +42,8 @@ export const SettingsGeneral: Component = () => {
checking: false,
})
const linux = createMemo(() => platform.platform === "desktop" && platform.os === "linux")
const check = () => {
if (!platform.checkUpdate) return
setStore("checking", true)
@@ -410,13 +414,49 @@ export const SettingsGeneral: Component = () => {
</SettingsRow>
</div>
</div>
<Show when={linux()}>
{(_) => {
const [valueResource, actions] = createResource(() => platform.getDisplayBackend?.())
const value = () => (valueResource.state === "pending" ? undefined : valueResource.latest)
const onChange = (checked: boolean) =>
platform.setDisplayBackend?.(checked ? "wayland" : "auto").finally(() => actions.refetch())
return (
<div class="flex flex-col gap-1">
<h3 class="text-14-medium text-text-strong pb-2">{language.t("settings.general.section.display")}</h3>
<div class="bg-surface-raised-base px-4 rounded-lg">
<SettingsRow
title={
<div class="flex items-center gap-2">
<span>{language.t("settings.general.row.wayland.title")}</span>
<Tooltip value={language.t("settings.general.row.wayland.tooltip")} placement="top">
<span class="text-text-weak">
<Icon name="help" size="small" />
</span>
</Tooltip>
</div>
}
description={language.t("settings.general.row.wayland.description")}
>
<div data-action="settings-wayland">
<Switch checked={value() === "wayland"} onChange={onChange} />
</div>
</SettingsRow>
</div>
</div>
)
}}
</Show>
</div>
</div>
)
}
interface SettingsRowProps {
title: string
title: string | JSX.Element
description: string | JSX.Element
children: JSX.Element
}

View File

@@ -57,6 +57,12 @@ export type Platform = {
/** Set the default server URL to use on app startup (platform-specific) */
setDefaultServerUrl?(url: string | null): Promise<void> | void
/** Get the preferred display backend (desktop only) */
getDisplayBackend?(): Promise<DisplayBackend | null> | DisplayBackend | null
/** Set the preferred display backend (desktop only) */
setDisplayBackend?(backend: DisplayBackend): Promise<void>
/** Parse markdown to HTML using native parser (desktop only, returns unprocessed code blocks) */
parseMarkdown?(markdown: string): Promise<string>
@@ -70,6 +76,8 @@ export type Platform = {
readClipboardImage?(): Promise<File | null>
}
export type DisplayBackend = "auto" | "wayland"
export const { use: usePlatform, provider: PlatformProvider } = createSimpleContext({
name: "Platform",
init: (props: { value: Platform }) => {

View File

@@ -28,13 +28,14 @@ function projectsKey(url: string) {
export const { use: useServer, provider: ServerProvider } = createSimpleContext({
name: "Server",
init: (props: { defaultUrl: string }) => {
init: (props: { defaultUrl: string; isSidecar?: boolean }) => {
const platform = usePlatform()
const [store, setStore, _, ready] = persisted(
Persist.global("server", ["server.v3"]),
createStore({
list: [] as string[],
currentSidecarUrl: "",
projects: {} as Record<string, StoredProject[]>,
lastProject: {} as Record<string, string>,
}),
@@ -59,7 +60,13 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext(
const fallback = normalizeServerUrl(props.defaultUrl)
if (fallback && url === fallback) {
setState("active", url)
batch(() => {
if (!store.list.includes(url)) {
// Add the fallback url to the list if it's not already in the list
setStore("list", store.list.length, url)
}
setState("active", url)
})
return
}
@@ -89,7 +96,20 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext(
if (state.active) return
const url = normalizeServerUrl(props.defaultUrl)
if (!url) return
setState("active", url)
batch(() => {
// Remove the previous startup sidecar url
if (store.currentSidecarUrl) {
remove(store.currentSidecarUrl)
}
// Add the new sidecar url
if (props.isSidecar && props.defaultUrl) {
add(props.defaultUrl)
setStore("currentSidecarUrl", props.defaultUrl)
}
setState("active", url)
})
})
const isReady = createMemo(() => ready() && !!state.active)

View File

@@ -588,6 +588,7 @@ export const dict = {
"settings.general.section.notifications": "System notifications",
"settings.general.section.updates": "Updates",
"settings.general.section.sounds": "Sound effects",
"settings.general.section.display": "Display",
"settings.general.row.language.title": "Language",
"settings.general.row.language.description": "Change the display language for OpenCode",
@@ -598,6 +599,11 @@ export const dict = {
"settings.general.row.font.title": "Font",
"settings.general.row.font.description": "Customise the mono font used in code blocks",
"settings.general.row.wayland.title": "Use native Wayland",
"settings.general.row.wayland.description": "Disable X11 fallback on Wayland. Requires restart.",
"settings.general.row.wayland.tooltip":
"On Linux with mixed refresh-rate monitors, native Wayland can be more stable.",
"settings.general.row.releaseNotes.title": "Release notes",
"settings.general.row.releaseNotes.description": "Show What's New popups after updates",

View File

@@ -1,3 +1,3 @@
export { PlatformProvider, type Platform } from "./context/platform"
export { PlatformProvider, type Platform, type DisplayBackend } from "./context/platform"
export { AppBaseProviders, AppInterface } from "./app"
export { useCommand } from "./context/command"

View File

@@ -21,8 +21,11 @@ const OPENCODE_PROJECT_ID = "4b0ea68d7af9a6031a7ffda7ad66e0cb83315750"
export const ProjectIcon = (props: { project: LocalProject; class?: string; notify?: boolean }): JSX.Element => {
const notification = useNotification()
const unseenCount = createMemo(() => notification.project.unseenCount(props.project.worktree))
const hasError = createMemo(() => notification.project.unseenHasError(props.project.worktree))
const dirs = createMemo(() => [props.project.worktree, ...(props.project.sandboxes ?? [])])
const unseenCount = createMemo(() =>
dirs().reduce((total, directory) => total + notification.project.unseenCount(directory), 0),
)
const hasError = createMemo(() => dirs().some((directory) => notification.project.unseenHasError(directory)))
const name = createMemo(() => props.project.name || getFilename(props.project.worktree))
return (
<div class={`relative size-8 shrink-0 rounded ${props.class ?? ""}`}>

View File

@@ -68,6 +68,80 @@ const TAG = {
tr: "tr",
} satisfies Record<Locale, string>
const DOCS = {
en: "root",
zh: "zh-cn",
zht: "zh-tw",
ko: "ko",
de: "de",
es: "es",
fr: "fr",
it: "it",
da: "da",
ja: "ja",
pl: "pl",
ru: "ru",
ar: "ar",
no: "nb",
br: "pt-br",
th: "th",
tr: "tr",
} satisfies Record<Locale, string>
const DOCS_SEGMENT = new Set([
"ar",
"bs",
"da",
"de",
"es",
"fr",
"it",
"ja",
"ko",
"nb",
"pl",
"pt-br",
"ru",
"th",
"tr",
"zh-cn",
"zh-tw",
])
function suffix(pathname: string) {
const index = pathname.search(/[?#]/)
if (index === -1) {
return {
path: fix(pathname),
suffix: "",
}
}
return {
path: fix(pathname.slice(0, index)),
suffix: pathname.slice(index),
}
}
export function docs(locale: Locale, pathname: string) {
const value = DOCS[locale]
const next = suffix(pathname)
if (next.path !== "/docs" && next.path !== "/docs/" && !next.path.startsWith("/docs/")) {
return `${next.path}${next.suffix}`
}
if (value === "root") return `${next.path}${next.suffix}`
const hit = /^\/docs\/([^/]+)(\/.*)?$/.exec(next.path)
if (hit && DOCS_SEGMENT.has(hit[1] ?? "")) {
return `${next.path}${next.suffix}`
}
if (next.path === "/docs") return `/docs/${value}${next.suffix}`
if (next.path === "/docs/") return `/docs/${value}/${next.suffix}`
return `/docs/${value}${next.path.slice("/docs".length)}${next.suffix}`
}
export function parseLocale(value: unknown): Locale | null {
if (typeof value !== "string") return null
if ((LOCALES as readonly string[]).includes(value)) return value as Locale
@@ -90,7 +164,7 @@ export function strip(pathname: string) {
export function route(locale: Locale, pathname: string) {
const next = strip(pathname)
if (next.startsWith("/docs")) return next
if (next.startsWith("/docs")) return docs(locale, next)
if (next.startsWith("/auth")) return next
if (next.startsWith("/workspace")) return next
if (locale === "en") return next

View File

@@ -1,14 +1,14 @@
import type { APIEvent } from "@solidjs/start/server"
import { LOCALE_HEADER, localeFromCookieHeader, parseLocale, tag } from "~/lib/language"
import { docs, localeFromRequest, tag } from "~/lib/language"
async function handler(evt: APIEvent) {
const req = evt.request.clone()
const url = new URL(req.url)
const targetUrl = `https://docs.opencode.ai${url.pathname}${url.search}`
const locale = localeFromRequest(req)
const targetUrl = `https://docs.opencode.ai${docs(locale, url.pathname)}${url.search}`
const headers = new Headers(req.headers)
const locale = parseLocale(req.headers.get(LOCALE_HEADER)) ?? localeFromCookieHeader(req.headers.get("cookie"))
if (locale) headers.set("accept-language", tag(locale))
headers.set("accept-language", tag(locale))
const response = await fetch(targetUrl, {
method: req.method,

View File

@@ -1,14 +1,14 @@
import type { APIEvent } from "@solidjs/start/server"
import { LOCALE_HEADER, localeFromCookieHeader, parseLocale, tag } from "~/lib/language"
import { docs, localeFromRequest, tag } from "~/lib/language"
async function handler(evt: APIEvent) {
const req = evt.request.clone()
const url = new URL(req.url)
const targetUrl = `https://docs.opencode.ai${url.pathname}${url.search}`
const locale = localeFromRequest(req)
const targetUrl = `https://docs.opencode.ai${docs(locale, url.pathname)}${url.search}`
const headers = new Headers(req.headers)
const locale = parseLocale(req.headers.get(LOCALE_HEADER)) ?? localeFromCookieHeader(req.headers.get("cookie"))
if (locale) headers.set("accept-language", tag(locale))
headers.set("accept-language", tag(locale))
const response = await fetch(targetUrl, {
method: req.method,

View File

@@ -294,7 +294,7 @@ export default function Download() {
</span>
<span>VS Code</span>
</div>
<a href="https://opencode.ai/docs/ide/" data-component="action-button">
<a href={language.route("/docs/ide/")} data-component="action-button">
{i18n.t("download.action.install")}
</a>
</div>
@@ -318,7 +318,7 @@ export default function Download() {
</span>
<span>Cursor</span>
</div>
<a href="https://opencode.ai/docs/ide/" data-component="action-button">
<a href={language.route("/docs/ide/")} data-component="action-button">
{i18n.t("download.action.install")}
</a>
</div>
@@ -335,7 +335,7 @@ export default function Download() {
</span>
<span>Zed</span>
</div>
<a href="https://opencode.ai/docs/ide/" data-component="action-button">
<a href={language.route("/docs/ide/")} data-component="action-button">
{i18n.t("download.action.install")}
</a>
</div>
@@ -352,7 +352,7 @@ export default function Download() {
</span>
<span>Windsurf</span>
</div>
<a href="https://opencode.ai/docs/ide/" data-component="action-button">
<a href={language.route("/docs/ide/")} data-component="action-button">
{i18n.t("download.action.install")}
</a>
</div>
@@ -369,7 +369,7 @@ export default function Download() {
</span>
<span>VSCodium</span>
</div>
<a href="https://opencode.ai/docs/ide/" data-component="action-button">
<a href={language.route("/docs/ide/")} data-component="action-button">
{i18n.t("download.action.install")}
</a>
</div>
@@ -393,7 +393,7 @@ export default function Download() {
</span>
<span>GitHub</span>
</div>
<a href="https://opencode.ai/docs/github/" data-component="action-button">
<a href={language.route("/docs/github/")} data-component="action-button">
{i18n.t("download.action.install")}
</a>
</div>
@@ -410,7 +410,7 @@ export default function Download() {
</span>
<span>GitLab</span>
</div>
<a href="https://opencode.ai/docs/gitlab/" data-component="action-button">
<a href={language.route("/docs/gitlab/")} data-component="action-button">
{i18n.t("download.action.install")}
</a>
</div>

View File

@@ -1,14 +1,14 @@
import type { APIEvent } from "@solidjs/start/server"
import { LOCALE_HEADER, localeFromCookieHeader, parseLocale, tag } from "~/lib/language"
import { docs, localeFromRequest, tag } from "~/lib/language"
async function handler(evt: APIEvent) {
const req = evt.request.clone()
const url = new URL(req.url)
const targetUrl = `https://docs.opencode.ai/docs${url.pathname}${url.search}`
const locale = localeFromRequest(req)
const targetUrl = `https://docs.opencode.ai${docs(locale, `/docs${url.pathname}`)}${url.search}`
const headers = new Headers(req.headers)
const locale = parseLocale(req.headers.get(LOCALE_HEADER)) ?? localeFromCookieHeader(req.headers.get("cookie"))
if (locale) headers.set("accept-language", tag(locale))
headers.set("accept-language", tag(locale))
const response = await fetch(targetUrl, {
method: req.method,

View File

@@ -9,10 +9,12 @@ import { GraphSection } from "./graph-section"
import { IconLogo } from "~/component/icon"
import { querySessionInfo, queryBillingInfo, createCheckoutUrl, formatBalance } from "../common"
import { useI18n } from "~/context/i18n"
import { useLanguage } from "~/context/language"
export default function () {
const params = useParams()
const i18n = useI18n()
const language = useLanguage()
const userInfo = createAsync(() => querySessionInfo(params.id!))
const billingInfo = createAsync(() => queryBillingInfo(params.id!))
const checkoutAction = useAction(createCheckoutUrl)
@@ -38,7 +40,7 @@ export default function () {
<p>
<span>
{i18n.t("workspace.home.banner.beforeLink")}{" "}
<a target="_blank" href="/docs/zen">
<a target="_blank" href={language.route("/docs/zen")}>
{i18n.t("common.learnMore")}
</a>
.

View File

@@ -18,7 +18,7 @@ crate-type = ["staticlib", "cdylib", "rlib"]
tauri-build = { version = "2", features = [] }
[dependencies]
tauri = { version = "2.9.5", features = ["macos-private-api", "devtools"] }
tauri = { version = "2.9.5", features = ["macos-private-api"] }
tauri-plugin-opener = "2"
tauri-plugin-deep-link = "2.4.6"
tauri-plugin-shell = "2"
@@ -56,6 +56,7 @@ webkit2gtk = "=2.0.2"
objc2 = "0.6"
objc2-web-kit = "0.3"
[target.'cfg(windows)'.dependencies]
windows = { version = "0.61", features = [
"Win32_Foundation",

View File

@@ -2,6 +2,8 @@ mod cli;
mod constants;
#[cfg(windows)]
mod job_object;
#[cfg(target_os = "linux")]
mod linux_display;
mod markdown;
mod server;
mod window_customizer;
@@ -194,6 +196,43 @@ fn check_macos_app(app_name: &str) -> bool {
.unwrap_or(false)
}
#[derive(serde::Serialize, serde::Deserialize, specta::Type)]
#[serde(rename_all = "camelCase")]
pub enum LinuxDisplayBackend {
Wayland,
Auto,
}
#[tauri::command]
#[specta::specta]
fn get_display_backend() -> Option<LinuxDisplayBackend> {
#[cfg(target_os = "linux")]
{
let prefer = linux_display::read_wayland().unwrap_or(false);
return Some(if prefer {
LinuxDisplayBackend::Wayland
} else {
LinuxDisplayBackend::Auto
});
}
#[cfg(not(target_os = "linux"))]
None
}
#[tauri::command]
#[specta::specta]
fn set_display_backend(_app: AppHandle, _backend: LinuxDisplayBackend) -> Result<(), String> {
#[cfg(target_os = "linux")]
{
let prefer = matches!(_backend, LinuxDisplayBackend::Wayland);
return linux_display::write_wayland(&_app, prefer);
}
#[cfg(not(target_os = "linux"))]
Ok(())
}
#[cfg(target_os = "linux")]
fn check_linux_app(app_name: &str) -> bool {
return true;
@@ -209,6 +248,8 @@ pub fn run() {
await_initialization,
server::get_default_server_url,
server::set_default_server_url,
get_display_backend,
set_display_backend,
markdown::parse_markdown_command,
check_app_exists
])

View File

@@ -0,0 +1,47 @@
use serde::{Deserialize, Serialize};
use serde_json::json;
use std::path::PathBuf;
use tauri::AppHandle;
use tauri_plugin_store::StoreExt;
use crate::constants::SETTINGS_STORE;
pub const LINUX_DISPLAY_CONFIG_KEY: &str = "linuxDisplayConfig";
#[derive(Default, Serialize, Deserialize)]
struct DisplayConfig {
wayland: Option<bool>,
}
fn dir() -> Option<PathBuf> {
Some(dirs::data_dir()?.join("ai.opencode.desktop"))
}
fn path() -> Option<PathBuf> {
dir().map(|dir| dir.join(SETTINGS_STORE))
}
pub fn read_wayland() -> Option<bool> {
let path = path()?;
let raw = std::fs::read_to_string(path).ok()?;
let config = serde_json::from_str::<DisplayConfig>(&raw).ok()?;
config.wayland
}
pub fn write_wayland(app: &AppHandle, value: bool) -> Result<(), String> {
let store = app
.store(SETTINGS_STORE)
.map_err(|e| format!("Failed to open settings store: {}", e))?;
store.set(
LINUX_DISPLAY_CONFIG_KEY,
json!(DisplayConfig {
wayland: Some(value),
}),
);
store
.save()
.map_err(|e| format!("Failed to save settings store: {}", e))?;
Ok(())
}

View File

@@ -2,6 +2,9 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
// borrowed from https://github.com/skyline69/balatro-mod-manager
#[cfg(target_os = "linux")]
mod display;
#[cfg(target_os = "linux")]
fn configure_display_backend() -> Option<String> {
use std::env;
@@ -23,12 +26,16 @@ fn configure_display_backend() -> Option<String> {
return None;
}
// Allow users to explicitly keep Wayland if they know their setup is stable.
let allow_wayland = matches!(
env::var("OC_ALLOW_WAYLAND"),
Ok(v) if matches!(v.to_ascii_lowercase().as_str(), "1" | "true" | "yes")
);
let prefer_wayland = display::read_wayland().unwrap_or(false);
let allow_wayland = prefer_wayland
|| matches!(
env::var("OC_ALLOW_WAYLAND"),
Ok(v) if matches!(v.to_ascii_lowercase().as_str(), "1" | "true" | "yes")
);
if allow_wayland {
if prefer_wayland {
return Some("Wayland session detected; using native Wayland from settings".into());
}
return Some("Wayland session detected; respecting OC_ALLOW_WAYLAND=1".into());
}

View File

@@ -10,6 +10,8 @@ export const commands = {
awaitInitialization: (events: Channel) => __TAURI_INVOKE<ServerReadyData>("await_initialization", { events }),
getDefaultServerUrl: () => __TAURI_INVOKE<string | null>("get_default_server_url"),
setDefaultServerUrl: (url: string | null) => __TAURI_INVOKE<null>("set_default_server_url", { url }),
getDisplayBackend: () => __TAURI_INVOKE<"wayland" | "auto" | null>("get_display_backend"),
setDisplayBackend: (backend: LinuxDisplayBackend) => __TAURI_INVOKE<null>("set_display_backend", { backend }),
parseMarkdownCommand: (markdown: string) => __TAURI_INVOKE<string>("parse_markdown_command", { markdown }),
checkAppExists: (appName: string) => __TAURI_INVOKE<boolean>("check_app_exists", { appName }),
};
@@ -22,6 +24,8 @@ export const events = {
/* Types */
export type InitStep = { phase: "server_waiting" } | { phase: "sqlite_waiting" } | { phase: "done" };
export type LinuxDisplayBackend = "wayland" | "auto";
export type LoadingWindowComplete = null;
export type ServerReadyData = {

View File

@@ -1,7 +1,14 @@
// @refresh reload
import { webviewZoom } from "./webview-zoom"
import { render } from "solid-js/web"
import { AppBaseProviders, AppInterface, PlatformProvider, Platform, useCommand } from "@opencode-ai/app"
import {
AppBaseProviders,
AppInterface,
PlatformProvider,
Platform,
DisplayBackend,
useCommand,
} from "@opencode-ai/app"
import { open, save } from "@tauri-apps/plugin-dialog"
import { getCurrent, onOpenUrl } from "@tauri-apps/plugin-deep-link"
import { openPath as openerOpenPath } from "@tauri-apps/plugin-opener"
@@ -9,6 +16,7 @@ import { open as shellOpen } from "@tauri-apps/plugin-shell"
import { type as ostype } from "@tauri-apps/plugin-os"
import { check, Update } from "@tauri-apps/plugin-updater"
import { getCurrentWindow } from "@tauri-apps/api/window"
import { invoke } from "@tauri-apps/api/core"
import { isPermissionGranted, requestPermission } from "@tauri-apps/plugin-notification"
import { relaunch } from "@tauri-apps/plugin-process"
import { AsyncStorage } from "@solid-primitives/storage"
@@ -338,6 +346,15 @@ const createPlatform = (password: Accessor<string | null>): Platform => ({
await commands.setDefaultServerUrl(url)
},
getDisplayBackend: async () => {
const result = await invoke<DisplayBackend | null>("get_display_backend").catch(() => null)
return result
},
setDisplayBackend: async (backend) => {
await invoke("set_display_backend", { backend }).catch(() => undefined)
},
parseMarkdown: (markdown: string) => commands.parseMarkdownCommand(markdown),
webviewZoom,
@@ -413,7 +430,7 @@ render(() => {
}
return (
<AppInterface defaultUrl={data().url}>
<AppInterface defaultUrl={data().url} isSidecar>
<Inner />
</AppInterface>
)

View File

@@ -32,6 +32,99 @@ export default defineConfig({
solidJs(),
starlight({
title: "OpenCode",
defaultLocale: "root",
locales: {
root: {
label: "English",
lang: "en",
dir: "ltr",
},
ar: {
label: "العربية",
lang: "ar",
dir: "rtl",
},
bs: {
label: "Bosanski",
lang: "bs-BA",
dir: "ltr",
},
da: {
label: "Dansk",
lang: "da-DK",
dir: "ltr",
},
de: {
label: "Deutsch",
lang: "de-DE",
dir: "ltr",
},
es: {
label: "Espa\u00f1ol",
lang: "es-ES",
dir: "ltr",
},
fr: {
label: "Fran\u00e7ais",
lang: "fr-FR",
dir: "ltr",
},
it: {
label: "Italiano",
lang: "it-IT",
dir: "ltr",
},
ja: {
label: "日本語",
lang: "ja-JP",
dir: "ltr",
},
ko: {
label: "한국어",
lang: "ko-KR",
dir: "ltr",
},
nb: {
label: "Norsk Bokm\u00e5l",
lang: "nb-NO",
dir: "ltr",
},
pl: {
label: "Polski",
lang: "pl-PL",
dir: "ltr",
},
"pt-br": {
label: "Portugu\u00eas (Brasil)",
lang: "pt-BR",
dir: "ltr",
},
ru: {
label: "Русский",
lang: "ru-RU",
dir: "ltr",
},
th: {
label: "ไทย",
lang: "th-TH",
dir: "ltr",
},
tr: {
label: "T\u00fcrk\u00e7e",
lang: "tr-TR",
dir: "ltr",
},
"zh-cn": {
label: "简体中文",
lang: "zh-CN",
dir: "ltr",
},
"zh-tw": {
label: "繁體中文",
lang: "zh-TW",
dir: "ltr",
},
},
favicon: "/favicon-v3.svg",
head: [
{
@@ -89,11 +182,51 @@ export default defineConfig({
"1-0",
{
label: "Usage",
translations: {
en: "Usage",
ar: "الاستخدام",
"bs-BA": "Korištenje",
"da-DK": "Brug",
"de-DE": "Nutzung",
"es-ES": "Uso",
"fr-FR": "Utilisation",
"it-IT": "Utilizzo",
"ja-JP": "使い方",
"ko-KR": "사용",
"nb-NO": "Bruk",
"pl-PL": "Użycie",
"pt-BR": "Uso",
"ru-RU": "Использование",
"th-TH": "การใช้งาน",
"tr-TR": "Kullanım",
"zh-CN": "使用",
"zh-TW": "使用",
},
items: ["tui", "cli", "web", "ide", "zen", "share", "github", "gitlab"],
},
{
label: "Configure",
translations: {
en: "Configure",
ar: "الإعداد",
"bs-BA": "Podešavanje",
"da-DK": "Konfiguration",
"de-DE": "Konfiguration",
"es-ES": "Configuración",
"fr-FR": "Configuration",
"it-IT": "Configurazione",
"ja-JP": "設定",
"ko-KR": "구성",
"nb-NO": "Konfigurasjon",
"pl-PL": "Konfiguracja",
"pt-BR": "Configuração",
"ru-RU": "Настройка",
"th-TH": "การกำหนดค่า",
"tr-TR": "Yapılandırma",
"zh-CN": "配置",
"zh-TW": "設定",
},
items: [
"tools",
"rules",
@@ -114,6 +247,26 @@ export default defineConfig({
{
label: "Develop",
translations: {
en: "Develop",
ar: "التطوير",
"bs-BA": "Razvoj",
"da-DK": "Udvikling",
"de-DE": "Entwicklung",
"es-ES": "Desarrollo",
"fr-FR": "Développement",
"it-IT": "Sviluppo",
"ja-JP": "開発",
"ko-KR": "개발",
"nb-NO": "Utvikling",
"pl-PL": "Rozwój",
"pt-BR": "Desenvolvimento",
"ru-RU": "Разработка",
"th-TH": "การพัฒนา",
"tr-TR": "Geliştirme",
"zh-CN": "开发",
"zh-TW": "開發",
},
items: ["sdk", "server", "plugins", "ecosystem"],
},
],
@@ -121,6 +274,7 @@ export default defineConfig({
Hero: "./src/components/Hero.astro",
Head: "./src/components/Head.astro",
Header: "./src/components/Header.astro",
Footer: "./src/components/Footer.astro",
SiteTitle: "./src/components/SiteTitle.astro",
},
plugins: [

View File

@@ -8,7 +8,7 @@ export default {
github: "https://github.com/anomalyco/opencode",
discord: "https://opencode.ai/discord",
headerLinks: [
{ name: "Home", url: "/" },
{ name: "Docs", url: "/docs/" },
{ name: "app.header.home", url: "/" },
{ name: "app.header.docs", url: "/docs/" },
],
}

View File

@@ -17,7 +17,7 @@
"@astrojs/solid-js": "5.1.0",
"@astrojs/starlight": "0.34.3",
"@fontsource/ibm-plex-mono": "5.2.5",
"@shikijs/transformers": "3.4.2",
"@shikijs/transformers": "3.20.0",
"@types/luxon": "catalog:",
"ai": "catalog:",
"astro": "5.7.13",
@@ -31,11 +31,13 @@
"remeda": "catalog:",
"shiki": "catalog:",
"solid-js": "catalog:",
"toolbeam-docs-theme": "0.4.8"
"toolbeam-docs-theme": "0.4.8",
"vscode-languageserver-types": "3.17.5"
},
"devDependencies": {
"opencode": "workspace:*",
"@types/node": "catalog:",
"@astrojs/check": "0.9.6",
"typescript": "catalog:"
}
}

View File

@@ -0,0 +1,125 @@
---
import config from "virtual:starlight/user-config"
import LanguageSelect from "@astrojs/starlight/components/LanguageSelect.astro"
import { Icon } from "@astrojs/starlight/components"
const { lang, editUrl, lastUpdated, entry } = Astro.locals.starlightRoute
const template = entry.data.template
const issueLink = Astro.locals.t("app.footer.issueLink", "Found a bug? Open an issue")
const discordLink = Astro.locals.t("app.footer.discordLink", "Join our Discord community")
const github = config.social?.find((item) => item.icon === "github")
const discord = config.social?.find((item) => item.icon === "discord")
---
{
template === "doc" && (
<footer class="doc">
<div class="meta sl-flex">
<div>
{
editUrl && (
<a href={editUrl} target="_blank" rel="noopener noreferrer" class="sl-flex">
<Icon name="pencil" size="1em" />
{Astro.locals.t("page.editLink")}
</a>
)
}
{
github && (
<a href={`${github.href}/issues/new`} target="_blank" rel="noopener noreferrer" class="sl-flex">
<Icon name={github.icon} size="1em" />
{issueLink}
</a>
)
}
{
discord && (
<a href={discord.href} target="_blank" rel="noopener noreferrer" class="sl-flex">
<Icon name={discord.icon} size="1em" />
{discordLink}
</a>
)
}
<LanguageSelect />
</div>
<div>
<p>&copy; <a target="_blank" rel="noopener noreferrer" href="https://anoma.ly">Anomaly</a></p>
<p title={Astro.locals.t("page.lastUpdated")}>
{Astro.locals.t("page.lastUpdated")} {" "}
{
lastUpdated ? (
<time datetime={lastUpdated.toISOString()}>
{lastUpdated.toLocaleDateString(lang, { dateStyle: "medium", timeZone: "UTC" })}
</time>
) : (
"-"
)
}
</p>
</div>
</div>
</footer>
)
}
<style>
footer.doc {
margin-top: 3rem;
border-top: 1px solid var(--sl-color-border);
}
.meta {
gap: 0.75rem 3rem;
justify-content: space-between;
flex-wrap: wrap;
margin-block: 3rem 1.5rem;
font-size: var(--sl-text-sm);
}
@media (min-width: 30rem) {
.meta {
flex-direction: row;
}
}
.doc a,
.doc p {
padding-block: 0.125rem;
}
.doc a {
gap: 0.4375rem;
align-items: center;
text-decoration: none;
color: var(--sl-color-text);
font-size: var(--sl-text-sm);
}
.doc a svg {
opacity: 0.85;
}
.doc p {
color: var(--sl-color-text-dimmed);
}
.doc :global(starlight-lang-select) {
display: inline-flex;
margin-top: 0.5rem;
}
.doc :global(starlight-lang-select select) {
min-width: 7em;
}
@media (min-width: 30rem) {
.doc p {
text-align: right;
}
}
.doc p a {
color: var(--sl-color-text-dimmed);
}
</style>

View File

@@ -1,10 +1,9 @@
---
import { Base64 } from "js-base64";
import type { Props } from '@astrojs/starlight/props'
import Default from '@astrojs/starlight/components/Head.astro'
import config from '../../config.mjs'
const base = import.meta.env.BASE_URL.slice(1)
const base = import.meta.env.BASE_URL.replace(/^\//, "").replace(/\/$/, "")
const slug = Astro.url.pathname.replace(/^\//, "").replace(/\/$/, "");
const {
@@ -12,7 +11,12 @@ const {
data: { title , description },
},
} = Astro.locals.starlightRoute;
const isDocs = slug.startsWith("docs")
const isDocs = base === "" ? true : slug === base || slug.startsWith(`${base}/`)
const t = Astro.locals.t as (key: string) => string
const titleSuffix = t("app.head.titleSuffix")
const shareSlug = base === "" ? "s" : `${base}/s`
const isShare = slug === shareSlug || slug.startsWith(`${shareSlug}/`)
const isHome = slug === "" || slug === base
let encodedTitle = '';
let ogImage = `${config.url}/social-share.png`;
@@ -38,13 +42,13 @@ if (isDocs) {
}
---
{ slug === "" && (
<title>{title} | AI coding agent built for the terminal</title>
{ isHome && (
<title>{title} | {titleSuffix}</title>
)}
<Default {...Astro.props}><slot /></Default>
{ (!slug.startsWith(`${base}/s`)) && (
{ !isShare && (
<meta property="og:image" content={ogImage} />
<meta property="twitter:image" content={ogImage} />
)}

View File

@@ -1,128 +1,136 @@
---
import config from '../../config.mjs';
import astroConfig from 'virtual:starlight/user-config';
import { Icon } from '@astrojs/starlight/components';
import { HeaderLinks } from 'toolbeam-docs-theme/components';
import Default from 'toolbeam-docs-theme/overrides/Header.astro';
import SocialIcons from 'virtual:starlight/components/SocialIcons';
import SiteTitle from '@astrojs/starlight/components/SiteTitle.astro';
import config from "../../config.mjs"
import astroConfig from "virtual:starlight/user-config"
import { getRelativeLocaleUrl } from "astro:i18n"
import { Icon } from "@astrojs/starlight/components"
import Default from "toolbeam-docs-theme/overrides/Header.astro"
import SiteTitle from "@astrojs/starlight/components/SiteTitle.astro"
const path = Astro.url.pathname;
const path = Astro.url.pathname
const locale = Astro.currentLocale || "root"
const route = Astro.locals.starlightRoute
const t = Astro.locals.t as (key: string) => string
const links = astroConfig.social || []
const headerLinks = config.headerLinks
const sharePath = /\/s(\/|$)/.test(path)
const links = astroConfig.social || [];
const headerLinks = config.headerLinks;
---
{ path.startsWith("/s")
? <div class="header sl-flex">
<div class="title-wrapper sl-flex">
<SiteTitle {...Astro.props} />
</div>
<div class="middle-group sl-flex">
{
headerLinks?.map(({ name, url }) => (
<a class="links" href={url}>{name}</a>
))
}
</div>
<div class="sl-hidden md:sl-flex right-group">
{
links.length > 0 && (
<div class="sl-flex social-icons">
{links.map(({ href, icon }) => (
<a {href} rel="me" target="_blank">
<Icon name={icon} size="1rem" />
</a>
))}
</div>
)
}
</div>
</div>
: <Default {...Astro.props}><slot /></Default>
function href(url: string) {
if (url === "/" || url === "/docs" || url === "/docs/") {
return getRelativeLocaleUrl(locale, "")
}
return url
}
---
{sharePath ? (
<div class="header sl-flex">
<div class="title-wrapper sl-flex">
<SiteTitle {...route} />
</div>
<div class="middle-group sl-flex">
{headerLinks?.map(({ name, url }) => (
<a class="links" href={href(url)}>{t(name)}</a>
))}
</div>
<div class="sl-hidden md:sl-flex right-group">
{links.length > 0 && (
<div class="sl-flex social-icons">
{links.map(({ href, icon }) => (
<a {href} rel="me" target="_blank">
<Icon name={icon} size="1rem" />
</a>
))}
</div>
)}
</div>
</div>
) : (
<Default {...route} />
)}
<style>
.header {
gap: var(--sl-nav-gap);
justify-content: space-between;
align-items: center;
height: 100%;
}
.header {
gap: var(--sl-nav-gap);
justify-content: space-between;
align-items: center;
height: 100%;
}
.title-wrapper {
/* Prevent long titles overflowing and covering the search and menu buttons on narrow viewports. */
overflow: clip;
/* Avoid clipping focus ring around link inside title wrapper. */
.title-wrapper {
/* Prevent long titles overflowing and covering the search and menu buttons on narrow viewports. */
overflow: clip;
/* Avoid clipping focus ring around link inside title wrapper. */
padding: calc(0.25rem + 2px) 0.25rem calc(0.25rem - 2px);
margin: -0.25rem;
}
margin: -0.25rem;
}
.middle-group {
justify-content: flex-end;
gap: var(--sl-nav-gap);
}
@media (max-width: 50rem) {
:global(:root[data-has-sidebar]) {
.middle-group {
display: none;
}
}
}
@media (min-width: 50rem) {
.middle-group {
display: flex;
}
}
.middle-group {
justify-content: flex-end;
gap: var(--sl-nav-gap);
}
.right-group,
.social-icons {
gap: 1rem;
align-items: center;
@media (max-width: 50rem) {
:global(:root[data-has-sidebar]) {
.middle-group {
display: none;
}
}
}
@media (min-width: 50rem) {
.middle-group {
display: flex;
}
}
.right-group,
.social-icons {
gap: 1rem;
align-items: center;
a {
line-height: 1;
line-height: 1;
svg {
color: var(--sl-color-text-dimmed);
}
svg {
color: var(--sl-color-text-dimmed);
}
a.links {
text-transform: uppercase;
font-size: var(--sl-text-sm);
color: var(--sl-color-text-secondary);
line-height: normal;
}
}
}
@media (min-width: 50rem) {
:global(:root[data-has-sidebar]) {
--__sidebar-pad: calc(2 * var(--sl-nav-pad-x));
}
:global(:root:not([data-has-toc])) {
--__toc-width: 0rem;
}
.header {
--__sidebar-width: max(0rem, var(--sl-content-inline-start, 0rem) - var(--sl-nav-pad-x));
--__main-column-fr: calc(
(
100% + var(--__sidebar-pad, 0rem) - var(--__toc-width, var(--sl-sidebar-width)) -
(2 * var(--__toc-width, var(--sl-nav-pad-x))) - var(--sl-content-inline-start, 0rem) -
var(--sl-content-width)
) / 2
);
display: grid;
grid-template-columns:
a.links {
text-transform: uppercase;
font-size: var(--sl-text-sm);
color: var(--sl-color-text-secondary);
line-height: normal;
}
}
@media (min-width: 50rem) {
:global(:root[data-has-sidebar]) {
--__sidebar-pad: calc(2 * var(--sl-nav-pad-x));
}
:global(:root:not([data-has-toc])) {
--__toc-width: 0rem;
}
.header {
--__sidebar-width: max(0rem, var(--sl-content-inline-start, 0rem) - var(--sl-nav-pad-x));
--__main-column-fr: calc(
(
100% + var(--__sidebar-pad, 0rem) - var(--__toc-width, var(--sl-sidebar-width)) -
(2 * var(--__toc-width, var(--sl-nav-pad-x))) - var(--sl-content-inline-start, 0rem) -
var(--sl-content-width)
) / 2
);
display: grid;
grid-template-columns:
/* 1 (site title): runs up until the main content columns left edge or the width of the title, whichever is the largest */
minmax(
calc(var(--__sidebar-width) + max(0rem, var(--__main-column-fr) - var(--sl-nav-gap))),
auto
)
/* 2 (search box): all free space that is available. */
1fr
/* 3 (right items): use the space that these need. */
auto;
align-content: center;
}
}
minmax(calc(var(--__sidebar-width) + max(0rem, var(--__main-column-fr) - var(--sl-nav-gap))), auto)
/* 2 (search box): all free space that is available. */
1fr
/* 3 (right items): use the space that these need. */
auto;
align-content: center;
}
}
</style>

View File

@@ -1,7 +1,7 @@
---
import { Image } from 'astro:assets';
import { getRelativeLocaleUrl } from 'astro:i18n';
import config from "virtual:starlight/user-config";
import type { Props } from '@astrojs/starlight/props';
import CopyIcon from "../assets/lander/copy.svg";
import CheckIcon from "../assets/lander/check.svg";
@@ -19,8 +19,14 @@ const imageAttrs = {
alt: image?.alt || '',
};
const github = config.social.filter(s => s.icon === 'github')[0];
const discord = config.social.filter(s => s.icon === 'discord')[0];
const github = (config.social || []).filter(s => s.icon === 'github')[0];
const discord = (config.social || []).filter(s => s.icon === 'discord')[0];
const locale = Astro.currentLocale || 'root';
const t = Astro.locals.t as (key: string) => string;
const docsHref = getRelativeLocaleUrl(locale, "")
const docsCliHref = getRelativeLocaleUrl(locale, "cli")
const docsIdeHref = getRelativeLocaleUrl(locale, "ide")
const docsGithubHref = getRelativeLocaleUrl(locale, "github")
const command = "curl -fsSL"
const protocol = "https://"
@@ -44,19 +50,21 @@ if (image) {
<div class="hero">
<section class="top">
<div class="logo">
<Image
src={darkImage}
{...imageAttrs}
class:list={{ 'light:sl-hidden': Boolean(lightImage) }}
/>
<Image src={lightImage} {...imageAttrs} class="dark:sl-hidden" />
{darkImage && (
<Image
src={darkImage}
{...imageAttrs}
class:list={{ 'light:sl-hidden': Boolean(lightImage) }}
/>
)}
{lightImage && <Image src={lightImage} {...imageAttrs} class="dark:sl-hidden" />}
</div>
<h1>The AI coding agent built for the terminal.</h1>
<h1>{t('app.lander.hero.title')}</h1>
</section>
<section class="cta">
<div class="col1">
<a href="/docs">Get Started</a>
<a href={docsHref}>{t('app.lander.cta.getStarted')}</a>
</div>
<div class="col2">
<button class="command" data-command={`${command} ${protocol}${url} ${bash}`}>
@@ -73,13 +81,13 @@ if (image) {
<section class="content">
<ul>
<li><b>Native TUI</b>: A responsive, native, themeable terminal UI.</li>
<li><b>LSP enabled</b>: Automatically loads the right LSPs for the LLM.</li>
<li><b>Multi-session</b>: Start multiple agents in parallel on the same project.</li>
<li><b>Shareable links</b>: Share a link to any sessions for reference or to debug.</li>
<li><b>GitHub Copilot</b>: Log in with GitHub to use your Copilot account.</li>
<li><b>ChatGPT Plus/Pro</b>: Log in with OpenAI to use your ChatGPT Plus or Pro account.</li>
<li><b>Use any model</b>: Supports 75+ LLM providers through <a href="https://models.dev">Models.dev</a>, including local models.</li>
<li><b>{t('app.lander.features.native_tui.title')}</b>: {t('app.lander.features.native_tui.description')}</li>
<li><b>{t('app.lander.features.lsp_enabled.title')}</b>: {t('app.lander.features.lsp_enabled.description')}</li>
<li><b>{t('app.lander.features.multi_session.title')}</b>: {t('app.lander.features.multi_session.description')}</li>
<li><b>{t('app.lander.features.shareable_links.title')}</b>: {t('app.lander.features.shareable_links.description')}</li>
<li><b>GitHub Copilot</b>: {t('app.lander.features.github_copilot.description')}</li>
<li><b>ChatGPT Plus/Pro</b>: {t('app.lander.features.chatgpt_plus_pro.description')}</li>
<li><b>{t('app.lander.features.use_any_model.title')}</b>: {t('app.lander.features.use_any_model.prefix')} <a href="https://models.dev">Models.dev</a>, {t('app.lander.features.use_any_model.suffix')}</li>
</ul>
</section>
@@ -149,26 +157,26 @@ if (image) {
<section class="images">
<div class="left">
<figure>
<figcaption>opencode TUI with the tokyonight theme</figcaption>
<a href="/docs/cli">
<Image src={TuiScreenshot} alt="opencode TUI with the tokyonight theme" />
<figcaption>{t('app.lander.images.tui.caption')}</figcaption>
<a href={docsCliHref}>
<Image src={TuiScreenshot} alt={t('app.lander.images.tui.alt')} />
</a>
</figure>
</div>
<div class="right">
<div class="row1">
<figure>
<figcaption>opencode in VS Code</figcaption>
<a href="/docs/ide">
<Image src={VscodeScreenshot} alt="opencode in VS Code" />
<figcaption>{t('app.lander.images.vscode.caption')}</figcaption>
<a href={docsIdeHref}>
<Image src={VscodeScreenshot} alt={t('app.lander.images.vscode.alt')} />
</a>
</figure>
</div>
<div class="row2">
<figure>
<figcaption>opencode in GitHub</figcaption>
<a href="/docs/github">
<Image src={GithubScreenshot} alt="opencode in GitHub" />
<figcaption>{t('app.lander.images.github.caption')}</figcaption>
<a href={docsGithubHref}>
<Image src={GithubScreenshot} alt={t('app.lander.images.github.alt')} />
</a>
</figure>
</div>

View File

@@ -1,8 +1,9 @@
import { For, Show, onMount, Suspense, onCleanup, createMemo, createSignal, SuspenseList, createEffect } from "solid-js"
import { For, Show, onMount, Suspense, onCleanup, createMemo, createSignal, SuspenseList } from "solid-js"
import { DateTime } from "luxon"
import { createStore, reconcile, unwrap } from "solid-js/store"
import { createStore, reconcile } from "solid-js/store"
import { IconArrowDown } from "./icons"
import { IconOpencode } from "./icons/custom"
import { ShareI18nProvider, formatCurrency, formatNumber, normalizeLocale } from "./share/common"
import styles from "./share.module.css"
import type { MessageV2 } from "opencode/session/message-v2"
import type { Message } from "opencode/session/message"
@@ -20,24 +21,29 @@ function scrollToAnchor(id: string) {
el.scrollIntoView({ behavior: "smooth" })
}
function getStatusText(status: [Status, string?]): string {
function getStatusText(status: [Status, string?], messages: Record<string, string>): string {
switch (status[0]) {
case "connected":
return "Connected, waiting for messages..."
return messages.status_connected_waiting
case "connecting":
return "Connecting..."
return messages.status_connecting
case "disconnected":
return "Disconnected"
return messages.status_disconnected
case "reconnecting":
return "Reconnecting..."
return messages.status_reconnecting
case "error":
return status[1] || "Error"
return status[1] || messages.status_error
default:
return "Unknown"
return messages.status_unknown
}
}
export default function Share(props: { id: string; api: string; info: Session.Info }) {
export default function Share(props: {
id: string
api: string
info: Session.Info
messages: { locale: string } & Record<string, string>
}) {
let lastScrollY = 0
let hasScrolledToAnchor = false
let scrollTimeout: number | undefined
@@ -57,6 +63,9 @@ export default function Share(props: { id: string; api: string; info: Session.In
}>({
info: {
id: props.id,
slug: props.info.slug,
projectID: props.info.projectID,
directory: props.info.directory,
title: props.info.title,
version: props.info.version,
time: {
@@ -67,22 +76,19 @@ export default function Share(props: { id: string; api: string; info: Session.In
messages: {},
})
const messages = createMemo(() => Object.values(store.messages).toSorted((a, b) => a.id?.localeCompare(b.id)))
const [connectionStatus, setConnectionStatus] = createSignal<[Status, string?]>(["disconnected", "Disconnected"])
createEffect(() => {
console.log(unwrap(store))
})
const [connectionStatus, setConnectionStatus] = createSignal<[Status, string?]>(["disconnected"])
onMount(() => {
const apiUrl = props.api
if (!props.id) {
setConnectionStatus(["error", "id not found"])
setConnectionStatus(["error", props.messages.error_id_not_found])
return
}
if (!apiUrl) {
console.error("API URL not found in environment variables")
setConnectionStatus(["error", "API URL not found"])
setConnectionStatus(["error", props.messages.error_api_url_not_found])
return
}
@@ -101,20 +107,16 @@ export default function Share(props: { id: string; api: string; info: Session.In
// Always use secure WebSocket protocol (wss)
const wsBaseUrl = apiUrl.replace(/^https?:\/\//, "wss://")
const wsUrl = `${wsBaseUrl}/share_poll?id=${props.id}`
console.log("Connecting to WebSocket URL:", wsUrl)
// Create WebSocket connection
socket = new WebSocket(wsUrl)
// Handle connection opening
socket.onopen = () => {
setConnectionStatus(["connected"])
console.log("WebSocket connection established")
}
// Handle incoming messages
socket.onmessage = (event) => {
console.log("WebSocket message received")
try {
const d = JSON.parse(event.data)
const [root, type, ...splits] = d.key.split("/")
@@ -147,12 +149,11 @@ export default function Share(props: { id: string; api: string; info: Session.In
// Handle errors
socket.onerror = (error) => {
console.error("WebSocket error:", error)
setConnectionStatus(["error", "Connection failed"])
setConnectionStatus(["error", props.messages.error_connection_failed])
}
// Handle connection close and reconnection
socket.onclose = (event) => {
console.log(`WebSocket closed: ${event.code} ${event.reason}`)
socket.onclose = () => {
setConnectionStatus(["reconnecting"])
// Try to reconnect after 2 seconds
@@ -166,7 +167,6 @@ export default function Share(props: { id: string; api: string; info: Session.In
// Clean up on component unmount
onCleanup(() => {
console.log("Cleaning up WebSocket connection")
if (socket) {
socket.close()
}
@@ -297,201 +297,212 @@ export default function Share(props: { id: string; api: string; info: Session.In
return (
<Show when={store.info}>
<main classList={{ [styles.root]: true, "not-content": true }}>
<div data-component="header">
<h1 data-component="header-title">{store.info?.title}</h1>
<div data-component="header-details">
<ul data-component="header-stats">
<li title="opencode version" data-slot="item">
<div data-slot="icon" title="opencode">
<IconOpencode width={16} height={16} />
</div>
<Show when={store.info?.version} fallback="v0.0.1">
<span>v{store.info?.version}</span>
</Show>
</li>
{Object.values(data().models).length > 0 ? (
<For each={Object.values(data().models)}>
{([provider, model]) => (
<li data-slot="item">
<div data-slot="icon" title={provider}>
<ProviderIcon model={model} />
</div>
<span data-slot="model">{model}</span>
</li>
)}
</For>
) : (
<li>
<span data-element-label>Models</span>
<span data-placeholder>&mdash;</span>
<ShareI18nProvider messages={props.messages}>
<main classList={{ [styles.root]: true, "not-content": true }}>
<div data-component="header">
<h1 data-component="header-title">{store.info?.title}</h1>
<div data-component="header-details">
<ul data-component="header-stats">
<li title={props.messages.opencode_version} data-slot="item">
<div data-slot="icon" title={props.messages.opencode_name}>
<IconOpencode width={16} height={16} />
</div>
<Show when={store.info?.version} fallback="v0.0.1">
<span>v{store.info?.version}</span>
</Show>
</li>
)}
</ul>
<div
data-component="header-time"
title={DateTime.fromMillis(data().created || 0).toLocaleString(DateTime.DATETIME_FULL_WITH_SECONDS)}
>
{DateTime.fromMillis(data().created || 0).toLocaleString(DateTime.DATETIME_MED)}
</div>
</div>
</div>
<div>
<Show when={data().messages.length > 0} fallback={<p>Waiting for messages...</p>}>
<div class={styles.parts}>
<SuspenseList revealOrder="forwards">
<For each={data().messages}>
{(msg, msgIndex) => {
const filteredParts = createMemo(() =>
msg.parts.filter((x, index) => {
if (x.type === "step-start" && index > 0) return false
if (x.type === "snapshot") return false
if (x.type === "patch") return false
if (x.type === "step-finish") return false
if (x.type === "text" && x.synthetic === true) return false
if (x.type === "tool" && x.tool === "todoread") return false
if (x.type === "text" && !x.text) return false
if (x.type === "tool" && (x.state.status === "pending" || x.state.status === "running"))
return false
return true
}),
)
return (
<Suspense>
<For each={filteredParts()}>
{(part, partIndex) => {
const last = createMemo(
() =>
data().messages.length === msgIndex() + 1 && filteredParts().length === partIndex() + 1,
)
onMount(() => {
const hash = window.location.hash.slice(1)
// Wait till all parts are loaded
if (
hash !== "" &&
!hasScrolledToAnchor &&
filteredParts().length === partIndex() + 1 &&
data().messages.length === msgIndex() + 1
) {
hasScrolledToAnchor = true
scrollToAnchor(hash)
}
})
return <Part last={last()} part={part} index={partIndex()} message={msg} />
}}
</For>
</Suspense>
)
}}
</For>
</SuspenseList>
<div data-section="part" data-part-type="summary">
<div data-section="decoration">
<span data-status={connectionStatus()[0]}></span>
</div>
<div data-section="content">
<p data-section="copy">{getStatusText(connectionStatus())}</p>
<ul data-section="stats">
<li>
<span data-element-label>Cost</span>
{data().cost !== undefined ? (
<span>${data().cost.toFixed(2)}</span>
) : (
<span data-placeholder>&mdash;</span>
)}
</li>
<li>
<span data-element-label>Input Tokens</span>
{data().tokens.input ? <span>{data().tokens.input}</span> : <span data-placeholder>&mdash;</span>}
</li>
<li>
<span data-element-label>Output Tokens</span>
{data().tokens.output ? (
<span>{data().tokens.output}</span>
) : (
<span data-placeholder>&mdash;</span>
)}
</li>
<li>
<span data-element-label>Reasoning Tokens</span>
{data().tokens.reasoning ? (
<span>{data().tokens.reasoning}</span>
) : (
<span data-placeholder>&mdash;</span>
)}
</li>
</ul>
</div>
</div>
</div>
</Show>
</div>
<Show when={debug}>
<div style={{ margin: "2rem 0" }}>
<div
style={{
border: "1px solid #ccc",
padding: "1rem",
"overflow-y": "auto",
}}
>
<Show when={data().messages.length > 0} fallback={<p>Waiting for messages...</p>}>
<ul style={{ "list-style-type": "none", padding: 0 }}>
<For each={data().messages}>
{(msg) => (
<li
style={{
padding: "0.75rem",
margin: "0.75rem 0",
"box-shadow": "0 1px 3px rgba(0,0,0,0.1)",
}}
>
<div>
<strong>Key:</strong> {msg.id}
{Object.values(data().models).length > 0 ? (
<For each={Object.values(data().models)}>
{([provider, model]) => (
<li data-slot="item">
<div data-slot="icon" title={provider}>
<ProviderIcon model={model} />
</div>
<pre>{JSON.stringify(msg, null, 2)}</pre>
<span data-slot="model">{model}</span>
</li>
)}
</For>
</ul>
</Show>
) : (
<li>
<span data-element-label>{props.messages.models}</span>
<span data-placeholder>&mdash;</span>
</li>
)}
</ul>
<div
data-component="header-time"
title={DateTime.fromMillis(data().created || 0)
.setLocale(normalizeLocale(props.messages.locale))
.toLocaleString(DateTime.DATETIME_FULL_WITH_SECONDS)}
>
{DateTime.fromMillis(data().created || 0)
.setLocale(normalizeLocale(props.messages.locale))
.toLocaleString(DateTime.DATETIME_MED)}
</div>
</div>
</div>
</Show>
<Show when={showScrollButton()}>
<button
type="button"
class={styles["scroll-button"]}
onClick={() => document.body.scrollIntoView({ behavior: "smooth", block: "end" })}
onMouseEnter={() => {
setIsButtonHovered(true)
if (scrollTimeout) {
clearTimeout(scrollTimeout)
}
}}
onMouseLeave={() => {
setIsButtonHovered(false)
if (showScrollButton()) {
scrollTimeout = window.setTimeout(() => {
if (!isButtonHovered()) {
setShowScrollButton(false)
}
}, 3000)
}
}}
title="Scroll to bottom"
aria-label="Scroll to bottom"
>
<IconArrowDown width={20} height={20} />
</button>
</Show>
</main>
<div>
<Show when={data().messages.length > 0} fallback={<p>{props.messages.waiting_for_messages}</p>}>
<div class={styles.parts}>
<SuspenseList revealOrder="forwards">
<For each={data().messages}>
{(msg, msgIndex) => {
const filteredParts = createMemo(() =>
msg.parts.filter((x, index) => {
if (x.type === "step-start" && index > 0) return false
if (x.type === "snapshot") return false
if (x.type === "patch") return false
if (x.type === "step-finish") return false
if (x.type === "text" && x.synthetic === true) return false
if (x.type === "tool" && x.tool === "todoread") return false
if (x.type === "text" && !x.text) return false
if (x.type === "tool" && (x.state.status === "pending" || x.state.status === "running"))
return false
return true
}),
)
return (
<Suspense>
<For each={filteredParts()}>
{(part, partIndex) => {
const last = createMemo(
() =>
data().messages.length === msgIndex() + 1 &&
filteredParts().length === partIndex() + 1,
)
onMount(() => {
const hash = window.location.hash.slice(1)
// Wait till all parts are loaded
if (
hash !== "" &&
!hasScrolledToAnchor &&
filteredParts().length === partIndex() + 1 &&
data().messages.length === msgIndex() + 1
) {
hasScrolledToAnchor = true
scrollToAnchor(hash)
}
})
return <Part last={last()} part={part} index={partIndex()} message={msg} />
}}
</For>
</Suspense>
)
}}
</For>
</SuspenseList>
<div data-section="part" data-part-type="summary">
<div data-section="decoration">
<span data-status={connectionStatus()[0]}></span>
</div>
<div data-section="content">
<p data-section="copy">{getStatusText(connectionStatus(), props.messages)}</p>
<ul data-section="stats">
<li>
<span data-element-label>{props.messages.cost}</span>
{data().cost !== undefined ? (
<span>{formatCurrency(data().cost, props.messages.locale)}</span>
) : (
<span data-placeholder>&mdash;</span>
)}
</li>
<li>
<span data-element-label>{props.messages.input_tokens}</span>
{data().tokens.input ? (
<span>{formatNumber(data().tokens.input, props.messages.locale)}</span>
) : (
<span data-placeholder>&mdash;</span>
)}
</li>
<li>
<span data-element-label>{props.messages.output_tokens}</span>
{data().tokens.output ? (
<span>{formatNumber(data().tokens.output, props.messages.locale)}</span>
) : (
<span data-placeholder>&mdash;</span>
)}
</li>
<li>
<span data-element-label>{props.messages.reasoning_tokens}</span>
{data().tokens.reasoning ? (
<span>{formatNumber(data().tokens.reasoning, props.messages.locale)}</span>
) : (
<span data-placeholder>&mdash;</span>
)}
</li>
</ul>
</div>
</div>
</div>
</Show>
</div>
<Show when={debug}>
<div style={{ margin: "2rem 0" }}>
<div
style={{
border: "1px solid #ccc",
padding: "1rem",
"overflow-y": "auto",
}}
>
<Show when={data().messages.length > 0} fallback={<p>{props.messages.waiting_for_messages}</p>}>
<ul style={{ "list-style-type": "none", padding: 0 }}>
<For each={data().messages}>
{(msg) => (
<li
style={{
padding: "0.75rem",
margin: "0.75rem 0",
"box-shadow": "0 1px 3px rgba(0,0,0,0.1)",
}}
>
<div>
<strong>{props.messages.debug_key}:</strong> {msg.id}
</div>
<pre>{JSON.stringify(msg, null, 2)}</pre>
</li>
)}
</For>
</ul>
</Show>
</div>
</div>
</Show>
<Show when={showScrollButton()}>
<button
type="button"
class={styles["scroll-button"]}
onClick={() => document.body.scrollIntoView({ behavior: "smooth", block: "end" })}
onMouseEnter={() => {
setIsButtonHovered(true)
if (scrollTimeout) {
clearTimeout(scrollTimeout)
}
}}
onMouseLeave={() => {
setIsButtonHovered(false)
if (showScrollButton()) {
scrollTimeout = window.setTimeout(() => {
if (!isButtonHovered()) {
setShowScrollButton(false)
}
}, 3000)
}
}}
title={props.messages.scroll_to_bottom}
aria-label={props.messages.scroll_to_bottom}
>
<IconArrowDown width={20} height={20} />
</button>
</Show>
</main>
</ShareI18nProvider>
</Show>
)
}
@@ -502,6 +513,8 @@ export function fromV1(v1: Message.Info): MessageWithParts {
id: v1.id,
sessionID: v1.metadata.sessionID,
role: "assistant",
parentID: "",
agent: "build",
time: {
created: v1.metadata.time.created,
completed: v1.metadata.time.completed,
@@ -521,7 +534,6 @@ export function fromV1(v1: Message.Info): MessageWithParts {
modelID: v1.metadata.assistant!.modelID,
providerID: v1.metadata.assistant!.providerID,
mode: "build",
system: v1.metadata.assistant!.system,
error: v1.metadata.error,
parts: v1.parts.flatMap((part, index): MessageV2.Part[] => {
const base = {
@@ -557,6 +569,8 @@ export function fromV1(v1: Message.Info): MessageWithParts {
if (part.toolInvocation.state === "partial-call") {
return {
status: "pending",
input: {},
raw: "",
}
}
@@ -596,6 +610,11 @@ export function fromV1(v1: Message.Info): MessageWithParts {
id: v1.id,
sessionID: v1.metadata.sessionID,
role: "user",
agent: "user",
model: {
providerID: "",
modelID: "",
},
time: {
created: v1.metadata.time.created,
},

View File

@@ -4,7 +4,7 @@ import config from 'virtual:starlight/user-config';
const { siteTitle, siteTitleHref } = Astro.locals.starlightRoute;
---
<a href="/" class="site-title sl-flex">
<a href={siteTitleHref} class="site-title sl-flex">
{
config.logo && logos.dark && (
<>

View File

@@ -1,16 +1,55 @@
import { createSignal, onCleanup, splitProps } from "solid-js"
import { createContext, createSignal, onCleanup, splitProps, useContext } from "solid-js"
import type { JSX } from "solid-js/jsx-runtime"
import { IconCheckCircle, IconHashtag } from "../icons"
export type ShareMessages = { locale: string } & Record<string, string>
const shareContext = createContext<ShareMessages>()
export function ShareI18nProvider(props: { messages: ShareMessages; children: JSX.Element }) {
return <shareContext.Provider value={props.messages}>{props.children}</shareContext.Provider>
}
export function useShareMessages() {
const value = useContext(shareContext)
if (value) {
return value
}
throw new Error("ShareI18nProvider is required")
}
export function normalizeLocale(locale: string) {
return locale === "root" ? "en" : locale
}
export function formatNumber(value: number, locale: string) {
return new Intl.NumberFormat(normalizeLocale(locale)).format(value)
}
export function formatCurrency(value: number, locale: string) {
return new Intl.NumberFormat(normalizeLocale(locale), {
style: "currency",
currency: "USD",
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}).format(value)
}
export function formatCount(value: number, locale: string, singular: string, plural: string) {
const unit = value === 1 ? singular : plural
return `${formatNumber(value, locale)} ${unit}`
}
interface AnchorProps extends JSX.HTMLAttributes<HTMLDivElement> {
id: string
}
export function AnchorIcon(props: AnchorProps) {
const [local, rest] = splitProps(props, ["id", "children"])
const [copied, setCopied] = createSignal(false)
const messages = useShareMessages()
return (
<div {...rest} data-element-anchor title="Link to this message" data-status={copied() ? "copied" : ""}>
<div {...rest} data-element-anchor title={messages.link_to_message} data-status={copied() ? "copied" : ""}>
<a
href={`#${local.id}`}
onClick={(e) => {
@@ -32,7 +71,7 @@ export function AnchorIcon(props: AnchorProps) {
<IconHashtag width={18} height={18} />
<IconCheckCircle width={18} height={18} />
</a>
<span data-element-tooltip>Copied!</span>
<span data-element-tooltip>{messages.copied}</span>
</div>
)
}
@@ -59,19 +98,33 @@ export function createOverflow() {
}
}
export function formatDuration(ms: number): string {
export function formatDuration(ms: number, locale: string): string {
const normalized = normalizeLocale(locale)
const ONE_SECOND = 1000
const ONE_MINUTE = 60 * ONE_SECOND
if (ms >= ONE_MINUTE) {
const minutes = Math.floor(ms / ONE_MINUTE)
return minutes === 1 ? `1min` : `${minutes}mins`
return new Intl.NumberFormat(normalized, {
style: "unit",
unit: "minute",
unitDisplay: "narrow",
maximumFractionDigits: 0,
}).format(Math.floor(ms / ONE_MINUTE))
}
if (ms >= ONE_SECOND) {
const seconds = Math.floor(ms / ONE_SECOND)
return `${seconds}s`
return new Intl.NumberFormat(normalized, {
style: "unit",
unit: "second",
unitDisplay: "narrow",
maximumFractionDigits: 0,
}).format(Math.floor(ms / ONE_SECOND))
}
return `${ms}ms`
return new Intl.NumberFormat(normalized, {
style: "unit",
unit: "millisecond",
unitDisplay: "narrow",
maximumFractionDigits: 0,
}).format(ms)
}

View File

@@ -1,6 +1,6 @@
import style from "./content-bash.module.css"
import { createResource, createSignal } from "solid-js"
import { createOverflow } from "./common"
import { createOverflow, useShareMessages } from "./common"
import { codeToHtml } from "shiki"
interface Props {
@@ -11,6 +11,7 @@ interface Props {
}
export function ContentBash(props: Props) {
const messages = useShareMessages()
const [commandHtml] = createResource(
() => props.command,
async (command) => {
@@ -59,7 +60,7 @@ export function ContentBash(props: Props) {
data-slot="expand-button"
onClick={() => setExpanded((e) => !e)}
>
{expanded() ? "Show less" : "Show more"}
{expanded() ? messages.show_less : messages.show_more}
</button>
)}
</div>

View File

@@ -1,6 +1,5 @@
import { codeToHtml, bundledLanguages } from "shiki"
import { createResource, Suspense } from "solid-js"
import { transformerNotationDiff } from "@shikijs/transformers"
import style from "./content-code.module.css"
interface Props {
@@ -20,7 +19,6 @@ export function ContentCode(props: Props) {
light: "github-light",
dark: "github-dark",
},
transformers: [transformerNotationDiff()],
})) as string
},
)

View File

@@ -1,6 +1,6 @@
import style from "./content-error.module.css"
import { type JSX, createSignal } from "solid-js"
import { createOverflow } from "./common"
import { createOverflow, useShareMessages } from "./common"
interface Props extends JSX.HTMLAttributes<HTMLDivElement> {
expand?: boolean
@@ -8,6 +8,7 @@ interface Props extends JSX.HTMLAttributes<HTMLDivElement> {
export function ContentError(props: Props) {
const [expanded, setExpanded] = createSignal(false)
const overflow = createOverflow()
const messages = useShareMessages()
return (
<div class={style.root} data-expanded={expanded() || props.expand === true ? true : undefined}>
@@ -16,7 +17,7 @@ export function ContentError(props: Props) {
</div>
{((!props.expand && overflow.status) || expanded()) && (
<button type="button" data-element-button-text onClick={() => setExpanded((e) => !e)}>
{expanded() ? "Show less" : "Show more"}
{expanded() ? messages.show_less : messages.show_more}
</button>
)}
</div>

View File

@@ -1,10 +1,9 @@
import { marked } from "marked"
import { codeToHtml } from "shiki"
import markedShiki from "marked-shiki"
import { createOverflow } from "./common"
import { createOverflow, useShareMessages } from "./common"
import { CopyButton } from "./copy-button"
import { createResource, createSignal } from "solid-js"
import { transformerNotationDiff } from "@shikijs/transformers"
import style from "./content-markdown.module.css"
const markedWithShiki = marked.use(
@@ -24,7 +23,6 @@ const markedWithShiki = marked.use(
light: "github-light",
dark: "github-dark",
},
transformers: [transformerNotationDiff()],
})
},
}),
@@ -44,6 +42,7 @@ export function ContentMarkdown(props: Props) {
)
const [expanded, setExpanded] = createSignal(false)
const overflow = createOverflow()
const messages = useShareMessages()
return (
<div
@@ -60,7 +59,7 @@ export function ContentMarkdown(props: Props) {
data-slot="expand-button"
onClick={() => setExpanded((e) => !e)}
>
{expanded() ? "Show less" : "Show more"}
{expanded() ? messages.show_less : messages.show_more}
</button>
)}
<CopyButton text={props.text} />

View File

@@ -1,6 +1,6 @@
import style from "./content-text.module.css"
import { createSignal } from "solid-js"
import { createOverflow } from "./common"
import { createOverflow, useShareMessages } from "./common"
import { CopyButton } from "./copy-button"
interface Props {
@@ -11,6 +11,7 @@ interface Props {
export function ContentText(props: Props) {
const [expanded, setExpanded] = createSignal(false)
const overflow = createOverflow()
const messages = useShareMessages()
return (
<div
@@ -28,7 +29,7 @@ export function ContentText(props: Props) {
data-slot="expand-button"
onClick={() => setExpanded((e) => !e)}
>
{expanded() ? "Show less" : "Show more"}
{expanded() ? messages.show_less : messages.show_more}
</button>
)}
<CopyButton text={props.text} />

View File

@@ -1,5 +1,6 @@
import { createSignal } from "solid-js"
import { IconClipboard, IconCheckCircle } from "../icons"
import { useShareMessages } from "./common"
import styles from "./copy-button.module.css"
interface CopyButtonProps {
@@ -8,6 +9,7 @@ interface CopyButtonProps {
export function CopyButton(props: CopyButtonProps) {
const [copied, setCopied] = createSignal(false)
const messages = useShareMessages()
function handleCopyClick() {
if (props.text) {
@@ -20,7 +22,13 @@ export function CopyButton(props: CopyButtonProps) {
return (
<div data-component="copy-button" class={styles.root}>
<button type="button" onClick={handleCopyClick} data-copied={copied() ? true : undefined}>
<button
type="button"
onClick={handleCopyClick}
data-copied={copied() ? true : undefined}
aria-label={copied() ? messages.copied : messages.copy}
title={copied() ? messages.copied : messages.copy}
>
{copied() ? <IconCheckCircle width={16} height={16} /> : <IconClipboard width={16} height={16} />}
</button>
</div>

View File

@@ -25,7 +25,7 @@ import { ContentDiff } from "./content-diff"
import { ContentText } from "./content-text"
import { ContentBash } from "./content-bash"
import { ContentError } from "./content-error"
import { formatDuration } from "../share/common"
import { formatCount, formatDuration, formatNumber, normalizeLocale, useShareMessages } from "../share/common"
import { ContentMarkdown } from "./content-markdown"
import type { MessageV2 } from "opencode/session/message-v2"
import type { Diagnostic } from "vscode-languageserver-types"
@@ -44,6 +44,7 @@ export interface PartProps {
export function Part(props: PartProps) {
const [copied, setCopied] = createSignal(false)
const id = createMemo(() => props.message.id + "-" + props.index)
const messages = useShareMessages()
return (
<div
@@ -55,7 +56,7 @@ export function Part(props: PartProps) {
data-copied={copied() ? true : undefined}
>
<div data-component="decoration">
<div data-slot="anchor" title="Link to this message">
<div data-slot="anchor" title={messages.link_to_message}>
<a
href={`#${id()}`}
onClick={(e) => {
@@ -126,7 +127,7 @@ export function Part(props: PartProps) {
<IconHashtag width={18} height={18} />
<IconCheckCircle width={18} height={18} />
</a>
<span data-slot="tooltip">Copied!</span>
<span data-slot="tooltip">{messages.copied}</span>
</div>
<div data-slot="bar"></div>
</div>
@@ -143,11 +144,13 @@ export function Part(props: PartProps) {
</div>
{props.last && props.message.role === "assistant" && props.message.time.completed && (
<Footer
title={DateTime.fromMillis(props.message.time.completed).toLocaleString(
DateTime.DATETIME_FULL_WITH_SECONDS,
)}
title={DateTime.fromMillis(props.message.time.completed)
.setLocale(normalizeLocale(messages.locale))
.toLocaleString(DateTime.DATETIME_FULL_WITH_SECONDS)}
>
{DateTime.fromMillis(props.message.time.completed).toLocaleString(DateTime.DATETIME_MED)}
{DateTime.fromMillis(props.message.time.completed)
.setLocale(normalizeLocale(messages.locale))
.toLocaleString(DateTime.DATETIME_MED)}
</Footer>
)}
</div>
@@ -155,13 +158,13 @@ export function Part(props: PartProps) {
{props.message.role === "assistant" && props.part.type === "reasoning" && (
<div data-component="tool">
<div data-component="tool-title">
<span data-slot="name">Thinking</span>
<span data-slot="name">{messages.thinking}</span>
</div>
<Show when={props.part.text}>
<div data-component="assistant-reasoning">
<ResultsButton showCopy="Show details" hideCopy="Hide details">
<ResultsButton showCopy={messages.show_details} hideCopy={messages.hide_details}>
<div data-component="assistant-reasoning-markdown">
<ContentMarkdown expand text={props.part.text || "Thinking..."} />
<ContentMarkdown expand text={props.part.text || messages.thinking_pending} />
</div>
</ResultsButton>
</div>
@@ -170,13 +173,7 @@ export function Part(props: PartProps) {
)}
{props.message.role === "user" && props.part.type === "file" && (
<div data-component="attachment">
<div data-slot="copy">Attachment</div>
<div data-slot="filename">{props.part.filename}</div>
</div>
)}
{props.message.role === "user" && props.part.type === "file" && (
<div data-component="attachment">
<div data-slot="copy">Attachment</div>
<div data-slot="copy">{messages.attachment}</div>
<div data-slot="filename">{props.part.filename}</div>
</div>
)}
@@ -188,7 +185,7 @@ export function Part(props: PartProps) {
)}
{props.part.type === "tool" && props.part.state.status === "error" && (
<div data-component="tool" data-tool="error">
<ContentError>{formatErrorString(props.part.state.error)}</ContentError>
<ContentError>{formatErrorString(props.part.state.error, messages.error)}</ContentError>
<Spacer />
</div>
)}
@@ -343,43 +340,45 @@ function getShikiLang(filename: string) {
return type ? (overrides[type] ?? type) : "plaintext"
}
function getDiagnostics(diagnosticsByFile: Record<string, Diagnostic[]>, currentFile: string): JSX.Element[] {
function getDiagnostics(
diagnosticsByFile: Record<string, Diagnostic[]>,
currentFile: string,
label: string,
): JSX.Element[] {
const result: JSX.Element[] = []
if (diagnosticsByFile === undefined || diagnosticsByFile[currentFile] === undefined) return result
for (const diags of Object.values(diagnosticsByFile)) {
for (const d of diags) {
if (d.severity !== 1) continue
for (const d of diagnosticsByFile[currentFile]) {
if (d.severity !== 1) continue
const line = d.range.start.line + 1
const column = d.range.start.character + 1
const line = d.range.start.line + 1
const column = d.range.start.character + 1
result.push(
<pre>
<span data-color="red" data-marker="label">
Error
</span>
<span data-color="dimmed" data-separator>
[{line}:{column}]
</span>
<span>{d.message}</span>
</pre>,
)
}
result.push(
<pre>
<span data-color="red" data-marker="label">
{label}
</span>
<span data-color="dimmed" data-separator>
[{line}:{column}]
</span>
<span>{d.message}</span>
</pre>,
)
}
return result
}
function formatErrorString(error: string): JSX.Element {
function formatErrorString(error: string, label: string): JSX.Element {
const errorMarker = "Error: "
const startsWithError = error.startsWith(errorMarker)
return startsWithError ? (
<pre>
<span data-color="red" data-marker="label" data-separator>
Error
{label}
</span>
<span>{error.slice(errorMarker.length)}</span>
</pre>
@@ -391,6 +390,7 @@ function formatErrorString(error: string): JSX.Element {
}
export function TodoWriteTool(props: ToolProps) {
const messages = useShareMessages()
const priority: Record<Todo["status"], number> = {
in_progress: 0,
pending: 1,
@@ -406,9 +406,9 @@ export function TodoWriteTool(props: ToolProps) {
<>
<div data-component="tool-title">
<span data-slot="name">
<Switch fallback="Updating plan">
<Match when={starting()}>Creating plan</Match>
<Match when={finished()}>Completing plan</Match>
<Switch fallback={messages.updating_plan}>
<Match when={starting()}>{messages.creating_plan}</Match>
<Match when={finished()}>{messages.completing_plan}</Match>
</Switch>
</span>
</div>
@@ -429,6 +429,8 @@ export function TodoWriteTool(props: ToolProps) {
}
export function GrepTool(props: ToolProps) {
const messages = useShareMessages()
return (
<>
<div data-component="tool-title">
@@ -439,7 +441,12 @@ export function GrepTool(props: ToolProps) {
<Switch>
<Match when={props.state.metadata?.matches && props.state.metadata?.matches > 0}>
<ResultsButton
showCopy={props.state.metadata?.matches === 1 ? "1 match" : `${props.state.metadata?.matches} matches`}
showCopy={formatCount(
props.state.metadata?.matches || 0,
messages.locale,
messages.match_one,
messages.match_other,
)}
>
<ContentText expand compact text={props.state.output} />
</ResultsButton>
@@ -482,6 +489,8 @@ export function ListTool(props: ToolProps) {
}
export function WebFetchTool(props: ToolProps) {
const messages = useShareMessages()
return (
<>
<div data-component="tool-title">
@@ -491,7 +500,7 @@ export function WebFetchTool(props: ToolProps) {
<div data-component="tool-result">
<Switch>
<Match when={props.state.metadata?.error}>
<ContentError>{formatErrorString(props.state.output)}</ContentError>
<ContentError>{formatErrorString(props.state.output, messages.error)}</ContentError>
</Match>
<Match when={props.state.output}>
<ResultsButton>
@@ -505,6 +514,7 @@ export function WebFetchTool(props: ToolProps) {
}
export function ReadTool(props: ToolProps) {
const messages = useShareMessages()
const filePath = createMemo(() => stripWorkingDirectory(props.state.input?.filePath, props.message.path.cwd))
return (
@@ -518,10 +528,10 @@ export function ReadTool(props: ToolProps) {
<div data-component="tool-result">
<Switch>
<Match when={props.state.metadata?.error}>
<ContentError>{formatErrorString(props.state.output)}</ContentError>
<ContentError>{formatErrorString(props.state.output, messages.error)}</ContentError>
</Match>
<Match when={typeof props.state.metadata?.preview === "string"}>
<ResultsButton showCopy="Show preview" hideCopy="Hide preview">
<ResultsButton showCopy={messages.show_preview} hideCopy={messages.hide_preview}>
<ContentCode lang={getShikiLang(filePath() || "")} code={props.state.metadata?.preview} />
</ResultsButton>
</Match>
@@ -537,8 +547,11 @@ export function ReadTool(props: ToolProps) {
}
export function WriteTool(props: ToolProps) {
const messages = useShareMessages()
const filePath = createMemo(() => stripWorkingDirectory(props.state.input?.filePath, props.message.path.cwd))
const diagnostics = createMemo(() => getDiagnostics(props.state.metadata?.diagnostics, props.state.input.filePath))
const diagnostics = createMemo(() =>
getDiagnostics(props.state.metadata?.diagnostics, props.state.input.filePath, messages.error),
)
return (
<>
@@ -554,10 +567,10 @@ export function WriteTool(props: ToolProps) {
<div data-component="tool-result">
<Switch>
<Match when={props.state.metadata?.error}>
<ContentError>{formatErrorString(props.state.output)}</ContentError>
<ContentError>{formatErrorString(props.state.output, messages.error)}</ContentError>
</Match>
<Match when={props.state.input?.content}>
<ResultsButton showCopy="Show contents" hideCopy="Hide contents">
<ResultsButton showCopy={messages.show_contents} hideCopy={messages.hide_contents}>
<ContentCode lang={getShikiLang(filePath() || "")} code={props.state.input?.content} />
</ResultsButton>
</Match>
@@ -568,8 +581,11 @@ export function WriteTool(props: ToolProps) {
}
export function EditTool(props: ToolProps) {
const messages = useShareMessages()
const filePath = createMemo(() => stripWorkingDirectory(props.state.input.filePath, props.message.path.cwd))
const diagnostics = createMemo(() => getDiagnostics(props.state.metadata?.diagnostics, props.state.input.filePath))
const diagnostics = createMemo(() =>
getDiagnostics(props.state.metadata?.diagnostics, props.state.input.filePath, messages.error),
)
return (
<>
@@ -582,7 +598,7 @@ export function EditTool(props: ToolProps) {
<div data-component="tool-result">
<Switch>
<Match when={props.state.metadata?.error}>
<ContentError>{formatErrorString(props.state.metadata?.message || "")}</ContentError>
<ContentError>{formatErrorString(props.state.metadata?.message || "", messages.error)}</ContentError>
</Match>
<Match when={props.state.metadata?.diff}>
<div data-component="diff">
@@ -609,6 +625,8 @@ export function BashTool(props: ToolProps) {
}
export function GlobTool(props: ToolProps) {
const messages = useShareMessages()
return (
<>
<div data-component="tool-title">
@@ -619,7 +637,12 @@ export function GlobTool(props: ToolProps) {
<Match when={props.state.metadata?.count && props.state.metadata?.count > 0}>
<div data-component="tool-result">
<ResultsButton
showCopy={props.state.metadata?.count === 1 ? "1 result" : `${props.state.metadata?.count} results`}
showCopy={formatCount(
props.state.metadata?.count || 0,
messages.locale,
messages.result_one,
messages.result_other,
)}
>
<ContentText expand compact text={props.state.output} />
</ResultsButton>
@@ -639,11 +662,12 @@ interface ResultsButtonProps extends ParentProps {
}
function ResultsButton(props: ResultsButtonProps) {
const [show, setShow] = createSignal(false)
const messages = useShareMessages()
return (
<>
<button type="button" data-component="button-text" data-more onClick={() => setShow((e) => !e)}>
<span>{show() ? props.hideCopy || "Hide results" : props.showCopy || "Show results"}</span>
<span>{show() ? props.hideCopy || messages.hide_results : props.showCopy || messages.show_results}</span>
<span data-slot="icon">
<Show when={show()} fallback={<IconChevronRight width={11} height={11} />}>
<IconChevronDown width={11} height={11} />
@@ -668,10 +692,19 @@ function Footer(props: ParentProps<{ title: string }>) {
}
function ToolFooter(props: { time: number }) {
return props.time > MIN_DURATION && <Footer title={`${props.time}ms`}>{formatDuration(props.time)}</Footer>
const messages = useShareMessages()
return (
props.time > MIN_DURATION && (
<Footer title={`${formatNumber(props.time, messages.locale)}ms`}>
{formatDuration(props.time, messages.locale)}
</Footer>
)
)
}
function TaskTool(props: ToolProps) {
const messages = useShareMessages()
return (
<>
<div data-component="tool-title">
@@ -679,7 +712,7 @@ function TaskTool(props: ToolProps) {
<span data-slot="target">{props.state.input.description}</span>
</div>
<div data-component="tool-input">&ldquo;{props.state.input.prompt}&rdquo;</div>
<ResultsButton showCopy="Show output" hideCopy="Hide output">
<ResultsButton showCopy={messages.show_output} hideCopy={messages.hide_output}>
<div data-component="tool-output">
<ContentMarkdown expand text={props.state.output} />
</div>
@@ -700,7 +733,7 @@ export function FallbackTool(props: ToolProps) {
<>
<div></div>
<div>{arg[0]}</div>
<div>{arg[1]}</div>
<div>{String(arg[1] ?? "")}</div>
</>
)}
</For>
@@ -720,10 +753,11 @@ export function FallbackTool(props: ToolProps) {
// Converts nested objects/arrays into [path, value] pairs.
// E.g. {a:{b:{c:1}}, d:[{e:2}, 3]} => [["a.b.c",1], ["d[0].e",2], ["d[1]",3]]
function flattenToolArgs(obj: any, prefix: string = ""): Array<[string, any]> {
const entries: Array<[string, any]> = []
function flattenToolArgs(obj: unknown, prefix: string = ""): Array<[string, unknown]> {
const entries: Array<[string, unknown]> = []
if (typeof obj !== "object" || obj === null) return entries
for (const [key, value] of Object.entries(obj)) {
for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {
const path = prefix ? `${prefix}.${key}` : key
if (value !== null && typeof value === "object") {

View File

@@ -1,7 +1,16 @@
import { defineCollection } from "astro:content"
import { docsLoader } from "@astrojs/starlight/loaders"
import { docsSchema } from "@astrojs/starlight/schema"
import { defineCollection, z } from "astro:content"
import { docsLoader, i18nLoader } from "@astrojs/starlight/loaders"
import { docsSchema, i18nSchema } from "@astrojs/starlight/schema"
import en from "./content/i18n/en.json"
const custom = Object.fromEntries(Object.keys(en).map((key) => [key, z.string()]))
export const collections = {
docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
i18n: defineCollection({
loader: i18nLoader(),
schema: i18nSchema({
extend: z.object(custom).catchall(z.string()),
}),
}),
}

View File

@@ -0,0 +1,67 @@
---
title: الانتقال إلى 1.0
description: ما الجديد في OpenCode 1.0.
---
OpenCode 1.0 هو إعادة كتابة كاملة لواجهة TUI.
انتقلنا من واجهة TUI المبنية على go+bubbletea، والتي كانت تعاني من مشاكل في الأداء والإمكانات، إلى إطار عمل داخلي (OpenTUI) مكتوب بـ zig+solidjs.
تعمل واجهة TUI الجديدة مثل القديمة لأنها تتصل بخادم opencode نفسه.
---
## الترقية
لا يفترض أن تتم ترقيتك تلقائيا إلى 1.0 إذا كنت تستخدم حاليا إصدارا أقدم.
لكن بعض الإصدارات القديمة من OpenCode كانت تجلب دائما أحدث إصدار.
للترقية يدويا، شغّل
```bash
$ opencode upgrade 1.0.0
```
للرجوع إلى 0.x، شغّل
```bash
$ opencode upgrade 0.15.31
```
---
## تغييرات تجربة الاستخدام
أصبح سجل الجلسة أكثر اختصارا، ولا يعرض التفاصيل الكاملة إلا لأداتي edit و bash.
أضفنا شريط أوامر تمر عبره تقريبا كل العمليات. اضغط ctrl+p لإظهاره في أي سياق ولرؤية كل ما يمكنك فعله.
أضفنا شريطا جانبيا للجلسة (يمكن إظهاره/إخفاؤه) يحتوي على معلومات مفيدة.
أزلنا بعض الوظائف التي لم نكن متأكدين أن أحدا يستخدمها فعلا. إذا كانت هناك ميزة مهمة مفقودة، فالرجاء فتح issue وسنعيدها بسرعة.
---
## تغييرات غير متوافقة
### إعادة تسمية اختصارات المفاتيح
- messages_revert -> messages_undo
- switch_agent -> agent_cycle
- switch_agent_reverse -> agent_cycle_reverse
- switch_mode -> agent_cycle
- switch_mode_reverse -> agent_cycle_reverse
### إزالة اختصارات المفاتيح
- messages_layout_toggle
- messages_next
- messages_previous
- file_diff_toggle
- file_search
- file_close
- file_list
- app_help
- project_init
- tool_details
- thinking_blocks

View File

@@ -0,0 +1,154 @@
---
title: دعم ACP
description: استخدم OpenCode في أي محرر متوافق مع ACP.
---
يدعم OpenCode بروتوكول [Agent Client Protocol](https://agentclientprotocol.com) أو (ACP)، مما يتيح لك استخدامه مباشرة في المحررات وبيئات التطوير المتكاملة (IDEs) المتوافقة.
:::tip
للاطلاع على قائمة بالمحررات والأدوات التي تدعم ACP، راجع [ACP progress report](https://zed.dev/blog/acp-progress-report#available-now).
:::
ACP بروتوكول مفتوح يوحّد آلية التواصل بين محررات الشيفرة ووكلاء البرمجة بالذكاء الاصطناعي.
---
## الإعداد
لاستخدام OpenCode عبر ACP، اضبط محررك ليشغّل الأمر `opencode acp`.
يشغّل هذا الأمر OpenCode كعملية فرعية متوافقة مع ACP تتواصل مع محررك عبر JSON-RPC باستخدام stdio.
فيما يلي أمثلة لمحررات شائعة تدعم ACP.
---
### Zed
أضف إلى إعدادات [Zed](https://zed.dev) (`~/.config/zed/settings.json`):
```json title="~/.config/zed/settings.json"
{
"agent_servers": {
"OpenCode": {
"command": "opencode",
"args": ["acp"]
}
}
}
```
لفتحه، استخدم الإجراء `agent: new thread` في **Command Palette**.
يمكنك أيضا ربط اختصار لوحة مفاتيح عبر تعديل `keymap.json`:
```json title="keymap.json"
[
{
"bindings": {
"cmd-alt-o": [
"agent::NewExternalAgentThread",
{
"agent": {
"custom": {
"name": "OpenCode",
"command": {
"command": "opencode",
"args": ["acp"]
}
}
}
}
]
}
}
]
```
---
### JetBrains IDEs
أضف إلى ملف acp.json الخاص بـ [JetBrains IDE](https://www.jetbrains.com/) وفقا لـ [documentation](https://www.jetbrains.com/help/ai-assistant/acp.html):
```json title="acp.json"
{
"agent_servers": {
"OpenCode": {
"command": "/absolute/path/bin/opencode",
"args": ["acp"]
}
}
}
```
لفتحه، اختر الوكيل الجديد 'OpenCode' من محدد الوكلاء في AI Chat.
---
### Avante.nvim
أضف إلى إعدادات [Avante.nvim](https://github.com/yetone/avante.nvim):
```lua
{
acp_providers = {
["opencode"] = {
command = "opencode",
args = { "acp" }
}
}
}
```
إذا احتجت إلى تمرير متغيرات البيئة:
```lua {6-8}
{
acp_providers = {
["opencode"] = {
command = "opencode",
args = { "acp" },
env = {
OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY")
}
}
}
}
```
---
### CodeCompanion.nvim
لاستخدام OpenCode كوكيل ACP في [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim)، أضف التالي إلى إعدادات Neovim:
```lua
require("codecompanion").setup({
interactions = {
chat = {
adapter = {
name = "opencode",
model = "claude-sonnet-4",
},
},
},
})
```
يضبط هذا الإعداد CodeCompanion لاستخدام OpenCode كوكيل ACP للدردشة.
إذا احتجت إلى تمرير متغيرات البيئة (مثل `OPENCODE_API_KEY`)، فارجع إلى [Configuring Adapters: Environment Variables](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) ضمن توثيق CodeCompanion.nvim للاطلاع على التفاصيل كاملة.
## الدعم
يعمل OpenCode عبر ACP بالطريقة نفسها التي يعمل بها في الطرفية. جميع الميزات مدعومة:
:::note
بعض أوامر الشرطة المائلة المضمنة مثل `/undo` و`/redo` غير مدعومة حاليا.
:::
- الأدوات المضمنة (عمليات الملفات، أوامر الطرفية، إلخ.)
- الأدوات المخصصة وأوامر الشرطة المائلة
- خوادم MCP المضبوطة في إعدادات OpenCode
- قواعد خاصة بالمشروع من `AGENTS.md`
- المنسقات (formatters) والمدققات (linters) المخصصة
- نظام الوكلاء والأذونات

View File

@@ -0,0 +1,746 @@
---
title: الوكلاء
description: هيّئ الوكلاء المتخصصين واستخدمهم.
---
الوكلاء هم مساعدون متخصصون بالذكاء الاصطناعي يمكن تهيئتهم لمهام وسير عمل محدد. يتيحون لك إنشاء أدوات مركزة مع موجّهات مخصصة ونماذج وصلاحية وصول للأدوات.
:::tip
استخدم وكيل plan لتحليل الشفرة ومراجعة الاقتراحات بدون إجراء أي تغييرات على الشفرة.
:::
يمكنك التبديل بين الوكلاء أثناء الجلسة أو استدعاؤهم عبر الإشارة بـ `@`.
---
## الأنواع
يوجد نوعان من الوكلاء في OpenCode: وكلاء أساسيون ووكلاء فرعيون.
---
### الوكلاء الأساسيون
الوكلاء الأساسيون هم المساعدون الرئيسيون الذين تتفاعل معهم مباشرة. يمكنك التنقل بينهم باستخدام مفتاح **Tab** أو اختصار `switch_agent` الذي قمت بتهيئته. يتولى هؤلاء الوكلاء محادثتك الرئيسية. يتم ضبط وصول الأدوات عبر الأذونات — على سبيل المثال، يمتلك Build جميع الأدوات مفعلة بينما يكون Plan مقيّدا.
:::tip
يمكنك استخدام مفتاح **Tab** للتبديل بين الوكلاء الأساسيين أثناء الجلسة.
:::
يأتي OpenCode مع وكيلين أساسيين مدمجين: **Build** و **Plan**. سنلقي نظرة عليهما أدناه.
---
### الوكلاء الفرعيون
الوكلاء الفرعيون هم مساعدين متخصصين يمكن للوكلاء الأساسيين استدعاؤهم لمهام محددة. يمكنك أيضا استدعاؤهم يدويا عبر **الإشارة بـ @** في رسائلك.
يأتي OpenCode مع وكيلين فرعيين مدمجين: **General** و **Explore**. سنلقي نظرة على ذلك أدناه.
---
## المدمجة
يأتي OpenCode مع وكيلين أساسيين مدمجين ووكيلين فرعيين مدمجين.
---
### استخدام build
_الوضع_: `primary`
Build هو الوكيل الأساسي **الافتراضي** مع تفعيل جميع الأدوات. هذا هو الوكيل القياسي لأعمال التطوير عندما تحتاج إلى وصول كامل لعمليات الملفات وأوامر النظام.
---
### استخدام plan
_الوضع_: `primary`
وكيل مقيّد صُمم للتخطيط والتحليل. نستخدم نظام أذونات لمنحك تحكما أكبر ومنع التغييرات غير المقصودة.
افتراضيا، يتم ضبط كل ما يلي على `ask`:
- `file edits`: جميع عمليات الكتابة والتصحيح (patches) والتحرير
- `bash`: جميع أوامر bash
يفيد هذا الوكيل عندما تريد من النموذج تحليل الشفرة أو اقتراح تغييرات أو إنشاء خطط بدون إجراء أي تعديلات فعلية على قاعدة الشفرة.
---
### استخدام general
_الوضع_: `subagent`
وكيل عام الغرض للبحث في أسئلة معقدة وتنفيذ مهام متعددة الخطوات. لديه وصول كامل للأدوات (باستثناء todo)، لذا يمكنه إجراء تغييرات على الملفات عند الحاجة. استخدمه لتشغيل عدة وحدات عمل بالتوازي.
---
### استخدام explore
_الوضع_: `subagent`
وكيل سريع للقراءة فقط لاستكشاف قواعد الشفرة. لا يستطيع تعديل الملفات. استخدمه عندما تحتاج إلى العثور بسرعة على ملفات عبر أنماط، أو البحث في الشفرة عن كلمات مفتاحية، أو الإجابة عن أسئلة حول قاعدة الشفرة.
---
### استخدام compaction
_الوضع_: `primary`
وكيل نظام مخفي يضغط السياق الطويل إلى ملخص أصغر. يعمل تلقائيا عند الحاجة ولا يمكن اختياره من واجهة المستخدم.
---
### استخدام title
_الوضع_: `primary`
وكيل نظام مخفي ينشئ عناوين قصيرة للجلسات. يعمل تلقائيا ولا يمكن اختياره من واجهة المستخدم.
---
### استخدام summary
_الوضع_: `primary`
وكيل نظام مخفي ينشئ ملخصات للجلسات. يعمل تلقائيا ولا يمكن اختياره من واجهة المستخدم.
---
## الاستخدام
1. للوكلاء الأساسيين، استخدم مفتاح **Tab** للتنقل بينهم أثناء الجلسة. يمكنك أيضا استخدام اختصار `switch_agent` الذي قمت بتهيئته.
2. يمكن استدعاء الوكلاء الفرعيين:
- **تلقائيا** بواسطة الوكلاء الأساسيين لمهام متخصصة بناء على أوصافهم.
- يدويا عبر **الإشارة بـ @** إلى وكيل فرعي في رسالتك. على سبيل المثال:
```txt frame="none"
@general help me search for this function
```
3. **التنقل بين الجلسات**: عندما ينشئ الوكلاء الفرعيون جلسات فرعية خاصة بهم، يمكنك التنقل بين الجلسة الأم وجميع الجلسات الفرعية باستخدام:
- **\<Leader>+Right** (أو اختصار `session_child_cycle` الذي قمت بتهيئته) للتنقل للأمام عبر parent → child1 → child2 → ... → parent
- **\<Leader>+Left** (أو اختصار `session_child_cycle_reverse` الذي قمت بتهيئته) للتنقل للخلف عبر parent ← child1 ← child2 ← ... ← parent
يتيح لك ذلك التبديل بسلاسة بين المحادثة الرئيسية وعمل الوكلاء الفرعيين المتخصص.
---
## التهيئة
يمكنك تخصيص الوكلاء المدمجين أو إنشاء وكلائك عبر التهيئة. يمكن تهيئة الوكلاء بطريقتين:
---
### JSON
هيّئ الوكلاء في ملف إعدادات `opencode.json`:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"build": {
"mode": "primary",
"model": "anthropic/claude-sonnet-4-20250514",
"prompt": "{file:./prompts/build.txt}",
"tools": {
"write": true,
"edit": true,
"bash": true
}
},
"plan": {
"mode": "primary",
"model": "anthropic/claude-haiku-4-20250514",
"tools": {
"write": false,
"edit": false,
"bash": false
}
},
"code-reviewer": {
"description": "Reviews code for best practices and potential issues",
"mode": "subagent",
"model": "anthropic/claude-sonnet-4-20250514",
"prompt": "You are a code reviewer. Focus on security, performance, and maintainability.",
"tools": {
"write": false,
"edit": false
}
}
}
}
```
---
### Markdown
يمكنك أيضا تعريف الوكلاء باستخدام ملفات Markdown. ضعها في:
- عام: `~/.config/opencode/agents/`
- لكل مشروع: `.opencode/agents/`
```markdown title="~/.config/opencode/agents/review.md"
---
description: Reviews code for quality and best practices
mode: subagent
model: anthropic/claude-sonnet-4-20250514
temperature: 0.1
tools:
write: false
edit: false
bash: false
---
You are in code review mode. Focus on:
- Code quality and best practices
- Potential bugs and edge cases
- Performance implications
- Security considerations
Provide constructive feedback without making direct changes.
```
يصبح اسم ملف Markdown هو اسم الوكيل. على سبيل المثال، ينشئ `review.md` وكيلا باسم `review`.
---
## الخيارات
لنلق نظرة على خيارات التهيئة هذه بمزيد من التفصيل.
---
### الوصف
استخدم خيار `description` لتقديم وصف موجز لما يفعله الوكيل ومتى ينبغي استخدامه.
```json title="opencode.json"
{
"agent": {
"review": {
"description": "Reviews code for best practices and potential issues"
}
}
}
```
هذا خيار تهيئة **إلزامي**.
---
### درجة الحرارة
تحكم في العشوائية والإبداع في ردود النموذج عبر إعداد `temperature`.
القيم الأقل تجعل الردود أكثر تركيزا وحتمية، بينما تزيد القيم الأعلى من الإبداع والتنوع.
```json title="opencode.json"
{
"agent": {
"plan": {
"temperature": 0.1
},
"creative": {
"temperature": 0.8
}
}
}
```
عادة تتراوح قيم `temperature` بين 0.0 و 1.0:
- **0.0-0.2**: ردود شديدة التركيز وحتمية، مثالية لتحليل الشفرة والتخطيط
- **0.3-0.5**: ردود متوازنة مع قدر من الإبداع، مناسبة لمهام التطوير العامة
- **0.6-1.0**: ردود أكثر إبداعا وتنوعا، مفيدة للعصف الذهني والاستكشاف
```json title="opencode.json"
{
"agent": {
"analyze": {
"temperature": 0.1,
"prompt": "{file:./prompts/analysis.txt}"
},
"build": {
"temperature": 0.3
},
"brainstorm": {
"temperature": 0.7,
"prompt": "{file:./prompts/creative.txt}"
}
}
}
```
إذا لم يتم تحديد temperature، يستخدم OpenCode القيم الافتراضية الخاصة بالنموذج؛ عادة 0 لمعظم النماذج و 0.55 لنماذج Qwen.
---
### الحد الأقصى للخطوات
تحكم في الحد الأقصى لعدد التكرارات الوكيلة التي يمكن لوكيل تنفيذها قبل أن يُجبر على الرد بنص فقط. يتيح ذلك للمستخدمين الذين يرغبون في التحكم بالتكاليف وضع حد للإجراءات الوكيلة.
إذا لم يتم ضبط هذا الخيار، سيستمر الوكيل بالتكرار حتى يقرر النموذج التوقف أو يقاطع المستخدم الجلسة.
```json title="opencode.json"
{
"agent": {
"quick-thinker": {
"description": "Fast reasoning with limited iterations",
"prompt": "You are a quick thinker. Solve problems with minimal steps.",
"steps": 5
}
}
}
```
عند بلوغ الحد، يتلقى الوكيل موجّها نظاميا خاصا يطلب منه الرد بملخص لعمله والمهام المتبقية الموصى بها.
:::caution
الحقل القديم `maxSteps` متقادم. استخدم `steps` بدلا منه.
:::
---
### التعطيل
اضبطه على `true` لتعطيل الوكيل.
```json title="opencode.json"
{
"agent": {
"review": {
"disable": true
}
}
}
```
---
### الموجّه
حدد ملف موجّه نظامي مخصص لهذا الوكيل عبر إعداد `prompt`. يجب أن يحتوي ملف الموجّه على تعليمات خاصة بهدف الوكيل.
```json title="opencode.json"
{
"agent": {
"review": {
"prompt": "{file:./prompts/code-review.txt}"
}
}
}
```
هذا المسار نسبي لمكان وجود ملف الإعدادات. لذلك يعمل هذا لكل من إعدادات OpenCode العامة وإعدادات المشروع.
---
### النموذج
استخدم إعداد `model` لتجاوز (override) النموذج لهذا الوكيل. يفيد ذلك لاستخدام نماذج مختلفة مُحسّنة لمهام مختلفة. على سبيل المثال، نموذج أسرع للتخطيط ونموذج أقدر للتنفيذ.
:::tip
إذا لم تحدد نموذجا، يستخدم الوكلاء الأساسيون [النموذج المُهيأ عالميا](/docs/config#models)، بينما يستخدم الوكلاء الفرعيون نموذج الوكيل الأساسي الذي استدعاهم.
:::
```json title="opencode.json"
{
"agent": {
"plan": {
"model": "anthropic/claude-haiku-4-20250514"
}
}
}
```
يستخدم معرّف النموذج في إعدادات OpenCode الصيغة `provider/model-id`. على سبيل المثال، إذا كنت تستخدم [OpenCode Zen](/docs/zen)، فستستخدم `opencode/gpt-5.1-codex` لـ GPT 5.1 Codex.
---
### الأدوات
تحكم في الأدوات المتاحة لهذا الوكيل عبر إعداد `tools`. يمكنك تفعيل أو تعطيل أدوات محددة بضبطها على `true` أو `false`.
```json title="opencode.json" {3-6,9-12}
{
"$schema": "https://opencode.ai/config.json",
"tools": {
"write": true,
"bash": true
},
"agent": {
"plan": {
"tools": {
"write": false,
"bash": false
}
}
}
}
```
:::note
إعدادات الوكيل الخاصة تتجاوز الإعدادات العامة.
:::
يمكنك أيضا استخدام المحارف البديلة (wildcards) للتحكم في عدة أدوات دفعة واحدة. على سبيل المثال، لتعطيل جميع الأدوات القادمة من خادم MCP:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"readonly": {
"tools": {
"mymcp_*": false,
"write": false,
"edit": false
}
}
}
}
```
[اعرف المزيد عن الأدوات](/docs/tools).
---
### الأذونات
يمكنك تهيئة الأذونات لإدارة الإجراءات التي يستطيع الوكيل تنفيذها. حاليا، يمكن تهيئة أذونات أدوات `edit` و `bash` و `webfetch` إلى:
- `"ask"` — طلب الموافقة قبل تشغيل الأداة
- `"allow"` — السماح بكل العمليات بدون موافقة
- `"deny"` — تعطيل الأداة
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"edit": "deny"
}
}
```
يمكنك تجاوز هذه الأذونات لكل وكيل.
```json title="opencode.json" {3-5,8-10}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"edit": "deny"
},
"agent": {
"build": {
"permission": {
"edit": "ask"
}
}
}
}
```
يمكنك أيضا ضبط الأذونات في وكلاء Markdown.
```markdown title="~/.config/opencode/agents/review.md"
---
description: Code review without edits
mode: subagent
permission:
edit: deny
bash:
"*": ask
"git diff": allow
"git log*": allow
"grep *": allow
webfetch: deny
---
حلل الشفرة فقط واقترح التغييرات.
```
يمكنك ضبط الأذونات لأوامر bash محددة.
```json title="opencode.json" {7}
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"build": {
"permission": {
"bash": {
"git push": "ask",
"grep *": "allow"
}
}
}
}
}
```
يمكن لهذا أن يقبل نمط glob.
```json title="opencode.json" {7}
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"build": {
"permission": {
"bash": {
"git *": "ask"
}
}
}
}
}
```
ويمكنك أيضا استخدام المحرف البديل `*` لإدارة الأذونات لكل الأوامر.
وبما أن آخر قاعدة مطابقة لها الأولوية، ضع قاعدة `*` أولا ثم القواعد الأكثر تخصيصا بعدها.
```json title="opencode.json" {8}
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"build": {
"permission": {
"bash": {
"*": "ask",
"git status *": "allow"
}
}
}
}
}
```
[اعرف المزيد عن الأذونات](/docs/permissions).
---
### الوضع
تحكم في وضع الوكيل عبر إعداد `mode`. يُستخدم خيار `mode` لتحديد كيفية استخدام الوكيل.
```json title="opencode.json"
{
"agent": {
"review": {
"mode": "subagent"
}
}
}
```
يمكن ضبط خيار `mode` على `primary` أو `subagent` أو `all`. إذا لم يتم تحديد `mode`، فالقيمة الافتراضية هي `all`.
---
### مخفي
أخفِ وكيلا فرعيا من قائمة الإكمال التلقائي لـ `@` عبر `hidden: true`. يفيد ذلك للوكلاء الفرعيين الداخليين الذين ينبغي استدعاؤهم برمجيا فقط بواسطة وكلاء آخرين عبر أداة Task.
```json title="opencode.json"
{
"agent": {
"internal-helper": {
"mode": "subagent",
"hidden": true
}
}
}
```
يؤثر هذا فقط على ظهور الوكيل للمستخدم في قائمة الإكمال التلقائي. لا يزال بإمكان النموذج استدعاء الوكلاء المخفيين عبر أداة Task إذا سمحت الأذونات.
:::note
ينطبق فقط على الوكلاء ذوي `mode: subagent`.
:::
---
### أذونات Task
تحكم في أي الوكلاء الفرعيين يمكن لوكيل استدعاؤهم عبر أداة Task باستخدام `permission.task`. يستخدم أنماط glob لمطابقة مرنة.
```json title="opencode.json"
{
"agent": {
"orchestrator": {
"mode": "primary",
"permission": {
"task": {
"*": "deny",
"orchestrator-*": "allow",
"code-reviewer": "ask"
}
}
}
}
}
```
عند ضبطها على `deny`، تتم إزالة الوكيل الفرعي بالكامل من وصف أداة Task، لذا لن يحاول النموذج استدعاءه.
:::tip
تُقيّم القواعد بالترتيب، و **آخر قاعدة مطابقة هي التي تفوز**. في المثال أعلاه، يطابق `orchestrator-planner` كلا من `*` (deny) و `orchestrator-*` (allow)، ولكن بما أن `orchestrator-*` تأتي بعد `*` فالنتيجة هي `allow`.
:::
:::tip
يمكن للمستخدمين دائما استدعاء أي وكيل فرعي مباشرة عبر قائمة الإكمال التلقائي لـ `@`، حتى لو كانت أذونات task للوكيل سترفض ذلك.
:::
---
### اللون
خصص المظهر البصري للوكيل في واجهة المستخدم عبر خيار `color`. يؤثر ذلك على كيفية ظهور الوكيل في الواجهة.
استخدم لونا سداسيا صالحا (مثل `#FF5733`) أو لون سمة: `primary` و `secondary` و `accent` و `success` و `warning` و `error` و `info`.
```json title="opencode.json"
{
"agent": {
"creative": {
"color": "#ff6b6b"
},
"code-reviewer": {
"color": "accent"
}
}
}
```
---
### Top P
تحكم في تنوع الردود عبر خيار `top_p`. بديل عن temperature للتحكم بالعشوائية.
```json title="opencode.json"
{
"agent": {
"brainstorm": {
"top_p": 0.9
}
}
}
```
تتراوح القيم من 0.0 إلى 1.0. القيم الأقل أكثر تركيزا، والقيم الأعلى أكثر تنوعا.
---
### خيارات إضافية
أي خيارات أخرى تحددها في تهيئة الوكيل سيتم **تمريرها مباشرة** إلى مزود النموذج كخيارات للنموذج. يتيح لك ذلك استخدام ميزات ومعاملات خاصة بالمزود.
على سبيل المثال، مع نماذج الاستدلال من OpenAI يمكنك التحكم في مجهود الاستدلال:
```json title="opencode.json" {6,7}
{
"agent": {
"deep-thinker": {
"description": "Agent that uses high reasoning effort for complex problems",
"model": "openai/gpt-5",
"reasoningEffort": "high",
"textVerbosity": "low"
}
}
}
```
هذه الخيارات الإضافية تعتمد على النموذج والمزود. راجع توثيق مزودك لمعرفة المعاملات المتاحة.
:::tip
شغّل `opencode models` لعرض قائمة بالنماذج المتاحة.
:::
---
## إنشاء وكلاء
يمكنك إنشاء وكلاء جدد باستخدام الأمر التالي:
```bash
opencode agent create
```
سيقوم هذا الأمر التفاعلي بما يلي:
1. سيسألك أين تريد حفظ الوكيل: عام (global) أو خاص بالمشروع.
2. سيطلب وصفا لما ينبغي أن يفعله الوكيل.
3. سيولّد موجّها نظاميا ومعرّفا مناسبا.
4. سيتيح لك اختيار الأدوات التي يمكن للوكيل الوصول إليها.
5. أخيرا، سينشئ ملف Markdown يحتوي تهيئة الوكيل.
---
## حالات الاستخدام
فيما يلي بعض حالات الاستخدام الشائعة لوكلاء مختلفين.
- **Build agent**: أعمال تطوير كاملة مع تفعيل جميع الأدوات
- **Plan agent**: تحليل وتخطيط بدون إجراء تغييرات
- **Review agent**: مراجعة الشفرة مع وصول للقراءة فقط بالإضافة إلى أدوات التوثيق
- **Debug agent**: يركز على التحقيق مع تفعيل أدوات bash والقراءة
- **Docs agent**: كتابة التوثيق مع عمليات الملفات بدون أوامر النظام
---
## أمثلة
فيما يلي بعض أمثلة الوكلاء التي قد تجدها مفيدة.
:::tip
هل لديك وكيل تود مشاركته؟ [قدّم PR](https://github.com/anomalyco/opencode).
:::
---
### وكيل التوثيق
```markdown title="~/.config/opencode/agents/docs-writer.md"
---
description: Writes and maintains project documentation
mode: subagent
tools:
bash: false
---
You are a technical writer. Create clear, comprehensive documentation.
Focus on:
- Clear explanations
- Proper structure
- Code examples
- User-friendly language
```
---
### مدقق أمني
```markdown title="~/.config/opencode/agents/security-auditor.md"
---
description: Performs security audits and identifies vulnerabilities
mode: subagent
tools:
write: false
edit: false
---
You are a security expert. Focus on identifying potential security issues.
Look for:
- Input validation vulnerabilities
- Authentication and authorization flaws
- Data exposure risks
- Dependency vulnerabilities
- Configuration security issues
```

View File

@@ -0,0 +1,601 @@
---
title: سطر الأوامر
description: خيارات وأوامر سطر أوامر OpenCode.
---
import { Tabs, TabItem } from "@astrojs/starlight/components"
يبدأ سطر أوامر OpenCode افتراضيا واجهة [TUI](/docs/tui) عند تشغيله بدون أي معاملات.
```bash
opencode
```
كما يدعم أيضا أوامر موثقة في هذه الصفحة، ما يتيح لك التفاعل مع OpenCode برمجيا.
```bash
opencode run "Explain how closures work in JavaScript"
```
---
### tui
بدء واجهة المستخدم الطرفية (TUI) الخاصة بـ OpenCode.
```bash
opencode [project]
```
#### الخيارات
| الخيار | المختصر | الوصف |
| ------------ | ------- | -------------------------------------------- |
| `--continue` | `-c` | متابعة الجلسة الأخيرة |
| `--session` | `-s` | معرّف الجلسة للمتابعة |
| `--prompt` | | الموجّه المراد استخدامه |
| `--model` | `-m` | النموذج المراد استخدامه بصيغة provider/model |
| `--agent` | | الوكيل المراد استخدامه |
| `--port` | | المنفذ الذي يتم الاستماع عليه |
| `--hostname` | | اسم المضيف الذي يتم الاستماع عليه |
---
## الأوامر
يتضمن سطر أوامر OpenCode أيضا الأوامر التالية.
---
### agent
إدارة وكلاء OpenCode.
```bash
opencode agent [command]
```
---
### attach
إرفاق طرفية بخادم الواجهة الخلفية لـ OpenCode قيد التشغيل بالفعل، والذي تم تشغيله عبر الأمرين `serve` أو `web`.
```bash
opencode attach [url]
```
يتيح ذلك استخدام واجهة TUI مع واجهة خلفية لـ OpenCode تعمل عن بعد. على سبيل المثال:
```bash
# Start the backend server for web/mobile access
opencode web --port 4096 --hostname 0.0.0.0
# In another terminal, attach the TUI to the running backend
opencode attach http://10.20.30.40:4096
```
#### الرايات
| الراية | المختصر | الوصف |
| ----------- | ------- | ----------------------------------- |
| `--dir` | | دليل العمل الذي ستبدأ منه واجهة TUI |
| `--session` | `-s` | معرّف الجلسة للمتابعة |
---
#### create
إنشاء وكيل جديد بإعدادات مخصصة.
```bash
opencode agent create
```
سيرشدك هذا الأمر خلال إنشاء وكيل جديد مع موجه نظام مخصص وإعدادات الأدوات.
---
#### list
عرض جميع الوكلاء المتاحين.
```bash
opencode agent list
```
---
### auth
أمر لإدارة بيانات الاعتماد وتسجيل الدخول لمزودي الخدمة.
```bash
opencode auth [command]
```
---
#### login
يعتمد OpenCode على قائمة المزودين في [Models.dev](https://models.dev)، لذا يمكنك استخدام `opencode auth login` لتهيئة مفاتيح API لأي مزود ترغب باستخدامه. يتم حفظ ذلك في `~/.local/share/opencode/auth.json`.
```bash
opencode auth login
```
عند تشغيل OpenCode يقوم بتحميل المزودين من ملف بيانات الاعتماد، وكذلك أي مفاتيح معرّفة في متغيرات البيئة لديك أو في ملف `.env` ضمن مشروعك.
---
#### list
يسرد جميع المزودين الذين تم توثيقهم كما هم محفوظون في ملف بيانات الاعتماد.
```bash
opencode auth list
```
أو النسخة المختصرة.
```bash
opencode auth ls
```
---
#### logout
يسجلك خارج مزود عبر حذفه من ملف بيانات الاعتماد.
```bash
opencode auth logout
```
---
### github
إدارة وكيل GitHub لأتمتة المستودع.
```bash
opencode github [command]
```
---
#### install
تثبيت وكيل GitHub في مستودعك.
```bash
opencode github install
```
يقوم ذلك بإعداد سير عمل GitHub Actions اللازم ويرشدك خلال عملية التهيئة. [اعرف المزيد](/docs/github).
---
#### run
تشغيل وكيل GitHub. يُستخدم هذا عادة ضمن GitHub Actions.
```bash
opencode github run
```
##### الرايات
| الراية | الوصف |
| --------- | ------------------------------------ |
| `--event` | حدث GitHub مُحاكى لتشغيل الوكيل عليه |
| `--token` | رمز وصول شخصي لـ GitHub |
---
### mcp
إدارة خوادم Model Context Protocol.
```bash
opencode mcp [command]
```
---
#### add
إضافة خادم MCP إلى تهيئتك.
```bash
opencode mcp add
```
سيرشدك هذا الأمر خلال إضافة خادم MCP محلي أو بعيد.
---
#### list
عرض جميع خوادم MCP المُهيأة وحالة اتصالها.
```bash
opencode mcp list
```
أو استخدم النسخة المختصرة.
```bash
opencode mcp ls
```
---
#### auth
إجراء المصادقة مع خادم MCP يدعم OAuth.
```bash
opencode mcp auth [name]
```
إذا لم تُحدِّد اسم خادم، فسيُطلب منك الاختيار من الخوادم المتاحة الداعمة لـ OAuth.
يمكنك أيضا عرض الخوادم الداعمة لـ OAuth وحالة المصادقة الخاصة بها.
```bash
opencode mcp auth list
```
أو استخدم النسخة المختصرة.
```bash
opencode mcp auth ls
```
---
#### logout
إزالة بيانات اعتماد OAuth لخادم MCP.
```bash
opencode mcp logout [name]
```
---
#### debug
تشخيص مشاكل اتصال OAuth لخادم MCP.
```bash
opencode mcp debug <name>
```
---
### models
عرض جميع النماذج المتاحة من المزودين المُهيأين.
```bash
opencode models [provider]
```
يعرض هذا الأمر جميع النماذج المتاحة عبر المزودين المُهيأين لديك بصيغة `provider/model`.
هذا مفيد لتحديد اسم النموذج الدقيق الذي ستستخدمه في [تهيئتك](/docs/config/).
يمكنك اختياريا تمرير معرّف مزود لتصفية النماذج حسب ذلك المزود.
```bash
opencode models anthropic
```
#### الرايات
| الراية | الوصف |
| ----------- | ------------------------------------------------------------- |
| `--refresh` | تحديث ذاكرة التخزين المؤقت للنماذج من models.dev |
| `--verbose` | استخدام مخرجات أكثر تفصيلا للنماذج (تشمل بيانات مثل التكاليف) |
استخدم الراية `--refresh` لتحديث قائمة النماذج المخزنة مؤقتا. يفيد ذلك عند إضافة نماذج جديدة إلى مزود وتريد رؤيتها في OpenCode.
```bash
opencode models --refresh
```
---
### run
تشغيل opencode في وضع غير تفاعلي عبر تمرير موجه مباشرة.
```bash
opencode run [message..]
```
هذا مفيد للبرمجة النصية والأتمتة، أو عندما تريد إجابة سريعة دون تشغيل واجهة TUI كاملة. على سبيل المثال.
```bash "opencode run"
opencode run Explain the use of context in Go
```
يمكنك أيضا الإرفاق بمثيل `opencode serve` قيد التشغيل لتجنّب زمن الإقلاع البارد لخوادم MCP في كل تشغيل:
```bash
# Start a headless server in one terminal
opencode serve
# In another terminal, run commands that attach to it
opencode run --attach http://localhost:4096 "Explain async/await in JavaScript"
```
#### الرايات
| الراية | المختصر | الوصف |
| ------------ | ------- | -------------------------------------------------------------- |
| `--command` | | الأمر المراد تشغيله؛ استخدم الرسالة كوسائط |
| `--continue` | `-c` | متابعة الجلسة الأخيرة |
| `--session` | `-s` | معرّف الجلسة للمتابعة |
| `--share` | | مشاركة الجلسة |
| `--model` | `-m` | النموذج المراد استخدامه بصيغة provider/model |
| `--agent` | | الوكيل المراد استخدامه |
| `--file` | `-f` | ملف/ملفات لإرفاقها بالرسالة |
| `--format` | | التنسيق: default (منسق) أو json (أحداث JSON خام) |
| `--title` | | عنوان للجلسة (يستخدم موجهًا مقتطعًا إن لم تُحدَّد قيمة) |
| `--attach` | | الإرفاق بخادم opencode قيد التشغيل (مثل http://localhost:4096) |
| `--port` | | منفذ الخادم المحلي (الافتراضي منفذ عشوائي) |
---
### serve
بدء خادم OpenCode بدون واجهة للوصول عبر API. راجع [توثيق الخادم](/docs/server) لواجهة HTTP الكاملة.
```bash
opencode serve
```
يشغّل هذا خادم HTTP يوفّر وصولا عبر API لوظائف opencode دون واجهة TUI. اضبط `OPENCODE_SERVER_PASSWORD` لتفعيل مصادقة HTTP الأساسية (اسم المستخدم الافتراضي `opencode`).
#### الرايات
| الراية | الوصف |
| ------------ | ----------------------------------------- |
| `--port` | المنفذ الذي يتم الاستماع عليه |
| `--hostname` | اسم المضيف الذي يتم الاستماع عليه |
| `--mdns` | تفعيل اكتشاف mDNS |
| `--cors` | أصول/منشأات إضافية للمتصفح للسماح بـ CORS |
---
### session
إدارة جلسات OpenCode.
```bash
opencode session [command]
```
---
#### list
عرض جميع جلسات OpenCode.
```bash
opencode session list
```
##### الرايات
| الراية | المختصر | الوصف |
| ------------- | ------- | ------------------------------------- |
| `--max-count` | `-n` | حصر النتائج في أحدث N جلسات |
| `--format` | | تنسيق المخرجات: table أو json (table) |
---
### stats
عرض إحصاءات استخدام الرموز والتكلفة لجلسات OpenCode لديك.
```bash
opencode stats
```
#### الرايات
| الراية | الوصف |
| ----------- | ------------------------------------------------------------------------- |
| `--days` | عرض الإحصاءات لآخر N يومًا (الافتراضي: كل الوقت) |
| `--tools` | عدد الأدوات المطلوب عرضها (الافتراضي: الكل) |
| `--models` | عرض تفصيل استخدام النماذج (مخفي افتراضيا). مرّر رقمًا لعرض أعلى N |
| `--project` | التصفية حسب المشروع (الافتراضي: كل المشاريع، سلسلة فارغة: المشروع الحالي) |
---
### export
تصدير بيانات الجلسة بصيغة JSON.
```bash
opencode export [sessionID]
```
إذا لم تُقدّم معرّف جلسة، فسيُطلب منك الاختيار من الجلسات المتاحة.
---
### import
استيراد بيانات الجلسة من ملف JSON أو رابط مشاركة OpenCode.
```bash
opencode import <file>
```
يمكنك الاستيراد من ملف محلي أو من رابط مشاركة OpenCode.
```bash
opencode import session.json
opencode import https://opncd.ai/s/abc123
```
---
### web
بدء خادم OpenCode بدون واجهة مع واجهة ويب.
```bash
opencode web
```
يشغّل هذا خادم HTTP ويفتح متصفح ويب للوصول إلى OpenCode عبر واجهة ويب. اضبط `OPENCODE_SERVER_PASSWORD` لتفعيل مصادقة HTTP الأساسية (اسم المستخدم الافتراضي `opencode`).
#### الرايات
| الراية | الوصف |
| ------------ | ----------------------------------------- |
| `--port` | المنفذ الذي يتم الاستماع عليه |
| `--hostname` | اسم المضيف الذي يتم الاستماع عليه |
| `--mdns` | تفعيل اكتشاف mDNS |
| `--cors` | أصول/منشأات إضافية للمتصفح للسماح بـ CORS |
---
### acp
بدء خادم ACP (Agent Client Protocol).
```bash
opencode acp
```
يشغّل هذا الأمر خادم ACP يتواصل عبر stdin/stdout باستخدام nd-JSON.
#### الرايات
| الراية | الوصف |
| ------------ | --------------------------------- |
| `--cwd` | دليل العمل |
| `--port` | المنفذ الذي يتم الاستماع عليه |
| `--hostname` | اسم المضيف الذي يتم الاستماع عليه |
---
### uninstall
إلغاء تثبيت OpenCode وإزالة جميع الملفات ذات الصلة.
```bash
opencode uninstall
```
#### الرايات
| الراية | المختصر | الوصف |
| --------------- | ------- | ----------------------------------- |
| `--keep-config` | `-c` | الإبقاء على ملفات التهيئة |
| `--keep-data` | `-d` | الإبقاء على بيانات الجلسات واللقطات |
| `--dry-run` | | عرض ما سيتم حذفه دون تنفيذ الحذف |
| `--force` | `-f` | تخطي مطالبات التأكيد |
---
### upgrade
تحديث opencode إلى أحدث إصدار أو إلى إصدار محدد.
```bash
opencode upgrade [target]
```
للترقية إلى أحدث إصدار.
```bash
opencode upgrade
```
للترقية إلى إصدار محدد.
```bash
opencode upgrade v0.1.48
```
#### الرايات
| الراية | المختصر | الوصف |
| ---------- | ------- | ----------------------------------------------------------- |
| `--method` | `-m` | طريقة التثبيت المستخدمة: curl أو npm أو pnpm أو bun أو brew |
---
## الخيارات العامة
يدعم سطر أوامر opencode الخيارات العامة التالية.
| الراية | المختصر | الوصف |
| -------------- | ------- | -------------------------------------- |
| `--help` | `-h` | عرض المساعدة |
| `--version` | `-v` | طباعة رقم الإصدار |
| `--print-logs` | | طباعة السجلات إلى stderr |
| `--log-level` | | مستوى السجل (DEBUG, INFO, WARN, ERROR) |
---
## متغيرات البيئة
يمكن تهيئة OpenCode باستخدام متغيرات البيئة.
| المتغير | النوع | الوصف |
| ------------------------------------- | ------- | --------------------------------------------------------- |
| `OPENCODE_AUTO_SHARE` | boolean | مشاركة الجلسات تلقائيا |
| `OPENCODE_GIT_BASH_PATH` | string | مسار ملف Git Bash التنفيذي على Windows |
| `OPENCODE_CONFIG` | string | مسار ملف التهيئة |
| `OPENCODE_CONFIG_DIR` | string | مسار دليل التهيئة |
| `OPENCODE_CONFIG_CONTENT` | string | محتوى تهيئة JSON مُضمّن |
| `OPENCODE_DISABLE_AUTOUPDATE` | boolean | تعطيل التحقق التلقائي من التحديثات |
| `OPENCODE_DISABLE_PRUNE` | boolean | تعطيل تنقية البيانات القديمة |
| `OPENCODE_DISABLE_TERMINAL_TITLE` | boolean | تعطيل تحديث عنوان الطرفية تلقائيا |
| `OPENCODE_PERMISSION` | string | تهيئة أذونات JSON مُضمّنة |
| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | boolean | تعطيل الإضافات الافتراضية |
| `OPENCODE_DISABLE_LSP_DOWNLOAD` | boolean | تعطيل تنزيل خوادم LSP تلقائيا |
| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolean | تفعيل النماذج التجريبية |
| `OPENCODE_DISABLE_AUTOCOMPACT` | boolean | تعطيل ضغط السياق تلقائيا |
| `OPENCODE_DISABLE_CLAUDE_CODE` | boolean | تعطيل القراءة من `.claude` (الموجه + المهارات) |
| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | boolean | تعطيل قراءة `~/.claude/CLAUDE.md` |
| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | boolean | تعطيل تحميل `.claude/skills` |
| `OPENCODE_DISABLE_MODELS_FETCH` | boolean | تعطيل جلب النماذج من مصادر بعيدة |
| `OPENCODE_FAKE_VCS` | string | مزود VCS وهمي لأغراض الاختبار |
| `OPENCODE_DISABLE_FILETIME_CHECK` | boolean | تعطيل التحقق من وقت الملف لتحسين الأداء |
| `OPENCODE_CLIENT` | string | معرّف العميل (الافتراضي `cli`) |
| `OPENCODE_ENABLE_EXA` | boolean | تفعيل أدوات بحث الويب من Exa |
| `OPENCODE_SERVER_PASSWORD` | string | تفعيل المصادقة الأساسية لخادمي `serve`/`web` |
| `OPENCODE_SERVER_USERNAME` | string | تجاوز اسم مستخدم المصادقة الأساسية (الافتراضي `opencode`) |
| `OPENCODE_MODELS_URL` | string | رابط مخصص لجلب تهيئة النماذج |
---
### تجريبي
تقوم متغيرات البيئة التالية بتفعيل ميزات تجريبية قد تتغير أو تتم إزالتها.
| المتغير | النوع | الوصف |
| ----------------------------------------------- | ------- | ------------------------------------------- |
| `OPENCODE_EXPERIMENTAL` | boolean | تفعيل جميع الميزات التجريبية |
| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | boolean | تفعيل اكتشاف الأيقونات |
| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | boolean | تعطيل النسخ عند التحديد في TUI |
| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | number | المهلة الافتراضية لأوامر bash بالميلي ثانية |
| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | number | الحد الأقصى لرموز المخرجات لاستجابات LLM |
| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | boolean | تفعيل مراقب الملفات لكامل الدليل |
| `OPENCODE_EXPERIMENTAL_OXFMT` | boolean | تفعيل مُنسّق oxfmt |
| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | boolean | تفعيل أداة LSP تجريبية |
| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | boolean | تعطيل مراقب الملفات |
| `OPENCODE_EXPERIMENTAL_EXA` | boolean | تفعيل ميزات Exa التجريبية |
| `OPENCODE_EXPERIMENTAL_LSP_TY` | boolean | تفعيل تدقيق أنواع LSP تجريبي |
| `OPENCODE_EXPERIMENTAL_MARKDOWN` | boolean | تفعيل ميزات markdown تجريبية |
| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | boolean | تفعيل وضع الخطة |

View File

@@ -0,0 +1,322 @@
---
title: الأوامر
description: أنشئ أوامر مخصصة للمهام المتكررة.
---
تتيح لك الأوامر المخصصة تحديد مُطالبة (prompt) تريد تشغيلها عند تنفيذ ذلك الأمر في واجهة TUI.
```bash frame="none"
/my-command
```
تُعدّ الأوامر المخصصة إضافةً إلى الأوامر المضمنة مثل `/init` و`/undo` و`/redo` و`/share` و`/help`. [اعرف المزيد](/docs/tui#commands).
---
## إنشاء ملفات الأوامر
أنشئ ملفات Markdown داخل الدليل `commands/` لتعريف أوامر مخصصة.
أنشئ الملف `.opencode/commands/test.md`:
```md title=".opencode/commands/test.md"
---
description: Run tests with coverage
agent: build
model: anthropic/claude-3-5-sonnet-20241022
---
Run the full test suite with coverage report and show any failures.
Focus on the failing tests and suggest fixes.
```
تُعرِّف ترويسة Frontmatter خصائص الأمر، بينما يصبح المحتوى هو القالب.
استخدم الأمر بكتابة `/` ثم اسم الأمر.
```bash frame="none"
"/test"
```
---
## الإعداد
يمكنك إضافة أوامر مخصصة عبر إعدادات OpenCode أو بإنشاء ملفات Markdown داخل الدليل `commands/`.
---
### JSON
استخدم خيار `command` في [config](/docs/config) الخاص بـ OpenCode:
```json title="opencode.jsonc" {4-12}
{
"$schema": "https://opencode.ai/config.json",
"command": {
// This becomes the name of the command
"test": {
// This is the prompt that will be sent to the LLM
"template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.",
// This is shown as the description in the TUI
"description": "Run tests with coverage",
"agent": "build",
"model": "anthropic/claude-3-5-sonnet-20241022"
}
}
}
```
يمكنك الآن تشغيل هذا الأمر في واجهة TUI:
```bash frame="none"
/test
```
---
### Markdown
يمكنك أيضًا تعريف الأوامر باستخدام ملفات Markdown. ضعها في:
- على مستوى النظام: `~/.config/opencode/commands/`
- لكل مشروع: `.opencode/commands/`
```markdown title="~/.config/opencode/commands/test.md"
---
description: Run tests with coverage
agent: build
model: anthropic/claude-3-5-sonnet-20241022
---
Run the full test suite with coverage report and show any failures.
Focus on the failing tests and suggest fixes.
```
يصبح اسم ملف Markdown هو اسم الأمر. على سبيل المثال، يتيح لك `test.md` تشغيل:
```bash frame="none"
/test
```
---
## إعداد المُطالبة
تدعم مُطالبات الأوامر المخصصة عدة عناصر نائبة (placeholders) وبنى خاصة.
---
### الوسائط
مرِّر وسائط إلى الأوامر باستخدام العنصر النائب `$ARGUMENTS`.
```md title=".opencode/commands/component.md"
---
description: Create a new component
---
Create a new React component named $ARGUMENTS with TypeScript support.
Include proper typing and basic structure.
```
شغِّل الأمر مع وسائط:
```bash frame="none"
/component Button
```
وسيُستبدل `$ARGUMENTS` بالقيمة `Button`.
يمكنك أيضًا الوصول إلى كل وسيط على حدة باستخدام المعاملات الموضعية:
- `$1` - الوسيط الأول
- `$2` - الوسيط الثاني
- `$3` - الوسيط الثالث
- وهكذا...
على سبيل المثال:
```md title=".opencode/commands/create-file.md"
---
description: Create a new file with content
---
Create a file named $1 in the directory $2
with the following content: $3
```
شغِّل الأمر:
```bash frame="none"
/create-file config.json src "{ \"key\": \"value\" }"
```
سيؤدي ذلك إلى استبدال:
- `$1` بـ `config.json`
- `$2` بـ `src`
- `$3` بـ `{ "key": "value" }`
---
### خرج الصدفة (Shell)
استخدم _!`command`_ لحقن خرج [أمر bash](/docs/tui#bash-commands) داخل مُطالبتك.
على سبيل المثال، لإنشاء أمر مخصص يُحلل تغطية الاختبارات:
```md title=".opencode/commands/analyze-coverage.md"
---
description: Analyze test coverage
---
Here are the current test results:
!`npm test`
Based on these results, suggest improvements to increase coverage.
```
أو لمراجعة التغييرات الأخيرة:
```md title=".opencode/commands/review-changes.md"
---
description: Review recent changes
---
Recent git commits:
!`git log --oneline -10`
Review these changes and suggest any improvements.
```
تُشغَّل الأوامر في دليل جذر مشروعك ويصبح خرجها جزءًا من المُطالبة.
---
### مراجع الملفات
ضمِّن الملفات في أمرك باستخدام `@` ثم اسم الملف.
```md title=".opencode/commands/review-component.md"
---
description: Review component
---
Review the component in @src/components/Button.tsx.
Check for performance issues and suggest improvements.
```
يُدرج محتوى الملف في المُطالبة تلقائيًا.
---
## الخيارات
لنلقِ نظرةً على خيارات الإعداد بالتفصيل.
---
### القالب (`template`)
يُعرِّف خيار `template` المُطالبة التي ستُرسل إلى نموذج اللغة (LLM) عند تنفيذ الأمر.
```json title="opencode.json"
{
"command": {
"test": {
"template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes."
}
}
}
```
هذا خيار إعداد **إلزامي**.
---
### الوصف (`description`)
استخدم خيار `description` لتقديم وصف موجز لما يفعله الأمر.
```json title="opencode.json"
{
"command": {
"test": {
"description": "Run tests with coverage"
}
}
}
```
يظهر هذا الوصف في واجهة TUI عند كتابة الأمر.
---
### الوكيل (`agent`)
استخدم إعداد `agent` لتحديد أي [agent](/docs/agents) ينبغي أن ينفّذ هذا الأمر (اختياريًا).
إذا كان هذا [subagent](/docs/agents/#subagents)، فسيؤدي الأمر افتراضيًا إلى تشغيل استدعاء subagent.
لإيقاف هذا السلوك، عيِّن `subtask` إلى `false`.
```json title="opencode.json"
{
"command": {
"review": {
"agent": "plan"
}
}
}
```
هذا خيار إعداد **اختياري**. إن لم تُحدده، فسيُستخدم agent الحالي افتراضيًا.
---
### مهمة فرعية (`subtask`)
استخدم القيمة المنطقية `subtask` لفرض أن يُشغِّل الأمر استدعاء [subagent](/docs/agents/#subagents).
يفيد هذا إذا أردت ألا يلوّث الأمر السياق الأساسي لديك، إذ سيُجبر (**force**) الـ agent على العمل كـ subagent،
حتى لو كان `mode` مضبوطًا على `primary` في إعدادات [agent](/docs/agents).
```json title="opencode.json"
{
"command": {
"analyze": {
"subtask": true
}
}
}
```
هذا خيار إعداد **اختياري**.
---
### النموذج (`model`)
استخدم إعداد `model` لتجاوز النموذج الافتراضي لهذا الأمر.
```json title="opencode.json"
{
"command": {
"analyze": {
"model": "anthropic/claude-3-5-sonnet-20241022"
}
}
}
```
هذا خيار إعداد **اختياري**.
---
## الأوامر المضمنة
يتضمن opencode عدة أوامر مضمنة مثل `/init` و`/undo` و`/redo` و`/share` و`/help`؛ [اعرف المزيد](/docs/tui#commands).
:::note
يمكن للأوامر المخصصة تجاوز الأوامر المضمنة.
:::
إذا عرّفت أمرًا مخصصًا بالاسم نفسه، فسيستبدل الأمر المضمن.

View File

@@ -0,0 +1,684 @@
---
title: الإعدادات
description: استخدام ملف إعدادات OpenCode بصيغة JSON.
---
يمكنك ضبط OpenCode باستخدام ملف إعدادات بصيغة JSON.
---
## التنسيق
يدعم OpenCode تنسيقي **JSON** و**JSONC** (JSON مع تعليقات).
```jsonc title="opencode.jsonc"
{
"$schema": "https://opencode.ai/config.json",
// Theme configuration
"theme": "opencode",
"model": "anthropic/claude-sonnet-4-5",
"autoupdate": true,
}
```
---
## المواقع
يمكنك وضع ملف الإعدادات في عدة مواقع مختلفة، ولكل موقع
ترتيب أولوية مختلف.
:::note
تُدمَج ملفات الإعدادات **معًا** ولا تُستبدَل.
:::
تُدمَج ملفات الإعدادات معًا ولا تُستبدَل. يتم جمع الإعدادات من مواقع الإعدادات التالية. تتجاوز الإعدادات اللاحقة الإعدادات السابقة فقط عند تعارض المفاتيح. أما الإعدادات غير المتعارضة فتبقى محفوظة من جميع الملفات.
على سبيل المثال، إذا كان الإعداد العام يضبط `theme: "opencode"` و`autoupdate: true`، وكان إعداد المشروع يضبط `model: "anthropic/claude-sonnet-4-5"`، فستتضمن الإعدادات النهائية الخيارات الثلاثة جميعها.
---
### ترتيب الأولوية
تُحمَّل مصادر الإعدادات بهذا الترتيب (المصادر اللاحقة تتجاوز السابقة):
1. **الإعدادات البعيدة** (من `.well-known/opencode`) - الإعدادات الافتراضية على مستوى المؤسسة
2. **الإعدادات العامة** (`~/.config/opencode/opencode.json`) - تفضيلات المستخدم
3. **إعدادات مخصصة** (`OPENCODE_CONFIG` env var) - تجاوزات مخصصة
4. **إعدادات المشروع** (`opencode.json` داخل المشروع) - إعدادات خاصة بالمشروع
5. **أدلة `.opencode`** - الوكلاء، الأوامر، الإضافات
6. **إعدادات ضمنية** (`OPENCODE_CONFIG_CONTENT` env var) - تجاوزات وقت التشغيل
هذا يعني أن إعدادات المشروع يمكنها تجاوز الإعدادات العامة، وأن الإعدادات العامة يمكنها تجاوز الإعدادات الافتراضية البعيدة على مستوى المؤسسة.
:::note
يستخدم الدليلان `.opencode` و`~/.config/opencode` **أسماء جمع** للأدلة الفرعية: `agents/` و`commands/` و`modes/` و`plugins/` و`skills/` و`tools/` و`themes/`. كما تُدعَم أسماء المفرد (مثل `agent/`) للتوافق مع الإصدارات السابقة.
:::
---
### عن بُعد
يمكن للمؤسسات توفير إعدادات افتراضية عبر نقطة النهاية `.well-known/opencode`. يتم جلب ذلك تلقائيًا عندما تقوم بالمصادقة مع مزوّد يدعم هذه الميزة.
تُحمَّل الإعدادات البعيدة أولًا لتكون طبقة الأساس. ويمكن لجميع مصادر الإعدادات الأخرى (العامة، وإعدادات المشروع) تجاوز هذه القيم الافتراضية.
على سبيل المثال، إذا كانت مؤسستك توفر خوادم MCP معطّلة افتراضيًا:
```json title="Remote config from .well-known/opencode"
{
"mcp": {
"jira": {
"type": "remote",
"url": "https://jira.example.com/mcp",
"enabled": false
}
}
}
```
يمكنك تفعيل خوادم محددة في إعداداتك المحلية:
```json title="opencode.json"
{
"mcp": {
"jira": {
"type": "remote",
"url": "https://jira.example.com/mcp",
"enabled": true
}
}
}
```
---
### عام
ضع إعدادات OpenCode العامة في `~/.config/opencode/opencode.json`. استخدم الإعدادات العامة للتفضيلات على مستوى المستخدم مثل السمات، والمزوّدين، أو اختصارات المفاتيح.
تتجاوز الإعدادات العامة القيم الافتراضية البعيدة الخاصة بالمؤسسة.
---
### لكل مشروع
أضف `opencode.json` في جذر مشروعك. تمتلك إعدادات المشروع أعلى أولوية بين ملفات الإعدادات القياسية، إذ تتجاوز الإعدادات العامة والبعيدة معًا.
:::tip
ضع إعدادات المشروع الخاصة في جذر مشروعك.
:::
عند تشغيل OpenCode، يبحث عن ملف إعدادات في الدليل الحالي أو يصعد حتى أقرب دليل Git.
ومن الآمن أيضًا تضمينه في Git، كما يستخدم نفس المخطط الخاص بالإعدادات العامة.
---
### مسار مخصص
حدّد مسار ملف إعدادات مخصصًا باستخدام متغير البيئة `OPENCODE_CONFIG`.
```bash
export OPENCODE_CONFIG=/path/to/my/custom-config.json
opencode run "Hello world"
```
تُحمَّل الإعدادات المخصصة بين الإعدادات العامة وإعدادات المشروع ضمن ترتيب الأولوية.
---
### دليل مخصص
حدّد دليل إعدادات مخصصًا باستخدام متغير البيئة `OPENCODE_CONFIG_DIR`.
سيتم البحث داخل هذا الدليل عن الوكلاء والأوامر والأوضاع والإضافات تمامًا مثل
الدليل القياسي `.opencode`، ويجب أن يتبع نفس البنية.
```bash
export OPENCODE_CONFIG_DIR=/path/to/my/config-directory
opencode run "Hello world"
```
يُحمَّل الدليل المخصص بعد الإعدادات العامة وأدلة `.opencode`، لذلك **يمكنه تجاوز** إعداداتها.
---
## المخطط
يحتوي ملف الإعدادات على مخطط مُعرَّف في [**`opencode.ai/config.json`**](https://opencode.ai/config.json).
يفترض أن يتمكن محررك من التحقق والإكمال التلقائي اعتمادًا على هذا المخطط.
---
### TUI
يمكنك ضبط الإعدادات الخاصة بـ TUI عبر الخيار `tui`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"tui": {
"scroll_speed": 3,
"scroll_acceleration": {
"enabled": true
},
"diff_style": "auto"
}
}
```
الخيارات المتاحة:
- `scroll_acceleration.enabled` - تفعيل تسارع التمرير بأسلوب macOS. **له أولوية على `scroll_speed`.**
- `scroll_speed` - مُضاعِف سرعة تمرير مخصص (الافتراضي: `3`، الحد الأدنى: `1`). يتم تجاهله إذا كان `scroll_acceleration.enabled` مساويًا لـ `true`.
- `diff_style` - التحكم في عرض `diff`. القيمة `"auto"` تتكيف مع عرض الطرفية، و`"stacked"` تعرض عمودًا واحدًا دائمًا.
[تعرف على المزيد حول استخدام TUI هنا](/docs/tui).
---
### الخادم
يمكنك ضبط إعدادات الخادم لأوامر `opencode serve` و`opencode web` عبر الخيار `server`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"server": {
"port": 4096,
"hostname": "0.0.0.0",
"mdns": true,
"mdnsDomain": "myproject.local",
"cors": ["http://localhost:5173"]
}
}
```
الخيارات المتاحة:
- `port` - المنفذ الذي سيتم الاستماع عليه.
- `hostname` - اسم المضيف الذي سيتم الاستماع عليه. عند تفعيل `mdns` وعدم ضبط اسم مضيف، تكون القيمة الافتراضية `0.0.0.0`.
- `mdns` - تفعيل اكتشاف الخدمة عبر mDNS. يتيح ذلك للأجهزة الأخرى على الشبكة اكتشاف خادم OpenCode.
- `mdnsDomain` - اسم نطاق مخصص لخدمة mDNS. القيمة الافتراضية هي `opencode.local`. مفيد لتشغيل عدة نُسخ على نفس الشبكة.
- `cors` - أصول إضافية مسموح بها لـ CORS عند استخدام خادم HTTP من عميل يعتمد على المتصفح. يجب أن تكون القيم أصولًا كاملة (البروتوكول + المضيف + منفذ اختياري)، مثل `https://app.example.com`.
[تعرف على المزيد حول الخادم هنا](/docs/server).
---
### الأدوات
يمكنك إدارة الأدوات التي يمكن لـ LLM استخدامها عبر الخيار `tools`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"tools": {
"write": false,
"bash": false
}
}
```
[تعرف على المزيد حول الأدوات هنا](/docs/tools).
---
### النماذج
يمكنك ضبط المزوّدين والنماذج التي تريد استخدامها في إعدادات OpenCode عبر الخيارات `provider` و`model` و`small_model`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"provider": {},
"model": "anthropic/claude-sonnet-4-5",
"small_model": "anthropic/claude-haiku-4-5"
}
```
يضبط الخيار `small_model` نموذجًا منفصلًا للمهام الخفيفة مثل توليد العناوين. افتراضيًا يحاول OpenCode استخدام نموذج أقل تكلفة إذا كان متاحًا لدى مزوّدك، وإلا فسيعود إلى النموذج الرئيسي.
قد تتضمن خيارات المزوّد `timeout` و`setCacheKey`:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"anthropic": {
"options": {
"timeout": 600000,
"setCacheKey": true
}
}
}
}
```
- `timeout` - مهلة الطلب بالميلي ثانية (الافتراضي: 300000). اضبطه إلى `false` لتعطيله.
- `setCacheKey` - يضمن تعيين مفتاح التخزين المؤقت دائمًا للمزوّد المحدد.
يمكنك أيضًا ضبط [النماذج المحلية](/docs/models#local). [تعرف على المزيد](/docs/models).
---
#### خيارات خاصة بالمزوّد
يدعم بعض المزوّدين خيارات إعداد إضافية تتجاوز الإعدادات العامة مثل `timeout` و`apiKey`.
##### Amazon Bedrock
يدعم Amazon Bedrock إعدادات خاصة بـ AWS:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"amazon-bedrock": {
"options": {
"region": "us-east-1",
"profile": "my-aws-profile",
"endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com"
}
}
}
}
```
- `region` - منطقة AWS لـ Bedrock (الافتراضي: متغير البيئة `AWS_REGION` أو `us-east-1`)
- `profile` - ملف تعريف AWS المُسمّى من `~/.aws/credentials` (الافتراضي: متغير البيئة `AWS_PROFILE`)
- `endpoint` - عنوان URL لنقطة نهاية مخصصة لنقاط نهاية VPC. هذا اسم بديل للخيار العام `baseURL` باستخدام مصطلحات AWS. إذا تم تحديدهما معًا، تكون أولوية `endpoint` أعلى.
:::note
لرموز Bearer (`AWS_BEARER_TOKEN_BEDROCK` أو `/connect`) أولوية أعلى من المصادقة القائمة على ملف التعريف. راجع [أولوية المصادقة](/docs/providers#authentication-precedence) للتفاصيل.
:::
[تعرف على المزيد حول إعداد Amazon Bedrock](/docs/providers#amazon-bedrock).
---
### السمات
يمكنك ضبط السمة التي تريد استخدامها في إعدادات OpenCode عبر الخيار `theme`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"theme": ""
}
```
[تعرف على المزيد هنا](/docs/themes).
---
### الوكلاء
يمكنك ضبط وكلاء متخصصين لمهام محددة عبر الخيار `agent`.
```jsonc title="opencode.jsonc"
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"code-reviewer": {
"description": "Reviews code for best practices and potential issues",
"model": "anthropic/claude-sonnet-4-5",
"prompt": "You are a code reviewer. Focus on security, performance, and maintainability.",
"tools": {
// Disable file modification tools for review-only agent
"write": false,
"edit": false,
},
},
},
}
```
يمكنك أيضًا تعريف الوكلاء باستخدام ملفات markdown في `~/.config/opencode/agents/` أو `.opencode/agents/`. [تعرف على المزيد هنا](/docs/agents).
---
### الوكيل الافتراضي
يمكنك تعيين الوكيل الافتراضي باستخدام الخيار `default_agent`. يحدد ذلك أي وكيل سيتم استخدامه عندما لا يتم تحديد وكيل صراحةً.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"default_agent": "plan"
}
```
يجب أن يكون الوكيل الافتراضي وكيلًا أساسيًا (وليس وكيلًا فرعيًا). يمكن أن يكون وكيلًا مدمجًا مثل `"build"` أو `"plan"`، أو [وكيلًا مخصصًا](/docs/agents) قمت بتعريفه. إذا لم يكن الوكيل المحدد موجودًا أو كان وكيلًا فرعيًا، فسيعود OpenCode إلى `"build"` مع تحذير.
ينطبق هذا الإعداد على جميع الواجهات: TUI وCLI (`opencode run`) وتطبيق سطح المكتب وGitHub Action.
---
### المشاركة
يمكنك ضبط ميزة [share](/docs/share) عبر الخيار `share`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"share": "manual"
}
```
يقبل هذا الإعداد القيم التالية:
- `"manual"` - السماح بالمشاركة اليدوية عبر الأوامر (الافتراضي)
- `"auto"` - مشاركة المحادثات الجديدة تلقائيًا
- `"disabled"` - تعطيل المشاركة بالكامل
افتراضيًا تكون المشاركة في الوضع اليدوي، حيث تحتاج إلى مشاركة المحادثات صراحةً باستخدام الأمر `/share`.
---
### الأوامر
يمكنك ضبط أوامر مخصصة للمهام المتكررة عبر الخيار `command`.
```jsonc title="opencode.jsonc"
{
"$schema": "https://opencode.ai/config.json",
"command": {
"test": {
"template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.",
"description": "Run tests with coverage",
"agent": "build",
"model": "anthropic/claude-haiku-4-5",
},
"component": {
"template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.",
"description": "Create a new component",
},
},
}
```
يمكنك أيضًا تعريف الأوامر باستخدام ملفات markdown في `~/.config/opencode/commands/` أو `.opencode/commands/`. [تعرف على المزيد هنا](/docs/commands).
---
### اختصارات المفاتيح
يمكنك تخصيص اختصارات المفاتيح عبر الخيار `keybinds`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"keybinds": {}
}
```
[تعرف على المزيد هنا](/docs/keybinds).
---
### التحديث التلقائي
سيقوم OpenCode بتنزيل أي تحديثات جديدة تلقائيًا عند بدء التشغيل. يمكنك تعطيل ذلك عبر الخيار `autoupdate`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"autoupdate": false
}
```
إذا لم تكن تريد التحديثات لكنك تريد الإشعار عند توفر نسخة جديدة، فاضبط `autoupdate` على `"notify"`.
لاحظ أن هذا يعمل فقط إذا لم يتم تثبيته عبر مدير حزم مثل Homebrew.
---
### المنسّقات
يمكنك ضبط منسّقات الشفرة عبر الخيار `formatter`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"formatter": {
"prettier": {
"disabled": true
},
"custom-prettier": {
"command": ["npx", "prettier", "--write", "$FILE"],
"environment": {
"NODE_ENV": "development"
},
"extensions": [".js", ".ts", ".jsx", ".tsx"]
}
}
}
```
[تعرف على المزيد حول المنسّقات هنا](/docs/formatters).
---
### الأذونات
افتراضيًا يسمح opencode **بجميع العمليات** دون الحاجة إلى موافقة صريحة. يمكنك تغيير ذلك عبر الخيار `permission`.
على سبيل المثال، لضمان أن أداتي `edit` و`bash` تتطلبان موافقة المستخدم:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"edit": "ask",
"bash": "ask"
}
}
```
[تعرف على المزيد حول الأذونات هنا](/docs/permissions).
---
### ضغط السياق
يمكنك التحكم في سلوك ضغط السياق عبر الخيار `compaction`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"compaction": {
"auto": true,
"prune": true
}
}
```
- `auto` - ضغط الجلسة تلقائيًا عند امتلاء السياق (الافتراضي: `true`).
- `prune` - إزالة مخرجات الأدوات القديمة لتوفير الرموز (tokens) (الافتراضي: `true`).
---
### المراقِب
يمكنك ضبط أنماط التجاهل لمراقِب الملفات عبر الخيار `watcher`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"watcher": {
"ignore": ["node_modules/**", "dist/**", ".git/**"]
}
}
```
تتبع الأنماط صياغة `glob`. استخدم ذلك لاستبعاد الأدلة المزدحمة من مراقبة الملفات.
---
### خوادم MCP
يمكنك ضبط خوادم MCP التي تريد استخدامها عبر الخيار `mcp`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {}
}
```
[تعرف على المزيد هنا](/docs/mcp-servers).
---
### الإضافات
[الإضافات](/docs/plugins) توسّع OpenCode بأدوات وخُطافات وتكاملات مخصصة.
ضع ملفات الإضافات في `.opencode/plugins/` أو `~/.config/opencode/plugins/`. يمكنك أيضًا تحميل إضافات من npm عبر الخيار `plugin`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-helicone-session", "@my-org/custom-plugin"]
}
```
[تعرف على المزيد هنا](/docs/plugins).
---
### التعليمات
يمكنك ضبط التعليمات الخاصة بالنموذج الذي تستخدمه عبر الخيار `instructions`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"]
}
```
يقبل هذا مصفوفة من المسارات وأنماط `glob` لملفات التعليمات. [تعرف على المزيد
حول القواعد هنا](/docs/rules).
---
### المزوّدون المعطّلون
يمكنك تعطيل المزوّدين الذين يتم تحميلهم تلقائيًا عبر الخيار `disabled_providers`. هذا مفيد عندما تريد منع تحميل مزوّدين معينين حتى لو كانت بيانات الاعتماد الخاصة بهم متاحة.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"disabled_providers": ["openai", "gemini"]
}
```
:::note
الخيار `disabled_providers` له أولوية على `enabled_providers`.
:::
يقبل الخيار `disabled_providers` مصفوفة من معرفات المزوّدين. عند تعطيل مزوّد:
- لن يتم تحميله حتى لو كانت متغيرات البيئة مضبوطة.
- لن يتم تحميله حتى لو كانت مفاتيح API مضبوطة عبر الأمر `/connect`.
- لن تظهر نماذج هذا المزوّد في قائمة اختيار النموذج.
---
### المزوّدون المفعّلون
يمكنك تحديد قائمة سماح للمزوّدين عبر الخيار `enabled_providers`. عند ضبطه، سيتم تفعيل المزوّدين المحددين فقط وسيتم تجاهل البقية.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"enabled_providers": ["anthropic", "openai"]
}
```
هذا مفيد عندما تريد تقييد OpenCode لاستخدام مزوّدين محددين بدلًا من تعطيلهم واحدًا تلو الآخر.
:::note
الخيار `disabled_providers` له أولوية على `enabled_providers`.
:::
إذا ظهر مزوّد ضمن كل من `enabled_providers` و`disabled_providers`، تكون أولوية `disabled_providers` أعلى للتوافق مع الإصدارات السابقة.
---
### تجريبي
يحتوي المفتاح `experimental` على خيارات قيد التطوير النشط.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"experimental": {}
}
```
:::caution
الخيارات التجريبية غير مستقرة. قد تتغير أو تُزال دون إشعار.
:::
---
## المتغيرات
يمكنك استخدام استبدال المتغيرات في ملفات الإعدادات للإشارة إلى متغيرات البيئة ومحتويات الملفات.
---
### متغيرات البيئة
استخدم `{env:VARIABLE_NAME}` لاستبدال متغيرات البيئة:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"model": "{env:OPENCODE_MODEL}",
"provider": {
"anthropic": {
"models": {},
"options": {
"apiKey": "{env:ANTHROPIC_API_KEY}"
}
}
}
}
```
إذا لم يكن متغير البيئة مضبوطًا، فسيتم استبداله بسلسلة فارغة.
---
### الملفات
استخدم `{file:path/to/file}` لاستبدال محتويات ملف:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"instructions": ["./custom-instructions.md"],
"provider": {
"openai": {
"options": {
"apiKey": "{file:~/.secrets/openai-key}"
}
}
}
}
```
يمكن أن تكون مسارات الملفات:
- نسبية إلى دليل ملف الإعدادات
- أو مسارات مطلقة تبدأ بـ `/` أو `~`
يُفيد ذلك في:
- الاحتفاظ بالبيانات الحساسة مثل مفاتيح API في ملفات منفصلة.
- تضمين ملفات تعليمات كبيرة دون تشويش ملف الإعدادات.
- مشاركة مقتطفات إعدادات مشتركة عبر عدة ملفات إعدادات.

View File

@@ -0,0 +1,162 @@
---
title: الأدوات المخصصة
description: أنشئ أدوات يمكن لـ LLM استدعاؤها في opencode.
---
الأدوات المخصصة هي دوال تنشئها يمكن لـ LLM استدعاؤها أثناء المحادثات. تعمل جنبا إلى جنب مع [الأدوات المدمجة](/docs/tools) في opencode مثل `read` و`write` و`bash`.
---
## إنشاء أداة
تُعرّف الأدوات كملفات **TypeScript** أو **JavaScript**. لكن تعريف الأداة يمكنه استدعاء سكربتات مكتوبة **بأي لغة** — إذ تُستخدم TypeScript أو JavaScript فقط لتعريف الأداة نفسه.
---
### الموقع
يمكن تعريفها:
- محليا بوضعها في مجلد `.opencode/tools/` داخل مشروعك.
- أو عالميا بوضعها في `~/.config/opencode/tools/`.
---
### البنية
أسهل طريقة لإنشاء أدوات هي استخدام المساعد `tool()` الذي يوفر أمان الأنواع والتحقق.
```ts title=".opencode/tools/database.ts" {1}
import { tool } from "@opencode-ai/plugin"
export default tool({
description: "Query the project database",
args: {
query: tool.schema.string().describe("SQL query to execute"),
},
async execute(args) {
// Your database logic here
return `Executed query: ${args.query}`
},
})
```
يصبح **اسم الملف** هو **اسم الأداة**. المثال أعلاه ينشئ أداة باسم `database`.
---
#### عدة أدوات في ملف واحد
يمكنك أيضا تصدير عدة أدوات من ملف واحد. يصبح كل تصدير **أداة مستقلة** باسم **`<filename>_<exportname>`**:
```ts title=".opencode/tools/math.ts"
import { tool } from "@opencode-ai/plugin"
export const add = tool({
description: "Add two numbers",
args: {
a: tool.schema.number().describe("First number"),
b: tool.schema.number().describe("Second number"),
},
async execute(args) {
return args.a + args.b
},
})
export const multiply = tool({
description: "Multiply two numbers",
args: {
a: tool.schema.number().describe("First number"),
b: tool.schema.number().describe("Second number"),
},
async execute(args) {
return args.a * args.b
},
})
```
ينشئ هذا أداتين: `math_add` و`math_multiply`.
---
### الوسائط
يمكنك استخدام `tool.schema`، وهو في الأساس [Zod](https://zod.dev)، لتعريف أنواع الوسائط.
```ts "tool.schema"
args: {
query: tool.schema.string().describe("SQL query to execute")
}
```
يمكنك أيضا استيراد [Zod](https://zod.dev) مباشرة وإرجاع كائن عادي:
```ts {6}
import { z } from "zod"
export default {
description: "Tool description",
args: {
param: z.string().describe("Parameter description"),
},
async execute(args, context) {
// Tool implementation
return "result"
},
}
```
---
### السياق
تستقبل الأدوات سياقا حول الجلسة الحالية:
```ts title=".opencode/tools/project.ts" {8}
import { tool } from "@opencode-ai/plugin"
export default tool({
description: "Get project information",
args: {},
async execute(args, context) {
// Access context information
const { agent, sessionID, messageID, directory, worktree } = context
return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}`
},
})
```
استخدم `context.directory` لدليل العمل الخاص بالجلسة.
استخدم `context.worktree` لجذر شجرة العمل (worktree) في git.
---
## أمثلة
### كتابة أداة بلغة Python
يمكنك كتابة أدواتك بأي لغة تريدها. إليك مثالا يجمع رقمين باستخدام Python.
أولا، أنشئ الأداة كسكربت Python:
```python title=".opencode/tools/add.py"
import sys
a = int(sys.argv[1])
b = int(sys.argv[2])
print(a + b)
```
ثم أنشئ تعريف الأداة الذي يستدعيه:
```ts title=".opencode/tools/python-add.ts" {10}
import { tool } from "@opencode-ai/plugin"
import path from "path"
export default tool({
description: "Add two numbers using Python",
args: {
a: tool.schema.number().describe("First number"),
b: tool.schema.number().describe("Second number"),
},
async execute(args, context) {
const script = path.join(context.worktree, ".opencode/tools/add.py")
const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text()
return result.trim()
},
})
```
هنا نستخدم أداة [`Bun.$`](https://bun.com/docs/runtime/shell) لتشغيل سكربت Python.

View File

@@ -0,0 +1,73 @@
---
title: النظام البيئي
description: مشاريع وتكاملات مبنية باستخدام OpenCode.
---
مجموعة من مشاريع المجتمع المبنية على OpenCode.
:::note
هل تريد إضافة مشروع مرتبط بـ OpenCode إلى هذه القائمة؟ قدّم PR.
:::
يمكنك أيضا الاطلاع على [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) و [opencode.cafe](https://opencode.cafe)؛ وهو مجتمع يجمع روابط النظام البيئي والمجتمع.
---
## الإضافات
| الاسم | الوصف |
| --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | تشغيل جلسات OpenCode تلقائيا داخل بيئات Daytona معزولة مع مزامنة git ومعاينات حية |
| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | حقن ترويسات جلسة Helicone تلقائيا لتجميع الطلبات |
| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | حقن أنواع TypeScript/Svelte تلقائيا في قراءات الملفات باستخدام أدوات البحث |
| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | استخدام اشتراك ChatGPT Plus/Pro بدلا من أرصدة واجهة API |
| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | استخدام خطة Gemini الحالية بدلا من فوترة API |
| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | استخدام نماذج Antigravity المجانية بدلا من فوترة API |
| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | عزل devcontainer متعدد الفروع مع استنساخات shallow ومنافذ تُعيَّن تلقائيا |
| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | ملحق Google Antigravity OAuth مع دعم Google Search ومعالجة API أكثر متانة |
| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | تحسين استخدام الرموز (tokens) عبر تقليم مخرجات الأدوات القديمة |
| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | إضافة دعم websearch أصلي للمزوّدين المدعومين بأسلوب مستند إلى Google |
| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | تمكين وكلاء الذكاء الاصطناعي من تشغيل عمليات بالخلفية داخل PTY وإرسال إدخال تفاعلي إليها. |
| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | إرشادات لأوامر shell غير التفاعلية - تمنع التعليق الناتج عن عمليات تعتمد على TTY |
| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | تتبع استخدام OpenCode عبر Wakatime |
| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | تنظيف جداول Markdown التي تنتجها نماذج LLM |
| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | تحرير الشيفرة أسرع بـ 10x باستخدام Morph Fast Apply API وعلامات تعديل كسولة |
| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | وكلاء خلفية وأدوات LSP/AST/MCP جاهزة ووكلاء منتقون وتوافق مع Claude Code |
| [opencode-notificator](https://github.com/panta82/opencode-notificator) | إشعارات سطح المكتب وتنبيهات صوتية لجلسات OpenCode |
| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | إشعارات سطح المكتب وتنبيهات صوتية لأحداث الأذونات والإكمال والأخطاء |
| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | تسمية جلسات Zellij تلقائيا بالاعتماد على سياق OpenCode وبمساعدة الذكاء الاصطناعي |
| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | تمكين وكلاء OpenCode من تحميل الموجهات عند الطلب عبر اكتشاف المهارات وحقنها |
| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | ذاكرة مستمرة عبر الجلسات باستخدام Supermemory |
| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | مراجعة تفاعلية للخطة مع تعليقات توضيحية مرئية ومشاركة خاصة/دون اتصال |
| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | توسيع /commands في opencode إلى نظام تنسيق قوي مع تحكم دقيق في التدفق |
| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | جدولة مهام متكررة باستخدام launchd (Mac) أو systemd (Linux) بصياغة cron |
| [micode](https://github.com/vtemian/micode) | سير عمل منظم: عصف ذهني → خطة → تنفيذ مع استمرارية الجلسة |
| [octto](https://github.com/vtemian/octto) | واجهة متصفح تفاعلية للعصف الذهني بالذكاء الاصطناعي مع نماذج متعددة الأسئلة |
| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | وكلاء خلفية على نمط Claude Code مع تفويض غير متزامن واستمرارية للسياق |
| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | إشعارات نظام تشغيل أصلية لـ OpenCode - اعرف متى تكتمل المهام |
| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | حزمة تنسيق متعددة الوكلاء - 16 مكوّنا، تثبيت واحد |
| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | git worktrees بلا تعقيد لـ OpenCode |
---
## المشاريع
| الاسم | الوصف |
| ------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------- |
| [kimaki](https://github.com/remorses/kimaki) | بوت Discord للتحكم بجلسات OpenCode، مبني على SDK |
| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | ملحق Neovim لموجهات تراعي المحرر، مبني على API |
| [portal](https://github.com/hosenur/portal) | واجهة ويب تركز على الجوال لـ OpenCode عبر Tailscale/VPN |
| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | قالب لبناء ملحقات OpenCode |
| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | واجهة Neovim لـ opencode - وكيل برمجة بالذكاء الاصطناعي يعمل في الطرفية |
| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | موفر Vercel AI SDK لاستخدام OpenCode عبر @opencode-ai/sdk |
| [OpenChamber](https://github.com/btriapitsyn/openchamber) | تطبيق ويب/سطح مكتب وامتداد VS Code لـ OpenCode |
| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | ملحق Obsidian يدمج OpenCode داخل واجهة Obsidian |
| [OpenWork](https://github.com/different-ai/openwork) | بديل مفتوح المصدر لـ Claude Cowork، مدعوم بـ OpenCode |
| [ocx](https://github.com/kdcokenny/ocx) | مدير امتدادات OpenCode مع ملفات تعريف محمولة ومعزولة. |
| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | تطبيق عميل لسطح المكتب والويب والجوال وعن بُعد لـ OpenCode |
---
## الوكلاء
| الاسم | الوصف |
| ----------------------------------------------------------------- | --------------------------------------------- |
| [Agentic](https://github.com/Cluster444/agentic) | وكلاء وأوامر ذكاء اصطناعي معيارية لتطوير منظم |
| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | إعدادات وموجهات ووكلاء وملحقات لسير عمل محسّن |

View File

@@ -0,0 +1,165 @@
---
title: المؤسسات
description: استخدام OpenCode بأمان داخل مؤسستك.
---
import config from "../../../../config.mjs"
export const email = `mailto:${config.email}`
OpenCode Enterprise مخصص للمؤسسات التي تريد التأكد من أن الشيفرة والبيانات لا تغادر بنيتها التحتية مطلقا. ويمكن تحقيق ذلك عبر استخدام إعدادات مركزية تتكامل مع SSO وبوابة AI الداخلية لديك.
:::note
لا يقوم OpenCode بتخزين أي من شيفرتك أو بيانات السياق.
:::
لبدء استخدام OpenCode Enterprise:
1. أجرِ تجربة داخلية مع فريقك.
2. **<a href={email}>اتصل بنا</a>** لمناقشة التسعير وخيارات التنفيذ.
---
## تجربة
OpenCode مفتوح المصدر ولا يخزن أي من شيفرتك أو بيانات السياق، لذا يمكن للمطورين لديك ببساطة [البدء](/docs/) وإجراء تجربة.
---
### التعامل مع البيانات
**لا يقوم OpenCode بتخزين شيفرتك أو بيانات السياق.** تتم جميع المعالجة محليا أو عبر استدعاءات API مباشرة إلى مزود AI لديك.
وهذا يعني أنه طالما أنك تستخدم مزودا تثق به، أو بوابة AI داخلية، يمكنك استخدام OpenCode بأمان.
الاستثناء الوحيد هنا هو ميزة `/share` الاختيارية.
---
#### مشاركة المحادثات
إذا فعّل المستخدم ميزة `/share`، فسيتم إرسال المحادثة والبيانات المرتبطة بها إلى الخدمة التي نستخدمها لاستضافة صفحات المشاركة هذه على opencode.ai.
يتم تقديم البيانات حاليا عبر شبكة الحافة الخاصة بـ CDN لدينا، وتُخزّن مؤقتا على الحافة بالقرب من مستخدميك.
نوصي بتعطيل ذلك أثناء التجربة.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"share": "disabled"
}
```
[تعرّف على المزيد حول المشاركة](/docs/share).
---
### ملكية الشيفرة
**أنت تملك كل الشيفرة التي ينتجها OpenCode.** لا توجد قيود ترخيص أو مطالبات بالملكية.
---
## التسعير
نستخدم نموذج تسعير لكل مقعد في OpenCode Enterprise. إذا كانت لديك بوابة LLM خاصة بك، فلن نفرض رسوما على الرموز (tokens) المستخدمة. لمزيد من التفاصيل حول التسعير وخيارات التنفيذ، **<a href={email}>اتصل بنا</a>**.
---
## النشر
بعد إكمال التجربة وعندما تكون جاهزا لاستخدام OpenCode داخل مؤسستك، يمكنك **<a href={email}>الاتصال بنا</a>** لمناقشة التسعير وخيارات التنفيذ.
---
### الإعدادات المركزية
يمكننا إعداد OpenCode لاستخدام إعدادات مركزية واحدة لكامل مؤسستك.
يمكن لهذه الإعدادات المركزية أن تتكامل مع مزود SSO لديك، وتضمن أن جميع المستخدمين يصلون فقط إلى بوابة AI الداخلية لديك.
---
### تكامل SSO
عبر الإعدادات المركزية، يمكن لـ OpenCode التكامل مع مزود SSO في مؤسستك لأغراض المصادقة.
يتيح ذلك لـ OpenCode الحصول على بيانات الاعتماد لبوابة AI الداخلية لديك عبر نظام إدارة الهوية الحالي لديك.
---
### بوابة AI الداخلية
مع الإعدادات المركزية، يمكن أيضا تهيئة OpenCode لاستخدام بوابة AI الداخلية لديك فقط.
يمكنك أيضا تعطيل جميع مزودي AI الآخرين، لضمان مرور جميع الطلبات عبر البنية التحتية المعتمدة في مؤسستك.
---
### الاستضافة الذاتية
بينما نوصي بتعطيل صفحات المشاركة لضمان ألا تغادر بياناتك مؤسستك مطلقا، يمكننا أيضا مساعدتك على استضافتها ذاتيا على بنيتك التحتية.
هذا موجود حاليا على خارطة طريقنا. إذا كنت مهتما، **<a href={email}>أخبرنا</a>**.
---
## الأسئلة الشائعة
<details>
<summary>ما هو OpenCode Enterprise؟</summary>
OpenCode Enterprise مخصص للمؤسسات التي تريد التأكد من أن الشيفرة والبيانات لا تغادر بنيتها التحتية مطلقا. ويمكن تحقيق ذلك عبر استخدام إعدادات مركزية تتكامل مع SSO وبوابة AI الداخلية لديك.
</details>
<details>
<summary>كيف أبدأ باستخدام OpenCode Enterprise؟</summary>
ابدأ ببساطة بتجربة داخلية مع فريقك. لا يقوم OpenCode افتراضيا بتخزين شيفرتك أو بيانات السياق، مما يجعل البدء سهلا.
ثم **<a href={email}>اتصل بنا</a>** لمناقشة التسعير وخيارات التنفيذ.
</details>
<details>
<summary>كيف يعمل تسعير المؤسسات؟</summary>
نقدم تسعيرا للمؤسسات لكل مقعد. إذا كانت لديك بوابة LLM خاصة بك، فلن نفرض رسوما على الرموز (tokens) المستخدمة. لمزيد من التفاصيل، **<a href={email}>اتصل بنا</a>** للحصول على عرض سعر مخصص بناء على احتياجات مؤسستك.
</details>
<details>
<summary>هل بياناتي آمنة مع OpenCode Enterprise؟</summary>
نعم. لا يقوم OpenCode بتخزين شيفرتك أو بيانات السياق. تتم جميع المعالجة محليا أو عبر استدعاءات API مباشرة إلى مزود AI لديك. ومع الإعدادات المركزية وتكامل SSO، تظل بياناتك آمنة داخل البنية التحتية لمؤسستك.
</details>
<details>
<summary>هل يمكننا استخدام سجل NPM خاص بنا؟</summary>
يدعم OpenCode سجلات npm الخاصة عبر دعم Bun الأصلي لملف `.npmrc`. إذا كانت مؤسستك تستخدم سجلا خاصا مثل JFrog Artifactory أو Nexus أو ما شابه ذلك، فتأكد من مصادقة المطورين قبل تشغيل OpenCode.
لإعداد المصادقة مع السجل الخاص بك:
```bash
npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/
```
سيؤدي ذلك إلى إنشاء `~/.npmrc` مع تفاصيل المصادقة. سيلتقط OpenCode هذا تلقائيا.
:::caution
يجب أن تكون مسجلا الدخول إلى السجل الخاص قبل تشغيل OpenCode.
:::
بدلا من ذلك، يمكنك تهيئة ملف `.npmrc` يدويا:
```bash title="~/.npmrc"
registry=https://your-company.jfrog.io/api/npm/npm-virtual/
//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN}
```
يجب أن يكون المطورون مسجلين الدخول إلى السجل الخاص قبل تشغيل OpenCode لضمان إمكانية تثبيت الحزم من سجل مؤسستك.
</details>

View File

@@ -0,0 +1,130 @@
---
title: المُنسِّقات
description: يستخدم OpenCode مُنسِّقات خاصة بكل لغة.
---
يُنسِّق OpenCode الملفات تلقائيا بعد كتابتها أو تعديلها باستخدام مُنسِّقات خاصة بكل لغة. يضمن ذلك أن الشيفرة التي يتم توليدها تتبع أساليب التنسيق المعتمدة في مشروعك.
---
## مُضمَّنة
يأتي OpenCode مع عدة مُنسِّقات مُضمَّنة للغات وأطر العمل الشائعة. فيما يلي قائمة بالمُنسِّقات وامتدادات الملفات المدعومة والأوامر أو خيارات الإعداد التي تحتاجها.
| المُنسِّق | الامتدادات | المتطلبات |
| -------------------- | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| gofmt | .go | يتوفر أمر `gofmt` |
| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | يتوفر أمر `mix` |
| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml، و[غير ذلك](https://prettier.io/docs/en/index.html) | وجود اعتماد `prettier` في `package.json` |
| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml، و[غير ذلك](https://biomejs.dev/) | ملف إعداد `biome.json(c)` |
| zig | .zig, .zon | يتوفر أمر `zig` |
| clang-format | .c, .cpp, .h, .hpp, .ino، و[غير ذلك](https://clang.llvm.org/docs/ClangFormat.html) | ملف إعداد `.clang-format` |
| ktlint | .kt, .kts | يتوفر أمر `ktlint` |
| ruff | .py, .pyi | يتوفر أمر `ruff` مع إعداد |
| rustfmt | .rs | يتوفر أمر `rustfmt` |
| cargofmt | .rs | يتوفر أمر `cargo fmt` |
| uv | .py, .pyi | يتوفر أمر `uv` |
| rubocop | .rb, .rake, .gemspec, .ru | يتوفر أمر `rubocop` |
| standardrb | .rb, .rake, .gemspec, .ru | يتوفر أمر `standardrb` |
| htmlbeautifier | .erb, .html.erb | يتوفر أمر `htmlbeautifier` |
| air | .R | يتوفر أمر `air` |
| dart | .dart | يتوفر أمر `dart` |
| ocamlformat | .ml, .mli | يتوفر أمر `ocamlformat` وملف إعداد `.ocamlformat` |
| terraform | .tf, .tfvars | يتوفر أمر `terraform` |
| gleam | .gleam | يتوفر أمر `gleam` |
| nixfmt | .nix | يتوفر أمر `nixfmt` |
| shfmt | .sh, .bash | يتوفر أمر `shfmt` |
| pint | .php | وجود اعتماد `laravel/pint` في `composer.json` |
| oxfmt (Experimental) | .js, .jsx, .ts, .tsx | وجود اعتماد `oxfmt` في `package.json` و[علم متغير بيئة تجريبي](/docs/cli/#experimental) |
| ormolu | .hs | يتوفر أمر `ormolu` |
لذا إذا كان مشروعك يتضمن `prettier` ضمن `package.json`، فسيستخدمه OpenCode تلقائيا.
---
## كيف يعمل
عندما يكتب OpenCode ملفا أو يحرره، فإنه:
1. يتحقق من امتداد الملف مقابل جميع المُنسِّقات المفعّلة.
2. يشغّل أمر المُنسِّق المناسب على الملف.
3. يطبق تغييرات التنسيق تلقائيا.
تتم هذه العملية في الخلفية لضمان الحفاظ على أساليب تنسيق الشيفرة دون أي خطوات يدوية.
---
## الإعداد
يمكنك تخصيص المُنسِّقات عبر قسم `formatter` في إعدادات OpenCode.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"formatter": {}
}
```
يدعم إعداد كل مُنسِّق ما يلي:
| الخاصية | النوع | الوصف |
| ------------- | -------- | ------------------------------------------------------ |
| `disabled` | boolean | اضبطها على `true` لتعطيل المُنسِّق |
| `command` | string[] | الأمر الذي سيتم تشغيله للتنسيق |
| `environment` | object | متغيرات البيئة التي يتم ضبطها عند تشغيل المُنسِّق |
| `extensions` | string[] | امتدادات الملفات التي يجب أن يتعامل معها هذا المُنسِّق |
لنلقِ نظرة على بعض الأمثلة.
---
### تعطيل المُنسِّقات
لتعطيل **جميع** المُنسِّقات على مستوى عام، اضبط `formatter` على `false`:
```json title="opencode.json" {3}
{
"$schema": "https://opencode.ai/config.json",
"formatter": false
}
```
لتعطيل مُنسِّق **محدد**، اضبط `disabled` على `true`:
```json title="opencode.json" {5}
{
"$schema": "https://opencode.ai/config.json",
"formatter": {
"prettier": {
"disabled": true
}
}
}
```
---
### مُنسِّقات مخصّصة
يمكنك تجاوز المُنسِّقات المُضمَّنة أو إضافة مُنسِّقات جديدة عبر تحديد الأمر ومتغيرات البيئة وامتدادات الملفات:
```json title="opencode.json" {4-14}
{
"$schema": "https://opencode.ai/config.json",
"formatter": {
"prettier": {
"command": ["npx", "prettier", "--write", "$FILE"],
"environment": {
"NODE_ENV": "development"
},
"extensions": [".js", ".ts", ".jsx", ".tsx"]
},
"custom-markdown-formatter": {
"command": ["deno", "fmt", "$FILE"],
"extensions": [".md"]
}
}
}
```
سيتم استبدال **العنصر النائب `$FILE`** في الأمر بمسار الملف الذي يجري تنسيقه.

View File

@@ -0,0 +1,321 @@
---
title: GitHub
description: استخدم OpenCode في GitHub Issues وPull Requests.
---
يتكامل OpenCode مع سير عمل GitHub لديك. اذكر `/opencode` أو `/oc` في تعليقك، وسيقوم OpenCode بتنفيذ المهام داخل GitHub Actions runner لديك.
---
## الميزات
- **فرز Issues**: اطلب من OpenCode الاطلاع على Issue وشرحها لك.
- **إصلاح وتنفيذ**: اطلب من OpenCode إصلاح Issue أو تنفيذ ميزة. وسيعمل على فرع جديد ويقدّم PR يضم كل التغييرات.
- **آمن**: يعمل OpenCode داخل GitHub runners لديك.
---
## التثبيت
شغّل الأمر التالي داخل مشروع موجود في مستودع GitHub:
```bash
opencode github install
```
سيأخذك هذا خلال تثبيت GitHub app، وإنشاء workflow، وإعداد secrets.
---
### الإعداد اليدوي
أو يمكنك إعداده يدويًا.
1. **تثبيت GitHub app**
انتقل إلى [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent). تأكد من تثبيته على المستودع الهدف.
2. **إضافة الـworkflow**
أضف ملف الـworkflow التالي إلى `.github/workflows/opencode.yml` في مستودعك. تأكد من ضبط `model` المناسب ومفاتيح API المطلوبة ضمن `env`.
```yml title=".github/workflows/opencode.yml" {24,26}
name: opencode
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
opencode:
if: |
contains(github.event.comment.body, '/oc') ||
contains(github.event.comment.body, '/opencode')
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 1
persist-credentials: false
- name: Run OpenCode
uses: anomalyco/opencode/github@latest
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
model: anthropic/claude-sonnet-4-20250514
# share: true
# github_token: xxxx
```
3. **تخزين مفاتيح API ضمن secrets**
في **settings** الخاصة بالمؤسسة أو المشروع، وسّع **Secrets and variables** في الشريط الجانبي الأيسر ثم اختر **Actions**، وأضف مفاتيح API المطلوبة.
---
## الإعدادات
- `model`: النموذج الذي سيستخدمه OpenCode. يأخذ الصيغة `provider/model`. هذا **مطلوب**.
- `agent`: الـagent الذي سيتم استخدامه. يجب أن يكون agent أساسيًا. يعود افتراضيًا إلى `default_agent` من الإعدادات أو `"build"` إذا لم يُعثر عليه.
- `share`: هل تتم مشاركة جلسة OpenCode. القيمة الافتراضية **true** للمستودعات العامة.
- `prompt`: موجه مخصص اختياري لتجاوز السلوك الافتراضي. استخدمه لتخصيص كيفية معالجة OpenCode للطلبات.
- `token`: GitHub access token اختياري لتنفيذ عمليات مثل إنشاء التعليقات، وcommit للتغييرات، وفتح Pull Requests. افتراضيًا يستخدم OpenCode installation access token الخاص بـOpenCode GitHub App، لذا تظهر commits والتعليقات وPull Requests وكأنها صادرة من التطبيق.
بدلًا من ذلك، يمكنك استخدام [`GITHUB_TOKEN` المدمج](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) في GitHub Action runner دون تثبيت OpenCode GitHub App. فقط تأكد من منح الأذونات المطلوبة في الـworkflow:
```yaml
permissions:
id-token: write
contents: write
pull-requests: write
issues: write
```
يمكنك أيضًا استخدام [رموز الوصول الشخصية](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT) إن فضّلت ذلك.
---
## الأحداث المدعومة
يمكن تشغيل OpenCode عبر أحداث GitHub التالية:
| نوع الحدث | يتم تشغيله عبر | التفاصيل |
| ----------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------- |
| `issue_comment` | تعليق على Issue أو PR | اذكر `/opencode` أو `/oc` في تعليقك. يقرأ OpenCode السياق ويمكنه إنشاء فروع، وفتح PRs، أو الرد. |
| `pull_request_review_comment` | تعليق على أسطر كود محددة في PR | اذكر `/opencode` أو `/oc` أثناء مراجعة الكود. يستلم OpenCode مسار الملف وأرقام الأسطر وسياق الـdiff. |
| `issues` | فتح Issue أو تعديلها | تشغيل OpenCode تلقائيًا عند إنشاء Issues أو تعديلها. يتطلب إدخال `prompt`. |
| `pull_request` | فتح PR أو تحديثه | تشغيل OpenCode تلقائيًا عند فتح PRs أو مزامنتها أو إعادة فتحها. مفيد للمراجعات الآلية. |
| `schedule` | جدول يعتمد على Cron | تشغيل OpenCode وفق جدول. يتطلب إدخال `prompt`. يذهب الناتج إلى logs وPRs (لا يوجد Issue للتعليق عليها). |
| `workflow_dispatch` | تشغيل يدوي من واجهة GitHub | تشغيل OpenCode عند الطلب عبر Actions tab. يتطلب إدخال `prompt`. يذهب الناتج إلى logs وPRs. |
### مثال للجدولة
شغّل OpenCode وفق جدول لتنفيذ مهام آلية:
```yaml title=".github/workflows/opencode-scheduled.yml"
name: Scheduled OpenCode Task
on:
schedule:
- cron: "0 9 * * 1" # Every Monday at 9am UTC
jobs:
opencode:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write
pull-requests: write
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Run OpenCode
uses: anomalyco/opencode/github@latest
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
model: anthropic/claude-sonnet-4-20250514
prompt: |
Review the codebase for any TODO comments and create a summary.
If you find issues worth addressing, open an issue to track them.
```
بالنسبة لأحداث `schedule`، يكون إدخال `prompt` **مطلوبًا** لعدم وجود تعليق لاستخراج التعليمات منه. تعمل عمليات الـworkflow المجدولة دون سياق مستخدم للتحقق من الأذونات، لذا يجب أن يمنح الـworkflow صلاحيات `contents: write` و`pull-requests: write` إذا كنت تتوقع أن ينشئ OpenCode فروعًا أو PRs.
---
### مثال Pull Request
راجع PRs تلقائيًا عند فتحها أو تحديثها:
```yaml title=".github/workflows/opencode-review.yml"
name: opencode-review
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
jobs:
review:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
pull-requests: read
issues: read
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: anomalyco/opencode/github@latest
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
model: anthropic/claude-sonnet-4-20250514
use_github_token: true
prompt: |
Review this pull request:
- Check for code quality issues
- Look for potential bugs
- Suggest improvements
```
بالنسبة لأحداث `pull_request`، إذا لم يتم توفير `prompt`، فإن OpenCode يراجع Pull Request افتراضيًا.
---
### مثال فرز Issues
قم بفرز Issues الجديدة تلقائيًا. يقوم هذا المثال بتصفية الحسابات الأقدم من 30 يومًا لتقليل الرسائل المزعجة:
```yaml title=".github/workflows/opencode-triage.yml"
name: Issue Triage
on:
issues:
types: [opened]
jobs:
triage:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write
pull-requests: write
issues: write
steps:
- name: Check account age
id: check
uses: actions/github-script@v7
with:
script: |
const user = await github.rest.users.getByUsername({
username: context.payload.issue.user.login
});
const created = new Date(user.data.created_at);
const days = (Date.now() - created) / (1000 * 60 * 60 * 24);
return days >= 30;
result-encoding: string
- uses: actions/checkout@v6
if: steps.check.outputs.result == 'true'
with:
persist-credentials: false
- uses: anomalyco/opencode/github@latest
if: steps.check.outputs.result == 'true'
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
model: anthropic/claude-sonnet-4-20250514
prompt: |
Review this issue. If there's a clear fix or relevant docs:
- Provide documentation links
- Add error handling guidance for code examples
Otherwise, do not comment.
```
بالنسبة لأحداث `issues`، يكون إدخال `prompt` **مطلوبًا** لعدم وجود تعليق لاستخراج التعليمات منه.
---
## الموجهات المخصصة
قم بتجاوز الموجه الافتراضي لتخصيص سلوك OpenCode ضمن الـworkflow لديك.
```yaml title=".github/workflows/opencode.yml"
- uses: anomalyco/opencode/github@latest
with:
model: anthropic/claude-sonnet-4-5
prompt: |
Review this pull request:
- Check for code quality issues
- Look for potential bugs
- Suggest improvements
```
يفيد ذلك في فرض معايير مراجعة محددة، أو معايير كتابة الكود، أو مجالات تركيز تناسب مشروعك.
---
## أمثلة
إليك بعض الأمثلة على كيفية استخدام OpenCode في GitHub.
- **شرح Issue**
أضف هذا التعليق داخل GitHub Issue.
```
/opencode explain this issue
```
سيقرأ OpenCode كامل النقاش، بما في ذلك جميع التعليقات، ويرد بشرح واضح.
- **إصلاح Issue**
داخل GitHub Issue، اكتب:
```
/opencode fix this
```
وسيُنشئ OpenCode فرعًا جديدًا، وينفّذ التغييرات، ويفتح PR يتضمنها.
- **مراجعة PRs وإجراء تغييرات**
اترك التعليق التالي على GitHub PR.
```
Delete the attachment from S3 when the note is removed /oc
```
سينفّذ OpenCode التغيير المطلوب ويعمل له commit إلى نفس PR.
- **مراجعة أسطر كود محددة**
اترك تعليقًا مباشرة على أسطر الكود في تبويب "Files" داخل PR. يكتشف OpenCode تلقائيًا الملف وأرقام الأسطر وسياق الـdiff لتقديم ردود دقيقة.
```
[Comment on specific lines in Files tab]
/oc add error handling here
```
عند التعليق على أسطر محددة، يستلم OpenCode:
- الملف الدقيق الذي تتم مراجعته
- أسطر الكود المحددة
- سياق الـdiff المحيط
- معلومات أرقام الأسطر
يسمح ذلك بطلبات أكثر تحديدًا دون الحاجة لذكر مسارات الملفات أو أرقام الأسطر يدويًا.

View File

@@ -0,0 +1,195 @@
---
title: GitLab
description: استخدم OpenCode في مشكلات GitLab وطلبات الدمج.
---
يتكامل OpenCode مع سير عمل GitLab لديك عبر خط أنابيب GitLab CI/CD أو عبر GitLab Duo.
في كلتا الحالتين، سيعمل OpenCode على مشغّلات GitLab لديك.
---
## GitLab CI
يعمل OpenCode ضمن خط أنابيب GitLab عادي. يمكنك دمجه في الخط كمكوّن [CI](https://docs.gitlab.com/ee/ci/components/).
هنا نستخدم مكوّن CI/CD أنشأه المجتمع لـ OpenCode — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode).
---
### الميزات
- **استخدام إعدادات مخصّصة لكل مهمة**: يمكنك إعداد OpenCode باستخدام دليل إعدادات مخصّص، مثل `./config/#custom-directory`، لتفعيل الوظائف أو تعطيلها في كل تشغيل لـ OpenCode.
- **إعداد بسيط**: يقوم مكوّن CI بإعداد OpenCode في الخلفية؛ كل ما عليك هو إنشاء إعدادات OpenCode والمطالبة (prompt) الأولية.
- **مرن**: يدعم مكوّن CI عدة مُدخلات لتخصيص سلوكه.
---
### الإعداد
1. احفظ JSON مصادقة OpenCode كمتغيرات بيئة CI من نوع File ضمن **Settings** > **CI/CD** > **Variables**. تأكد من تعيينها على "Masked and hidden".
2. أضف ما يلي إلى ملف `.gitlab-ci.yml`.
```yaml title=".gitlab-ci.yml"
include:
- component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2
inputs:
config_dir: ${CI_PROJECT_DIR}/opencode-config
auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON
command: optional-custom-command
message: "Your prompt here"
```
لمزيد من المُدخلات وحالات الاستخدام، [اطّلع على الوثائق](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) الخاصة بهذا المكوّن.
---
## GitLab Duo
يتكامل OpenCode مع سير عمل GitLab لديك.
اذكر `@opencode` في تعليق، وسينفّذ OpenCode المهام ضمن خط أنابيب GitLab CI لديك.
---
### الميزات
- **فرز المشكلات**: اطلب من OpenCode النظر في مشكلة وشرحها لك.
- **الإصلاح والتنفيذ**: اطلب من OpenCode إصلاح مشكلة أو تنفيذ ميزة.
سيُنشئ فرعًا جديدًا ويرفع طلب دمج بالتغييرات.
- **آمن**: يعمل OpenCode على مشغّلات GitLab لديك.
---
### الإعداد
يعمل OpenCode ضمن خط أنابيب GitLab CI/CD لديك، وإليك ما ستحتاجه لإعداده:
:::tip
اطّلع على [**وثائق GitLab**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) للحصول على تعليمات محدّثة.
:::
1. قم بتهيئة بيئة GitLab لديك
2. أعد إعداد CI/CD
3. احصل على مفتاح API من مزوّد نموذج ذكاء اصطناعي
4. أنشئ حساب خدمة
5. اضبط متغيرات CI/CD
6. أنشئ ملف إعداد للتدفق، وإليك مثالًا:
<details>
<summary>إعدادات التدفق</summary>
```yaml
image: node:22-slim
commands:
- echo "Installing opencode"
- npm install --global opencode-ai
- echo "Installing glab"
- export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE
- apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/*
- curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash
- apt-get install --yes glab
- echo "Configuring glab"
- echo $GITLAB_HOST
- echo "Creating OpenCode auth configuration"
- mkdir --parents ~/.local/share/opencode
- |
cat > ~/.local/share/opencode/auth.json << EOF
{
"anthropic": {
"type": "api",
"key": "$ANTHROPIC_API_KEY"
}
}
EOF
- echo "Configuring git"
- git config --global user.email "opencode@gitlab.com"
- git config --global user.name "OpenCode"
- echo "Testing glab"
- glab issue list
- echo "Running OpenCode"
- |
opencode run "
You are an AI assistant helping with GitLab operations.
Context: $AI_FLOW_CONTEXT
Task: $AI_FLOW_INPUT
Event: $AI_FLOW_EVENT
Please execute the requested task using the available GitLab tools.
Be thorough in your analysis and provide clear explanations.
<important>
Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands.
If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it.
You don't need to commit or push up changes, those will be done automatically based on the file changes you make.
</important>
"
- git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF
- echo "Checking for git changes and pushing if any exist"
- |
if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then
echo "Git changes detected, adding and pushing..."
git add .
if git diff --cached --quiet; then
echo "No staged changes to commit"
else
echo "Committing changes to branch: $CI_WORKLOAD_REF"
git commit --message "Codex changes"
echo "Pushing changes up to $CI_WORKLOAD_REF"
git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF
echo "Changes successfully pushed"
fi
else
echo "No git changes detected, skipping push"
fi
variables:
- ANTHROPIC_API_KEY
- GITLAB_TOKEN_OPENCODE
- GITLAB_HOST
```
</details>
يمكنك الرجوع إلى [وثائق GitLab CLI agents](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) للحصول على تعليمات مفصلة.
---
### أمثلة
فيما يلي بعض الأمثلة على كيفية استخدام OpenCode في GitLab.
:::tip
يمكنك ضبطه لاستخدام عبارة تشغيل مختلفة عن `@opencode`.
:::
- **شرح مشكلة**
أضف هذا التعليق في مشكلة على GitLab.
```
@opencode explain this issue
```
سيقرأ OpenCode المشكلة ويرد بشرح واضح.
- **إصلاح مشكلة**
في مشكلة على GitLab، قل:
```
@opencode fix this
```
سيُنشئ OpenCode فرعًا جديدًا، وينفّذ التغييرات، ويفتح طلب دمج بالتغييرات.
- **مراجعة طلبات الدمج**
اترك التعليق التالي على طلب دمج في GitLab.
```
@opencode review this merge request
```
سيُراجع OpenCode طلب الدمج ويقدّم ملاحظات.

View File

@@ -0,0 +1,48 @@
---
title: IDE
description: امتداد OpenCode لـ VS Code و Cursor وغيرها من بيئات التطوير
---
يتكامل OpenCode مع VS Code و Cursor أو أي IDE يدعم الطرفية. ما عليك سوى تشغيل `opencode` في الطرفية للبدء.
---
## الاستخدام
- **تشغيل سريع**: استخدم `Cmd+Esc` (Mac) أو `Ctrl+Esc` (Windows/Linux) لفتح OpenCode في عرض طرفية مقسّم، أو للتركيز على جلسة طرفية موجودة إذا كانت قيد التشغيل بالفعل.
- **جلسة جديدة**: استخدم `Cmd+Shift+Esc` (Mac) أو `Ctrl+Shift+Esc` (Windows/Linux) لبدء جلسة طرفية جديدة لـ OpenCode حتى لو كانت هناك جلسة مفتوحة. يمكنك أيضا النقر على زر OpenCode في واجهة المستخدم.
- **وعي بالسياق**: شارك تلقائيا تحديدك الحالي أو تبويبك مع OpenCode.
- **اختصارات الإشارة إلى الملفات**: استخدم `Cmd+Option+K` (Mac) أو `Alt+Ctrl+K` (Linux/Windows) لإدراج مراجع الملفات. مثلا: `@File#L37-42`.
---
## التثبيت
لتثبيت OpenCode على VS Code والتفرعات الشائعة مثل Cursor و Windsurf و VSCodium:
1. افتح VS Code
2. افتح الطرفية المدمجة
3. شغّل `opencode` - سيتم تثبيت الامتداد تلقائيا
أما إذا كنت تريد استخدام IDE الخاص بك عند تشغيل `/editor` أو `/export` من واجهة TUI، فستحتاج إلى ضبط `export EDITOR="code --wait"`. [اعرف المزيد](/docs/tui/#editor-setup).
---
### التثبيت اليدوي
ابحث عن **OpenCode** في Extension Marketplace وانقر **Install**.
---
### استكشاف الأخطاء وإصلاحها
إذا فشل تثبيت الامتداد تلقائيا:
- تأكد من أنك تشغّل `opencode` داخل الطرفية المدمجة.
- تأكد من تثبيت واجهة سطر الأوامر (CLI) الخاصة بـ IDE لديك:
- لـ VS Code: أمر `code`
- لـ Cursor: أمر `cursor`
- لـ Windsurf: أمر `windsurf`
- لـ VSCodium: أمر `codium`
- إذا لم تكن مثبتة، شغّل `Cmd+Shift+P` (Mac) أو `Ctrl+Shift+P` (Windows/Linux) وابحث عن "Shell Command: Install 'code' command in PATH" (أو ما يعادله في IDE لديك)
- تأكد من أن VS Code لديه الصلاحية لتثبيت الامتدادات

View File

@@ -0,0 +1,343 @@
---
title: مقدمة
description: ابدأ باستخدام OpenCode.
---
import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console
[**OpenCode**](/) هو وكيل ترميز بالذكاء الاصطناعي مفتوح المصدر. يتوفر كواجهة طرفية، وتطبيق لسطح المكتب، أو إضافة لبيئة تطوير متكاملة (IDE).
![واجهة OpenCode الطرفية مع سمة opencode](../../../assets/lander/screenshot.png)
لنبدأ.
---
#### المتطلبات
لاستخدام OpenCode في الطرفية، ستحتاج إلى:
1. محاكي طرفية حديث مثل:
- [WezTerm](https://wezterm.org) متعدد المنصات
- [Alacritty](https://alacritty.org) متعدد المنصات
- [Ghostty](https://ghostty.org) على Linux وmacOS
- [Kitty](https://sw.kovidgoyal.net/kitty/) على Linux وmacOS
2. مفاتيح API لمزوّدي نماذج اللغة (LLM) الذين تريد استخدامهم.
---
## التثبيت
أسهل طريقة لتثبيت OpenCode هي عبر سكربت التثبيت.
```bash
curl -fsSL https://opencode.ai/install | bash
```
يمكنك أيضا تثبيته عبر الأوامر التالية:
- **باستخدام Node.js**
<Tabs>
<TabItem label="npm">
```bash
npm install -g opencode-ai
```
</TabItem>
<TabItem label="Bun">
```bash
bun install -g opencode-ai
```
</TabItem>
<TabItem label="pnpm">
```bash
pnpm install -g opencode-ai
```
</TabItem>
<TabItem label="Yarn">
```bash
yarn global add opencode-ai
```
</TabItem>
</Tabs>
- **باستخدام Homebrew على macOS وLinux**
```bash
brew install anomalyco/tap/opencode
```
> نوصي باستخدام tap الخاص بـ OpenCode للحصول على أحدث الإصدارات. صيغة `brew install opencode` الرسمية تُدار بواسطة فريق Homebrew ويتم تحديثها بوتيرة أقل.
- **باستخدام Paru على Arch Linux**
```bash
paru -S opencode-bin
```
#### Windows
:::tip[موصى به: استخدم WSL]
لأفضل تجربة على Windows، نوصي باستخدام [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). يوفر أداء أفضل وتوافقا كاملا مع ميزات OpenCode.
:::
- **باستخدام Chocolatey**
```bash
choco install opencode
```
- **باستخدام Scoop**
```bash
scoop install opencode
```
- **باستخدام NPM**
```bash
npm install -g opencode-ai
```
- **باستخدام Mise**
```bash
mise use -g github:anomalyco/opencode
```
- **باستخدام Docker**
```bash
docker run -it --rm ghcr.io/anomalyco/opencode
```
دعم تثبيت OpenCode على Windows باستخدام Bun قيد العمل حاليا.
يمكنك أيضا تنزيل الملف التنفيذي من صفحة [Releases](https://github.com/anomalyco/opencode/releases).
---
## الإعداد
مع OpenCode يمكنك استخدام أي مزود LLM عبر إعداد مفاتيح API الخاصة به.
إذا كنت جديدا على استخدام مزوّدي LLM، فنوصي باستخدام [OpenCode Zen](/docs/zen).
إنها قائمة منتقاة من النماذج تم اختبارها والتحقق منها بواسطة فريق OpenCode.
1. شغّل الأمر `/connect` في واجهة TUI، واختر opencode، ثم انتقل إلى [opencode.ai/auth](https://opencode.ai/auth).
```txt
/connect
```
2. سجّل الدخول، وأضف تفاصيل الدفع، ثم انسخ مفتاح API.
3. الصق مفتاح API.
```txt
┌ API key
└ enter
```
بدلا من ذلك يمكنك اختيار أحد المزوّدين الآخرين. [اعرف المزيد](/docs/providers#directory).
---
## التهيئة
بعد أن قمت بإعداد مزوّد، يمكنك الانتقال إلى المشروع الذي تريد العمل عليه.
```bash
cd /path/to/project
```
ثم شغّل OpenCode.
```bash
opencode
```
بعد ذلك، هيّئ OpenCode للمشروع عبر تشغيل الأمر التالي.
```bash frame="none"
/init
```
سيجعل هذا OpenCode يحلل مشروعك ويُنشئ ملف `AGENTS.md` في جذر المشروع.
:::tip
يستحسن أن تقوم بعمل commit لملف `AGENTS.md` الخاص بمشروعك إلى Git.
:::
يساعد هذا OpenCode على فهم بنية المشروع وأنماط الترميز المستخدمة.
---
## الاستخدام
أصبحت الآن جاهزا لاستخدام OpenCode للعمل على مشروعك. لا تتردد في سؤاله أي شيء!
إذا كنت جديدا على استخدام وكيل ترميز بالذكاء الاصطناعي، فإليك بعض الأمثلة التي قد تساعد.
---
### اطرح أسئلة
يمكنك أن تطلب من OpenCode شرح قاعدة الشيفرة لك.
:::tip
استخدم المفتاح `@` للبحث التقريبي عن الملفات داخل المشروع.
:::
```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```
يفيد هذا عندما تكون هناك أجزاء من قاعدة الشيفرة لم تعمل عليها.
---
### أضف ميزات
يمكنك أن تطلب من OpenCode إضافة ميزات جديدة إلى مشروعك، لكننا نوصي أولا بطلب إنشاء خطة.
1. **أنشئ خطة**
لدى OpenCode _وضع Plan_ يعطل قدرته على إجراء التغييرات، ويقترح بدلا من ذلك _كيف_ سينفّذ الميزة.
انتقل إليه باستخدام مفتاح **Tab**. سترى مؤشرا لذلك في الزاوية السفلية اليمنى.
```bash frame="none" title="Switch to Plan mode"
<TAB>
```
الآن لنصف ما نريده أن يفعله.
```txt frame="none"
When a user deletes a note, we'd like to flag it as deleted in the database.
Then create a screen that shows all the recently deleted notes.
From this screen, the user can undelete a note or permanently delete it.
```
احرص على تزويد OpenCode بتفاصيل كافية ليفهم ما تريد. يساعد أن تتحدث إليه كما لو كنت تتحدث إلى مطور مبتدئ ضمن فريقك.
:::tip
أعطِ OpenCode سياقا وأمثلة كافية لمساعدته على فهم ما تريد.
:::
2. **حسّن الخطة**
بعد أن يقدم لك خطة، يمكنك إعطاؤه ملاحظات أو إضافة تفاصيل أكثر.
```txt frame="none"
We'd like to design this new screen using a design I've used before.
[Image #1] Take a look at this image and use it as a reference.
```
:::tip
اسحب الصور وأفلِتها داخل الطرفية لإضافتها إلى الطلب.
:::
يستطيع OpenCode فحص أي صور تزوده بها وإضافتها إلى الطلب. يمكنك فعل ذلك عبر سحب الصورة وإفلاتها داخل الطرفية.
3. **ابنِ الميزة**
عندما تشعر بالارتياح للخطة، عد إلى _وضع Build_ بالضغط على مفتاح **Tab** مرة أخرى.
```bash frame="none"
<TAB>
```
ثم اطلب منه تنفيذ التغييرات.
```bash frame="none"
Sounds good! Go ahead and make the changes.
```
---
### نفّذ تغييرات
للتغييرات الأبسط، يمكنك أن تطلب من OpenCode تنفيذها مباشرة دون الحاجة لمراجعة خطة أولا.
```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```
تأكد من تقديم قدر مناسب من التفاصيل لكي يجري OpenCode التغييرات الصحيحة.
---
### تراجع عن التغييرات
لنفترض أنك طلبت من OpenCode إجراء بعض التغييرات.
```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```
لكن تتضح لك لاحقا أنها ليست ما تريده. يمكنك **التراجع** عن التغييرات باستخدام الأمر `/undo`.
```bash frame="none"
/undo
```
سيقوم OpenCode الآن بعكس التغييرات التي أُجريت ويعرض رسالتك الأصلية مجددا.
```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```
من هنا يمكنك تعديل الطلب وطلب المحاولة مرة أخرى.
:::tip
يمكنك تشغيل `/undo` عدة مرات للتراجع عن عدة تغييرات.
:::
أو يمكنك **إعادة تنفيذ** التغييرات باستخدام الأمر `/redo`.
```bash frame="none"
/redo
```
---
## المشاركة
يمكن [مشاركة المحادثات](/docs/share) التي تجريها مع OpenCode مع فريقك.
```bash frame="none"
/share
```
سيقوم هذا بإنشاء رابط للمحادثة الحالية ونسخه إلى الحافظة.
:::note
لا تتم مشاركة المحادثات افتراضيا.
:::
إليك [مثالا لمحادثة](https://opencode.ai/s/4XP1fce5) مع OpenCode.
---
## التخصيص
وهذا كل شيء! أصبحت الآن محترفا في استخدام OpenCode.
لتجعله مناسبا لك، نوصي بـ [اختيار سمة](/docs/themes)، و[تخصيص اختصارات لوحة المفاتيح](/docs/keybinds)، و[إعداد منسقات الشيفرة](/docs/formatters)، و[إنشاء أوامر مخصصة](/docs/commands)، أو التجربة مع [إعدادات OpenCode](/docs/config).

View File

@@ -0,0 +1,192 @@
---
title: اختصارات لوحة المفاتيح
description: خصّص اختصارات لوحة المفاتيح.
---
يوفّر OpenCode قائمة باختصارات لوحة المفاتيح يمكنك تخصيصها عبر إعدادات OpenCode.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"keybinds": {
"leader": "ctrl+x",
"app_exit": "ctrl+c,ctrl+d,<leader>q",
"editor_open": "<leader>e",
"theme_list": "<leader>t",
"sidebar_toggle": "<leader>b",
"scrollbar_toggle": "none",
"username_toggle": "none",
"status_view": "<leader>s",
"tool_details": "none",
"session_export": "<leader>x",
"session_new": "<leader>n",
"session_list": "<leader>l",
"session_timeline": "<leader>g",
"session_fork": "none",
"session_rename": "none",
"session_share": "none",
"session_unshare": "none",
"session_interrupt": "escape",
"session_compact": "<leader>c",
"session_child_cycle": "<leader>right",
"session_child_cycle_reverse": "<leader>left",
"session_parent": "<leader>up",
"messages_page_up": "pageup,ctrl+alt+b",
"messages_page_down": "pagedown,ctrl+alt+f",
"messages_line_up": "ctrl+alt+y",
"messages_line_down": "ctrl+alt+e",
"messages_half_page_up": "ctrl+alt+u",
"messages_half_page_down": "ctrl+alt+d",
"messages_first": "ctrl+g,home",
"messages_last": "ctrl+alt+g,end",
"messages_next": "none",
"messages_previous": "none",
"messages_copy": "<leader>y",
"messages_undo": "<leader>u",
"messages_redo": "<leader>r",
"messages_last_user": "none",
"messages_toggle_conceal": "<leader>h",
"model_list": "<leader>m",
"model_cycle_recent": "f2",
"model_cycle_recent_reverse": "shift+f2",
"model_cycle_favorite": "none",
"model_cycle_favorite_reverse": "none",
"variant_cycle": "ctrl+t",
"command_list": "ctrl+p",
"agent_list": "<leader>a",
"agent_cycle": "tab",
"agent_cycle_reverse": "shift+tab",
"input_clear": "ctrl+c",
"input_paste": "ctrl+v",
"input_submit": "return",
"input_newline": "shift+return,ctrl+return,alt+return,ctrl+j",
"input_move_left": "left,ctrl+b",
"input_move_right": "right,ctrl+f",
"input_move_up": "up",
"input_move_down": "down",
"input_select_left": "shift+left",
"input_select_right": "shift+right",
"input_select_up": "shift+up",
"input_select_down": "shift+down",
"input_line_home": "ctrl+a",
"input_line_end": "ctrl+e",
"input_select_line_home": "ctrl+shift+a",
"input_select_line_end": "ctrl+shift+e",
"input_visual_line_home": "alt+a",
"input_visual_line_end": "alt+e",
"input_select_visual_line_home": "alt+shift+a",
"input_select_visual_line_end": "alt+shift+e",
"input_buffer_home": "home",
"input_buffer_end": "end",
"input_select_buffer_home": "shift+home",
"input_select_buffer_end": "shift+end",
"input_delete_line": "ctrl+shift+d",
"input_delete_to_line_end": "ctrl+k",
"input_delete_to_line_start": "ctrl+u",
"input_backspace": "backspace,shift+backspace",
"input_delete": "ctrl+d,delete,shift+delete",
"input_undo": "ctrl+-,super+z",
"input_redo": "ctrl+.,super+shift+z",
"input_word_forward": "alt+f,alt+right,ctrl+right",
"input_word_backward": "alt+b,alt+left,ctrl+left",
"input_select_word_forward": "alt+shift+f,alt+shift+right",
"input_select_word_backward": "alt+shift+b,alt+shift+left",
"input_delete_word_forward": "alt+d,alt+delete,ctrl+delete",
"input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace",
"history_previous": "up",
"history_next": "down",
"terminal_suspend": "ctrl+z",
"terminal_title_toggle": "none",
"tips_toggle": "<leader>h",
"display_thinking": "none"
}
}
```
---
## مفتاح القائد
يستخدم OpenCode مفتاح `leader` لمعظم اختصارات لوحة المفاتيح. يساعد ذلك على تجنّب التعارضات في الطرفية لديك.
افتراضيا، يكون `ctrl+x` هو مفتاح القائد، وتتطلّب معظم الإجراءات أن تضغط أولا مفتاح القائد ثم الاختصار. على سبيل المثال، لبدء جلسة جديدة اضغط `ctrl+x` أولا ثم اضغط `n`.
لا يلزم استخدام مفتاح قائد لاختصاراتك، لكننا نوصي بذلك.
---
## تعطيل اختصار
يمكنك تعطيل أي اختصار بإضافة معرّف الاختصار إلى ملف الإعدادات بقيمة "none".
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"keybinds": {
"session_compact": "none"
}
}
```
---
## اختصارات موجّه سطح المكتب
يدعم حقل إدخال الموجّه في تطبيق OpenCode لسطح المكتب اختصارات شائعة لتحرير النص على نمط Readline/Emacs. هذه الاختصارات مدمجة حاليا ولا يمكن تخصيصها عبر `opencode.json`.
| الاختصار | الإجراء |
| -------- | ------------------------------------------ |
| `ctrl+a` | الانتقال إلى بداية السطر الحالي |
| `ctrl+e` | الانتقال إلى نهاية السطر الحالي |
| `ctrl+b` | تحريك المؤشر للخلف حرفا واحدا |
| `ctrl+f` | تحريك المؤشر للأمام حرفا واحدا |
| `alt+b` | تحريك المؤشر للخلف كلمة واحدة |
| `alt+f` | تحريك المؤشر للأمام كلمة واحدة |
| `ctrl+d` | حذف الحرف الموجود تحت المؤشر |
| `ctrl+k` | حذف حتى نهاية السطر |
| `ctrl+u` | حذف حتى بداية السطر |
| `ctrl+w` | حذف الكلمة السابقة |
| `alt+d` | حذف الكلمة التالية |
| `ctrl+t` | تبديل موضعي حرفين |
| `ctrl+g` | إلغاء النوافذ المنبثقة / إيقاف الرد الجاري |
---
## مفتاح Shift+Enter
بعض الطرفيات لا ترسل مفاتيح التعديل مع Enter افتراضيا. قد تحتاج إلى ضبط طرفيتك لإرسال `Shift+Enter` كسلسلة هروب.
### Windows Terminal
افتح ملف `settings.json` الموجود في:
```
%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json
```
أضف هذا إلى مصفوفة `actions` على مستوى الجذر:
```json
"actions": [
{
"command": {
"action": "sendInput",
"input": "\u001b[13;2u"
},
"id": "User.sendInput.ShiftEnterCustom"
}
]
```
أضف هذا إلى مصفوفة `keybindings` على مستوى الجذر:
```json
"keybindings": [
{
"keys": "shift+enter",
"id": "User.sendInput.ShiftEnterCustom"
}
]
```
احفظ الملف ثم أعد تشغيل Windows Terminal أو افتح علامة تبويب جديدة.

View File

@@ -0,0 +1,188 @@
---
title: خوادم LSP
description: يتكامل OpenCode مع خوادم LSP لديك.
---
يتكامل OpenCode مع بروتوكول خادم اللغة (LSP) لمساعدة النموذج اللغوي الكبير على التفاعل مع قاعدة الشيفرة لديك. ويستخدم التشخيصات لتزويد النموذج بتغذية راجعة.
---
## المدمجة
يأتي OpenCode مع عدة خوادم LSP مدمجة للغات الشائعة:
| خادم LSP | الامتدادات | المتطلبات |
| ------------------ | ------------------------------------------------------------------- | ---------------------------------------------------- |
| astro | .astro | يثبت تلقائيا لمشاريع Astro |
| bash | .sh, .bash, .zsh, .ksh | يثبت `bash-language-server` تلقائيا |
| clangd | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++ | يثبت تلقائيا لمشاريع C/C++ |
| csharp | .cs | تثبيت `.NET SDK` |
| clojure-lsp | .clj, .cljs, .cljc, .edn | توفر أمر `clojure-lsp` |
| dart | .dart | توفر أمر `dart` |
| deno | .ts, .tsx, .js, .jsx, .mjs | توفر أمر `deno` (يكتشف تلقائيا deno.json/deno.jsonc) |
| elixir-ls | .ex, .exs | توفر أمر `elixir` |
| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue | وجود تبعية `eslint` في المشروع |
| fsharp | .fs, .fsi, .fsx, .fsscript | تثبيت `.NET SDK` |
| gleam | .gleam | توفر أمر `gleam` |
| gopls | .go | توفر أمر `go` |
| hls | .hs, .lhs | توفر أمر `haskell-language-server-wrapper` |
| jdtls | .java | تثبيت `Java SDK (version 21+)` |
| kotlin-ls | .kt, .kts | يثبت تلقائيا لمشاريع Kotlin |
| lua-ls | .lua | يثبت تلقائيا لمشاريع Lua |
| nixd | .nix | توفر أمر `nixd` |
| ocaml-lsp | .ml, .mli | توفر أمر `ocamllsp` |
| oxlint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | وجود تبعية `oxlint` في المشروع |
| php intelephense | .php | يثبت تلقائيا لمشاريع PHP |
| prisma | .prisma | توفر أمر `prisma` |
| pyright | .py, .pyi | تثبيت تبعية `pyright` |
| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru | توفر أمري `ruby` و `gem` |
| rust | .rs | توفر أمر `rust-analyzer` |
| sourcekit-lsp | .swift, .objc, .objcpp | تثبيت `swift` (على macOS عبر `xcode`) |
| svelte | .svelte | يثبت تلقائيا لمشاريع Svelte |
| terraform | .tf, .tfvars | يثبت تلقائيا من إصدارات GitHub |
| tinymist | .typ, .typc | يثبت تلقائيا من إصدارات GitHub |
| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | وجود تبعية `typescript` في المشروع |
| vue | .vue | يثبت تلقائيا لمشاريع Vue |
| yaml-ls | .yaml, .yml | يثبت `yaml-language-server` من Red Hat تلقائيا |
| zls | .zig, .zon | توفر أمر `zig` |
تُفعَّل خوادم LSP تلقائيا عند اكتشاف أحد امتدادات الملفات المذكورة أعلاه واستيفاء المتطلبات.
:::note
يمكنك تعطيل تنزيلات خوادم LSP التلقائية عبر ضبط متغير البيئة `OPENCODE_DISABLE_LSP_DOWNLOAD` على `true`.
:::
---
## كيف يعمل
عندما يفتح opencode ملفا، فإنه:
1. يفحص امتداد الملف مقابل جميع خوادم LSP المفعّلة.
2. يشغّل خادم LSP المناسب إذا لم يكن قيد التشغيل بالفعل.
---
## الإعداد
يمكنك تخصيص خوادم LSP عبر قسم `lsp` في إعدادات opencode.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"lsp": {}
}
```
يدعم كل خادم LSP ما يلي:
| الخاصية | النوع | الوصف |
| ---------------- | -------- | ------------------------------------------------- |
| `disabled` | boolean | اضبطها على `true` لتعطيل خادم LSP |
| `command` | string[] | الأمر المستخدم لتشغيل خادم LSP |
| `extensions` | string[] | امتدادات الملفات التي يجب أن يعالجها خادم LSP هذا |
| `env` | object | متغيرات البيئة التي تُضبط عند تشغيل الخادم |
| `initialization` | object | خيارات التهيئة التي تُرسل إلى خادم LSP |
لنلق نظرة على بعض الأمثلة.
---
### متغيرات البيئة
استخدم الخاصية `env` لضبط متغيرات البيئة عند تشغيل خادم LSP:
```json title="opencode.json" {5-7}
{
"$schema": "https://opencode.ai/config.json",
"lsp": {
"rust": {
"env": {
"RUST_LOG": "debug"
}
}
}
}
```
---
### خيارات التهيئة
استخدم الخاصية `initialization` لتمرير خيارات التهيئة إلى خادم LSP. هذه إعدادات خاصة بالخادم تُرسل أثناء طلب LSP `initialize`:
```json title="opencode.json" {5-9}
{
"$schema": "https://opencode.ai/config.json",
"lsp": {
"typescript": {
"initialization": {
"preferences": {
"importModuleSpecifierPreference": "relative"
}
}
}
}
}
```
:::note
تختلف خيارات التهيئة بحسب خادم LSP. راجع توثيق خادم LSP لديك لمعرفة الخيارات المتاحة.
:::
---
### تعطيل خوادم LSP
لتعطيل **جميع** خوادم LSP على مستوى التطبيق، اضبط `lsp` على `false`:
```json title="opencode.json" {3}
{
"$schema": "https://opencode.ai/config.json",
"lsp": false
}
```
لتعطيل خادم LSP **بعينه**، اضبط `disabled` على `true`:
```json title="opencode.json" {5}
{
"$schema": "https://opencode.ai/config.json",
"lsp": {
"typescript": {
"disabled": true
}
}
}
```
---
### خوادم LSP مخصصة
يمكنك إضافة خوادم LSP مخصصة عبر تحديد الأمر وامتدادات الملفات:
```json title="opencode.json" {4-7}
{
"$schema": "https://opencode.ai/config.json",
"lsp": {
"custom-lsp": {
"command": ["custom-lsp-server", "--stdio"],
"extensions": [".custom"]
}
}
}
```
---
## معلومات إضافية
### PHP Intelephense
يوفر PHP Intelephense ميزات مدفوعة عبر مفتاح ترخيص. يمكنك تزويده بمفتاح الترخيص عبر وضع (فقط) المفتاح داخل ملف نصي في:
- على macOS/Linux: `$HOME/intelephense/licence.txt`
- على Windows: `%USERPROFILE%/intelephense/licence.txt`
يجب أن يحتوي الملف على مفتاح الترخيص فقط دون أي محتوى إضافي.

View File

@@ -0,0 +1,492 @@
---
title: خوادم MCP
description: أضف أدوات MCP محلية وبعيدة.
---
يمكنك إضافة أدوات خارجية إلى OpenCode باستخدام _Model Context Protocol_، أو MCP. يدعم OpenCode خوادم محلية وبعيدة.
بعد إضافتها، تصبح أدوات MCP متاحة تلقائيا للـ LLM إلى جانب الأدوات المضمنة.
---
#### تنبيهات
عند استخدام خادم MCP فإنه يضيف إلى السياق. وقد يتراكم ذلك بسرعة إذا كان لديك الكثير من الأدوات. لذلك نوصي بالتحلّي بالحذر عند اختيار خوادم MCP التي تستخدمها.
:::tip
تضيف خوادم MCP إلى سياقك، لذا احرص على اختيار ما تفعّله منها بعناية.
:::
تميل بعض خوادم MCP، مثل خادم GitHub MCP، إلى إضافة الكثير من الرموز (tokens) وقد تتجاوز حد السياق بسهولة.
---
## التمكين
يمكنك تعريف خوادم MCP في [إعدادات OpenCode](https://opencode.ai/docs/config/) ضمن `mcp`. أضف كل خادم MCP باسم فريد. ويمكنك الإشارة إلى ذلك الخادم بالاسم عند توجيه الطلب إلى الـ LLM.
```jsonc title="opencode.jsonc" {6}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"name-of-mcp-server": {
// ...
"enabled": true,
},
"name-of-other-mcp-server": {
// ...
},
},
}
```
يمكنك أيضا تعطيل خادم عبر ضبط `enabled` على `false`. يفيد ذلك إذا أردت تعطيله مؤقتا دون إزالته من إعداداتك.
---
### تجاوز القيم الافتراضية البعيدة
يمكن للمنظمات توفير خوادم MCP الافتراضية عبر نقطة النهاية `.well-known/opencode` الخاصة بها. قد تكون هذه الخوادم معطّلة افتراضيا، مما يتيح للمستخدمين تفعيل ما يحتاجونه فقط.
لتفعيل خادم معيّن من الإعدادات البعيدة الخاصة بمؤسستك، أضفه إلى إعداداتك المحلية مع `enabled: true`:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"jira": {
"type": "remote",
"url": "https://jira.example.com/mcp",
"enabled": true
}
}
}
```
تتغلب قيم إعداداتك المحلية على القيم الافتراضية البعيدة. راجع [أولوية الإعدادات](/docs/config#precedence-order) لمزيد من التفاصيل.
---
## محلي
أضف خوادم MCP المحلية عبر ضبط `type` على `"local"` ضمن كائن `mcp`.
```jsonc title="opencode.jsonc" {15}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-local-mcp-server": {
"type": "local",
// Or ["bun", "x", "my-mcp-command"]
"command": ["npx", "-y", "my-mcp-command"],
"enabled": true,
"environment": {
"MY_ENV_VAR": "my_env_var_value",
},
},
},
}
```
الأمر `command` هو الطريقة التي يتم بها تشغيل خادم MCP المحلي. ويمكنك أيضا تمرير قائمة بمتغيرات البيئة.
على سبيل المثال، إليك كيفية إضافة خادم MCP التجريبي [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything).
```jsonc title="opencode.jsonc"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"mcp_everything": {
"type": "local",
"command": ["npx", "-y", "@modelcontextprotocol/server-everything"],
},
},
}
```
ولاستخدامه يمكنني إضافة `use the mcp_everything tool` إلى طلباتي.
```txt "mcp_everything"
use the mcp_everything tool to add the number 3 and 4
```
---
#### الخيارات
فيما يلي جميع الخيارات المتاحة لتهيئة خادم MCP محلي.
| الخيار | النوع | مطلوب | الوصف |
| ------------- | ------- | ----- | -------------------------------------------------------------------------------- |
| `type` | String | Y | نوع اتصال خادم MCP، ويجب أن يكون `"local"`. |
| `command` | Array | Y | الأمر والوسائط اللازمة لتشغيل خادم MCP. |
| `environment` | Object | | متغيرات البيئة التي يتم تعيينها عند تشغيل الخادم. |
| `enabled` | Boolean | | تفعيل خادم MCP أو تعطيله عند بدء التشغيل. |
| `timeout` | Number | | المهلة بالمللي ثانية لجلب الأدوات من خادم MCP. القيمة الافتراضية 5000 (5 ثوانٍ). |
---
## بعيد
أضف خوادم MCP البعيدة عبر ضبط `type` على `"remote"`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-remote-mcp": {
"type": "remote",
"url": "https://my-mcp-server.com",
"enabled": true,
"headers": {
"Authorization": "Bearer MY_API_KEY"
}
}
}
}
```
يمثل `url` عنوان URL لخادم MCP البعيد، وباستخدام خيار `headers` يمكنك تمرير قائمة من الرؤوس (headers).
---
#### الخيارات
| الخيار | النوع | مطلوب | الوصف |
| --------- | ------- | ----- | -------------------------------------------------------------------------------- |
| `type` | String | Y | نوع اتصال خادم MCP، ويجب أن يكون `"remote"`. |
| `url` | String | Y | عنوان URL لخادم MCP البعيد. |
| `enabled` | Boolean | | تفعيل خادم MCP أو تعطيله عند بدء التشغيل. |
| `headers` | Object | | الرؤوس التي يتم إرسالها مع الطلب. |
| `oauth` | Object | | إعدادات مصادقة OAuth. راجع قسم [OAuth](#oauth) أدناه. |
| `timeout` | Number | | المهلة بالمللي ثانية لجلب الأدوات من خادم MCP. القيمة الافتراضية 5000 (5 ثوانٍ). |
---
## OAuth
يتولى OpenCode تلقائيا معالجة مصادقة OAuth لخوادم MCP البعيدة. عندما يتطلب خادم ما المصادقة، سيقوم OpenCode بما يلي:
1. اكتشاف استجابة 401 وبدء تدفق OAuth
2. استخدام **Dynamic Client Registration (RFC 7591)** إذا كان الخادم يدعمه
3. تخزين الرموز (tokens) بشكل آمن للطلبات المستقبلية
---
### تلقائي
بالنسبة لمعظم خوادم MCP التي تدعم OAuth، لا تحتاج إلى إعدادات خاصة. ما عليك سوى تهيئة الخادم البعيد:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-oauth-server": {
"type": "remote",
"url": "https://mcp.example.com/mcp"
}
}
}
```
إذا كان الخادم يتطلب المصادقة، فسيطلب منك OpenCode المصادقة عند أول محاولة لاستخدامه. وإذا لم يحدث ذلك، يمكنك [تشغيل التدفق يدويا](#authenticating) باستخدام `opencode mcp auth <server-name>`.
---
### مُسجَّل مسبقا
إذا كانت لديك بيانات اعتماد العميل من موفّر خادم MCP، يمكنك تهيئتها:
```json title="opencode.json" {7-11}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-oauth-server": {
"type": "remote",
"url": "https://mcp.example.com/mcp",
"oauth": {
"clientId": "{env:MY_MCP_CLIENT_ID}",
"clientSecret": "{env:MY_MCP_CLIENT_SECRET}",
"scope": "tools:read tools:execute"
}
}
}
}
```
---
### المصادقة
يمكنك تشغيل المصادقة يدويا أو إدارة بيانات الاعتماد.
صادِق مع خادم MCP معيّن:
```bash
opencode mcp auth my-oauth-server
```
اعرض جميع خوادم MCP وحالة المصادقة الخاصة بها:
```bash
opencode mcp list
```
احذف بيانات الاعتماد المخزنة:
```bash
opencode mcp logout my-oauth-server
```
سيفتح أمر `mcp auth` متصفحك للتفويض. بعد إكمال التفويض، سيخزّن OpenCode الرموز بشكل آمن في `~/.local/share/opencode/mcp-auth.json`.
---
#### تعطيل OAuth
إذا أردت تعطيل OAuth التلقائي لخادم ما (على سبيل المثال، للخوادم التي تستخدم مفاتيح API بدلا من ذلك)، فاضبط `oauth` على `false`:
```json title="opencode.json" {7}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-api-key-server": {
"type": "remote",
"url": "https://mcp.example.com/mcp",
"oauth": false,
"headers": {
"Authorization": "Bearer {env:MY_API_KEY}"
}
}
}
}
```
---
#### خيارات OAuth
| الخيار | النوع | الوصف |
| -------------- | --------------- | ------------------------------------------------------------------------ |
| `oauth` | Object \| false | كائن إعدادات OAuth، أو `false` لتعطيل الاكتشاف التلقائي لـ OAuth. |
| `clientId` | String | معرّف عميل OAuth. إذا لم يُحدَّد، ستتم محاولة التسجيل الديناميكي للعميل. |
| `clientSecret` | String | سرّ عميل OAuth، إذا كان مطلوبا من خادم التفويض. |
| `scope` | String | نطاقات OAuth المطلوبة أثناء التفويض. |
#### تصحيح الأخطاء
إذا فشل خادم MCP بعيد في المصادقة، يمكنك تشخيص المشكلة باستخدام:
```bash
# View auth status for all OAuth-capable servers
opencode mcp auth list
# Debug connection and OAuth flow for a specific server
opencode mcp debug my-oauth-server
```
يعرض أمر `mcp debug` حالة المصادقة الحالية، ويختبر اتصال HTTP، ويحاول تنفيذ تدفق اكتشاف OAuth.
---
## الإدارة
تتوفر خوادم MCP لديك كأدوات داخل OpenCode إلى جانب الأدوات المضمنة. لذا يمكنك إدارتها عبر إعدادات OpenCode مثل أي أداة أخرى.
---
### عام
هذا يعني أنه يمكنك تفعيلها أو تعطيلها على مستوى عام.
```json title="opencode.json" {14}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-mcp-foo": {
"type": "local",
"command": ["bun", "x", "my-mcp-command-foo"]
},
"my-mcp-bar": {
"type": "local",
"command": ["bun", "x", "my-mcp-command-bar"]
}
},
"tools": {
"my-mcp-foo": false
}
}
```
يمكننا أيضا استخدام نمط glob لتعطيل جميع خوادم MCP المطابقة.
```json title="opencode.json" {14}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-mcp-foo": {
"type": "local",
"command": ["bun", "x", "my-mcp-command-foo"]
},
"my-mcp-bar": {
"type": "local",
"command": ["bun", "x", "my-mcp-command-bar"]
}
},
"tools": {
"my-mcp*": false
}
}
```
هنا نستخدم نمط glob `my-mcp*` لتعطيل جميع خوادم MCP.
---
### لكل وكيل
إذا كان لديك عدد كبير من خوادم MCP فقد ترغب في تفعيلها لكل وكيل على حدة وتعطيلها على المستوى العام. للقيام بذلك:
1. عطّلها كأداة على المستوى العام.
2. في [إعدادات الوكيل](/docs/agents#tools)، فعّل خادم MCP كأداة.
```json title="opencode.json" {11, 14-18}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-mcp": {
"type": "local",
"command": ["bun", "x", "my-mcp-command"],
"enabled": true
}
},
"tools": {
"my-mcp*": false
},
"agent": {
"my-agent": {
"tools": {
"my-mcp*": true
}
}
}
}
```
---
#### أنماط Glob
يستخدم نمط glob أنماطا بسيطة من مطابقة glob:
- `*` يطابق صفرا أو أكثر من أي محرف (على سبيل المثال، `"my-mcp*"` يطابق `my-mcp_search` و`my-mcp_list` وغيرها.)
- `?` يطابق محرفا واحدا بالضبط
- جميع المحارف الأخرى تُطابق حرفيا
:::note
تُسجَّل أدوات خادم MCP مع اسم الخادم كبادئة، لذا لتعطيل جميع أدوات خادم ما استخدم ببساطة:
```
"mymcpservername_*": false
```
:::
---
## أمثلة
فيما يلي أمثلة لبعض خوادم MCP الشائعة. يمكنك إرسال PR إذا أردت توثيق خوادم أخرى.
---
### Sentry
أضف [خادم MCP الخاص بـ Sentry](https://mcp.sentry.dev) للتفاعل مع مشاريع Sentry والقضايا (issues) الخاصة بك.
```json title="opencode.json" {4-8}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"sentry": {
"type": "remote",
"url": "https://mcp.sentry.dev/mcp",
"oauth": {}
}
}
}
```
بعد إضافة الإعدادات، قم بالمصادقة مع Sentry:
```bash
opencode mcp auth sentry
```
سيؤدي ذلك إلى فتح نافذة متصفح لإكمال تدفق OAuth وربط OpenCode بحساب Sentry الخاص بك.
بعد المصادقة، يمكنك استخدام أدوات Sentry في طلباتك للاستعلام عن القضايا والمشاريع وبيانات الأخطاء.
```txt "use sentry"
Show me the latest unresolved issues in my project. use sentry
```
---
### Context7
أضف [خادم MCP الخاص بـ Context7](https://github.com/upstash/context7) للبحث في المستندات.
```json title="opencode.json" {4-7}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"context7": {
"type": "remote",
"url": "https://mcp.context7.com/mcp"
}
}
}
```
إذا كنت قد سجلت للحصول على حساب مجاني، يمكنك استخدام مفتاح API للحصول على حدود أعلى لمعدل الطلبات.
```json title="opencode.json" {7-9}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"context7": {
"type": "remote",
"url": "https://mcp.context7.com/mcp",
"headers": {
"CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}"
}
}
}
}
```
هنا نفترض أنك عيّنت متغير البيئة `CONTEXT7_API_KEY`.
أضف `use context7` إلى طلباتك لاستخدام خادم MCP الخاص بـ Context7.
```txt "use context7"
Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7
```
بدلا من ذلك، يمكنك إضافة شيء مثل هذا إلى [AGENTS.md](/docs/rules/).
```md title="AGENTS.md"
When you need to search docs, use `context7` tools.
```
---
### Grep by Vercel
أضف خادم MCP الخاص بـ [Grep by Vercel](https://grep.app) للبحث في مقتطفات الشيفرة على GitHub.
```json title="opencode.json" {4-7}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"gh_grep": {
"type": "remote",
"url": "https://mcp.grep.app"
}
}
}
```
وبما أننا سمّينا خادم MCP الخاص بنا `gh_grep`، يمكنك إضافة `use the gh_grep tool` إلى طلباتك لجعل الوكيل يستخدمه.
```txt "use the gh_grep tool"
What's the right way to set a custom domain in an SST Astro component? use the gh_grep tool
```
بدلا من ذلك، يمكنك إضافة شيء مثل هذا إلى [AGENTS.md](/docs/rules/).
```md title="AGENTS.md"
If you are unsure how to do something, use `gh_grep` to search code examples from GitHub.
```

View File

@@ -0,0 +1,222 @@
---
title: النماذج
description: تهيئة مزوّد LLM والنموذج.
---
يستخدم OpenCode كلاً من [AI SDK](https://ai-sdk.dev/) و[Models.dev](https://models.dev) لدعم **أكثر من 75 مزوّداً لنماذج LLM**، كما يدعم تشغيل النماذج محلياً.
---
## المزوّدون
أكثر المزوّدين شيوعاً مُحمَّلون مسبقاً افتراضياً. إذا أضفت بيانات اعتماد أحد المزوّدين عبر الأمر `/connect` فستكون متاحة عند تشغيل OpenCode.
تعرّف على المزيد حول [المزوّدين](/docs/providers).
---
## اختر نموذجاً
بعد تهيئة المزوّد يمكنك اختيار النموذج الذي تريده بكتابة:
```bash frame="none"
/models
```
---
## النماذج الموصى بها
هناك الكثير من النماذج المتاحة، وتظهر نماذج جديدة كل أسبوع.
:::tip
ننصح باستخدام أحد النماذج التي نوصي بها.
:::
لكن القليل منها فقط يكون جيداً في كلٍ من توليد الشيفرة واستدعاء الأدوات.
فيما يلي عدة نماذج تعمل جيداً مع OpenCode، دون ترتيب معيّن. (هذه ليست قائمة شاملة وقد لا تكون محدَّثة دائماً):
- GPT 5.2
- GPT 5.1 Codex
- Claude Opus 4.5
- Claude Sonnet 4.5
- Minimax M2.1
- Gemini 3 Pro
---
## تعيين الافتراضي
لتعيين أحد هذه النماذج كنموذج افتراضي، يمكنك ضبط المفتاح `model` في ملف إعدادات OpenCode.
```json title="opencode.json" {3}
{
"$schema": "https://opencode.ai/config.json",
"model": "lmstudio/google/gemma-3n-e4b"
}
```
المعرّف الكامل هنا يكون بالشكل `provider_id/model_id`. على سبيل المثال، إذا كنت تستخدم [OpenCode Zen](/docs/zen) فستستخدم `opencode/gpt-5.1-codex` لنموذج GPT 5.1 Codex.
إذا كنت قد هيّأت [مزوّداً مخصّصاً](/docs/providers#custom)، فإن `provider_id` هو المفتاح الموجود ضمن قسم `provider` في إعداداتك، و`model_id` هو المفتاح الموجود ضمن `provider.models`.
---
## إعداد النماذج
يمكنك ضبط خيارات النموذج على مستوى عام عبر ملف الإعدادات.
```jsonc title="opencode.jsonc" {7-12,19-24}
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"openai": {
"models": {
"gpt-5": {
"options": {
"reasoningEffort": "high",
"textVerbosity": "low",
"reasoningSummary": "auto",
"include": ["reasoning.encrypted_content"],
},
},
},
},
"anthropic": {
"models": {
"claude-sonnet-4-5-20250929": {
"options": {
"thinking": {
"type": "enabled",
"budgetTokens": 16000,
},
},
},
},
},
},
}
```
هنا نقوم بضبط إعدادات عامة لنموذجين مدمجين: `gpt-5` عند الوصول إليه عبر مزوّد `openai`، و`claude-sonnet-4-20250514` عند الوصول إليه عبر مزوّد `anthropic`.
يمكن العثور على أسماء المزوّدين والنماذج المدمجة على [Models.dev](https://models.dev).
يمكنك أيضاً ضبط هذه الخيارات لأي وكلاء تستخدمهم. تتجاوز إعدادات الوكيل أي خيارات عامة هنا. [اعرف المزيد](/docs/agents/#additional).
كما يمكنك تعريف متغيّرات مخصّصة تُوسّع المتغيّرات المدمجة. تتيح لك المتغيّرات ضبط إعدادات مختلفة للنموذج نفسه دون إنشاء إدخالات مكرّرة:
```jsonc title="opencode.jsonc" {6-21}
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"opencode": {
"models": {
"gpt-5": {
"variants": {
"high": {
"reasoningEffort": "high",
"textVerbosity": "low",
"reasoningSummary": "auto",
},
"low": {
"reasoningEffort": "low",
"textVerbosity": "low",
"reasoningSummary": "auto",
},
},
},
},
},
},
}
```
---
## المتغيّرات
تدعم العديد من النماذج عدة متغيّرات بإعدادات مختلفة. يأتي OpenCode مع متغيّرات افتراضية مدمجة للمزوّدين الشائعين.
### المتغيّرات المدمجة
يأتي OpenCode مع متغيّرات افتراضية لعدد كبير من المزوّدين:
**Anthropic**:
- `high` - ميزانية تفكير مرتفعة (الافتراضي)
- `max` - أقصى ميزانية تفكير
**OpenAI**:
تختلف حسب النموذج، لكن بشكل عام:
- `none` - بدون استدلال
- `minimal` - أقل جهد للاستدلال
- `low` - جهد استدلال منخفض
- `medium` - جهد استدلال متوسط
- `high` - جهد استدلال مرتفع
- `xhigh` - جهد استدلال مرتفع جداً
**Google**:
- `low` - جهد/ميزانية رموز أقل
- `high` - جهد/ميزانية رموز أعلى
:::tip
هذه القائمة ليست شاملة. لدى العديد من المزوّدين الآخرين إعدادات افتراضية مدمجة أيضاً.
:::
### متغيّرات مخصّصة
يمكنك تجاوز المتغيّرات الموجودة أو إضافة متغيّراتك الخاصة:
```jsonc title="opencode.jsonc" {7-18}
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"openai": {
"models": {
"gpt-5": {
"variants": {
"thinking": {
"reasoningEffort": "high",
"textVerbosity": "low",
},
"fast": {
"disabled": true,
},
},
},
},
},
},
}
```
### التبديل بين المتغيّرات
استخدم اختصار لوحة المفاتيح `variant_cycle` للتبديل بسرعة بين المتغيّرات. [اعرف المزيد](/docs/keybinds).
---
## تحميل النماذج
عند بدء تشغيل OpenCode، يتحقق من النماذج وفق ترتيب الأولوية التالي:
1. خيار سطر الأوامر `--model` أو `-m`. الصيغة هي نفسها الموجودة في ملف الإعدادات: `provider_id/model_id`.
2. قائمة النماذج في إعدادات OpenCode.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"model": "anthropic/claude-sonnet-4-20250514"
}
```
الصيغة هنا هي `provider/model`.
3. آخر نموذج تم استخدامه.
4. أول نموذج وفق أولوية داخلية.

View File

@@ -0,0 +1,331 @@
---
title: الأوضاع
description: أوضاع مختلفة لحالات استخدام مختلفة.
---
:::caution
يتم الآن ضبط الأوضاع عبر خيار `agent` في إعدادات opencode. أصبح خيار
`mode` مُهمَلًا الآن. [اعرف المزيد](/docs/agents).
:::
تتيح لك الأوضاع في opencode تخصيص السلوك والأدوات والمطالبات لحالات استخدام مختلفة.
يأتي مع وضعين مدمجين: **build** و **plan**. يمكنك تخصيصهما أو إعداد
أوضاعك الخاصة عبر إعدادات opencode.
يمكنك التبديل بين الأوضاع أثناء الجلسة أو إعدادها في ملف الإعدادات لديك.
---
## الأوضاع المدمجة
يأتي opencode مع وضعين مدمجين.
---
### Build
وضع Build هو الوضع **الافتراضي** مع تفعيل جميع الأدوات. هذا هو الوضع القياسي لأعمال التطوير عندما تحتاج إلى وصول كامل لعمليات الملفات وأوامر النظام.
---
### Plan
وضع مقيَّد مُصمَّم للتخطيط والتحليل. في وضع plan، تكون الأدوات التالية مُعطَّلة افتراضيًا:
- `write` - لا يمكن إنشاء ملفات جديدة
- `edit` - لا يمكن تعديل الملفات الموجودة، باستثناء الملفات الموجودة في `.opencode/plans/*.md` لتفصيل الخطة نفسها
- `patch` - لا يمكن تطبيق التصحيحات
- `bash` - لا يمكن تنفيذ أوامر الصدفة
يكون هذا الوضع مفيدًا عندما تريد من الذكاء الاصطناعي تحليل الشيفرة، أو اقتراح تغييرات، أو إنشاء خطط دون إجراء أي تعديلات فعلية على قاعدة الشيفرة لديك.
---
## التبديل
يمكنك التبديل بين الأوضاع أثناء الجلسة باستخدام مفتاح _Tab_، أو اختصار `switch_mode` الذي قمت بإعداده.
انظر أيضًا: [Formatters](/docs/formatters) لمعلومات حول إعدادات تنسيق الشيفرة.
---
## الإعداد
يمكنك تخصيص الأوضاع المدمجة أو إنشاء أوضاعك الخاصة عبر الإعدادات. يمكن إعداد الأوضاع بطريقتين:
### إعدادات JSON
قم بإعداد الأوضاع في ملف الإعدادات `opencode.json` لديك:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"mode": {
"build": {
"model": "anthropic/claude-sonnet-4-20250514",
"prompt": "{file:./prompts/build.txt}",
"tools": {
"write": true,
"edit": true,
"bash": true
}
},
"plan": {
"model": "anthropic/claude-haiku-4-20250514",
"tools": {
"write": false,
"edit": false,
"bash": false
}
}
}
}
```
### إعدادات Markdown
يمكنك أيضًا تعريف الأوضاع باستخدام ملفات markdown. ضعها في:
- عالمي: `~/.config/opencode/modes/`
- للمشروع: `.opencode/modes/`
```markdown title="~/.config/opencode/modes/review.md"
---
model: anthropic/claude-sonnet-4-20250514
temperature: 0.1
tools:
write: false
edit: false
bash: false
---
You are in code review mode. Focus on:
- Code quality and best practices
- Potential bugs and edge cases
- Performance implications
- Security considerations
Provide constructive feedback without making direct changes.
```
يصبح اسم ملف markdown هو اسم الوضع (على سبيل المثال، `review.md` ينشئ وضعًا باسم `review`).
لنلقِ نظرة على خيارات الإعداد هذه بمزيد من التفصيل.
---
### النموذج
استخدم إعداد `model` لتجاوز النموذج الافتراضي لهذا الوضع. يفيد ذلك عند استخدام نماذج مختلفة مُحسَّنة لمهام مختلفة؛ مثل نموذج أسرع للتخطيط ونموذج أكثر قدرة للتنفيذ.
```json title="opencode.json"
{
"mode": {
"plan": {
"model": "anthropic/claude-haiku-4-20250514"
}
}
}
```
---
### درجة الحرارة
تحكَّم في العشوائية والإبداع في ردود الذكاء الاصطناعي عبر إعداد `temperature`. القيم الأقل تجعل الردود أكثر تركيزًا وحتمية، بينما تزيد القيم الأعلى الإبداع والتنوّع.
```json title="opencode.json"
{
"mode": {
"plan": {
"temperature": 0.1
},
"creative": {
"temperature": 0.8
}
}
}
```
تتراوح قيم درجة الحرارة عادةً بين 0.0 و 1.0:
- **0.0-0.2**: ردود شديدة التركيز وحتمية، مثالية لتحليل الشيفرة والتخطيط
- **0.3-0.5**: ردود متوازنة مع قدر من الإبداع، مناسبة لمهام التطوير العامة
- **0.6-1.0**: ردود أكثر إبداعًا وتنوّعًا، مفيدة للعصف الذهني والاستكشاف
```json title="opencode.json"
{
"mode": {
"analyze": {
"temperature": 0.1,
"prompt": "{file:./prompts/analysis.txt}"
},
"build": {
"temperature": 0.3
},
"brainstorm": {
"temperature": 0.7,
"prompt": "{file:./prompts/creative.txt}"
}
}
}
```
إذا لم يتم تحديد درجة الحرارة، يستخدم opencode القيم الافتراضية الخاصة بكل نموذج (عادةً 0 لمعظم النماذج و 0.55 لنماذج Qwen).
---
### الموجّه
حدِّد ملف موجّه نظام (system prompt) مخصص لهذا الوضع عبر إعداد `prompt`. ينبغي أن يحتوي ملف الموجّه على تعليمات مرتبطة بهدف هذا الوضع.
```json title="opencode.json"
{
"mode": {
"review": {
"prompt": "{file:./prompts/code-review.txt}"
}
}
}
```
هذا المسار نسبي بالنسبة لموقع ملف الإعدادات. لذلك يعمل مع
إعدادات opencode العالمية وكذلك إعدادات المشروع.
---
### الأدوات
تحكَّم في الأدوات المتاحة في هذا الوضع عبر إعداد `tools`. يمكنك تفعيل أدوات محددة أو تعطيلها بضبطها على `true` أو `false`.
```json
{
"mode": {
"readonly": {
"tools": {
"write": false,
"edit": false,
"bash": false,
"read": true,
"grep": true,
"glob": true
}
}
}
}
```
إذا لم يتم تحديد أدوات، فستكون جميع الأدوات مفعّلة افتراضيًا.
---
#### الأدوات المتاحة
فيما يلي جميع الأدوات التي يمكن التحكم بها عبر إعدادات الوضع.
| الأداة | الوصف |
| ----------- | -------------------------- |
| `bash` | تنفيذ أوامر الصدفة |
| `edit` | تعديل الملفات الموجودة |
| `write` | إنشاء ملفات جديدة |
| `read` | قراءة محتويات الملفات |
| `grep` | البحث في محتويات الملفات |
| `glob` | العثور على الملفات حسب نمط |
| `list` | سرد محتويات الدليل |
| `patch` | تطبيق تصحيحات على الملفات |
| `todowrite` | إدارة قوائم المهام |
| `todoread` | قراءة قوائم المهام |
| `webfetch` | جلب محتوى الويب |
---
## أوضاع مخصصة
يمكنك إنشاء أوضاعك المخصصة بإضافتها إلى الإعدادات. فيما يلي أمثلة باستخدام كلا الأسلوبين:
### باستخدام إعدادات JSON
```json title="opencode.json" {4-14}
{
"$schema": "https://opencode.ai/config.json",
"mode": {
"docs": {
"prompt": "{file:./prompts/documentation.txt}",
"tools": {
"write": true,
"edit": true,
"bash": false,
"read": true,
"grep": true,
"glob": true
}
}
}
}
```
### باستخدام ملفات markdown
أنشئ ملفات الأوضاع في `.opencode/modes/` لأوضاع خاصة بالمشروع أو في `~/.config/opencode/modes/` لأوضاع عالمية:
```markdown title=".opencode/modes/debug.md"
---
temperature: 0.1
tools:
bash: true
read: true
grep: true
write: false
edit: false
---
You are in debug mode. Your primary goal is to help investigate and diagnose issues.
Focus on:
- Understanding the problem through careful analysis
- Using bash commands to inspect system state
- Reading relevant files and logs
- Searching for patterns and anomalies
- Providing clear explanations of findings
Do not make any changes to files. Only investigate and report.
```
```markdown title="~/.config/opencode/modes/refactor.md"
---
model: anthropic/claude-sonnet-4-20250514
temperature: 0.2
tools:
edit: true
read: true
grep: true
glob: true
---
You are in refactoring mode. Focus on improving code quality without changing functionality.
Priorities:
- Improve code readability and maintainability
- Apply consistent naming conventions
- Reduce code duplication
- Optimize performance where appropriate
- Ensure all tests continue to pass
```
---
### حالات الاستخدام
فيما يلي بعض حالات الاستخدام الشائعة لأوضاع مختلفة.
- **Build mode**: أعمال تطوير كاملة مع تفعيل جميع الأدوات
- **Plan mode**: التحليل والتخطيط دون إجراء تغييرات
- **Review mode**: مراجعة الشيفرة مع وصول للقراءة فقط بالإضافة إلى أدوات التوثيق
- **Debug mode**: تركيز على الاستقصاء مع تفعيل أدوات `bash` و `read`
- **Docs mode**: كتابة التوثيق مع عمليات الملفات لكن دون أوامر النظام
قد تجد أيضًا أن نماذج مختلفة تكون أنسب لحالات استخدام مختلفة.

View File

@@ -0,0 +1,57 @@
---
title: الشبكة
description: إعداد الوكلاء والشهادات المخصصة.
---
يدعم OpenCode متغيرات بيئة الوكيل (proxy) القياسية والشهادات المخصصة لبيئات الشبكات المؤسسية.
---
## الوكيل
يتبع OpenCode متغيرات بيئة الوكيل القياسية.
```bash
# HTTPS proxy (recommended)
export HTTPS_PROXY=https://proxy.example.com:8080
# HTTP proxy (if HTTPS not available)
export HTTP_PROXY=http://proxy.example.com:8080
# Bypass proxy for local server (required)
export NO_PROXY=localhost,127.0.0.1
```
:::caution
تتواصل واجهة TUI مع خادم HTTP محلي. يجب تجاوز الوكيل لهذا الاتصال لمنع حلقات التوجيه.
:::
يمكنك إعداد منفذ الخادم واسم المضيف باستخدام [أعلام سطر الأوامر](/docs/cli#run).
---
### المصادقة
إذا كان الوكيل يتطلب مصادقة أساسية، فأدرج بيانات الاعتماد في عنوان URL.
```bash
export HTTPS_PROXY=http://username:password@proxy.example.com:8080
```
:::caution
تجنّب تضمين كلمات المرور بشكل ثابت. استخدم متغيرات البيئة أو تخزين بيانات اعتماد آمن.
:::
بالنسبة للوكلاء الذين يتطلبون مصادقة متقدمة مثل NTLM أو Kerberos، فكّر في استخدام بوابة LLM تدعم طريقة المصادقة لديك.
---
## الشهادات المخصصة
إذا كانت مؤسستك تستخدم سلطات تصديق (CA) مخصصة لاتصالات HTTPS، فقم بإعداد OpenCode ليثق بها.
```bash
export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem
```
يعمل ذلك لكل من اتصالات الوكيل والوصول المباشر إلى واجهات برمجة التطبيقات.

View File

@@ -0,0 +1,227 @@
---
title: الأذونات
description: تحكّم في الإجراءات التي تتطلب موافقة قبل تنفيذها.
---
يستخدم OpenCode إعداد `permission` لتحديد ما إذا كان إجراءٌ ما سيُنفّذ تلقائيًا، أو سيطلب موافقتك، أو سيتم حظره.
اعتبارًا من `v1.1.1`، تم إهمال إعداد `tools` القديم (المنطقي) ودمجه ضمن `permission`. ولا يزال إعداد `tools` القديم مدعومًا للتوافق مع الإصدارات السابقة.
---
## الإجراءات
يؤول كل حكم أذونات إلى إحدى القيم التالية:
- `"allow"` — تشغيل دون موافقة
- `"ask"` — طلب الموافقة
- `"deny"` — حظر الإجراء
---
## الإعداد
يمكنك تعيين الأذونات بشكل عام (باستخدام `*`) ثم تجاوزها لأدوات محددة.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"*": "ask",
"bash": "allow",
"edit": "deny"
}
}
```
يمكنك أيضًا تعيين جميع الأذونات دفعة واحدة:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": "allow"
}
```
---
## قواعد دقيقة (صيغة الكائن)
في معظم الأذونات، يمكنك استخدام كائن لتطبيق إجراءات مختلفة بناءً على مُدخلات الأداة.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"npm *": "allow",
"rm *": "deny",
"grep *": "allow"
},
"edit": {
"*": "deny",
"packages/web/src/content/docs/*.mdx": "allow"
}
}
}
```
تُقيَّم القواعد عبر مطابقة الأنماط، مع كون **آخر قاعدة مطابقة هي التي تُطبَّق**. من الشائع وضع قاعدة الشمول `"*"` أولًا ثم القواعد الأكثر تحديدًا بعدها.
### أحرف البدل
تستخدم أنماط الأذونات مطابقة بسيطة لأحرف البدل:
- `*` يطابق صفرًا أو أكثر من أي حرف
- `?` يطابق حرفًا واحدًا بالضبط
- جميع الأحرف الأخرى تُطابق حرفيًا
### توسيع مجلد المنزل
يمكنك استخدام `~` أو `$HOME` في بداية النمط للإشارة إلى مجلد المنزل. هذا مفيد خصوصًا لقواعد [`external_directory`](#external-directories).
- `~/projects/*` -> `/Users/username/projects/*`
- `$HOME/projects/*` -> `/Users/username/projects/*`
- `~` -> `/Users/username`
### الأدلة الخارجية
استخدم `external_directory` للسماح باستدعاءات الأدوات التي تلمس مسارات خارج دليل العمل الذي بدأ منه OpenCode. ينطبق ذلك على أي أداة تأخذ مسارًا كمدخل (مثل `read` و`edit` و`list` و`glob` و`grep` والعديد من أوامر `bash`).
توسيع المنزل (مثل `~/...`) يؤثر فقط على طريقة كتابة النمط. لا يجعل ذلك المسار الخارجي جزءًا من مساحة العمل الحالية، لذا يجب السماح بالمسارات خارج دليل العمل عبر `external_directory` أيضًا.
على سبيل المثال، يتيح هذا الوصول إلى كل ما يقع تحت `~/projects/personal/`:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"external_directory": {
"~/projects/personal/**": "allow"
}
}
}
```
أي دليل مسموح به هنا يرث نفس القيم الافتراضية لمساحة العمل الحالية. وبما أن [`read` افتراضيًا هو `allow`](#defaults)، فإن عمليات القراءة تكون مسموحة أيضًا للعناصر ضمن `external_directory` ما لم يتم تجاوز ذلك. أضِف قواعد صريحة عندما يجب تقييد أداة ما في هذه المسارات، مثل حظر التعديلات مع الإبقاء على القراءة:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"external_directory": {
"~/projects/personal/**": "allow"
},
"edit": {
"~/projects/personal/**": "deny"
}
}
}
```
اجعل القائمة مقتصرة على المسارات الموثوقة، ثم أضِف طبقات إضافية من قواعد `allow` أو `deny` حسب الحاجة لأدوات أخرى (مثل `bash`).
---
## الأذونات المتاحة
تُعرَّف أذونات OpenCode بأسماء الأدوات، بالإضافة إلى بعض حواجز الأمان:
- `read` — قراءة ملف (يطابق مسار الملف)
- `edit` — جميع تعديلات الملفات (يشمل `edit` و`write` و`patch` و`multiedit`)
- `glob` — مطابقة أسماء الملفات (يطابق نمط الـ glob)
- `grep` — البحث في المحتوى (يطابق نمط regex)
- `list` — سرد الملفات في دليل (يطابق مسار الدليل)
- `bash` — تشغيل أوامر الصدفة (يطابق الأوامر المُحلَّلة مثل `git status --porcelain`)
- `task` — تشغيل وكلاء فرعيين (يطابق نوع الوكيل الفرعي)
- `skill` — تحميل مهارة (يطابق اسم المهارة)
- `lsp` — تشغيل استعلامات LSP (حاليًا دون قواعد دقيقة)
- `todoread`, `todowrite` — قراءة/تحديث قائمة المهام
- `webfetch` — جلب عنوان URL (يطابق الـ URL)
- `websearch`, `codesearch` — بحث الويب/الكود (يطابق الاستعلام)
- `external_directory` — يُفعَّل عندما تلمس أداة مسارات خارج دليل عمل المشروع
- `doom_loop` — يُفعَّل عندما يتكرر نفس استدعاء الأداة 3 مرات مع نفس المُدخلات
---
## القيم الافتراضية
إذا لم تحدد شيئًا، يبدأ OpenCode بقيم افتراضية متساهلة:
- معظم الأذونات افتراضيًا تكون `"allow"`.
- `doom_loop` و`external_directory` افتراضيًا تكون `"ask"`.
- `read` هو `"allow"`، لكن ملفات `.env` تكون مرفوضة افتراضيًا:
```json title="opencode.json"
{
"permission": {
"read": {
"*": "allow",
"*.env": "deny",
"*.env.*": "deny",
"*.env.example": "allow"
}
}
}
```
---
## ماذا تفعل `"ask"`
عندما يطلب OpenCode الموافقة، تعرض الواجهة ثلاث نتائج ممكنة:
- `once` — الموافقة على هذا الطلب فقط
- `always` — الموافقة على الطلبات المستقبلية المطابقة للأنماط المقترحة (لباقي جلسة OpenCode الحالية)
- `reject` — رفض الطلب
مجموعة الأنماط التي ستوافق عليها `always` تُوفَّر من الأداة نفسها (على سبيل المثال، موافقات `bash` عادةً ما تُدرج بادئة أمر آمنة في القائمة البيضاء مثل `git status*`).
---
## الوكلاء
يمكنك تجاوز الأذونات لكل وكيل. تُدمَج أذونات الوكلاء مع الإعداد العام، وتكون قواعد الوكيل هي ذات الأولوية. [تعرّف أكثر](/docs/agents#permissions) على أذونات الوكلاء.
:::note
ارجع إلى قسم [قواعد دقيقة (صيغة الكائن)](#granular-rules-object-syntax) للحصول على أمثلة أكثر تفصيلًا حول مطابقة الأنماط.
:::
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"git commit *": "deny",
"git push *": "deny",
"grep *": "allow"
}
},
"agent": {
"build": {
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"git commit *": "ask",
"git push *": "deny",
"grep *": "allow"
}
}
}
}
}
```
يمكنك أيضًا ضبط أذونات الوكيل في Markdown:
```markdown title="~/.config/opencode/agents/review.md"
---
description: Code review without edits
mode: subagent
permission:
edit: deny
bash: ask
webfetch: deny
---
Only analyze code and suggest changes.
```
:::tip
استخدم مطابقة الأنماط للأوامر التي تحتوي على معاملات. يسمح `"grep *"` بتنفيذ `grep pattern file.txt`، بينما سيحظر `"grep"` وحده ذلك. تعمل أوامر مثل `git status` للسلوك الافتراضي، لكنها تتطلب إذنًا صريحًا (مثل `"git status *"`) عند تمرير معاملات.
:::

View File

@@ -0,0 +1,385 @@
---
title: الإضافات
description: اكتب إضافاتك الخاصة لتوسيع OpenCode.
---
تتيح لك الإضافات توسيع OpenCode عبر ربطها بأحداث مختلفة وتخصيص السلوك. يمكنك إنشاء إضافات لإضافة ميزات جديدة، أو التكامل مع خدمات خارجية، أو تعديل السلوك الافتراضي لـ OpenCode.
للاطلاع على أمثلة، راجع [الإضافات](/docs/ecosystem#plugins) التي أنشأها المجتمع.
---
## استخدام إضافة
هناك طريقتان لتحميل الإضافات.
---
### من ملفات محلية
ضع ملفات JavaScript أو TypeScript في دليل الإضافات.
- `.opencode/plugins/` - إضافات على مستوى المشروع
- `~/.config/opencode/plugins/` - إضافات عامة
تُحمَّل الملفات في هذه الأدلة تلقائيا عند بدء التشغيل.
---
### من npm
حدّد حزم npm في ملف الإعدادات.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"]
}
```
يتم دعم حزم npm العادية والحزم ذات النطاق (scoped).
تصفّح الإضافات المتاحة في [النظام البيئي](/docs/ecosystem#plugins).
---
### كيفية تثبيت الإضافات
**إضافات npm** تُثبَّت تلقائيا باستخدام Bun عند بدء التشغيل. تُخزَّن الحزم واعتمادياتها مؤقتا في `~/.cache/opencode/node_modules/`.
**الإضافات المحلية** تُحمَّل مباشرة من دليل الإضافات. لاستخدام حزم خارجية، يجب إنشاء `package.json` داخل دليل الإعدادات لديك (راجع [الاعتماديات](#dependencies))، أو نشر الإضافة على npm ثم [إضافتها إلى إعداداتك](/docs/config#plugins).
---
### ترتيب التحميل
تُحمَّل الإضافات من جميع المصادر وتعمل جميع الخطافات بالتتابع. ترتيب التحميل هو:
1. إعدادات عامة (`~/.config/opencode/opencode.json`)
2. إعدادات المشروع (`opencode.json`)
3. دليل الإضافات العام (`~/.config/opencode/plugins/`)
4. دليل إضافات المشروع (`.opencode/plugins/`)
تُحمَّل حزم npm المكررة ذات الاسم والإصدار نفسيهما مرة واحدة. ومع ذلك، تُحمَّل الإضافة المحلية وإضافة npm ذات الاسم المشابه كلتاهما بشكل مستقل.
---
## إنشاء إضافة
الإضافة هي **وحدة JavaScript/TypeScript** تصدّر دالة إضافة واحدة أو أكثر.
تستقبل كل دالة كائنا للسياق وتعيد كائنا للخطافات.
---
### الاعتماديات
يمكن للإضافات المحلية والأدوات المخصصة استخدام حزم npm خارجية. أضف `package.json` إلى دليل الإعدادات لديك متضمنا الاعتماديات التي تحتاجها.
```json title=".opencode/package.json"
{
"dependencies": {
"shescape": "^2.1.0"
}
}
```
يشغّل OpenCode الأمر `bun install` عند بدء التشغيل لتثبيتها. بعد ذلك يمكن لإضافاتك وأدواتك استيرادها.
```ts title=".opencode/plugins/my-plugin.ts"
import { escape } from "shescape"
export const MyPlugin = async (ctx) => {
return {
"tool.execute.before": async (input, output) => {
if (input.tool === "bash") {
output.args.command = escape(output.args.command)
}
},
}
}
```
---
### البنية الأساسية
```js title=".opencode/plugins/example.js"
export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
console.log("Plugin initialized!")
return {
// Hook implementations go here
}
}
```
تستقبل دالة الإضافة ما يلي:
- `project`: معلومات المشروع الحالي.
- `directory`: دليل العمل الحالي.
- `worktree`: مسار git worktree.
- `client`: عميل SDK لـ opencode للتفاعل مع الذكاء الاصطناعي.
- `$`: واجهة [shell API](https://bun.com/docs/runtime/shell) الخاصة بـ Bun لتنفيذ الأوامر.
---
### دعم TypeScript
بالنسبة لإضافات TypeScript، يمكنك استيراد الأنواع من حزمة الإضافة:
```ts title="my-plugin.ts" {1}
import type { Plugin } from "@opencode-ai/plugin"
export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
return {
// Type-safe hook implementations
}
}
```
---
### الأحداث
يمكن للإضافات الاشتراك في الأحداث كما هو موضح أدناه في قسم الأمثلة. فيما يلي قائمة بالأحداث المتاحة.
#### أحداث الأوامر
- `command.executed`
#### أحداث الملفات
- `file.edited`
- `file.watcher.updated`
#### أحداث التثبيت
- `installation.updated`
#### أحداث LSP
- `lsp.client.diagnostics`
- `lsp.updated`
#### أحداث الرسائل
- `message.part.removed`
- `message.part.updated`
- `message.removed`
- `message.updated`
#### أحداث الأذونات
- `permission.asked`
- `permission.replied`
#### أحداث الخادم
- `server.connected`
#### أحداث الجلسة
- `session.created`
- `session.compacted`
- `session.deleted`
- `session.diff`
- `session.error`
- `session.idle`
- `session.status`
- `session.updated`
#### أحداث Todo
- `todo.updated`
#### أحداث الصدفة
- `shell.env`
#### أحداث الأدوات
- `tool.execute.after`
- `tool.execute.before`
#### أحداث واجهة TUI
- `tui.prompt.append`
- `tui.command.execute`
- `tui.toast.show`
---
## أمثلة
فيما يلي بعض أمثلة الإضافات التي يمكنك استخدامها لتوسيع opencode.
---
### إرسال إشعارات
أرسل إشعارات عند وقوع أحداث معينة:
```js title=".opencode/plugins/notification.js"
export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => {
return {
event: async ({ event }) => {
// Send notification on session completion
if (event.type === "session.idle") {
await $`osascript -e 'display notification "Session completed!" with title "opencode"'`
}
},
}
}
```
نستخدم `osascript` لتشغيل AppleScript على macOS. هنا نستخدمه لإرسال إشعارات.
:::note
إذا كنت تستخدم تطبيق OpenCode لسطح المكتب، فيمكنه إرسال إشعارات النظام تلقائيا عند جاهزية الرد أو عند حدوث خطأ في جلسة.
:::
---
### حماية .env
امنع opencode من قراءة ملفات `.env`:
```javascript title=".opencode/plugins/env-protection.js"
export const EnvProtection = async ({ project, client, $, directory, worktree }) => {
return {
"tool.execute.before": async (input, output) => {
if (input.tool === "read" && output.args.filePath.includes(".env")) {
throw new Error("Do not read .env files")
}
},
}
}
```
---
### حقن متغيرات البيئة
احقن متغيرات البيئة في جميع عمليات تنفيذ الصدفة (أدوات الذكاء الاصطناعي وطرفيات المستخدم):
```javascript title=".opencode/plugins/inject-env.js"
export const InjectEnvPlugin = async () => {
return {
"shell.env": async (input, output) => {
output.env.MY_API_KEY = "secret"
output.env.PROJECT_ROOT = input.cwd
},
}
}
```
---
### أدوات مخصصة
يمكن للإضافات أيضا إضافة أدوات مخصصة إلى opencode:
```ts title=".opencode/plugins/custom-tools.ts"
import { type Plugin, tool } from "@opencode-ai/plugin"
export const CustomToolsPlugin: Plugin = async (ctx) => {
return {
tool: {
mytool: tool({
description: "This is a custom tool",
args: {
foo: tool.schema.string(),
},
async execute(args, context) {
const { directory, worktree } = context
return `Hello ${args.foo} from ${directory} (worktree: ${worktree})`
},
}),
},
}
}
```
تقوم الدالة المساعدة `tool` بإنشاء أداة مخصصة يمكن لـ opencode استدعاؤها. تأخذ دالة مخطط Zod وتعيد تعريف أداة يتضمن:
- `description`: ما الذي تفعله الأداة
- `args`: مخطط Zod لوسائط الأداة
- `execute`: الدالة التي تُشغَّل عند استدعاء الأداة
ستكون أدواتك المخصصة متاحة لـ opencode إلى جانب الأدوات المضمنة.
---
### التسجيل
استخدم `client.app.log()` بدلا من `console.log` للتسجيل البنيوي:
```ts title=".opencode/plugins/my-plugin.ts"
export const MyPlugin = async ({ client }) => {
await client.app.log({
body: {
service: "my-plugin",
level: "info",
message: "Plugin initialized",
extra: { foo: "bar" },
},
})
}
```
المستويات: `debug`, `info`, `warn`, `error`. راجع [توثيق SDK](https://opencode.ai/docs/sdk) للتفاصيل.
---
### خطافات الضغط
خصّص السياق الذي يتم تضمينه عند ضغط جلسة:
```ts title=".opencode/plugins/compaction.ts"
import type { Plugin } from "@opencode-ai/plugin"
export const CompactionPlugin: Plugin = async (ctx) => {
return {
"experimental.session.compacting": async (input, output) => {
// Inject additional context into the compaction prompt
output.context.push(`
## Custom Context
Include any state that should persist across compaction:
- Current task status
- Important decisions made
- Files being actively worked on
`)
},
}
}
```
يعمل الخطاف `experimental.session.compacting` قبل أن ينشئ نموذج اللغة الكبير (LLM) ملخص المتابعة. استخدمه لحقن سياق خاص بالمجال قد يفوته موجّه الضغط الافتراضي.
يمكنك أيضا استبدال موجّه الضغط بالكامل عبر ضبط `output.prompt`:
```ts title=".opencode/plugins/custom-compaction.ts"
import type { Plugin } from "@opencode-ai/plugin"
export const CustomCompactionPlugin: Plugin = async (ctx) => {
return {
"experimental.session.compacting": async (input, output) => {
// Replace the entire compaction prompt
output.prompt = `
You are generating a continuation prompt for a multi-agent swarm session.
Summarize:
1. The current task and its status
2. Which files are being modified and by whom
3. Any blockers or dependencies between agents
4. The next steps to complete the work
Format as a structured prompt that a new agent can use to resume work.
`
},
}
}
```
عند ضبط `output.prompt` فإنه يستبدل موجّه الضغط الافتراضي بالكامل. يتم تجاهل المصفوفة `output.context` في هذه الحالة.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,180 @@
---
title: القواعد
description: اضبط تعليمات مخصصة لـ opencode.
---
يمكنك تزويد opencode بتعليمات مخصصة عبر إنشاء ملف `AGENTS.md`. هذا مشابه لقواعد Cursor. يحتوي هذا الملف على تعليمات تُضاف إلى سياق نموذج اللغة (LLM) لتخصيص سلوكه لمشروعك المحدد.
---
## التهيئة
لإنشاء ملف `AGENTS.md` جديد، يمكنك تشغيل الأمر `/init` في opencode.
:::tip
يُستحسن عمل commit لملف `AGENTS.md` الخاص بمشروعك إلى Git.
:::
سيقوم ذلك بفحص مشروعك وكل محتوياته لفهم طبيعة المشروع وتوليد ملف `AGENTS.md` بناءً على ذلك. يساعد هذا opencode على التنقّل داخل المشروع بشكل أفضل.
إذا كان لديك ملف `AGENTS.md` موجود بالفعل، فسيحاول هذا إضافة محتوى إليه.
---
## مثال
يمكنك أيضًا إنشاء هذا الملف يدويًا. إليك مثالًا على بعض الأمور التي يمكنك وضعها في ملف `AGENTS.md`.
```markdown title="AGENTS.md"
# SST v3 Monorepo Project
This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management.
## Project Structure
- `packages/` - Contains all workspace packages (functions, core, web, etc.)
- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts)
- `sst.config.ts` - Main SST configuration with dynamic imports
## Code Standards
- Use TypeScript with strict mode enabled
- Shared code goes in `packages/core/` with proper exports configuration
- Functions go in `packages/functions/`
- Infrastructure should be split into logical files in `infra/`
## Monorepo Conventions
- Import shared modules using workspace names: `@my-app/core/example`
```
نضيف هنا تعليمات خاصة بالمشروع، وسيتم مشاركتها عبر فريقك.
---
## الأنواع
يدعم opencode أيضًا قراءة ملف `AGENTS.md` من مواقع متعددة، ولكل موقع غرض مختلف.
### المشروع
ضع ملف `AGENTS.md` في جذر مشروعك للقواعد الخاصة بالمشروع. لا تُطبَّق هذه القواعد إلا عند العمل داخل هذا المجلد أو مجلداته الفرعية.
### عام
يمكنك أيضًا وضع قواعد عامة في ملف `~/.config/opencode/AGENTS.md`. تُطبَّق هذه القواعد على جميع جلسات opencode.
وبما أن هذا الملف لا يتم عمل commit له إلى Git ولا تتم مشاركته مع فريقك، نوصي باستخدامه لتحديد أي قواعد شخصية يجب أن يلتزم بها نموذج اللغة.
### التوافق مع Claude Code
للمستخدمين الذين ينتقلون من Claude Code، يدعم OpenCode اصطلاحات ملفات Claude Code كبدائل احتياطية:
- **قواعد المشروع**: `CLAUDE.md` في دليل مشروعك (يُستخدم إذا لم يوجد `AGENTS.md`)
- **قواعد عامة**: `~/.claude/CLAUDE.md` (يُستخدم إذا لم يوجد `~/.config/opencode/AGENTS.md`)
- **المهارات**: `~/.claude/skills/` — راجع [مهارات الوكيل](/docs/skills/) للتفاصيل
لإيقاف التوافق مع Claude Code، عيّن أحد متغيرات البيئة التالية:
```bash
export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support
export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md
export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills
```
---
## الأولوية
عند بدء opencode، يبحث عن ملفات القواعد بهذا الترتيب:
1. **ملفات محلية** عبر التنقّل صعودًا من الدليل الحالي (`AGENTS.md`, `CLAUDE.md`)
2. **ملف عام** في `~/.config/opencode/AGENTS.md`
3. **ملف Claude Code** في `~/.claude/CLAUDE.md` (ما لم يتم تعطيله)
يتم اعتماد أول ملف مطابق ضمن كل فئة. على سبيل المثال، إذا كان لديك كل من `AGENTS.md` و`CLAUDE.md` فسيتم استخدام `AGENTS.md` فقط. وبالمثل، تكون الأولوية لملف `~/.config/opencode/AGENTS.md` على `~/.claude/CLAUDE.md`.
---
## تعليمات مخصصة
يمكنك تحديد ملفات تعليمات مخصصة في `opencode.json` أو في الملف العام `~/.config/opencode/opencode.json`. يتيح ذلك لك ولفريقك إعادة استخدام القواعد الموجودة بدلًا من تكرارها داخل AGENTS.md.
مثال:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"]
}
```
يمكنك أيضًا استخدام عناوين URL بعيدة لتحميل التعليمات من الويب.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"]
}
```
يتم جلب التعليمات البعيدة بمهلة قدرها 5 ثوانٍ.
تُدمَج جميع ملفات التعليمات مع ملفات `AGENTS.md` لديك.
---
## الإشارة إلى ملفات خارجية
على الرغم من أن opencode لا يقوم تلقائيًا بتحليل مراجع الملفات داخل `AGENTS.md`، يمكنك تحقيق وظيفة مشابهة بطريقتين:
### استخدام opencode.json
النهج الموصى به هو استخدام الحقل `instructions` في `opencode.json`:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"]
}
```
### تعليمات يدوية في AGENTS.md
يمكنك تعليم opencode قراءة ملفات خارجية عبر تقديم تعليمات صريحة داخل `AGENTS.md`. إليك مثالًا عمليًا:
```markdown title="AGENTS.md"
# TypeScript Project Rules
## External File Loading
CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand.
Instructions:
- Do NOT preemptively load all references - use lazy loading based on actual need
- When loaded, treat content as mandatory instructions that override defaults
- Follow references recursively when needed
## Development Guidelines
For TypeScript code style and best practices: @docs/typescript-guidelines.md
For React component architecture and hooks patterns: @docs/react-patterns.md
For REST API design and error handling: @docs/api-standards.md
For testing strategies and coverage requirements: @test/testing-guidelines.md
## General Guidelines
Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md.
```
يتيح لك هذا النهج ما يلي:
- إنشاء ملفات قواعد معيارية قابلة لإعادة الاستخدام
- مشاركة القواعد عبر المشاريع باستخدام symlinks أو git submodules
- إبقاء AGENTS.md موجزًا مع الإشارة إلى إرشادات تفصيلية
- ضمان أن opencode يحمّل الملفات فقط عند الحاجة للمهمة المحددة
:::tip
بالنسبة للمستودعات متعددة الحزم (monorepos) أو المشاريع ذات المعايير المشتركة، فإن استخدام `opencode.json` مع أنماط glob (مثل `packages/*/AGENTS.md`) أسهل للصيانة من التعليمات اليدوية.
:::

View File

@@ -0,0 +1,391 @@
---
title: مجموعة تطوير البرمجيات (SDK)
description: عميل JavaScript آمن الأنواع لخادم opencode.
---
import config from "../../../../config.mjs"
export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts`
توفر SDK الخاصة بـ opencode لـ JS/TS عميلا آمنا للأنواع للتفاعل مع الخادم.
استخدمها لبناء التكاملات والتحكم في opencode برمجيا.
[اعرف المزيد](/docs/server) حول كيفية عمل الخادم. للاطلاع على أمثلة، تفقد [المشاريع](/docs/ecosystem#projects) التي أنشأها المجتمع.
---
## التثبيت
ثبّت SDK من npm:
```bash
npm install @opencode-ai/sdk
```
---
## إنشاء عميل
أنشئ مثيلا من opencode:
```javascript
import { createOpencode } from "@opencode-ai/sdk"
const { client } = await createOpencode()
```
هذا يشغّل خادما وعميلا معا.
#### الخيارات
| الخيار | النوع | الوصف | الافتراضي |
| ---------- | ------------- | ----------------------------- | ----------- |
| `hostname` | `string` | اسم مضيف الخادم | `127.0.0.1` |
| `port` | `number` | منفذ الخادم | `4096` |
| `signal` | `AbortSignal` | إشارة إلغاء للإيقاف | `undefined` |
| `timeout` | `number` | مهلة بدء الخادم بالمللي ثانية | `5000` |
| `config` | `Config` | كائن الإعدادات | `{}` |
---
## الإعدادات
يمكنك تمرير كائن إعدادات لتخصيص السلوك. سيستمر المثيل في التقاط `opencode.json` لديك، لكن يمكنك تجاوز الإعدادات أو إضافة إعدادات مباشرة:
```javascript
import { createOpencode } from "@opencode-ai/sdk"
const opencode = await createOpencode({
hostname: "127.0.0.1",
port: 4096,
config: {
model: "anthropic/claude-3-5-sonnet-20241022",
},
})
console.log(`Server running at ${opencode.server.url}`)
opencode.server.close()
```
## العميل فقط
إذا كان لديك مثيل opencode يعمل بالفعل، يمكنك إنشاء مثيل عميل للاتصال به:
```javascript
import { createOpencodeClient } from "@opencode-ai/sdk"
const client = createOpencodeClient({
baseUrl: "http://localhost:4096",
})
```
#### الخيارات
| الخيار | النوع | الوصف | الافتراضي |
| --------------- | ---------- | --------------------------------- | ----------------------- |
| `baseUrl` | `string` | عنوان URL للخادم | `http://localhost:4096` |
| `fetch` | `function` | تنفيذ fetch مخصص | `globalThis.fetch` |
| `parseAs` | `string` | طريقة تحليل الاستجابة | `auto` |
| `responseStyle` | `string` | أسلوب الإرجاع: `data` أو `fields` | `fields` |
| `throwOnError` | `boolean` | رمي الأخطاء بدلا من إرجاعها | `false` |
---
## الأنواع
تتضمن SDK تعريفات TypeScript لجميع أنواع واجهات برمجة التطبيقات. استوردها مباشرة:
```typescript
import type { Session, Message, Part } from "@opencode-ai/sdk"
```
جميع الأنواع مولّدة من مواصفات OpenAPI الخاصة بالخادم ومتاحة في <a href={typesUrl}>ملف الأنواع</a>.
---
## الأخطاء
يمكن أن ترمي SDK أخطاء يمكنك التقاطها ومعالجتها:
```typescript
try {
await client.session.get({ path: { id: "invalid-id" } })
} catch (error) {
console.error("Failed to get session:", (error as Error).message)
}
```
---
## واجهات برمجة التطبيقات
توفر SDK جميع واجهات الخادم عبر عميل آمن للأنواع.
---
### عام (`global`)
| الطريقة | الوصف | الاستجابة |
| ----------------- | ---------------------------- | ------------------------------------ |
| `global.health()` | التحقق من صحة الخادم وإصداره | `{ healthy: true, version: string }` |
---
#### أمثلة
```javascript
const health = await client.global.health()
console.log(health.data.version)
```
---
### التطبيق (`app`)
| الطريقة | الوصف | الاستجابة |
| -------------- | ------------------------- | ------------------------------------------- |
| `app.log()` | كتابة إدخال في السجل | `boolean` |
| `app.agents()` | سرد جميع الوكلاء المتاحين | <a href={typesUrl}><code>Agent[]</code></a> |
---
#### أمثلة
```javascript
// Write a log entry
await client.app.log({
body: {
service: "my-app",
level: "info",
message: "Operation completed",
},
})
// List available agents
const agents = await client.app.agents()
```
---
### المشروع (`project`)
| الطريقة | الوصف | الاستجابة |
| ------------------- | ------------------ | --------------------------------------------- |
| `project.list()` | سرد جميع المشاريع | <a href={typesUrl}><code>Project[]</code></a> |
| `project.current()` | جلب المشروع الحالي | <a href={typesUrl}><code>Project</code></a> |
---
#### أمثلة
```javascript
// List all projects
const projects = await client.project.list()
// Get current project
const currentProject = await client.project.current()
```
---
### المسار (`path`)
| الطريقة | الوصف | الاستجابة |
| ------------ | ----------------- | ---------------------------------------- |
| `path.get()` | جلب المسار الحالي | <a href={typesUrl}><code>Path</code></a> |
---
#### أمثلة
```javascript
// Get current path information
const pathInfo = await client.path.get()
```
---
### الإعدادات (`config`)
| الطريقة | الوصف | الاستجابة |
| -------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `config.get()` | جلب معلومات الإعدادات | <a href={typesUrl}><code>Config</code></a> |
| `config.providers()` | سرد المزوّدين والنماذج الافتراضية | `{ providers: `<a href={typesUrl}><code>Provider[]</code></a>`, default: { [key: string]: string } }` |
---
#### أمثلة
```javascript
const config = await client.config.get()
const { providers, default: defaults } = await client.config.providers()
```
---
### الجلسات (`session`)
| الطريقة | الوصف | ملاحظات |
| ---------------------------------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `session.list()` | سرد الجلسات | يعيد <a href={typesUrl}><code>Session[]</code></a> |
| `session.get({ path })` | جلب جلسة | يعيد <a href={typesUrl}><code>Session</code></a> |
| `session.children({ path })` | سرد الجلسات الفرعية | يعيد <a href={typesUrl}><code>Session[]</code></a> |
| `session.create({ body })` | إنشاء جلسة | يعيد <a href={typesUrl}><code>Session</code></a> |
| `session.delete({ path })` | حذف جلسة | يعيد `boolean` |
| `session.update({ path, body })` | تحديث خصائص الجلسة | يعيد <a href={typesUrl}><code>Session</code></a> |
| `session.init({ path, body })` | تحليل التطبيق وإنشاء `AGENTS.md` | يعيد `boolean` |
| `session.abort({ path })` | إيقاف جلسة قيد التشغيل | يعيد `boolean` |
| `session.share({ path })` | مشاركة جلسة | يعيد <a href={typesUrl}><code>Session</code></a> |
| `session.unshare({ path })` | إلغاء مشاركة جلسة | يعيد <a href={typesUrl}><code>Session</code></a> |
| `session.summarize({ path, body })` | تلخيص جلسة | يعيد `boolean` |
| `session.messages({ path })` | سرد الرسائل في جلسة | يعيد `{ info: `<a href={typesUrl}><code>Message</code></a>`, parts: `<a href={typesUrl}><code>Part[]</code></a>`}[]` |
| `session.message({ path })` | جلب تفاصيل الرسالة | يعيد `{ info: `<a href={typesUrl}><code>Message</code></a>`, parts: `<a href={typesUrl}><code>Part[]</code></a>`}` |
| `session.prompt({ path, body })` | إرسال رسالة مطالبة | `body.noReply: true` يعيد UserMessage (للسياق فقط). الافتراضي يعيد <a href={typesUrl}><code>AssistantMessage</code></a> مع استجابة AI |
| `session.command({ path, body })` | إرسال أمر إلى الجلسة | يعيد `{ info: `<a href={typesUrl}><code>AssistantMessage</code></a>`, parts: `<a href={typesUrl}><code>Part[]</code></a>`}` |
| `session.shell({ path, body })` | تشغيل أمر shell | يعيد <a href={typesUrl}><code>AssistantMessage</code></a> |
| `session.revert({ path, body })` | التراجع عن رسالة | يعيد <a href={typesUrl}><code>Session</code></a> |
| `session.unrevert({ path })` | استعادة الرسائل المتراجع عنها | يعيد <a href={typesUrl}><code>Session</code></a> |
| `postSessionByIdPermissionsByPermissionId({ path, body })` | الاستجابة لطلب إذن | يعيد `boolean` |
---
#### أمثلة
```javascript
// Create and manage sessions
const session = await client.session.create({
body: { title: "My session" },
})
const sessions = await client.session.list()
// Send a prompt message
const result = await client.session.prompt({
path: { id: session.id },
body: {
model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" },
parts: [{ type: "text", text: "Hello!" }],
},
})
// Inject context without triggering AI response (useful for plugins)
await client.session.prompt({
path: { id: session.id },
body: {
noReply: true,
parts: [{ type: "text", text: "You are a helpful assistant." }],
},
})
```
---
### الملفات
| الطريقة | الوصف | الاستجابة |
| ------------------------- | ----------------------------------- | -------------------------------------------------------------------------------------------- |
| `find.text({ query })` | البحث عن نص داخل الملفات | مصفوفة من كائنات المطابقة مع `path` و`lines` و`line_number` و`absolute_offset` و`submatches` |
| `find.files({ query })` | العثور على الملفات والمجلدات بالاسم | `string[]` (مسارات) |
| `find.symbols({ query })` | العثور على رموز مساحة العمل | <a href={typesUrl}><code>Symbol[]</code></a> |
| `file.read({ query })` | قراءة ملف | `{ type: "raw" \| "patch", content: string }` |
| `file.status({ query? })` | جلب حالة الملفات المتتبَّعة | <a href={typesUrl}><code>File[]</code></a> |
يدعم `find.files` بعض حقول الاستعلام الاختيارية:
- `type`: `"file"` أو `"directory"`
- `directory`: تجاوز جذر المشروع لعملية البحث
- `limit`: الحد الأقصى للنتائج (1200)
---
#### أمثلة
```javascript
// Search and read files
const textResults = await client.find.text({
query: { pattern: "function.*opencode" },
})
const files = await client.find.files({
query: { query: "*.ts", type: "file" },
})
const directories = await client.find.files({
query: { query: "packages", type: "directory", limit: 20 },
})
const content = await client.file.read({
query: { path: "src/index.ts" },
})
```
---
### واجهة TUI (`tui`)
| الطريقة | الوصف | الاستجابة |
| ------------------------------ | ---------------------- | --------- |
| `tui.appendPrompt({ body })` | إلحاق نص بالمطالبة | `boolean` |
| `tui.openHelp()` | فتح مربع حوار المساعدة | `boolean` |
| `tui.openSessions()` | فتح محدد الجلسات | `boolean` |
| `tui.openThemes()` | فتح محدد السمات | `boolean` |
| `tui.openModels()` | فتح محدد النماذج | `boolean` |
| `tui.submitPrompt()` | إرسال المطالبة الحالية | `boolean` |
| `tui.clearPrompt()` | مسح المطالبة | `boolean` |
| `tui.executeCommand({ body })` | تنفيذ أمر | `boolean` |
| `tui.showToast({ body })` | عرض إشعار toast | `boolean` |
---
#### أمثلة
```javascript
// Control TUI interface
await client.tui.appendPrompt({
body: { text: "Add this to prompt" },
})
await client.tui.showToast({
body: { message: "Task completed", variant: "success" },
})
```
---
### المصادقة (`auth`)
| الطريقة | الوصف | الاستجابة |
| ------------------- | ---------------------------- | --------- |
| `auth.set({ ... })` | تعيين بيانات اعتماد المصادقة | `boolean` |
---
#### أمثلة
```javascript
await client.auth.set({
path: { id: "anthropic" },
body: { type: "api", key: "your-api-key" },
})
```
---
### الأحداث (`event`)
| الطريقة | الوصف | الاستجابة |
| ------------------- | -------------------------- | -------------------------- |
| `event.subscribe()` | تدفق أحداث مرسلة من الخادم | تدفق أحداث مرسلة من الخادم |
---
#### أمثلة
```javascript
// Listen to real-time events
const events = await client.event.subscribe()
for await (const event of events.stream) {
console.log("Event:", event.type, event.properties)
}
```

View File

@@ -0,0 +1,287 @@
---
title: الخادم
description: تفاعل مع خادم opencode عبر HTTP.
---
import config from "../../../../config.mjs"
export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts`
يشغّل الأمر `opencode serve` خادما HTTP دون واجهة ويعرض نقطة نهاية OpenAPI يمكن لعميل opencode استخدامها.
---
### الاستخدام
```bash
opencode serve [--port <number>] [--hostname <string>] [--cors <origin>]
```
#### الخيارات
| الخيار | الوصف | الافتراضي |
| --------------- | ------------------------------------- | ---------------- |
| `--port` | المنفذ الذي يستمع عليه | `4096` |
| `--hostname` | اسم المضيف الذي يستمع عليه | `127.0.0.1` |
| `--mdns` | تفعيل اكتشاف mDNS | `false` |
| `--mdns-domain` | اسم نطاق مخصص لخدمة mDNS | `opencode.local` |
| `--cors` | أصول (Origins) متصفح إضافية مسموح بها | `[]` |
يمكن تمرير `--cors` عدة مرات:
```bash
opencode serve --cors http://localhost:5173 --cors https://app.example.com
```
---
### المصادقة
عيّن `OPENCODE_SERVER_PASSWORD` لحماية الخادم باستخدام مصادقة HTTP الأساسية. اسم المستخدم افتراضيا هو `opencode`، أو عيّن `OPENCODE_SERVER_USERNAME` لتغييره. ينطبق ذلك على كل من `opencode serve` و `opencode web`.
```bash
OPENCODE_SERVER_PASSWORD=your-password opencode serve
```
---
### كيف يعمل
عند تشغيل `opencode` يبدأ تشغيل واجهة طرفية تفاعلية (TUI) وخادما. تكون الـ TUI هي
العميل الذي يتحدث إلى الخادم. يوفّر الخادم نقطة نهاية لمواصفة OpenAPI 3.1.
وتُستخدم هذه النقطة أيضا لتوليد [SDK](/docs/sdk).
:::tip
استخدم خادم opencode للتفاعل مع opencode برمجيا.
:::
تتيح هذه البنية لـ opencode دعم عدة عملاء وتمكّنك من التفاعل مع opencode برمجيا.
يمكنك تشغيل `opencode serve` لبدء خادم مستقل. إذا كانت واجهة opencode الطرفية (TUI)
قيد التشغيل، فسيبدأ `opencode serve` خادما جديدا.
---
#### الاتصال بخادم موجود
عند بدء الـ TUI تقوم بتعيين منفذ واسم مضيف عشوائيا. يمكنك بدلا من ذلك تمرير [الخيارات](/docs/cli) `--hostname` و `--port`، ثم استخدامهما للاتصال بخادمها.
يمكن استخدام نقطة النهاية [`/tui`](#tui) للتحكم في الـ TUI عبر الخادم. على سبيل المثال، يمكنك تعبئة الموجّه مسبقا أو تشغيله. يُستخدم هذا الإعداد بواسطة ملحقات OpenCode لـ [IDE](/docs/ide).
---
## المواصفات
ينشر الخادم مواصفة OpenAPI 3.1 ويمكن عرضها على:
```
http://<hostname>:<port>/doc
```
على سبيل المثال: `http://localhost:4096/doc`. استخدم المواصفة لتوليد عملاء أو لفحص أنواع الطلبات والاستجابات. أو اعرضها في مستكشف Swagger.
---
## واجهات API
يعرض خادم opencode واجهات API التالية.
---
### عام
| الطريقة | المسار | الوصف | الاستجابة |
| ------- | ---------------- | ------------------------------------ | ------------------------------------ |
| `GET` | `/global/health` | الحصول على صحة الخادم وإصداره | `{ healthy: true, version: string }` |
| `GET` | `/global/event` | الحصول على الأحداث العامة (تدفق SSE) | تدفق أحداث |
---
### المشروع
| الطريقة | المسار | الوصف | الاستجابة |
| ------- | ------------------ | ------------------------- | --------------------------------------------- |
| `GET` | `/project` | سرد جميع المشاريع | <a href={typesUrl}><code>Project[]</code></a> |
| `GET` | `/project/current` | الحصول على المشروع الحالي | <a href={typesUrl}><code>Project</code></a> |
---
### المسار و VCS
| الطريقة | المسار | الوصف | الاستجابة |
| ------- | ------- | ------------------------------------- | ------------------------------------------- |
| `GET` | `/path` | الحصول على المسار الحالي | <a href={typesUrl}><code>Path</code></a> |
| `GET` | `/vcs` | الحصول على معلومات VCS للمشروع الحالي | <a href={typesUrl}><code>VcsInfo</code></a> |
---
### المثيل
| الطريقة | المسار | الوصف | الاستجابة |
| ------- | ------------------- | ----------------------- | --------- |
| `POST` | `/instance/dispose` | التخلص من المثيل الحالي | `boolean` |
---
### الإعدادات
| الطريقة | المسار | الوصف | الاستجابة |
| ------- | ------------------- | --------------------------------- | ---------------------------------------------------------------------------------------- |
| `GET` | `/config` | الحصول على معلومات الإعدادات | <a href={typesUrl}><code>Config</code></a> |
| `PATCH` | `/config` | تحديث الإعدادات | <a href={typesUrl}><code>Config</code></a> |
| `GET` | `/config/providers` | سرد المزوّدين والنماذج الافتراضية | `{ providers: `<a href={typesUrl}>Provider[]</a>`, default: { [key: string]: string } }` |
---
### المزوّد
| الطريقة | المسار | الوصف | الاستجابة |
| ------- | -------------------------------- | ----------------------------- | ----------------------------------------------------------------------------------- |
| `GET` | `/provider` | سرد جميع المزوّدين | `{ all: `<a href={typesUrl}>Provider[]</a>`, default: {...}, connected: string[] }` |
| `GET` | `/provider/auth` | الحصول على طرق مصادقة المزوّد | `{ [providerID: string]: `<a href={typesUrl}>ProviderAuthMethod[]</a>` }` |
| `POST` | `/provider/{id}/oauth/authorize` | تفويض مزوّد باستخدام OAuth | <a href={typesUrl}><code>ProviderAuthAuthorization</code></a> |
| `POST` | `/provider/{id}/oauth/callback` | معالجة رد نداء OAuth لمزوّد | `boolean` |
---
### الجلسات
| الطريقة | المسار | الوصف | الملاحظات |
| -------- | ---------------------------------------- | ------------------------------------- | -------------------------------------------------------------------------------- |
| `GET` | `/session` | سرد جميع الجلسات | يعيد <a href={typesUrl}><code>Session[]</code></a> |
| `POST` | `/session` | إنشاء جلسة جديدة | المتن: `{ parentID?, title? }`، يعيد <a href={typesUrl}><code>Session</code></a> |
| `GET` | `/session/status` | الحصول على حالة الجلسات جميعها | يعيد `{ [sessionID: string]: `<a href={typesUrl}>SessionStatus</a>` }` |
| `GET` | `/session/:id` | الحصول على تفاصيل الجلسة | يعيد <a href={typesUrl}><code>Session</code></a> |
| `DELETE` | `/session/:id` | حذف جلسة وجميع بياناتها | يعيد `boolean` |
| `PATCH` | `/session/:id` | تحديث خصائص الجلسة | المتن: `{ title? }`، يعيد <a href={typesUrl}><code>Session</code></a> |
| `GET` | `/session/:id/children` | الحصول على الجلسات الفرعية لجلسة | يعيد <a href={typesUrl}><code>Session[]</code></a> |
| `GET` | `/session/:id/todo` | الحصول على قائمة المهام (todo) للجلسة | يعيد <a href={typesUrl}><code>Todo[]</code></a> |
| `POST` | `/session/:id/init` | تحليل التطبيق وإنشاء `AGENTS.md` | المتن: `{ messageID, providerID, modelID }`، يعيد `boolean` |
| `POST` | `/session/:id/fork` | تفريع جلسة موجودة عند رسالة | المتن: `{ messageID? }`، يعيد <a href={typesUrl}><code>Session</code></a> |
| `POST` | `/session/:id/abort` | إلغاء جلسة قيد التشغيل | يعيد `boolean` |
| `POST` | `/session/:id/share` | مشاركة جلسة | يعيد <a href={typesUrl}><code>Session</code></a> |
| `DELETE` | `/session/:id/share` | إلغاء مشاركة جلسة | يعيد <a href={typesUrl}><code>Session</code></a> |
| `GET` | `/session/:id/diff` | الحصول على diff لهذه الجلسة | الاستعلام: `messageID?`، يعيد <a href={typesUrl}><code>FileDiff[]</code></a> |
| `POST` | `/session/:id/summarize` | تلخيص الجلسة | المتن: `{ providerID, modelID }`، يعيد `boolean` |
| `POST` | `/session/:id/revert` | التراجع عن رسالة | المتن: `{ messageID, partID? }`، يعيد `boolean` |
| `POST` | `/session/:id/unrevert` | استعادة جميع الرسائل المتراجع عنها | يعيد `boolean` |
| `POST` | `/session/:id/permissions/:permissionID` | الرد على طلب إذن | المتن: `{ response, remember? }`، يعيد `boolean` |
---
### الرسائل
| الطريقة | المسار | الوصف | الملاحظات |
| ------- | --------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET` | `/session/:id/message` | سرد رسائل جلسة | الاستعلام: `limit?`، يعيد `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}[]` |
| `POST` | `/session/:id/message` | إرسال رسالة والانتظار للحصول على رد | المتن: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`، يعيد `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}` |
| `GET` | `/session/:id/message/:messageID` | الحصول على تفاصيل الرسالة | يعيد `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}` |
| `POST` | `/session/:id/prompt_async` | إرسال رسالة بشكل غير متزامن (بدون انتظار) | المتن: مثل `/session/:id/message`، يعيد `204 No Content` |
| `POST` | `/session/:id/command` | تنفيذ أمر شرطة مائلة (slash) | المتن: `{ messageID?, agent?, model?, command, arguments }`، يعيد `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}` |
| `POST` | `/session/:id/shell` | تشغيل أمر في الصدفة (shell) | المتن: `{ agent, model?, command }`، يعيد `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}` |
---
### الأوامر
| الطريقة | المسار | الوصف | الاستجابة |
| ------- | ---------- | ---------------- | --------------------------------------------- |
| `GET` | `/command` | سرد جميع الأوامر | <a href={typesUrl}><code>Command[]</code></a> |
---
### الملفات
| الطريقة | المسار | الوصف | الاستجابة |
| ------- | ------------------------ | ----------------------------------- | --------------------------------------------------------------------------------------------------- |
| `GET` | `/find?pattern=<pat>` | البحث عن نص داخل الملفات | مصفوفة من كائنات المطابقة تحتوي على `path` و`lines` و`line_number` و`absolute_offset` و`submatches` |
| `GET` | `/find/file?query=<q>` | العثور على الملفات والمجلدات بالاسم | `string[]` (مسارات) |
| `GET` | `/find/symbol?query=<q>` | العثور على رموز مساحة العمل | <a href={typesUrl}><code>Symbol[]</code></a> |
| `GET` | `/file?path=<path>` | سرد الملفات والمجلدات | <a href={typesUrl}><code>FileNode[]</code></a> |
| `GET` | `/file/content?path=<p>` | قراءة ملف | <a href={typesUrl}><code>FileContent</code></a> |
| `GET` | `/file/status` | الحصول على حالة الملفات المتعقّبة | <a href={typesUrl}><code>File[]</code></a> |
#### معلمات الاستعلام لـ `/find/file`
- `query` (مطلوب) — سلسلة البحث (مطابقة ضبابية)
- `type` (اختياري) — حصر النتائج في `"file"` أو `"directory"`
- `directory` (اختياري) — تجاوز جذر المشروع لأجل البحث
- `limit` (اختياري) — الحد الأقصى للنتائج (1200)
- `dirs` (اختياري) — خيار قديم (إرجاع `"false"` يعيد الملفات فقط)
---
### الأدوات (تجريبية)
| الطريقة | المسار | الوصف | الاستجابة |
| ------- | ------------------------------------------- | --------------------------------- | -------------------------------------------- |
| `GET` | `/experimental/tool/ids` | سرد جميع معرّفات الأدوات | <a href={typesUrl}><code>ToolIDs</code></a> |
| `GET` | `/experimental/tool?provider=<p>&model=<m>` | سرد الأدوات مع مخططات JSON لنموذج | <a href={typesUrl}><code>ToolList</code></a> |
---
### LSP والمنسّقات و MCP
| الطريقة | المسار | الوصف | الاستجابة |
| ------- | ------------ | ------------------------- | -------------------------------------------------------- |
| `GET` | `/lsp` | الحصول على حالة خادم LSP | <a href={typesUrl}><code>LSPStatus[]</code></a> |
| `GET` | `/formatter` | الحصول على حالة المنسّقات | <a href={typesUrl}><code>FormatterStatus[]</code></a> |
| `GET` | `/mcp` | الحصول على حالة خادم MCP | `{ [name: string]: `<a href={typesUrl}>MCPStatus</a>` }` |
| `POST` | `/mcp` | إضافة خادم MCP ديناميكيا | المتن: `{ name, config }`، يعيد كائن حالة MCP |
---
### الوكلاء
| الطريقة | المسار | الوصف | الاستجابة |
| ------- | -------- | ------------------------- | ------------------------------------------- |
| `GET` | `/agent` | سرد جميع الوكلاء المتاحين | <a href={typesUrl}><code>Agent[]</code></a> |
---
### التسجيل
| الطريقة | المسار | الوصف | الاستجابة |
| ------- | ------ | ------------------------------------------------------------- | --------- |
| `POST` | `/log` | كتابة إدخال سجل. المتن: `{ service, level, message, extra? }` | `boolean` |
---
### TUI
| الطريقة | المسار | الوصف | الاستجابة |
| ------- | ----------------------- | ------------------------------------------ | ------------- |
| `POST` | `/tui/append-prompt` | إلحاق نص بالموجّه | `boolean` |
| `POST` | `/tui/open-help` | فتح مربع حوار المساعدة | `boolean` |
| `POST` | `/tui/open-sessions` | فتح محدد الجلسات | `boolean` |
| `POST` | `/tui/open-themes` | فتح محدد السمات | `boolean` |
| `POST` | `/tui/open-models` | فتح محدد النماذج | `boolean` |
| `POST` | `/tui/submit-prompt` | إرسال الموجّه الحالي | `boolean` |
| `POST` | `/tui/clear-prompt` | مسح الموجّه | `boolean` |
| `POST` | `/tui/execute-command` | تنفيذ أمر (`{ command }`) | `boolean` |
| `POST` | `/tui/show-toast` | عرض toast (`{ title?, message, variant }`) | `boolean` |
| `GET` | `/tui/control/next` | الانتظار لطلب التحكم التالي | كائن طلب تحكم |
| `POST` | `/tui/control/response` | الاستجابة لطلب تحكم (`{ body }`) | `boolean` |
---
### المصادقة
| الطريقة | المسار | الوصف | الاستجابة |
| ------- | ----------- | ------------------------------------------------------------- | --------- |
| `PUT` | `/auth/:id` | تعيين بيانات اعتماد المصادقة. يجب أن يطابق المتن مخطط المزوّد | `boolean` |
---
### الأحداث
| الطريقة | المسار | الوصف | الاستجابة |
| ------- | -------- | -------------------------------------------------------------------------------- | -------------------------- |
| `GET` | `/event` | تدفق أحداث مرسلة من الخادم (SSE). أول حدث هو `server.connected` ثم أحداث الحافلة | تدفق أحداث مرسلة من الخادم |
---
### التوثيق
| الطريقة | المسار | الوصف | الاستجابة |
| ------- | ------ | ------------------ | ------------------------------ |
| `GET` | `/doc` | مواصفة OpenAPI 3.1 | صفحة HTML تتضمن مواصفة OpenAPI |

View File

@@ -0,0 +1,127 @@
---
title: المشاركة
description: شارك محادثات OpenCode الخاصة بك.
---
تتيح لك ميزة المشاركة في OpenCode إنشاء روابط عامة لمحادثات OpenCode الخاصة بك، بحيث يمكنك التعاون مع زملائك أو الحصول على المساعدة من الآخرين.
:::note
المحادثات المشتركة متاحة للعامة لأي شخص لديه الرابط.
:::
---
## كيف تعمل
عند مشاركة محادثة، يقوم OpenCode بما يلي:
1. ينشئ عنوان URL عاما فريدا لجلستك
2. يزامن سجل محادثتك مع خوادمنا
3. يجعل المحادثة متاحة عبر رابط قابل للمشاركة — `opncd.ai/s/<share-id>`
---
## المشاركة
يدعم OpenCode ثلاثة أوضاع للمشاركة تتحكم في كيفية مشاركة المحادثات:
---
### يدوي (افتراضي)
افتراضيا، يستخدم OpenCode وضع المشاركة اليدوي. لا تتم مشاركة الجلسات تلقائيا، لكن يمكنك مشاركتها يدويا باستخدام الأمر `/share`:
```
/share
```
سيُنشئ هذا عنوان URL فريدا وسيُنسخ إلى الحافظة.
لضبط الوضع اليدوي صراحة في [ملف الإعدادات](/docs/config):
```json title="opencode.json"
{
"$schema": "https://opncd.ai/config.json",
"share": "manual"
}
```
---
### المشاركة التلقائية
يمكنك تفعيل المشاركة التلقائية لجميع المحادثات الجديدة عبر ضبط خيار `share` إلى `"auto"` في [ملف الإعدادات](/docs/config):
```json title="opencode.json"
{
"$schema": "https://opncd.ai/config.json",
"share": "auto"
}
```
عند تفعيل المشاركة التلقائية، ستتم مشاركة كل محادثة جديدة تلقائيا وسيتم إنشاء رابط لها.
---
### معطلة
يمكنك تعطيل المشاركة بالكامل عبر ضبط خيار `share` إلى `"disabled"` في [ملف الإعدادات](/docs/config):
```json title="opencode.json"
{
"$schema": "https://opncd.ai/config.json",
"share": "disabled"
}
```
لفرض ذلك على مستوى فريقك لمشروع معين، أضفه إلى ملف `opencode.json` في مشروعك ثم قم بإدراجه في Git.
---
## إلغاء المشاركة
لإيقاف مشاركة محادثة وإزالتها من الوصول العام:
```
/unshare
```
سيؤدي ذلك إلى إزالة رابط المشاركة وحذف البيانات المتعلقة بالمحادثة.
---
## الخصوصية
هناك بعض الأمور التي ينبغي وضعها في الاعتبار عند مشاركة محادثة.
---
### الاحتفاظ بالبيانات
تظل المحادثات المشتركة متاحة حتى تقوم بإلغاء مشاركتها صراحة. يشمل ذلك:
- سجل المحادثة كاملا
- جميع الرسائل والردود
- بيانات تعريف الجلسة
---
### توصيات
- شارك فقط المحادثات التي لا تتضمن معلومات حساسة.
- راجع محتوى المحادثة قبل مشاركتها.
- ألغِ مشاركة المحادثات عند اكتمال التعاون.
- تجنب مشاركة المحادثات التي تتضمن شيفرة مملوكة أو بيانات سرية.
- للمشاريع الحساسة، عطّل المشاركة بالكامل.
---
## للمؤسسات
في عمليات النشر الخاصة بالمؤسسات، يمكن أن تكون ميزة المشاركة:
- **معطلة** بالكامل للامتثال الأمني
- **مقيدة** على المستخدمين الموثقين عبر SSO فقط
- **مستضافة ذاتيا** على بنيتك التحتية الخاصة
[تعرّف على المزيد](/docs/enterprise) حول استخدام OpenCode في مؤسستك.

View File

@@ -0,0 +1,222 @@
---
title: "مهارات الوكيل"
description: "عرّف سلوكاً قابلاً لإعادة الاستخدام عبر تعريفات SKILL.md"
---
تتيح مهارات الوكيل لـ OpenCode اكتشاف تعليمات قابلة لإعادة الاستخدام من مستودعك أو من دليل المنزل.
تُحمَّل المهارات عند الطلب عبر أداة `skill` المدمجة — يرى الوكلاء المهارات المتاحة ويمكنهم تحميل المحتوى الكامل عند الحاجة.
---
## وضع الملفات
أنشئ مجلداً واحداً لكل اسم مهارة وضع بداخله ملف `SKILL.md`.
يبحث OpenCode في هذه المواقع:
- إعدادات المشروع: `.opencode/skills/<name>/SKILL.md`
- إعدادات عامة: `~/.config/opencode/skills/<name>/SKILL.md`
- مشروع متوافق مع Claude: `.claude/skills/<name>/SKILL.md`
- عام متوافق مع Claude: `~/.claude/skills/<name>/SKILL.md`
- مشروع متوافق مع الوكلاء: `.agents/skills/<name>/SKILL.md`
- عام متوافق مع الوكلاء: `~/.agents/skills/<name>/SKILL.md`
---
## فهم الاكتشاف
بالنسبة لمسارات المشروع المحلية، يتدرج OpenCode صعوداً من دليل العمل الحالي حتى يصل إلى `git worktree`.
ويحمّل أي ملفات مطابقة لـ `skills/*/SKILL.md` داخل `.opencode/` وأي ملفات مطابقة لـ `.claude/skills/*/SKILL.md` أو `.agents/skills/*/SKILL.md` على طول الطريق.
كما تُحمَّل التعريفات العامة أيضاً من `~/.config/opencode/skills/*/SKILL.md` و `~/.claude/skills/*/SKILL.md` و `~/.agents/skills/*/SKILL.md`.
---
## كتابة بيانات `frontmatter`
يجب أن يبدأ كل ملف `SKILL.md` بـ `frontmatter` بتنسيق YAML.
لا يتم التعرف إلا على الحقول التالية:
- `name` (مطلوب)
- `description` (مطلوب)
- `license` (اختياري)
- `compatibility` (اختياري)
- `metadata` (اختياري، خريطة من سلسلة إلى سلسلة)
يتم تجاهل أي حقول `frontmatter` غير معروفة.
---
## التحقق من الأسماء
يجب أن يكون `name`:
- بطول 164 حرفاً
- أحرفاً وأرقاماً بحروف صغيرة مع فواصل شرطة مفردة
- لا يبدأ ولا ينتهي بـ `-`
- لا يحتوي على `--` متتالية
- يطابق اسم الدليل الذي يحتوي على `SKILL.md`
التعبير النمطي المكافئ:
```text
^[a-z0-9]+(-[a-z0-9]+)*$
```
---
## اتباع قواعد الطول
يجب أن يكون `description` بطول 1-1024 حرفاً.
اجعله محدداً بما يكفي كي يختار الوكيل بشكل صحيح.
---
## استخدم مثالاً
أنشئ `.opencode/skills/git-release/SKILL.md` بهذا الشكل:
```markdown
---
name: git-release
description: Create consistent releases and changelogs
license: MIT
compatibility: opencode
metadata:
audience: maintainers
workflow: github
---
## What I do
- Draft release notes from merged PRs
- Propose a version bump
- Provide a copy-pasteable `gh release create` command
## When to use me
Use this when you are preparing a tagged release.
Ask clarifying questions if the target versioning scheme is unclear.
```
---
## التعرّف على وصف الأداة
يعرض OpenCode المهارات المتاحة في وصف أداة `skill`.
يتضمن كل إدخال اسم المهارة ووصفها:
```xml
<available_skills>
<skill>
<name>git-release</name>
<description>Create consistent releases and changelogs</description>
</skill>
</available_skills>
```
يقوم الوكيل بتحميل مهارة عبر استدعاء الأداة:
```
skill({ name: "git-release" })
```
---
## تهيئة الصلاحيات
تحكم في المهارات التي يمكن للوكلاء الوصول إليها باستخدام صلاحيات مبنية على أنماط داخل `opencode.json`:
```json
{
"permission": {
"skill": {
"*": "allow",
"pr-review": "allow",
"internal-*": "deny",
"experimental-*": "ask"
}
}
}
```
| الصلاحية | السلوك |
| -------- | -------------------------------------- |
| `allow` | تُحمَّل المهارة فوراً |
| `deny` | تُخفى المهارة عن الوكيل ويُرفض الوصول |
| `ask` | يُطلب من المستخدم الموافقة قبل التحميل |
تدعم الأنماط أحرف البدل: يطابق `internal-*` كلاً من `internal-docs` و `internal-tools` وغير ذلك.
---
## تجاوز الإعدادات لكل وكيل
امنح وكلاء محددين صلاحيات مختلفة عن الإعدادات الافتراضية العامة.
**للوكلاء المخصصين** (في `frontmatter` الخاص بالوكيل):
```yaml
---
permission:
skill:
"documents-*": "allow"
---
```
**للوكلاء المدمجين** (في `opencode.json`):
```json
{
"agent": {
"plan": {
"permission": {
"skill": {
"internal-*": "allow"
}
}
}
}
}
```
---
## تعطيل أداة skill
عطّل المهارات بالكامل للوكلاء الذين لا ينبغي أن يستخدموها:
**للوكلاء المخصصين**:
```yaml
---
tools:
skill: false
---
```
**للوكلاء المدمجين**:
```json
{
"agent": {
"plan": {
"tools": {
"skill": false
}
}
}
}
```
عند تعطيلها، يتم حذف قسم `<available_skills>` بالكامل.
---
## استكشاف أخطاء التحميل
إذا لم تظهر مهارة:
1. تحقّق من أن `SKILL.md` مكتوب بأحرف كبيرة بالكامل
2. تحقّق من أن `frontmatter` تتضمن `name` و `description`
3. تأكد من أن أسماء المهارات فريدة عبر جميع المواقع
4. تحقّق من الصلاحيات — المهارات ذات `deny` تكون مخفية عن الوكلاء

View File

@@ -0,0 +1,369 @@
---
title: السمات
description: اختر سمة مدمجة أو عرّف سمة خاصة بك.
---
مع OpenCode يمكنك الاختيار من بين عدة سمات مدمجة، أو استخدام سمة تتكيّف مع سمة طرفيتك، أو تعريف سمة مخصصة خاصة بك.
افتراضيًا، يستخدم OpenCode سمتنا `opencode`.
---
## متطلبات الطرفية
لكي تُعرض السمات بشكل صحيح مع لوحة ألوانها الكاملة، يجب أن تدعم طرفيتك **truecolor** (ألوان 24-بت). تدعم معظم الطرفيات الحديثة ذلك افتراضيًا، لكن قد تحتاج إلى تفعيله:
- **التحقق من الدعم**: شغّل `echo $COLORTERM` - يجب أن يطبع `truecolor` أو `24bit`
- **تفعيل truecolor**: اضبط متغير البيئة `COLORTERM=truecolor` في ملف إعدادات الصدفة
- **توافق الطرفية**: تأكد من أن محاكي الطرفية يدعم ألوان 24-بت (معظم الطرفيات الحديثة مثل iTerm2 وAlacritty وKitty وWindows Terminal والإصدارات الحديثة من GNOME Terminal تدعم ذلك)
بدون دعم truecolor، قد تظهر السمات بدقة ألوان أقل أو تعود إلى أقرب تقريب ضمن 256 لونًا.
---
## السمات المدمجة
يأتي OpenCode مع عدة سمات مدمجة.
| الاسم | الوصف |
| ---------------------- | --------------------------------------------------------------------------- |
| `system` | يتكيّف مع لون خلفية طرفيتك |
| `tokyonight` | مبني على سمة [Tokyonight](https://github.com/folke/tokyonight.nvim) |
| `everforest` | مبني على سمة [Everforest](https://github.com/sainnhe/everforest) |
| `ayu` | مبني على السمة الداكنة [Ayu](https://github.com/ayu-theme) |
| `catppuccin` | مبني على سمة [Catppuccin](https://github.com/catppuccin) |
| `catppuccin-macchiato` | مبني على سمة [Catppuccin](https://github.com/catppuccin) |
| `gruvbox` | مبني على سمة [Gruvbox](https://github.com/morhetz/gruvbox) |
| `kanagawa` | مبني على سمة [Kanagawa](https://github.com/rebelot/kanagawa.nvim) |
| `nord` | مبني على سمة [Nord](https://github.com/nordtheme/nord) |
| `matrix` | سمة خضراء على أسود بأسلوب الهاكر |
| `one-dark` | مبني على السمة الداكنة [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) |
وغير ذلك؛ نضيف سمات جديدة باستمرار.
---
## سمة النظام
صُممت سمة `system` لتتكيّف تلقائيًا مع مخطط ألوان طرفيتك. وعلى عكس السمات التقليدية التي تستخدم ألوانًا ثابتة، فإن سمة _system_:
- **توليد تدرج رمادي**: تنشئ تدرجًا رماديًا مخصصًا اعتمادًا على لون خلفية طرفيتك، بما يضمن أفضل تباين.
- **استخدام ألوان ANSI**: تستفيد من ألوان ANSI القياسية (0-15) لإبراز الصياغة وعناصر الواجهة، والتي تحترم لوحة ألوان طرفيتك.
- **الحفاظ على افتراضيات الطرفية**: تستخدم `none` لألوان النص والخلفية للحفاظ على مظهر طرفيتك الأصلي.
سمة النظام مناسبة للمستخدمين الذين:
- يريدون أن يطابق OpenCode مظهر طرفيتهم
- يستخدمون مخططات ألوان مخصصة للطرفية
- يفضلون مظهرًا متسقًا عبر جميع تطبيقات الطرفية
---
## استخدام سمة
يمكنك اختيار سمة بفتح منتقي السمات باستخدام الأمر `/theme`. أو يمكنك تحديدها في [الضبط](/docs/config).
```json title="opencode.json" {3}
{
"$schema": "https://opencode.ai/config.json",
"theme": "tokyonight"
}
```
---
## سمات مخصصة
يدعم OpenCode نظام سمات مرنًا قائمًا على JSON يتيح للمستخدمين إنشاء السمات وتخصيصها بسهولة.
---
### التسلسل الهرمي
تُحمَّل السمات من عدة مجلدات بالترتيب التالي، حيث تتجاوز المجلدات اللاحقة المجلدات السابقة:
1. **السمات المدمجة** - تكون مضمنة داخل الملف التنفيذي
2. **مجلد ضبط المستخدم** - معرّف في `~/.config/opencode/themes/*.json` أو `$XDG_CONFIG_HOME/opencode/themes/*.json`
3. **مجلد جذر المشروع** - معرّف في `<project-root>/.opencode/themes/*.json`
4. **مجلد العمل الحالي** - معرّف في `./.opencode/themes/*.json`
إذا احتوت عدة مجلدات على سمة بالاسم نفسه، فستُستخدم السمة من المجلد ذي الأولوية الأعلى.
---
### إنشاء سمة
لإنشاء سمة مخصصة، أنشئ ملف JSON في أحد مجلدات السمات.
للسمات على مستوى المستخدم:
```bash no-frame
mkdir -p ~/.config/opencode/themes
vim ~/.config/opencode/themes/my-theme.json
```
وللسمات الخاصة بالمشروع:
```bash no-frame
mkdir -p .opencode/themes
vim .opencode/themes/my-theme.json
```
---
### تنسيق JSON
تستخدم السمات تنسيق JSON مرنًا مع دعم لـ:
- **ألوان سداسية عشرية**: `"#ffffff"`
- **ألوان ANSI**: `3` (0-255)
- **مراجع الألوان**: `"primary"` أو تعريفات مخصصة
- **متغيرات داكن/فاتح**: `{"dark": "#000", "light": "#fff"}`
- **بدون لون**: `"none"` - يستخدم اللون الافتراضي للطرفية أو يكون شفافًا
---
### تعريفات الألوان
قسم `defs` اختياري، ويتيح لك تعريف ألوان قابلة لإعادة الاستخدام يمكن الإشارة إليها داخل السمة.
---
### افتراضيات الطرفية
يمكن استخدام القيمة الخاصة `"none"` لأي لون لوراثة اللون الافتراضي للطرفية. هذا مفيد خصوصًا لإنشاء سمات تمتزج بسلاسة مع مخطط ألوان طرفيتك:
- `"text": "none"` - يستخدم لون المقدمة الافتراضي للطرفية
- `"background": "none"` - يستخدم لون الخلفية الافتراضي للطرفية
---
### مثال
إليك مثالًا على سمة مخصصة:
```json title="my-theme.json"
{
"$schema": "https://opencode.ai/theme.json",
"defs": {
"nord0": "#2E3440",
"nord1": "#3B4252",
"nord2": "#434C5E",
"nord3": "#4C566A",
"nord4": "#D8DEE9",
"nord5": "#E5E9F0",
"nord6": "#ECEFF4",
"nord7": "#8FBCBB",
"nord8": "#88C0D0",
"nord9": "#81A1C1",
"nord10": "#5E81AC",
"nord11": "#BF616A",
"nord12": "#D08770",
"nord13": "#EBCB8B",
"nord14": "#A3BE8C",
"nord15": "#B48EAD"
},
"theme": {
"primary": {
"dark": "nord8",
"light": "nord10"
},
"secondary": {
"dark": "nord9",
"light": "nord9"
},
"accent": {
"dark": "nord7",
"light": "nord7"
},
"error": {
"dark": "nord11",
"light": "nord11"
},
"warning": {
"dark": "nord12",
"light": "nord12"
},
"success": {
"dark": "nord14",
"light": "nord14"
},
"info": {
"dark": "nord8",
"light": "nord10"
},
"text": {
"dark": "nord4",
"light": "nord0"
},
"textMuted": {
"dark": "nord3",
"light": "nord1"
},
"background": {
"dark": "nord0",
"light": "nord6"
},
"backgroundPanel": {
"dark": "nord1",
"light": "nord5"
},
"backgroundElement": {
"dark": "nord1",
"light": "nord4"
},
"border": {
"dark": "nord2",
"light": "nord3"
},
"borderActive": {
"dark": "nord3",
"light": "nord2"
},
"borderSubtle": {
"dark": "nord2",
"light": "nord3"
},
"diffAdded": {
"dark": "nord14",
"light": "nord14"
},
"diffRemoved": {
"dark": "nord11",
"light": "nord11"
},
"diffContext": {
"dark": "nord3",
"light": "nord3"
},
"diffHunkHeader": {
"dark": "nord3",
"light": "nord3"
},
"diffHighlightAdded": {
"dark": "nord14",
"light": "nord14"
},
"diffHighlightRemoved": {
"dark": "nord11",
"light": "nord11"
},
"diffAddedBg": {
"dark": "#3B4252",
"light": "#E5E9F0"
},
"diffRemovedBg": {
"dark": "#3B4252",
"light": "#E5E9F0"
},
"diffContextBg": {
"dark": "nord1",
"light": "nord5"
},
"diffLineNumber": {
"dark": "nord2",
"light": "nord4"
},
"diffAddedLineNumberBg": {
"dark": "#3B4252",
"light": "#E5E9F0"
},
"diffRemovedLineNumberBg": {
"dark": "#3B4252",
"light": "#E5E9F0"
},
"markdownText": {
"dark": "nord4",
"light": "nord0"
},
"markdownHeading": {
"dark": "nord8",
"light": "nord10"
},
"markdownLink": {
"dark": "nord9",
"light": "nord9"
},
"markdownLinkText": {
"dark": "nord7",
"light": "nord7"
},
"markdownCode": {
"dark": "nord14",
"light": "nord14"
},
"markdownBlockQuote": {
"dark": "nord3",
"light": "nord3"
},
"markdownEmph": {
"dark": "nord12",
"light": "nord12"
},
"markdownStrong": {
"dark": "nord13",
"light": "nord13"
},
"markdownHorizontalRule": {
"dark": "nord3",
"light": "nord3"
},
"markdownListItem": {
"dark": "nord8",
"light": "nord10"
},
"markdownListEnumeration": {
"dark": "nord7",
"light": "nord7"
},
"markdownImage": {
"dark": "nord9",
"light": "nord9"
},
"markdownImageText": {
"dark": "nord7",
"light": "nord7"
},
"markdownCodeBlock": {
"dark": "nord4",
"light": "nord0"
},
"syntaxComment": {
"dark": "nord3",
"light": "nord3"
},
"syntaxKeyword": {
"dark": "nord9",
"light": "nord9"
},
"syntaxFunction": {
"dark": "nord8",
"light": "nord8"
},
"syntaxVariable": {
"dark": "nord7",
"light": "nord7"
},
"syntaxString": {
"dark": "nord14",
"light": "nord14"
},
"syntaxNumber": {
"dark": "nord15",
"light": "nord15"
},
"syntaxType": {
"dark": "nord7",
"light": "nord7"
},
"syntaxOperator": {
"dark": "nord9",
"light": "nord9"
},
"syntaxPunctuation": {
"dark": "nord4",
"light": "nord0"
}
}
}
```

View File

@@ -0,0 +1,379 @@
---
title: الأدوات
description: إدارة الأدوات التي يمكن لـ LLM استخدامها.
---
تتيح الأدوات لـ LLM تنفيذ إجراءات داخل قاعدة الشفرة الخاصة بك. يأتي OpenCode مع مجموعة من الأدوات المدمجة، لكن يمكنك توسيعه عبر [أدوات مخصصة](/docs/custom-tools) أو [خوادم MCP](/docs/mcp-servers).
افتراضيا، تكون جميع الأدوات **مفعلة** ولا تحتاج إلى إذن للتشغيل. يمكنك التحكم في سلوك الأدوات عبر [الأذونات](/docs/permissions).
---
## التهيئة
استخدم الحقل `permission` للتحكم في سلوك الأدوات. يمكنك السماح أو الرفض أو طلب الموافقة لكل أداة.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"edit": "deny",
"bash": "ask",
"webfetch": "allow"
}
}
```
يمكنك أيضا استخدام أحرف البدل للتحكم في عدة أدوات دفعة واحدة. على سبيل المثال، لطلب الموافقة على جميع الأدوات القادمة من خادم MCP:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"mymcp_*": "ask"
}
}
```
[اعرف المزيد](/docs/permissions) حول تهيئة الأذونات.
---
## المدمجة
فيما يلي جميع الأدوات المدمجة المتاحة في OpenCode.
---
### bash
نفذ أوامر الصدفة (Shell) في بيئة مشروعك.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"bash": "allow"
}
}
```
تتيح هذه الأداة لـ LLM تشغيل أوامر الطرفية مثل `npm install` و`git status` أو أي أمر صدفة آخر.
---
### edit
عدّل الملفات الموجودة باستخدام استبدال نصي مطابق تماما.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"edit": "allow"
}
}
```
تجري هذه الأداة تعديلات دقيقة على الملفات عبر استبدال مقاطع نصية متطابقة. وهي الطريقة الأساسية التي يعدّل بها LLM الشفرة.
---
### write
أنشئ ملفات جديدة أو اكتب فوق الملفات الموجودة.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"edit": "allow"
}
}
```
استخدم هذا للسماح لـ LLM بإنشاء ملفات جديدة. سيكتب فوق الملفات الموجودة إذا كانت موجودة بالفعل.
:::note
تُدار أداة `write` عبر إذن `edit`، والذي يشمل جميع تعديلات الملفات (`edit` و`write` و`patch` و`multiedit`).
:::
---
### read
اقرأ محتويات الملفات من قاعدة الشفرة الخاصة بك.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"read": "allow"
}
}
```
تقرأ هذه الأداة الملفات وتعيد محتوياتها. وتدعم قراءة نطاقات محددة من الأسطر للملفات الكبيرة.
---
### grep
ابحث في محتوى الملفات باستخدام التعابير النمطية (Regex).
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"grep": "allow"
}
}
```
بحث سريع في المحتوى عبر قاعدة الشفرة الخاصة بك. يدعم صياغة Regex الكاملة وتصفية الملفات عبر أنماط المسارات.
---
### glob
اعثر على الملفات عبر مطابقة الأنماط.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"glob": "allow"
}
}
```
ابحث عن الملفات باستخدام أنماط glob مثل `**/*.js` أو `src/**/*.ts`. يعيد مسارات الملفات المطابقة مرتبة حسب وقت التعديل.
---
### list
اعرض قائمة بالملفات والمجلدات في مسار محدد.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"list": "allow"
}
}
```
تعرض هذه الأداة محتويات المجلد. وتقبل أنماط glob لتصفية النتائج.
---
### lsp (experimental)
تفاعل مع خوادم LSP التي قمت بتهيئتها للحصول على ميزات ذكاء الشفرة مثل التعاريف والمراجع ومعلومات التحويم وتسلسل الاستدعاءات.
:::note
هذه الأداة متاحة فقط عند ضبط `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (أو `OPENCODE_EXPERIMENTAL=true`).
:::
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"lsp": "allow"
}
}
```
تتضمن العمليات المدعومة: `goToDefinition` و`findReferences` و`hover` و`documentSymbol` و`workspaceSymbol` و`goToImplementation` و`prepareCallHierarchy` و`incomingCalls` و`outgoingCalls`.
لتهيئة خوادم LSP المتاحة لمشروعك، راجع [خوادم LSP](/docs/lsp).
---
### patch
طبّق الرقع (Patches) على الملفات.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"edit": "allow"
}
}
```
تطبق هذه الأداة ملفات الرقع على قاعدة الشفرة الخاصة بك. وهي مفيدة لتطبيق الفروقات (Diffs) والرقع من مصادر متعددة.
:::note
تُدار أداة `patch` عبر إذن `edit`، والذي يشمل جميع تعديلات الملفات (`edit` و`write` و`patch` و`multiedit`).
:::
---
### skill
حمّل [مهارة](/docs/skills) (ملف `SKILL.md`) وأعد محتواها ضمن المحادثة.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"skill": "allow"
}
}
```
---
### todowrite
أدِر قوائم المهام أثناء جلسات البرمجة.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"todowrite": "allow"
}
}
```
تنشئ هذه الأداة قوائم المهام وتحدّثها لتتبع التقدم أثناء العمليات المعقدة. يستخدمها LLM لتنظيم المهام متعددة الخطوات.
:::note
هذه الأداة معطلة للوكلاء الفرعيين افتراضيا، لكن يمكنك تفعيلها يدويا. [اعرف المزيد](/docs/agents/#permissions)
:::
---
### todoread
اقرأ قوائم المهام الموجودة.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"todoread": "allow"
}
}
```
تقرأ هذه الأداة الحالة الحالية لقائمة المهام. يستخدمها LLM لتتبع المهام المعلقة أو المكتملة.
:::note
هذه الأداة معطلة للوكلاء الفرعيين افتراضيا، لكن يمكنك تفعيلها يدويا. [اعرف المزيد](/docs/agents/#permissions)
:::
---
### webfetch
اجلب محتوى الويب.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"webfetch": "allow"
}
}
```
تتيح هذه الأداة لـ LLM جلب صفحات الويب وقراءتها. وهي مفيدة للبحث عن التوثيق أو لاستكشاف موارد عبر الإنترنت.
---
### websearch
ابحث في الويب عن معلومات.
:::note
هذه الأداة متاحة فقط عند استخدام مزود OpenCode أو عند ضبط متغير البيئة `OPENCODE_ENABLE_EXA` على أي قيمة منطقية صحيحة (مثل `true` أو `1`).
للتفعيل عند تشغيل OpenCode:
```bash
OPENCODE_ENABLE_EXA=1 opencode
```
:::
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"websearch": "allow"
}
}
```
تجري عمليات بحث على الويب باستخدام Exa AI للعثور على معلومات ذات صلة عبر الإنترنت. وهي مفيدة للبحث في المواضيع، والعثور على أحداث جارية، أو جمع معلومات تتجاوز حد بيانات التدريب.
لا يلزم مفتاح API - إذ تتصل الأداة مباشرة بخدمة MCP المستضافة لدى Exa AI دون مصادقة.
:::tip
استخدم `websearch` عندما تحتاج إلى العثور على معلومات (Discovery)، واستخدم `webfetch` عندما تحتاج إلى جلب محتوى من رابط محدد (Retrieval).
:::
---
### question
اطرح على المستخدم أسئلة أثناء التنفيذ.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"question": "allow"
}
}
```
تتيح هذه الأداة لـ LLM طرح أسئلة على المستخدم أثناء المهمة. وهي مفيدة من أجل:
- جمع تفضيلات المستخدم أو متطلباته
- توضيح التعليمات غير الواضحة
- الحصول على قرارات حول خيارات التنفيذ
- تقديم خيارات حول الاتجاه الذي يجب اتباعه
يتضمن كل سؤال عنوانا ونص السؤال وقائمة بالخيارات. يمكن للمستخدمين الاختيار من الخيارات المتاحة أو كتابة إجابة مخصصة. وعند وجود عدة أسئلة، يمكن للمستخدمين التنقل بينها قبل إرسال جميع الإجابات.
---
## أدوات مخصصة
تتيح لك الأدوات المخصصة تعريف دوالك الخاصة التي يمكن لـ LLM استدعاؤها. تُعرّف هذه الأدوات في ملف التهيئة ويمكنها تنفيذ شفرة عشوائية.
[اعرف المزيد](/docs/custom-tools) حول إنشاء أدوات مخصصة.
---
## خوادم MCP
تتيح لك خوادم MCP (Model Context Protocol) دمج أدوات وخدمات خارجية. يشمل ذلك الوصول إلى قواعد البيانات وتكاملات API وخدمات الجهات الخارجية.
[اعرف المزيد](/docs/mcp-servers) حول تهيئة خوادم MCP.
---
## التفاصيل الداخلية
داخليا، تستخدم أدوات مثل `grep` و`glob` و`list` أداة [ripgrep](https://github.com/BurntSushi/ripgrep) في الخلفية. افتراضيا، يحترم ripgrep أنماط `.gitignore`، ما يعني أن الملفات والمجلدات المدرجة في `.gitignore` ستُستبعد من عمليات البحث وعرض القوائم.
---
### Ignore patterns
لتضمين ملفات يتم تجاهلها عادة، أنشئ ملف `.ignore` في جذر المشروع. يمكن لهذا الملف السماح صراحة بمسارات محددة.
```text title=".ignore"
!node_modules/
!dist/
!build/
```
على سبيل المثال، يسمح ملف `.ignore` هذا لـ ripgrep بالبحث داخل مجلدات `node_modules/` و`dist/` و`build/` حتى لو كانت مدرجة في `.gitignore`.

View File

@@ -0,0 +1,299 @@
---
title: استكشاف الأخطاء وإصلاحها
description: المشكلات الشائعة وكيفية حلها.
---
لاستكشاف المشكلات في OpenCode وإصلاحها، ابدأ بالتحقق من السجلات والبيانات المحلية التي يخزنها على القرص.
---
## السجلات
يتم حفظ ملفات السجل في:
- **macOS/Linux**: `~/.local/share/opencode/log/`
- **Windows**: اضغط `WIN+R` والصق `%USERPROFILE%\.local\share\opencode\log`
تتم تسمية ملفات السجل بطوابع زمنية (مثل `2025-01-09T123456.log`) ويتم الاحتفاظ بأحدث 10 ملفات سجل.
يمكنك ضبط مستوى السجل باستخدام خيار سطر الأوامر `--log-level` للحصول على معلومات تصحيح أكثر تفصيلا. على سبيل المثال: `opencode --log-level DEBUG`.
---
## التخزين
يخزن opencode بيانات الجلسات وبيانات التطبيق الأخرى على القرص في:
- **macOS/Linux**: `~/.local/share/opencode/`
- **Windows**: اضغط `WIN+R` والصق `%USERPROFILE%\.local\share\opencode`
يحتوي هذا الدليل على:
- `auth.json` - بيانات المصادقة مثل مفاتيح API ورموز OAuth
- `log/` - سجلات التطبيق
- `project/` - بيانات خاصة بالمشروع مثل بيانات الجلسة والرسائل
- إذا كان المشروع داخل مستودع Git، فسيتم تخزينه في `./<project-slug>/storage/`
- إذا لم يكن داخل مستودع Git، فسيتم تخزينه في `./global/storage/`
---
## تطبيق سطح المكتب
يشغل OpenCode Desktop خادما محليا لـ OpenCode (العملية الجانبية `opencode-cli`) في الخلفية. معظم المشكلات سببها إضافة لا تعمل بشكل صحيح، أو ذاكرة تخزين مؤقت تالفة، أو إعداد خادم غير صحيح.
### فحوصات سريعة
- أغلق التطبيق تماما ثم أعد تشغيله.
- إذا عرض التطبيق شاشة خطأ، انقر **Restart** وانسخ تفاصيل الخطأ.
- على macOS فقط: قائمة `OpenCode` -> **Reload Webview** (يفيد إذا كانت الواجهة فارغة/متجمدة).
---
### تعطيل الإضافات
إذا كان تطبيق سطح المكتب يتعطل عند التشغيل، أو يتوقف عن الاستجابة، أو يتصرف بشكل غريب، فابدأ بتعطيل الإضافات.
#### تحقق من الإعدادات العامة
افتح ملف الإعدادات العام وابحث عن المفتاح `plugin`.
- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (أو `~/.config/opencode/opencode.json`)
- **macOS/Linux** (عمليات تثبيت أقدم): `~/.local/share/opencode/opencode.jsonc`
- **Windows**: اضغط `WIN+R` والصق `%USERPROFILE%\.config\opencode\opencode.jsonc`
إذا كانت لديك إضافات مضبوطة، فقم بتعطيلها مؤقتا بإزالة المفتاح أو ضبطه على مصفوفة فارغة:
```jsonc
{
"$schema": "https://opencode.ai/config.json",
"plugin": [],
}
```
#### تحقق من أدلة الإضافات
يمكن لـ OpenCode أيضا تحميل إضافات محلية من القرص. انقلها مؤقتا إلى مكان آخر (أو أعد تسمية المجلد) ثم أعد تشغيل تطبيق سطح المكتب:
- **إضافات عامة**
- **macOS/Linux**: `~/.config/opencode/plugins/`
- **Windows**: اضغط `WIN+R` والصق `%USERPROFILE%\.config\opencode\plugins`
- **إضافات المشروع** (فقط إذا كنت تستخدم إعدادات لكل مشروع)
- `<your-project>/.opencode/plugins/`
إذا عاد التطبيق للعمل، فأعد تفعيل الإضافات واحدة تلو الأخرى لمعرفة أيها يسبب المشكلة.
---
### مسح ذاكرة التخزين المؤقت
إذا لم يساعد تعطيل الإضافات (أو كانت عملية تثبيت إضافة عالقة)، فامسح ذاكرة التخزين المؤقت حتى يتمكن OpenCode من إعادة بنائها.
1. أغلق OpenCode Desktop تماما.
2. احذف دليل ذاكرة التخزين المؤقت:
- **macOS**: Finder -> `Cmd+Shift+G` -> الصق `~/.cache/opencode`
- **Linux**: احذف `~/.cache/opencode` (أو شغّل `rm -rf ~/.cache/opencode`)
- **Windows**: اضغط `WIN+R` والصق `%USERPROFILE%\.cache\opencode`
3. أعد تشغيل OpenCode Desktop.
---
### إصلاح مشكلات اتصال الخادم
يمكن لـ OpenCode Desktop إما تشغيل خادمه المحلي (افتراضيا) أو الاتصال بعنوان URL لخادم قمت بتهيئته.
إذا ظهرت نافذة **"Connection Failed"** (أو لم يتجاوز التطبيق شاشة البداية)، فتحقق مما إذا كان هناك عنوان URL مخصص للخادم.
#### مسح عنوان URL الافتراضي لخادم سطح المكتب
من شاشة Home، انقر اسم الخادم (مع نقطة الحالة) لفتح محدد الخوادم. في قسم **Default server**، انقر **Clear**.
#### إزالة `server.port` / `server.hostname` من الإعدادات
إذا كان `opencode.json(c)` يحتوي على قسم `server`، فأزله مؤقتا ثم أعد تشغيل تطبيق سطح المكتب.
#### تحقق من متغيرات البيئة
إذا كان `OPENCODE_PORT` مضبوطا في بيئتك، فسيحاول تطبيق سطح المكتب استخدام ذلك المنفذ للخادم المحلي.
- أزل ضبط `OPENCODE_PORT` (أو اختر منفذا متاحا) ثم أعد التشغيل.
---
### Linux: مشكلات Wayland / X11
على Linux، قد تتسبب بعض إعدادات Wayland في نوافذ فارغة أو أخطاء في مدير التركيب (compositor).
- إذا كنت تستخدم Wayland وكانت نافذة التطبيق فارغة/يتعطل، فجرّب التشغيل مع `OC_ALLOW_WAYLAND=1`.
- إذا جعل ذلك الأمور أسوأ، فأزل هذا المتغير وجرّب التشغيل ضمن جلسة X11 بدلا من ذلك.
---
### Windows: بيئة تشغيل WebView2
على Windows، يتطلب OpenCode Desktop وجود **WebView2 Runtime** الخاصة بـ Microsoft Edge. إذا فتح التطبيق نافذة فارغة أو لم يبدأ، فقم بتثبيت/تحديث WebView2 ثم جرّب مجددا.
---
### Windows: مشكلات الأداء العامة
إذا كنت تواجه بطءا في الأداء، أو مشكلات في الوصول إلى الملفات، أو مشكلات في الطرفية على Windows، فجرّب استخدام [WSL (نظام Windows الفرعي لـ Linux)](/docs/windows-wsl). يوفر WSL بيئة Linux تعمل بسلاسة أكبر مع ميزات OpenCode.
---
### الإشعارات لا تظهر
لا يعرض OpenCode Desktop إشعارات النظام إلا عندما:
- تكون الإشعارات مفعلة لـ OpenCode في إعدادات نظام التشغيل، و
- تكون نافذة التطبيق غير نشطة.
---
### إعادة تعيين تخزين تطبيق سطح المكتب (كحل أخير)
إذا لم يبدأ التطبيق ولم تتمكن من مسح الإعدادات من داخل الواجهة، فأعد تعيين الحالة المحفوظة لتطبيق سطح المكتب.
1. أغلق OpenCode Desktop.
2. اعثر على هذه الملفات واحذفها (توجد في دليل بيانات تطبيق OpenCode Desktop):
- `opencode.settings.dat` (عنوان URL الافتراضي لخادم سطح المكتب)
- `opencode.global.dat` و `opencode.workspace.*.dat` (حالة الواجهة مثل الخوادم/المشاريع الأخيرة)
للعثور على الدليل بسرعة:
- **macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (ثم ابحث عن أسماء الملفات أعلاه)
- **Linux**: ابحث ضمن `~/.local/share` عن أسماء الملفات أعلاه
- **Windows**: اضغط `WIN+R` -> `%APPDATA%` (ثم ابحث عن أسماء الملفات أعلاه)
---
## الحصول على المساعدة
إذا كنت تواجه مشكلات مع OpenCode:
1. **الإبلاغ عن المشكلات على GitHub**
أفضل طريقة للإبلاغ عن الأخطاء أو طلب الميزات هي عبر مستودعنا على GitHub:
[**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues)
قبل إنشاء مشكلة جديدة، ابحث في المشكلات الموجودة لمعرفة ما إذا كانت مشكلتك قد تم الإبلاغ عنها بالفعل.
2. **انضم إلى Discord**
للحصول على مساعدة فورية ونقاشات المجتمع، انضم إلى خادم Discord الخاص بنا:
[**opencode.ai/discord**](https://opencode.ai/discord)
---
## مشكلات شائعة
فيما يلي بعض المشكلات الشائعة وكيفية حلها.
---
### OpenCode لا يبدأ
1. تحقق من السجلات بحثا عن رسائل الخطأ
2. جرّب التشغيل مع `--print-logs` لرؤية المخرجات في الطرفية
3. تأكد من أنك تستخدم أحدث إصدار عبر `opencode upgrade`
---
### مشكلات المصادقة
1. جرّب إعادة المصادقة باستخدام الأمر `/connect` في واجهة TUI
2. تحقق من أن مفاتيح API الخاصة بك صالحة
3. تأكد من أن شبكتك تسمح بالاتصال بواجهة API الخاصة بالمزوّد
---
### النموذج غير متاح
1. تحقق من أنك قمت بالمصادقة مع المزوّد
2. تأكد من أن اسم النموذج في الإعدادات صحيح
3. قد تتطلب بعض النماذج صلاحيات وصول محددة أو اشتراكات
إذا واجهت `ProviderModelNotFoundError` فمن المرجح أنك تشير إلى نموذج بشكل غير صحيح في مكان ما.
يجب الإشارة إلى النماذج بهذه الصيغة: `<providerId>/<modelId>`
أمثلة:
- `openai/gpt-4.1`
- `openrouter/google/gemini-2.5-flash`
- `opencode/kimi-k2`
لمعرفة النماذج التي لديك صلاحية الوصول إليها، شغّل `opencode models`
---
### ProviderInitError
إذا واجهت ProviderInitError، فمن المحتمل أن إعداداتك غير صالحة أو تالفة.
لحل ذلك:
1. أولا، تحقق من أن المزوّد مضبوط بشكل صحيح باتباع [دليل المزوّدين](/docs/providers)
2. إذا استمرت المشكلة، فجرّب مسح الإعدادات المخزنة لديك:
```bash
rm -rf ~/.local/share/opencode
```
على Windows، اضغط `WIN+R` واحذف: `%USERPROFILE%\.local\share\opencode`
3. أعد المصادقة مع المزوّد باستخدام الأمر `/connect` في واجهة TUI.
---
### AI_APICallError ومشكلات حزم المزوّد
إذا واجهت أخطاء في استدعاءات API، فقد يكون السبب حزم مزوّد قديمة. يقوم opencode بتثبيت حزم المزوّد (OpenAI و Anthropic و Google وغير ذلك) ديناميكيا عند الحاجة ويقوم بتخزينها مؤقتا محليا.
لحل مشكلات حزم المزوّد:
1. امسح ذاكرة التخزين المؤقت لحزم المزوّد:
```bash
rm -rf ~/.cache/opencode
```
على Windows، اضغط `WIN+R` واحذف: `%USERPROFILE%\.cache\opencode`
2. أعد تشغيل opencode لإعادة تثبيت أحدث حزم المزوّد
سيجبر ذلك opencode على تنزيل أحدث إصدارات حزم المزوّد، وهو ما يحل غالبا مشكلات التوافق مع معاملات النماذج وتغييرات API.
---
### النسخ/اللصق لا يعمل على Linux
يحتاج مستخدمو Linux إلى تثبيت إحدى أدوات الحافظة التالية حتى تعمل ميزة النسخ/اللصق:
**لأنظمة X11:**
```bash
apt install -y xclip
# or
apt install -y xsel
```
**لأنظمة Wayland:**
```bash
apt install -y wl-clipboard
```
**للبيئات بدون واجهة رسومية (Headless):**
```bash
apt install -y xvfb
# and run:
Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
export DISPLAY=:99.0
```
سيكتشف opencode ما إذا كنت تستخدم Wayland ويفضل `wl-clipboard`، وإلا فسيحاول العثور على أدوات الحافظة بالترتيب التالي: `xclip` ثم `xsel`.

View File

@@ -0,0 +1,386 @@
---
title: TUI
description: استخدام واجهة المستخدم الطرفية (TUI) في OpenCode.
---
import { Tabs, TabItem } from "@astrojs/starlight/components"
يوفّر OpenCode واجهة طرفية تفاعلية (TUI) للعمل على مشاريعك باستخدام نموذج لغوي كبير.
يؤدي تشغيل OpenCode إلى بدء واجهة TUI للدليل الحالي.
```bash
opencode
```
أو يمكنك تشغيلها لدليل عمل محدد.
```bash
opencode /path/to/project
```
بعد الدخول إلى واجهة TUI، يمكنك إرسال رسالة كطلب.
```text
Give me a quick summary of the codebase.
```
---
## مراجع الملفات
يمكنك الإشارة إلى الملفات في رسائلك باستخدام `@`. يُجري ذلك بحثا ضبابيا عن الملفات ضمن دليل العمل الحالي.
:::tip
يمكنك أيضا استخدام `@` للإشارة إلى الملفات في رسائلك.
:::
```text "@packages/functions/src/api/index.ts"
How is auth handled in @packages/functions/src/api/index.ts?
```
تُضاف محتويات الملف إلى المحادثة تلقائيا.
---
## أوامر Bash
ابدأ الرسالة بـ `!` لتشغيل أمر في الصدفة.
```bash frame="none"
!ls -la
```
يُضاف خرج الأمر إلى المحادثة كنتيجة أداة.
---
## الأوامر
عند استخدام واجهة OpenCode الطرفية، يمكنك كتابة `/` متبوعة باسم أمر لتنفيذ الإجراءات بسرعة. مثلا:
```bash frame="none"
/help
```
تملك معظم الأوامر أيضا اختصارا باستخدام `ctrl+x` كمفتاح قائد، حيث إن `ctrl+x` هو المفتاح القائد الافتراضي. [اعرف المزيد](/docs/keybinds).
فيما يلي جميع أوامر الشرطة المائلة المتاحة:
---
### connect
أضف موفّرا إلى OpenCode. يتيح لك اختيار أحد الموفّرين المتاحين وإضافة مفاتيح API الخاصة بهم.
```bash frame="none"
/connect
```
---
### compact
قم بضغط الجلسة الحالية. _الاسم المستعار_: `/summarize`
```bash frame="none"
/compact
```
**اختصار لوحة المفاتيح:** `ctrl+x c`
---
### details
بدّل عرض تفاصيل تنفيذ الأدوات.
```bash frame="none"
/details
```
**اختصار لوحة المفاتيح:** `ctrl+x d`
---
### editor
افتح محررا خارجيا لكتابة الرسائل. يستخدم المحرر المحدد في متغير البيئة `EDITOR`. [اعرف المزيد](#editor-setup).
```bash frame="none"
/editor
```
**اختصار لوحة المفاتيح:** `ctrl+x e`
---
### exit
اخرج من OpenCode. _الأسماء المستعارة_: `/quit`, `/q`
```bash frame="none"
/exit
```
**اختصار لوحة المفاتيح:** `ctrl+x q`
---
### export
صدّر المحادثة الحالية إلى Markdown وافتحها في المحرر الافتراضي لديك. يستخدم المحرر المحدد في متغير البيئة `EDITOR`. [اعرف المزيد](#editor-setup).
```bash frame="none"
/export
```
**اختصار لوحة المفاتيح:** `ctrl+x x`
---
### help
اعرض مربع حوار المساعدة.
```bash frame="none"
/help
```
**اختصار لوحة المفاتيح:** `ctrl+x h`
---
### init
أنشئ ملف `AGENTS.md` أو حدّثه. [اعرف المزيد](/docs/rules).
```bash frame="none"
/init
```
**اختصار لوحة المفاتيح:** `ctrl+x i`
---
### models
اعرض النماذج المتاحة.
```bash frame="none"
/models
```
**اختصار لوحة المفاتيح:** `ctrl+x m`
---
### new
ابدأ جلسة جديدة. _الاسم المستعار_: `/clear`
```bash frame="none"
/new
```
**اختصار لوحة المفاتيح:** `ctrl+x n`
---
### redo
أعِد تنفيذ رسالة تم التراجع عنها سابقا. متاح فقط بعد استخدام `/undo`.
:::tip
ستتم أيضا استعادة أي تغييرات على الملفات.
:::
داخليا، يستخدم هذا Git لإدارة تغييرات الملفات. لذلك يجب أن يكون مشروعك **مستودع Git**.
```bash frame="none"
/redo
```
**اختصار لوحة المفاتيح:** `ctrl+x r`
---
### sessions
اعرض الجلسات وبدّل بينها. _الأسماء المستعارة_: `/resume`, `/continue`
```bash frame="none"
/sessions
```
**اختصار لوحة المفاتيح:** `ctrl+x l`
---
### share
شارك الجلسة الحالية. [اعرف المزيد](/docs/share).
```bash frame="none"
/share
```
**اختصار لوحة المفاتيح:** `ctrl+x s`
---
### themes
اعرض السمات المتاحة.
```bash frame="none"
/theme
```
**اختصار لوحة المفاتيح:** `ctrl+x t`
---
### thinking
بدّل إظهار كتل التفكير/الاستدلال في المحادثة. عند تفعيله، يمكنك رؤية عملية استدلال النموذج للنماذج التي تدعم التفكير الموسّع.
:::note
يتحكم هذا الأمر فقط فيما إذا كانت كتل التفكير **تُعرض**؛ ولا يفعّل أو يعطّل قدرات الاستدلال في النموذج. لتبديل قدرات الاستدلال فعليا، استخدم `ctrl+t` للتنقّل بين إصدارات النموذج.
:::
```bash frame="none"
/thinking
```
---
### undo
تراجع عن آخر رسالة في المحادثة. يزيل أحدث رسالة للمستخدم، وكل الردود اللاحقة، وأي تغييرات على الملفات.
:::tip
سيتم أيضا التراجع عن أي تغييرات على الملفات.
:::
داخليا، يستخدم هذا Git لإدارة تغييرات الملفات. لذلك يجب أن يكون مشروعك **مستودع Git**.
```bash frame="none"
/undo
```
**اختصار لوحة المفاتيح:** `ctrl+x u`
---
### unshare
ألغِ مشاركة الجلسة الحالية. [اعرف المزيد](/docs/share#un-sharing).
```bash frame="none"
/unshare
```
---
## إعداد المحرر
يستخدم الأمران `/editor` و`/export` المحرر المحدد في متغير البيئة `EDITOR`.
<Tabs>
<TabItem label="لينكس/macOS">
```bash
# Example for nano or vim
export EDITOR=nano
export EDITOR=vim
# For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc.
# include --wait
export EDITOR="code --wait"
```
لجعل ذلك دائما، أضف هذا إلى ملف تهيئة الصدفة لديك؛
`~/.bashrc`، `~/.zshrc`، إلخ.
</TabItem>
<TabItem label="ويندوز (CMD)">
```bash
set EDITOR=notepad
# For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc.
# include --wait
set EDITOR=code --wait
```
لجعل ذلك دائما، استخدم **System Properties** > **Environment Variables**.
</TabItem>
<TabItem label="ويندوز (PowerShell)">
```powershell
$env:EDITOR = "notepad"
# For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc.
# include --wait
$env:EDITOR = "code --wait"
```
لجعل ذلك دائما، أضف هذا إلى ملف تهيئة PowerShell لديك.
</TabItem>
</Tabs>
تتضمن خيارات المحررات الشائعة ما يلي:
- `code` - Visual Studio Code
- `cursor` - Cursor
- `windsurf` - Windsurf
- `nvim` - محرر Neovim
- `vim` - محرر Vim
- `nano` - محرر Nano
- `notepad` - Windows Notepad
- `subl` - Sublime Text
:::note
تحتاج بعض المحررات مثل VS Code إلى التشغيل مع الخيار `--wait`.
:::
تحتاج بعض المحررات إلى وسائط سطر الأوامر لتعمل بوضع الحجب. يجعل الخيار `--wait` عملية المحرر تنتظر حتى يتم إغلاقها.
---
## الإعداد
يمكنك تخصيص سلوك واجهة TUI عبر ملف إعدادات OpenCode.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"tui": {
"scroll_speed": 3,
"scroll_acceleration": {
"enabled": true
}
}
}
```
### الخيارات
- `scroll_acceleration` - فعّل تسارع التمرير على نمط macOS لتمرير سلس وطبيعي. عند تفعيله، تزداد سرعة التمرير مع إيماءات التمرير السريعة وتبقى دقيقة للحركات الأبطأ. **يتقدّم هذا الإعداد على `scroll_speed` ويستبدله عند تفعيله.**
- `scroll_speed` - يتحكم في سرعة تمرير واجهة TUI عند استخدام أوامر التمرير (الحد الأدنى: `1`). القيمة الافتراضية هي `3`. **ملاحظة: يتم تجاهل هذا إذا تم ضبط `scroll_acceleration.enabled` على `true`.**
---
## التخصيص
يمكنك تخصيص جوانب مختلفة من عرض واجهة TUI باستخدام لوحة الأوامر (`ctrl+x h` أو `/help`). تبقى هذه الإعدادات محفوظة عبر عمليات إعادة التشغيل.
---
#### عرض اسم المستخدم
بدّل ما إذا كان اسم المستخدم يظهر في رسائل الدردشة. يمكنك الوصول إلى هذا عبر:
- لوحة الأوامر: ابحث عن "username" أو "hide username"
- يُحفظ الإعداد تلقائيا وسيتم تذكره عبر جلسات واجهة TUI

View File

@@ -0,0 +1,142 @@
---
title: الويب
description: استخدام OpenCode في متصفحك.
---
يمكن تشغيل OpenCode كتطبيق ويب داخل متصفحك، ليمنحك تجربة البرمجة القوية بالذكاء الاصطناعي نفسها دون الحاجة إلى الطرفية.
![OpenCode Web - جلسة جديدة](../../../assets/web/web-homepage-new-session.png)
## البدء
ابدأ تشغيل واجهة الويب عبر تنفيذ:
```bash
opencode web
```
يؤدي ذلك إلى تشغيل خادم محلي على `127.0.0.1` بمنفذ عشوائي متاح، ويفتح OpenCode تلقائيا في المتصفح الافتراضي لديك.
:::caution
إذا لم يتم تعيين `OPENCODE_SERVER_PASSWORD` فسيكون الخادم دون حماية. هذا مناسب للاستخدام المحلي، لكنه يجب أن يكون مُعينا عند إتاحة الوصول عبر الشبكة.
:::
:::tip[مستخدمو Windows]
لأفضل تجربة، شغّل `opencode web` من [WSL](/docs/windows-wsl) بدلا من PowerShell. يضمن ذلك وصولا صحيحا إلى نظام الملفات وتكاملا أفضل مع الطرفية.
:::
---
## الإعدادات
يمكنك ضبط خادم الويب باستخدام خيارات سطر الأوامر أو عبر [ملف الإعدادات](/docs/config).
### المنفذ
افتراضيا، يختار OpenCode منفذا متاحا. يمكنك تحديد منفذ:
```bash
opencode web --port 4096
```
### اسم المضيف
افتراضيا، يرتبط الخادم بـ `127.0.0.1` (للاستخدام المحلي فقط). لجعل OpenCode متاحا على شبكتك:
```bash
opencode web --hostname 0.0.0.0
```
عند استخدام `0.0.0.0` سيعرض OpenCode كلا من عناوين الوصول المحلي وعناوين الشبكة:
```
Local access: http://localhost:4096
Network access: http://192.168.1.100:4096
```
### اكتشاف mDNS
فعّل mDNS لجعل خادمك قابلا للاكتشاف على الشبكة المحلية:
```bash
opencode web --mdns
```
يضبط ذلك تلقائيا اسم المضيف إلى `0.0.0.0` ويعلن عن الخادم باسم `opencode.local`.
يمكنك تخصيص اسم نطاق mDNS لتشغيل عدة نسخ على الشبكة نفسها:
```bash
opencode web --mdns --mdns-domain myproject.local
```
### CORS
للسماح بنطاقات إضافية عبر CORS (مفيد للواجهات الأمامية المخصصة):
```bash
opencode web --cors https://example.com
```
### المصادقة
لحماية الوصول، عيّن كلمة مرور عبر متغير البيئة `OPENCODE_SERVER_PASSWORD`:
```bash
OPENCODE_SERVER_PASSWORD=secret opencode web
```
اسم المستخدم الافتراضي هو `opencode`، ويمكن تغييره عبر `OPENCODE_SERVER_USERNAME`.
---
## استخدام واجهة الويب
بعد التشغيل، تتيح لك واجهة الويب الوصول إلى جلسات OpenCode الخاصة بك.
### الجلسات
اعرض جلساتك وأدرها من الصفحة الرئيسية. يمكنك رؤية الجلسات النشطة وبدء جلسات جديدة.
![OpenCode Web - جلسة نشطة](../../../assets/web/web-homepage-active-session.png)
### حالة الخادم
انقر على "See Servers" لعرض الخوادم المتصلة وحالتها.
![OpenCode Web - See Servers (عرض الخوادم)](../../../assets/web/web-homepage-see-servers.png)
---
## إرفاق طرفية
يمكنك إرفاق واجهة طرفية (TUI) بخادم ويب قيد التشغيل:
```bash
# Start the web server
opencode web --port 4096
# In another terminal, attach the TUI
opencode attach http://localhost:4096
```
يتيح لك ذلك استخدام واجهة الويب والطرفية في الوقت نفسه، مع مشاركة الجلسات والحالة نفسها.
---
## ملف الإعدادات
يمكنك أيضا ضبط إعدادات الخادم داخل ملف الإعدادات `opencode.json`:
```json
{
"server": {
"port": 4096,
"hostname": "0.0.0.0",
"mdns": true,
"cors": ["https://example.com"]
}
}
```
تكون خيارات سطر الأوامر ذات أولوية أعلى من إعدادات ملف الإعدادات.

View File

@@ -0,0 +1,113 @@
---
title: Windows (WSL)
description: شغّل OpenCode على Windows باستخدام WSL لأفضل تجربة.
---
import { Steps } from "@astrojs/starlight/components"
رغم أن OpenCode يمكن تشغيله مباشرة على Windows، نوصي باستخدام [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) للحصول على أفضل تجربة. يوفر WSL بيئة Linux تعمل بسلاسة مع ميزات OpenCode.
:::tip[لماذا WSL؟]
يوفر WSL أداء أفضل لنظام الملفات، ودعمًا كاملًا للطرفية، وتوافقًا مع أدوات التطوير التي يعتمد عليها OpenCode.
:::
---
## الإعداد
<Steps>
1. **ثبّت WSL**
إذا لم تقم بذلك بعد، [ثبّت WSL](https://learn.microsoft.com/en-us/windows/wsl/install) باستخدام دليل Microsoft الرسمي.
2. **ثبّت OpenCode داخل WSL**
بعد إعداد WSL، افتح طرفية WSL وثبّت OpenCode باستخدام إحدى [طرق التثبيت](/docs/).
```bash
curl -fsSL https://opencode.ai/install | bash
```
3. **استخدم OpenCode من WSL**
انتقل إلى مجلد مشروعك (يمكنك الوصول لملفات Windows عبر `/mnt/c/` و`/mnt/d/` وغيرها) ثم شغّل OpenCode.
```bash
cd /mnt/c/Users/YourName/project
opencode
```
</Steps>
---
## تطبيق سطح المكتب + خادم WSL
إذا كنت تفضّل تطبيق OpenCode لسطح المكتب لكن تريد تشغيل الخادم داخل WSL:
1. **ابدأ الخادم داخل WSL** مع `--hostname 0.0.0.0` للسماح بالاتصالات الخارجية:
```bash
opencode serve --hostname 0.0.0.0 --port 4096
```
2. **اربط تطبيق سطح المكتب** على `http://localhost:4096`
:::note
إذا لم يعمل `localhost` في إعدادك، اتصل باستخدام عنوان IP الخاص بـ WSL بدلًا منه (من داخل WSL: `hostname -I`) واستخدم `http://<wsl-ip>:4096`.
:::
:::caution
عند استخدام `--hostname 0.0.0.0`، اضبط `OPENCODE_SERVER_PASSWORD` لحماية الخادم.
```bash
OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0
```
:::
---
## عميل الويب + WSL
لأفضل تجربة ويب على Windows:
1. **شغّل `opencode web` من طرفية WSL** بدلًا من PowerShell:
```bash
opencode web --hostname 0.0.0.0
```
2. **افتحه من متصفح Windows** عبر `http://localhost:<port>` (يعرض OpenCode الرابط)
تشغيل `opencode web` من WSL يضمن وصولًا صحيحًا لنظام الملفات وتكاملًا أفضل مع الطرفية، مع بقائه متاحًا من متصفح Windows.
---
## الوصول إلى ملفات Windows
يمكن لـ WSL الوصول إلى جميع ملفات Windows عبر مجلد `/mnt/`:
- قرص `C:` → `/mnt/c/`
- قرص `D:` → `/mnt/d/`
- وهكذا...
مثال:
```bash
cd /mnt/c/Users/YourName/Documents/project
opencode
```
:::tip
لأفضل سلاسة، يمكنك استنساخ/نسخ المستودع إلى نظام ملفات WSL (مثل `~/code/`) وتشغيل OpenCode من هناك.
:::
---
## نصائح
- شغّل OpenCode داخل WSL للمشاريع المخزنة على أقراص Windows حتى يكون الوصول للملفات سلسًا
- استخدم [إضافة WSL في VS Code](https://code.visualstudio.com/docs/remote/wsl) مع OpenCode لسير عمل تطوير متكامل
- إعدادات OpenCode وجلساته تُخزَّن داخل بيئة WSL في `~/.local/share/opencode/`

View File

@@ -0,0 +1,243 @@
---
title: Zen
description: قائمة منتقاة من النماذج يوفّرها OpenCode.
---
import config from "../../../../config.mjs"
export const console = config.console
export const email = `mailto:${config.email}`
OpenCode Zen هي قائمة بالنماذج التي اختبرها فريق OpenCode وتحقّق منها.
:::note
OpenCode Zen متاح حاليا بنسخة تجريبية.
:::
يعمل Zen مثل أي مزوّد آخر في OpenCode. تسجّل الدخول إلى OpenCode Zen وتحصل على
مفتاح API. استخدامه **اختياري بالكامل** ولا تحتاج إليه لاستخدام OpenCode.
---
## الخلفية
توجد نماذج كثيرة جدا، لكن عددا قليلا فقط منها يعمل بشكل جيد كعوامل للبرمجة.
بالإضافة إلى ذلك، فإن معظم المزوّدين يختلفون كثيرا في طريقة الإعداد؛ لذلك قد
تحصل على أداء وجودة مختلفين بشكل كبير.
:::tip
اختبرنا مجموعة منتقاة من النماذج والمزوّدين الذين يعملون جيدا مع OpenCode.
:::
لذلك إذا كنت تستخدم نموذجا عبر خدمة مثل OpenRouter، فلن تكون واثقا أبدا من أنك
تحصل على أفضل نسخة من النموذج الذي تريده.
لمعالجة ذلك، قمنا بعدة أمور:
1. اختبرنا مجموعة منتقاة من النماذج وتحدثنا مع فرقها حول افضل طريقة لتشغيلها.
2. ثم عملنا مع عدد من المزوّدين للتأكد من تقديمها بشكل صحيح.
3. أخيرا، قمنا بقياس أداء توليفة النموذج/المزوّد وخرجنا بقائمة نوصي بها بثقة.
OpenCode Zen هو بوابة للذكاء الاصطناعي تتيح لك الوصول إلى هذه النماذج.
---
## كيف يعمل
يعمل OpenCode Zen مثل أي مزوّد آخر في OpenCode.
1. تسجّل الدخول إلى **<a href={console}>OpenCode Zen</a>**، وتضيف تفاصيل الفوترة، ثم تنسخ مفتاح API.
2. تشغّل الأمر `/connect` في واجهة TUI، وتختار OpenCode Zen، ثم تلصق مفتاح API.
3. شغّل `/models` في واجهة TUI لعرض قائمة النماذج التي نوصي بها.
يتم احتساب الرسوم لكل طلب، ويمكنك إضافة رصيد إلى حسابك.
---
## نقاط النهاية
يمكنك أيضا الوصول إلى نماذجنا عبر نقاط نهاية API التالية.
| النموذج | معرّف النموذج | نقطة النهاية | حزمة AI SDK |
| ------------------ | ------------------ | -------------------------------------------------- | --------------------------- |
| GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5.1 Codex | gpt-5.1-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5.1 Codex Max | gpt-5.1-codex-max | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5.1 Codex Mini | gpt-5.1-codex-mini | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` |
| Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` |
| MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| MiniMax M2.1 Free | minimax-m2.1-free | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| GLM 4.7 Free | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Big Pickle | big-pickle | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
يستخدم [معرّف النموذج](/docs/config/#models) في إعدادات OpenCode الصيغة `opencode/<model-id>`.
على سبيل المثال، بالنسبة إلى GPT 5.2 Codex ستستخدم `opencode/gpt-5.2-codex` في إعداداتك.
---
### النماذج
يمكنك جلب القائمة الكاملة بالنماذج المتاحة وبياناتها الوصفية من:
```
https://opencode.ai/zen/v1/models
```
---
## التسعير
ندعم نموذج الدفع حسب الاستخدام. فيما يلي الأسعار **لكل 1M tokens**.
| النموذج | الإدخال | الإخراج | قراءة مخزنة | كتابة مخزنة |
| --------------------------------- | ------- | ------- | ----------- | ----------- |
| Big Pickle | Free | Free | Free | - |
| MiniMax M2.1 Free | Free | Free | Free | - |
| MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - |
| GLM 4.7 Free | Free | Free | Free | - |
| GLM 4.7 | $0.60 | $2.20 | $0.10 | - |
| GLM 4.6 | $0.60 | $2.20 | $0.10 | - |
| Kimi K2.5 Free | Free | Free | Free | - |
| Kimi K2.5 | $0.60 | $3.00 | $0.08 | - |
| Kimi K2 Thinking | $0.40 | $2.50 | - | - |
| Kimi K2 | $0.40 | $2.50 | - | - |
| Qwen3 Coder 480B | $0.45 | $1.50 | - | - |
| Claude Sonnet 4.5 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 |
| Claude Sonnet 4.5 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 |
| Claude Sonnet 4 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 |
| Claude Sonnet 4 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 |
| Claude Haiku 4.5 | $1.00 | $5.00 | $0.10 | $1.25 |
| Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 |
| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 |
| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 |
| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 |
| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 |
| Gemini 3 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - |
| Gemini 3 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - |
| Gemini 3 Flash | $0.50 | $3.00 | $0.05 | - |
| GPT 5.2 | $1.75 | $14.00 | $0.175 | - |
| GPT 5.2 Codex | $1.75 | $14.00 | $0.175 | - |
| GPT 5.1 | $1.07 | $8.50 | $0.107 | - |
| GPT 5.1 Codex | $1.07 | $8.50 | $0.107 | - |
| GPT 5.1 Codex Max | $1.25 | $10.00 | $0.125 | - |
| GPT 5.1 Codex Mini | $0.25 | $2.00 | $0.025 | - |
| GPT 5 | $1.07 | $8.50 | $0.107 | - |
| GPT 5 Codex | $1.07 | $8.50 | $0.107 | - |
| GPT 5 Nano | Free | Free | Free | - |
قد تلاحظ _Claude Haiku 3.5_ في سجل الاستخدام. هذا [نموذج منخفض التكلفة](/docs/config/#models) يُستخدم لتوليد عناوين جلساتك.
:::note
يتم تمرير رسوم بطاقات الائتمان بالتكلفة الفعلية (4.4% + $0.30 لكل معاملة)؛ ولا نفرض أي رسوم إضافية غير ذلك.
:::
النماذج المجانية:
- GLM 4.7 Free متاح على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج.
- Kimi K2.5 Free متاح على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج.
- MiniMax M2.1 Free متاح على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج.
- Big Pickle نموذج خفي ومتاح مجانا على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج.
<a href={email}>تواصل معنا</a> إذا كانت لديك أي أسئلة.
---
### إعادة الشحن التلقائي
إذا انخفض رصيدك عن $5، فسيقوم Zen تلقائيا بإعادة شحن $20.
يمكنك تغيير مبلغ إعادة الشحن التلقائي. ويمكنك أيضا تعطيل إعادة الشحن التلقائي بالكامل.
---
### الحدود الشهرية
يمكنك أيضا تعيين حد شهري للاستخدام لمساحة العمل بالكامل ولكل عضو في فريقك.
على سبيل المثال، لنفترض أنك ضبطت حد الاستخدام الشهري على $20، فلن يتجاوز Zen مبلغ $20 خلال شهر.
لكن إذا كانت إعادة الشحن التلقائي مفعّلة، فقد ينتهي الأمر بخصم أكثر من $20 إذا انخفض رصيدك عن $5.
---
## الخصوصية
تتم استضافة جميع نماذجنا في الولايات المتحدة. يلتزم مزوّدونا بسياسة عدم الاحتفاظ بالبيانات (zero-retention) ولا يستخدمون بياناتك لتدريب النماذج، مع الاستثناءات التالية:
- Big Pickle: خلال فترة إتاحته المجانية، قد تُستخدم البيانات المجمعة لتحسين النموذج.
- GLM 4.7 Free: خلال فترة إتاحته المجانية، قد تُستخدم البيانات المجمعة لتحسين النموذج.
- Kimi K2.5 Free: خلال فترة إتاحته المجانية، قد تُستخدم البيانات المجمعة لتحسين النموذج.
- MiniMax M2.1 Free: خلال فترة إتاحته المجانية، قد تُستخدم البيانات المجمعة لتحسين النموذج.
- OpenAI APIs: يتم الاحتفاظ بالطلبات لمدة 30 يوما وفقا لـ [سياسات بيانات OpenAI](https://platform.openai.com/docs/guides/your-data).
- Anthropic APIs: يتم الاحتفاظ بالطلبات لمدة 30 يوما وفقا لـ [سياسات بيانات Anthropic](https://docs.anthropic.com/en/docs/claude-code/data-usage).
---
## للفرق
يعمل Zen بشكل ممتاز للفرق أيضا. يمكنك دعوة زملاء الفريق، وتعيين الأدوار، وتنظيم
النماذج التي يستخدمها فريقك، والمزيد.
:::note
مساحات العمل مجانية حاليا للفرق كجزء من النسخة التجريبية.
:::
إدارة مساحة العمل مجانية حاليا للفرق كجزء من النسخة التجريبية. سنشارك المزيد من التفاصيل حول التسعير قريبا.
---
### الأدوار
يمكنك دعوة زملاء الفريق إلى مساحة عملك وتعيين الأدوار:
- **Admin**: إدارة النماذج والأعضاء ومفاتيح API والفوترة
- **Member**: إدارة مفاتيح API الخاصة به فقط
يمكن للمسؤولين أيضا تعيين حدود إنفاق شهرية لكل عضو للسيطرة على التكاليف.
---
### صلاحيات الوصول للنماذج
يمكن للمسؤولين تفعيل نماذج محددة لمساحة العمل أو تعطيلها. ستعيد الطلبات المرسلة إلى نموذج معطّل خطأ.
يفيد ذلك في الحالات التي تريد فيها تعطيل استخدام نموذج يقوم بجمع البيانات.
---
### استخدم مفتاحك الخاص
يمكنك استخدام مفاتيح API الخاصة بك لدى OpenAI أو Anthropic مع الاستمرار في الوصول إلى نماذج أخرى ضمن Zen.
عند استخدام مفاتيحك الخاصة، تتم فوترة tokens مباشرة من المزوّد وليس من Zen.
على سبيل المثال، قد تكون لدى مؤسستك بالفعل مفاتيح لـ OpenAI أو Anthropic وتريد استخدامها بدلا من المفتاح الذي يوفّره Zen.
---
## الأهداف
أنشأنا OpenCode Zen من أجل:
1. **قياس الأداء** لأفضل النماذج/المزوّدين لعوامل البرمجة.
2. إتاحة خيارات **عالية الجودة** دون خفض الأداء أو توجيه الطلبات إلى مزوّدين أرخص.
3. تمرير أي **انخفاض في الأسعار** عبر البيع بالتكلفة؛ بحيث تكون الزيادة الوحيدة لتغطية رسوم المعالجة.
4. عدم فرض **أي ارتباط حصري (lock-in)** عبر تمكينك من استخدامه مع أي عامل برمجة آخر، مع إتاحة استخدام أي مزوّد آخر مع OpenCode أيضا.

View File

@@ -0,0 +1,54 @@
---
title: Migracija na 1.0
description: Šta je novo u OpenCode 1.0.
---
OpenCode 1.0 je potpuna revizija TUI-ja.
Prešli smo sa TUI zasnovanog na go+bubbletea koji je imao problema sa performansama i mogućnostima na interni okvir (OpenTUI) napisan u zig+solidjs.
Novi TUI radi kao stari jer se povezuje na isti opencode server.
---
## Upgrade
Ne biste trebali biti automatski nadograđeni na 1.0 ako trenutno koristite prethodnu
verzija. Međutim, neke starije verzije OpenCode-a uvijek uzimaju najnoviju verziju.
Za ručnu nadogradnju, pokrenite
```bash
$ opencode upgrade 1.0.0
```
Za vraćanje na 0.x, pokrenite
```bash
$ opencode upgrade 0.15.31
```
---
## UX promjene
Historija sesije je komprimovanija i prikazuje samo sve detalje alata za uređivanje i bash.
Dodali smo komandnu traku kroz koju prolazi skoro sve. Pritisnite ctrl+p da prikažete u bilo kom kontekstu i vidite sve što možete učiniti.
Dodatna bočna traka sesije (može se prebaciti) sa korisnim informacijama.
Uklonili smo neke funkcije za koje nismo bili sigurni da ih neko koristi. Ako nešto važno nedostaje, otvorite problem i brzo ćemo ga dodati.
---
## Revolucionarne promjene
### Tastature su preimenovane
- povratne_poruke -> poništite_poruke
- switch_agent -> agent_cycle
- switch_agent_reverse -> agent_cycle_reverse
- switch_mode -> agent_cycle
- switch_mode_reverse -> agent_cycle_reverse
### Linkovi za degustatore su uklonjeni
- messages_layout_toggle
- poruke_sljedeće
- messages_previous
- file_diff_toggle
- file_search
- file_close
- lista_datoteka
- app_help
- project_init
- detalji alata
- razmišljanje_blokovi

View File

@@ -0,0 +1,156 @@
---
title: ACP podrška
description: Koristite OpenCode u bilo kojem uređivaču kompatibilnom sa ACP.
---
OpenCode podržava [Agent Client Protocol](https://agentclientprotocol.com) (ACP), što vam omogućava da ga koristite direktno u kompatibilnim uređivačima i IDE-ovima.
:::tip
Za listu uređivača i alata koji podržavaju ACP, pogledajte [ACP izvještaj o napretku](https://zed.dev/blog/acp-progress-report#available-now).
:::
ACP je otvoreni protokol koji standardizira komunikaciju između uređivača koda i AI coding agenata.
---
## Konfiguriši
Da biste koristili OpenCode putem ACP-a, konfigurirajte svoj uređivač da pokrene naredbu `opencode acp`.
Naredba pokreće OpenCode kao ACP-kompatibilan podproces koji komunicira sa vašim uređivačem preko JSON-RPC-a kroz stdio.
Ispod su primjeri za popularne uređivače koji podržavaju ACP.
---
### Zed
Dodajte u svoju [Zed](https://zed.dev) konfiguraciju (`~/.config/zed/settings.json`):
```json title="~/.config/zed/settings.json"
{
"agent_servers": {
"OpenCode": {
"command": "opencode",
"args": ["acp"]
}
}
}
```
Da biste ga otvorili, koristite akciju `agent: new thread` u **Command Palette**.
Također možete vezati prečicu na tastaturi uređivanjem vašeg `keymap.json`:
```json title="keymap.json"
[
{
"bindings": {
"cmd-alt-o": [
"agent::NewExternalAgentThread",
{
"agent": {
"custom": {
"name": "OpenCode",
"command": {
"command": "opencode",
"args": ["acp"]
}
}
}
}
]
}
}
]
```
---
### JetBrains IDE-ovi
Dodajte u svoj [JetBrains IDE](https://www.jetbrains.com/) `acp.json` prema [dokumentaciji](https://www.jetbrains.com/help/ai-assistant/acp.html):
```json title="acp.json"
{
"agent_servers": {
"OpenCode": {
"command": "/absolute/path/bin/opencode",
"args": ["acp"]
}
}
}
```
Da biste ga otvorili, koristite novog "OpenCode" agenta u AI Chat agent selektoru.
---
### Avante.nvim
Dodajte u svoju [Avante.nvim](https://github.com/yetone/avante.nvim) konfiguraciju:
```lua
{
acp_providers = {
["opencode"] = {
command = "opencode",
args = { "acp" }
}
}
}
```
Ako trebate proslijediti varijable okruženja:
```lua {6-8}
{
acp_providers = {
["opencode"] = {
command = "opencode",
args = { "acp" },
env = {
OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY")
}
}
}
}
```
---
### CodeCompanion.nvim
Da koristite OpenCode kao ACP agenta u [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim), dodajte sljedeće u svoju Neovim konfiguraciju:
```lua
require("codecompanion").setup({
interactions = {
chat = {
adapter = {
name = "opencode",
model = "claude-sonnet-4",
},
},
},
})
```
Ova konfiguracija postavlja CodeCompanion da koristi OpenCode kao ACP chat agenta.
Ako trebate proslijediti varijable okruženja (kao što je `OPENCODE_API_KEY`), pogledajte [Configuring Adapters: Environment Variables](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) u dokumentaciji CodeCompanion.nvim.
## Podrška
OpenCode radi isto kroz ACP kao i u terminalu. Podržane su sve funkcije:
:::note
Neke ugrađene komande kao što su `/undo` i `/redo` trenutno nisu podržane.
:::
- Ugrađeni alati (operacije sa datotekama, naredbe terminala, itd.)
- Prilagođeni alati i komande kosih crta
- MCP serveri konfigurisani u vašoj OpenCode konfiguraciji
- Pravila specifična za projekat `AGENTS.md`
- Prilagođeni formateri i linteri
- Agenti i sistem dozvola

View File

@@ -0,0 +1,651 @@
---
title: Agenti
description: Konfigurirajte i koristite specijalizirane agente.
---
Agenti su specijalizirani AI asistenti koji se mogu konfigurirati za specifične zadatke i tokove posla. Oni vam omogućavaju da kreirate fokusirane alate sa prilagođenim upitima, modelima i pristupom alatima.
:::tip
Koristite agenta plana za analizu koda i pregled prijedloga bez ikakvih promjena koda.
:::
Možete se prebacivati između agenata tokom sesije ili ih pozvati spominjanjem `@`.
---
## Vrsta
Postoje dvije vrste agenata u OpenCode-u; primarni agensi i subagensi.
---
### Primarni agenti
Primarni agenti su glavni pomoćnici s kojima direktno komunicirate. Možete se kretati kroz njih pomoću tipke **Tab** ili vašeg konfigurisanog povezivanja tipki `switch_agent`. Ovi agenti vode vaš glavni razgovor. Pristup alatima se konfiguriše putem dozvola — na primjer, Build ima omogućene sve alate dok je Plan ograničen.
::: tip
Možete koristiti tipku **Tab** za prebacivanje između primarnih agenata tokom sesije.
:::
OpenCode dolazi sa dva ugrađena primarna agenta, **Build** i **Plan**. Hoćemo
pogledajte ove u nastavku.
---
### Subagent
Subagenti su specijalizovani pomoćnici koje primarni agenti mogu pozvati za određene zadatke. Možete ih i ručno pozvati **@ spominjanjem** u svojim porukama.
OpenCode dolazi sa dva ugrađena subagenta, **General** i **Explore**. Ovo ćemo pogledati u nastavku.
---
## Embedded
OpenCode dolazi sa dva ugrađena primarna agenta i dva ugrađena subagenta.
---
### Koristi build
_Način_: `primary`
Build je **podrazumevani** primarni agent sa svim omogućenim alatima. Ovo je standardni agent za razvojni rad gdje vam je potreban pun pristup operacijama datoteka i sistemskim komandama.
---
### Koristite plan
_Način_: `primary`
Konačan agent dizajniran za planiranje i analizu. Koristimo sistem dozvola kako bismo vam pružili veću kontrolu i spriječili neželjene promjene.
Prema zadanim postavkama, sve sljedeće je postavljeno na `ask`:
- `file edits`: Sva upisivanja, zakrpe i uređivanja
- `bash`: Sve bash komande
Ovaj agent je koristan kada želite da LLM analizira kod, predloži promjene ili kreira planove bez stvarnih modifikacija vaše baze koda.
---
### Upotreba općenito
_Način_: `subagent`
Agent opće namjene za istraživanje složenih pitanja i izvršavanje zadataka u više koraka. Ima potpuni pristup alatima (osim zadataka), tako da može mijenjati fajl kada je to potrebno. Koristite ovo za paralelno pokretanje više jedinica rada.
---
### Koristite explore
_Način_: `subagent`
Brzi agent samo za čitanje za istraživanje kodnih baza. Nije moguće mijenjati fajlove. Koristite ovo kada trebate brzo pronaći datoteke po uzorku, pretražiti kod za ključne riječi ili odgovoriti na pitanja o bazi kodova.
---
### Koristite zbijanje
_Način_: `primary`
Skriveni sistemski agent koji sažima dugi kontekst u manji sažetak. Pokreće se automatski kada je potrebno i ne može se odabrati u korisničkom interfejsu.
---
### Koristite naslov
_Način_: `primary`
Skriveni sistemski agent koji generiše kratke naslove sesija. Pokreće se automatski i ne može se odabrati u korisničkom interfejsu.
---
### Koristi sažetak
_Način_: `primary`
Skriveni sistemski agent koji kreira sažetke sesije. Pokreće se automatski i ne može se odabrati u korisničkom interfejsu.
---
## Upotreba
1. Za primarne agente, koristite taster **Tab** za kretanje kroz njih tokom sesije. Također možete koristiti svoju konfiguriranu vezu tipke `switch_agent`.
2. Subagenti se mogu pozvati:
- **Automatski** od strane primarnih agenata za specijalizovane zadatke na osnovu njihovih opisa.
- Ručno **@ spominjanjem** subagenta u vašoj poruci. Na primjer.
```txt frame="none"
@general help me search for this function
```
3. **Navigacija između sesija**: Kada subagenti kreiraju vlastite podređene sesije, možete se kretati između roditeljske sesije i svih podređenih sesija koristeći:
- **\<Leader>+Desno** (ili vaša konfigurirana `session_child_cycle` veza) za petlju naprijed kroz roditelj → dijete1 → dijete2 → ... → roditelj
- **\<Leader>+Levo** (ili vaše konfigurirano povezivanje tipki `session_child_cycle_reverse`) za kretanje unazad kroz roditelj ← dijete1 ← dijete2 ← ... ← roditelj
Ovo vam omogućava neprimetno prebacivanje između glavnog razgovora i rada specijalizovanog podagenta.
---
## Konfiguriši
Možete prilagoditi ugrađene agente ili kreirati vlastite kroz konfiguraciju. Agenti se mogu konfigurisati na dva načina:
---
### JSON
Konfigurirajte agente u svom konfiguracijskom fajlu `opencode.json`:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"build": {
"mode": "primary",
"model": "anthropic/claude-sonnet-4-20250514",
"prompt": "{file:./prompts/build.txt}",
"tools": {
"write": true,
"edit": true,
"bash": true
}
},
"plan": {
"mode": "primary",
"model": "anthropic/claude-haiku-4-20250514",
"tools": {
"write": false,
"edit": false,
"bash": false
}
},
"code-reviewer": {
"description": "Reviews code for best practices and potential issues",
"mode": "subagent",
"model": "anthropic/claude-sonnet-4-20250514",
"prompt": "You are a code reviewer. Focus on security, performance, and maintainability.",
"tools": {
"write": false,
"edit": false
}
}
}
}
```
---
### Markdown
Također možete definirati agente koristeći mardown datoteke. Stavite ih u:
- Globalno: `~/.config/opencode/agents/`
- Po projektu: `.opencode/agents/
````markdown title="~/.config/opencode/agents/review.md"
---
opis: Recenzira kod za kvalitet i najbolje prakse
način rada: subagent
model: anthropic/claude-sonnet-4-20250514
temperatura: 0.1
alati:
napisati: netačno
edit: false
bash: lažno
---
Nalazite se u načinu pregleda koda. Fokusirajte se na:
- Kvalitet koda i najbolje prakse
- Potencijalne greške i rubni slučajevi
- Implikacije na performanse
- Sigurnosna pitanja
Dajte konstruktivne povratne informacije bez direktnih promjena.
```
Ime marginalne datoteke postaje ime agenta. Na primjer, `review.md` kreira `review` agenta.
---
## Opcije
Pogledajmo ove opcije konfiguracije detaljno.
---
### Opis
Koristite opciju `description` da pružite kratak opis onoga što agent radi i kada ga koristiti.
```json title="opencode.json"
{
"agent": {
"review": {
"description": "Reviews code for best practices and potential issues"
}
}
}
```
Ovo je **obavezna** opcija konfiguracije.
---
### Temperatura
Kontrolišite slučajnost i kreativnost odgovora LLM-a pomoću `temperature` konfiguracije.
Niže vrijednosti čine odgovore fokusiranijim i determinističkim, dok više vrijednosti povećavaju kreativnost i varijabilnost.
```json title="opencode.json"
{
"agent": {
"plan": {
"temperatura": 0,1 },
"kreativno": {
"temperatura": 0,8 }
}
}
```
Vrijednosti temperature se obično kreću od 0,0 do 1,0:
- **0,0-0,2**: Vrlo fokusirani i deterministički odgovori, idealni za analizu i planiranje koda
- **0,3-0,5**: Uravnoteženi odgovori sa malo kreativnosti, dobro za opšte razvojne zadatke
- **0,6-1,0**: kreativniji i raznovrsniji odgovori, korisni za razmišljanje i istraživanje
```json title="opencode.json"
{
"agent": {
"analyze": {
"temperature": 0.1,
"prompt": "{file:./prompts/analysis.txt}"
},
"build": {
"temperature": 0.3
},
"brainstorm": {
"temperature": 0.7,
"prompt": "{file:./prompts/creative.txt}"
}
}
}
```
Ako temperatura nije navedena, OpenCode koristi standardne postavke specifične za model; obično 0 za većinu modela, 0,55 za Qwen modele.
---
### Maks. stepenice
Kontrolirajte maksimalni broj iteracija agenta koje agent može izvesti prije nego što bude prisiljen da odgovori samo tekstom. Ovo omogućava korisnicima koji žele kontrolirati troškove da postave ograničenje na akcije agenta.
Ako ovo nije postavljeno, agent će nastaviti iterirati sve dok model ne odluči da se zaustavi ili korisnik ne prekine sesiju.
```json title="opencode.json"
{
"agent": {
"brzo mislilac": {
"opis": "Brzo razmišljanje s ograničenim iteracijama",
"prompt": "Vi brzo mislite. Riješite probleme minimalnim koracima.",
"koraci": 5 }
}
}
```
Kada se dostigne ograničenje, agent prima poseban sistemski prompt koji ga upućuje da odgovori sa rezimeom svog rada i preporučenim preostalim zadacima.
:::oprez
Naslijeđeno polje `maxSteps` je zastarjelo. Umjesto toga koristite `steps`.
:::
---
### Onemogući
Postavite na `true` da onemogućite agenta.
```json title="opencode.json"
{
"agent": {
"review": {
"disable": true
}
}
}
```
---
### Prompt
Navedite prilagođenu sistemsku prompt datoteku za ovog agenta sa `prompt` konfiguracijom. Datoteka s promptom treba da sadrži upute specifične za svrhu agenta.
```json title="opencode.json"
{
"agent": {
"recenzija": {
"prompt": "{file:./prompts/code-review.txt}" }
}
}
```
Ova putanja je relativna u odnosu na mjesto gdje se nalazi konfiguracijski fajl. Dakle, ovo radi i za globalnu OpenCode konfiguraciju i za konfiguraciju specifične za projekat.
---
### Model
Koristite `model` konfiguraciju da nadjačate model za ovog agenta. Korisno za korištenje različitih modela optimiziranih za različite zadatke. Na primjer, brži model za planiranje, sposobniji model za implementaciju.
:::tip
Ako ne navedete model, primarni agenti koriste [model globalno konfiguriran](/docs/config#models) dok će podagenti koristiti model primarnog agenta koji je pozvao subagenta.
:::
```json title="opencode.json"
{
"agent": {
"plan": {
"model": "anthropic/claude-haiku-4-20250514" }
}
}
```
ID modela u vašoj OpenCode konfiguraciji koristi format `provider/model-id`. Na primjer, ako koristite [OpenCode Zen](/docs/zen), koristili biste `opencode/gpt-5.1-codex` za GPT 5.1 Codex.
---
### Uvijek
Kontrolirajte koji su alati dostupni u ovom agentu koristeći konfiguraciju `tools`. Možete omogućiti ili onemogućiti određene alate tako što ćete ih postaviti na `true` ili `false`.
```json title="opencode.json" {3-6,9-12}
{
"$schema": "https://opencode.ai/config.json",
"tools": {
"write": true,
"bash": true
},
"agent": {
"plan": {
"tools": {
"write": false,
"bash": false
}
}
}
}
```
:::napomena
Konfiguracija specifična za agenta poništava globalnu konfiguraciju.
:::
Također možete koristiti zamjenske znakove za kontrolu više alata odjednom. Na primjer, da onemogućite sve alate sa MCP servera:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"samo za čitanje": {
"alati": {
"mymcp_*": lažno,
"pisati": lažno,
"uredi": netačno }
}
}
}
```
[Saznajte više o alatima](/docs/tools).
---
### Dozvole
Možete konfigurirati dozvole za upravljanje radnjama koje agent može poduzeti. Trenutno se dozvole za alate `edit`, `bash` i `webfetch` mogu konfigurirati na:
- `"ask"` — Zatražite odobrenje prije pokretanja alata
- `"allow"` — Dozvoli sve operacije bez odobrenja
- `"deny"` — Onemogućite alat
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"edit": "deny"
}
}
```
Možete nadjačati ove dozvole po agentu.
```json title="opencode.json" {3-5,8-10}
{
"$schema": "https://opencode.ai/config.json",
"dozvola": {
"edit": "odbiti" },
"agent": {
"build": {
"dozvola": {
"uredi": "pitaj" }
}
}
}
```
Također možete postaviti dozvole u Markdown agentima.
```markdown title="~/.config/opencode/agents/review.md"
---
description: Code review without edits
mode: subagent
permission:
edit: deny
bash:
"*": ask
"git diff": allow
"git log*": allow
"grep *": allow
webfetch: deny
---
Only analyze code and suggest changes.
```
Možete postaviti dozvole za određene bash komande.
```json title="opencode.json" {7}
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"build": {
"dozvola": {
"bash": {
"git push": "pitaj",
"grep *": "dozvoli" }
}
}
}
}
```
Ovo može poprimiti oblik lopte.
```json title="opencode.json" {7}
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"build": {
"permission": {
"bash": {
"git *": "ask"
}
}
}
}
}
```
Također možete koristiti zamjenski znak `*` za kontrolu dozvola za sve komande.
Budući da posljednje podudarno pravilo ima prednost, prvo postavite zamjenski znak `*`, a zatim navedena pravila.
```json title="opencode.json" {8}
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"build": {
"dozvola": {
"bash": {
"*": "pitaj",
"git status *": "dozvoli" }
}
}
}
}
```
[Saznajte više o dozvolama](/docs/permissions).
---
### Mode
Kontrolirajte način rada agenta koristeći konfiguraciju `mode`. Opcija `mode` se koristi da specificira kako se agent može koristiti.
```json title="opencode.json"
{
"agent": {
"review": {
"mode": "subagent"
}
}
}
```
Opcija `mode` se može postaviti na `primary`, `subagent` ili `all`. Ako `mode` nije specificirano, podrazumevano je `all`.
---
### Skriveno
Sakrij podagenta iz `@` menija za automatsko dovršavanje sa `hidden: true`. Korisno za interne podagente koje bi drugi agenti trebali programski pozvati samo preko Task alata.
```json title="opencode.json"
{
"agent": {
"interni-pomoćnik": {
"mode": "subagent",
"skriveno": istina }
}
}
```
Ovo utiče samo na vidljivost korisnika u meniju za automatsko dovršavanje. Model i dalje može pozvati skrivene agente putem alata Zadatak ako dozvole dozvoljavaju.
:::napomena
Odnosi se samo na `mode: subagent` agente.
:::
---
### Dozvole za zadatak
Kontrolirajte koje podagente agent može pozvati preko Task alata sa `permission.task`. Koristi glob uzorke za fleksibilno uparivanje.
```json title="opencode.json"
{
"agent": {
"orchestrator": {
"mode": "primary",
"permission": {
"task": {
"*": "deny",
"orchestrator-*": "allow",
"code-reviewer": "ask"
}
}
}
}
}
```
Kada se postavi na `deny`, subagent se u potpunosti uklanja iz opisa alata za zadatak, tako da ga model neće pokušati pozvati.
:::tip
Pravila se procjenjuju po redoslijedu i **pobjeđuje **poslednje odgovarajuće pravilo**. U gornjem primjeru, `orchestrator-planner` odgovara i `*` (odbije) i `orchestrator-*` (dozvoli), ali pošto `orchestrator-*` dolazi nakon `*`, rezultat je `allow`.
:::
:::tip
Korisnici uvijek mogu pozvati bilo kojeg subagenta direktno preko `@` menija za autodovršavanje, čak i ako bi dozvole za zadatak agenta to uskratile.
:::
---
### Boja
Prilagodite vizualni izgled agenta u korisničkom sučelju s opcijom `color`. Ovo utiče na to kako se agent pojavljuje u interfejsu.
Koristite važeću heksadecimalnu boju (npr. `#FF5733`) ili boju teme: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`.
```json title="opencode.json"
{
"agent": {
"kreativno": {
"boja": "#ff6b6b" },
"code-reviewer": {
"boja": "akcent" }
}
}
```
---
### Leglo P
Kontrolirajte raznolikost odgovora s opcijom `top_p`. Alternativa temperaturi za kontrolu nasumice.
```json title="opencode.json"
{
"agent": {
"brainstorm": {
"top_p": 0.9
}
}
}
```
Vrijednosti se kreću od 0,0 do 1,0. Niže vrijednosti su više fokusirane, više vrijednosti raznovrsnije.
---
### Dodatni
Sve druge opcije koje navedete u konfiguraciji agenta će biti **direktno proslijeđene** dobavljaču kao opcije modela. Ovo vam omogućava da koristite karakteristike i parametre specifične za provajdera.
Na primjer, sa OpenAI-jevim modelima rezonovanja, možete kontrolisati napor rasuđivanja:
```json title="opencode.json" {6,7}
{
"agent": {
"duboki mislilac": {
"opis": "Agent koji koristi veliki napor u razmišljanju za složene probleme",
"model": "openai/gpt-5",
"reasoningEffort": "visoko",
"textVerbosity": "niska" }
}
}
```
Ove dodatne opcije su specifične za model i dobavljača. U dokumentaciji vašeg provajdera provjerite dostupne parametre.
:::tip
Pokrenite `opencode models` da vidite listu dostupnih modela.
:::
---
## Kreirajte agente
Možete kreirati nove agente koristeći sljedeću naredbu:
```bash
opencode agent create
```
Ova interaktivna komanda će:
1. Pitajte gdje da sačuvate agenta; globalno ili specifično za projekat.
2. Opis onoga što agent treba da uradi.
3. Generirajte odgovarajući sistemski prompt i identifikator.
4. Omogućite vam da odaberete kojim alatima agent može pristupiti.
5. Konačno, kreirajte markdown datoteku s konfiguracijom agenta.
---
## Slučajevi upotrebe
Evo nekoliko uobičajenih slučajeva upotrebe različitih agenata.
- **Build agent**: Potpuni razvojni rad sa svim omogućenim alatima
- **Agent za plan**: Analiza i planiranje bez unošenja promjena
- **Agent za pregled**: Pregled koda sa pristupom samo za čitanje plus alati za dokumentaciju
- **Agent za otklanjanje grešaka**: Fokusiran na istragu sa omogućenim bash i alatima za čitanje
- **Docs agent**: Pisanje dokumentacije sa operacijama datoteka, ali bez sistemskih naredbi
---
## Primjeri
Evo nekoliko primjera agenata koji bi vam mogli biti korisni.
::: momak
Imate li agenta kojeg biste željeli podijeliti? [Pošalji PR](https://github.com/anomalyco/opencode).
:::
---
### Agent za dokumentaciju
```markdown title="~/.config/opencode/agents/docs-writer.md"
---
opis: Piše i vodi projektnu dokumentaciju
način rada: subagent
alati:
bash: lažno
---
Vi ste tehnički pisac. Kreirajte jasnu, sveobuhvatnu dokumentaciju.
Fokusirajte se na:
- Jasna objašnjenja
- Pravilna struktura
- Primjeri kodova
- Jezik prilagođen korisniku
```
---
### Sigurnosni revizor
```markdown title="~/.config/opencode/agents/security-auditor.md"
---
description: Performs security audits and identifies vulnerabilities
mode: subagent
tools:
write: false
edit: false
---
You are a security expert. Focus on identifying potential security issues.
Look for:
- Input validation vulnerabilities
- Authentication and authorization flaws
- Data exposure risks
- Dependency vulnerabilities
- Configuration security issues
```

View File

@@ -0,0 +1,540 @@
---
title: CLI
description: OpenCode CLI opcije i naredbe.
---
import { Tabs, TabItem } from "@astrojs/starlight/components"
OpenCode CLI po defaultu pokreće [TUI](/docs/tui) kada se pokrene bez ikakvih argumenata.
```bash
opencode
```
Ali takođe prihvata komande kao što je dokumentovano na ovoj stranici. Ovo vam omogućava programsku interakciju sa OpenCodeom.
```bash
opencode run "Explain how closures work in JavaScript"
```
---
### tui
Pokrenite korisnički interfejs OpenCode terminala.
```bash
opencode [project]
```
#### Zastave
| Zastava | Kratko | Opis || ------------ | ----- | ------------------------------------------ |
| `--continue` | `-c` | Nastavite posljednju sesiju |
| `--session` | `-s` | ID sesije za nastavak |
| `--prompt` | | Uputstvo za upotrebu |
| `--model` | `-m` | Model za korištenje u obliku dobavljača/modela |
| `--agent` | | Agent za korištenje |
| `--port` | | Port za slušanje na |
| `--hostname` | | Slušajte ime hosta |
---
## komandante
OpenCode CLI takođe ima sledeće komande.
---
### agent
Upravljajte agentima za OpenCode.
```bash
opencode agent [command]
```
---
### prilog
Priključite terminal na već pokrenut OpenCode backend server pokrenut putem `serve` ili `web` komandi.
```bash
opencode attach [url]
```
Ovo omogućava korištenje TUI-ja sa udaljenim OpenCode backend-om. na primjer:
```bash
# Start the backend server for web/mobile access
opencode web --port 4096 --hostname 0.0.0.0
# In another terminal, attach the TUI to the running backend
opencode attach http://10.20.30.40:4096
```
#### Zastave
| Zastava | Kratko | Opis || ----------- | ----- | --------------------------------- |
| `--dir` | | Radni direktorij za pokretanje TUI u |
| `--session` | `-s` | ID sesije za nastavak |
---
#### kreiraj
Kreirajte novog agenta s prilagođenom konfiguracijom.
```bash
opencode agent create
```
Ova komanda će vas voditi kroz kreiranje novog agenta sa prilagođenim sistemskim promptom i konfiguracijom alata.
---
#### lista
Navedite sve dostupne agente.
```bash
opencode agent list
```
---
### auth
Naredba za upravljanje vjerodajnicama i prijavom za provajdere.
```bash
opencode auth [command]
```
---
#### aplikacija
OpenCode pokreće lista provajdera na [Models.dev](https://models.dev), tako da možete koristiti `opencode auth login` da konfigurirate API ključeve za bilo kojeg provajdera kojeg želite koristiti. Ovo je pohranjeno u `~/.local/share/opencode/auth.json`.
```bash
opencode auth login
```
Kada se OpenCode pokrene, učitava dobavljače iz datoteke vjerodajnica. I ako postoje neki ključevi definirani u vašim okruženjima ili `.env` fajl u vašem projektu.
---
#### lista
Navodi sve autentifikovane dobavljače pohranjene u datoteci akreditiva.
```bash
opencode auth lista
```
Ili kratka verzija.
```bash
opencode auth ls
```
---
#### odjava
Odjavljuje vas s provajdera tako što ga briše iz datoteke vjerodajnica.
```bash
opencode auth logout
```
---
### github
Upravljajte GitHub agentom za automatizaciju spremišta.
```bash
opencode github [command]
```
---
#### instaliraj
Instalirajte GitHub agenta u svoje spremište.
```bash
opencode github instalacija
```
Ovo postavlja neophodni tok rada GitHub Actions i vodi vas kroz proces konfiguracije. [Saznajte više](/docs/github).
---
#### trči
Pokrenite GitHub agent. Ovo se obično koristi u GitHub akcijama.
```bash
opencode github run
```
##### Zastave
| Zastava | Opis || --------- | -------------------------------------- |
| `--event` | GitHub lažni događaj za pokretanje agenta za |
| `--token` | GitHub token ličnog pristupa |
---
### mcp
Upravljajte serverima protokola konteksta modela.
```bash
opencode mcp [command]
```
---
#### dodaj
Dodajte MCP server svojoj konfiguraciji.
```bash
opencode mcp add
```
Ova komanda će vas voditi kroz dodavanje lokalnog ili udaljenog MCP servera.
---
#### lista
Navedite sve konfigurirane MCP servere i njihov status veze.
```bash
opencode mcp lista
```
Ili koristite kratku verziju.
```bash
opencode mcp ls
```
---
#### auth
Autentifikujte se sa MCP serverom koji je omogućen za OAuth.
```bash
opencode mcp auth [name]
```
Ako ne navedete ime servera, od vas će biti zatraženo da izaberete neki od dostupnih servera koji podržavaju OAuth.
Također možete navesti servere koji podržavaju OAuth i njihov status provjere autentičnosti.
```bash
opencode mcp auth list
```
Ili koristite kratku verziju.
```bash
opencode mcp auth ls
```
---
#### odjava
Uklonite OAuth vjerodajnice za MCP server.
```bash
opencode mcp logout [name]
```
---
#### otklanjanje grešaka
Otklanjanje grešaka OAuth veze sa MCP serverom.
```bash
opencode mcp debug <name>
```
---
### model
Navedite sve dostupne modele konfiguriranih provajdera.
```bash
opencode models [provider]
```
Ova naredba prikazuje sve modele dostupne kod vaših konfiguriranih provajdera u formatu `provider/model`.
Ovo je korisno za pronalaženje tačnog naziva modela za korištenje u [vašoj konfiguraciji](/docs/config/).
Opciono možete proslijediti ID provajdera za filtriranje modela po tom dobavljaču.
```bash
opencode models anthropic
```
#### Zastave
| Zastava | Opis || ----------- | ------------------------------------------------------------ |
| `--refresh` | Osvježite predmemoriju modela sa models.dev |
| `--verbose` | Koristite detaljniji izlaz modela (uključuje metapodatke poput troškova) |
Koristite `--refresh` zastavicu da ažurirate keširanu listu modela. Ovo je korisno kada su novi modeli dodani provajderu i želite da ih vidite u OpenCode-u.
```bash
opencode models --refresh
```
---
### trči
Pokrenite opencode u neinteraktivnom modu tako što ćete direktno proslijediti prompt.
```bash
opencode run [message..]
```
Ovo je korisno za skriptiranje, automatizaciju ili kada želite brz odgovor bez pokretanja punog TUI-ja. Na primjer.
```bash "opencode run"
opencode run Explain the use of context in Go
```
Također možete priključiti pokrenutu `opencode serve` instancu kako biste izbjegli vrijeme hladnog pokretanja MCP servera pri svakom pokretanju:
```bash
# Start a headless server in one terminal
opencode serve
# U drugom terminalu, pokrenite komande koje se vezuju za njega
opencode run --attach http://localhost:4096 "Objasni async/await u JavaScriptu"
```
#### Zastave
| Zastava | Kratko | Opis || ------------ | ----- | ------------------------------------------------------------------ |
| `--command` | | Naredba za pokretanje, koristite poruku za args |
| `--continue` | `-c` | Nastavite posljednju sesiju |
| `--session` | `-s` | ID sesije za nastavak |
| `--share` | | Podijelite sesiju |
| `--model` | `-m` | Model za korištenje u obliku provider/model |
| `--agent` | | Agent za korištenje |
| `--file` | `-f` | Fajlovi koje treba priložiti poruci |
| `--format` | | Format: default (formatiran) ili json (sirovi JSON događaji) |
| `--title` | | Naslov sesije (koristi skraćeni prompt ako nije navedena vrijednost) |
| `--attach` | | Priključite na pokrenuti opencode server (npr. http://localhost:4096) |
| `--port` | | Port za lokalni server (zadano na nasumični port) |
---
### poslužiti
Pokrenite OpenCode server bez glave za pristup API-ju. Pogledajte [server docs](/docs/server) za kompletan HTTP interfejs.
```bash
opencode serve
```
Ovo pokreće HTTP server koji pruža API pristup funkcionalnosti otvorenog koda bez TUI interfejsa. Postavite `OPENCODE_SERVER_PASSWORD` da omogućite HTTP osnovnu auth (korisničko ime je zadano na `opencode`).
#### Zastave
| Zastava | Opis || ------------ | ------------------------------------------ |
| `--port` | Port za slušanje na |
| `--hostname` | Ime hosta za slušanje |
| `--mdns` | Omogući mDNS otkrivanje |
| `--cors` | Dodatni izvor(a) pretraživača koji dozvoljavaju CORS |
---
### sesija
Upravljajte OpenCode sesijama.
```bash
opencode sesija [naredba]
```
---
#### lista
Navedite sve OpenCode sesije.
```bash
opencode session list
```
##### Zastave
| Zastava | Kratko | Opis || ------------- | ----- | ------------------------------------ |
| `--max-count` | `-n` | Ograničenje na N najnovijih sesija |
| `--format` | | Izlazni format: tablica ili json (tabela) |
---
### statistika
Prikaži statistiku upotrebe tokena i troškova za vaše OpenCode sesije.
```bash
opencode stats
```
#### Zastave
| Zastava | Opis || ----------- | ------------------------------------------------------------------------------------- |
| `--days` | Prikaži statistiku za zadnjih N dana (sva vremena) |
| `--tools` | Broj alata za prikaz (svi) |
| `--models` | Prikaži raščlambu korištenja modela (skriveno prema zadanim postavkama). Proslijedite broj za prikaz vrha N |
| `--project` | Filtriraj po projektu (svi projekti, prazan niz: trenutni projekt) |
---
### izvoz
Izvezite podatke sesije kao JSON.
```bash
opencode export [sessionID]
```
Ako ne unesete ID sesije, od vas će biti zatraženo da odaberete neku od dostupnih sesija.
---
### uvoz
Uvezite podatke sesije iz JSON datoteke ili OpenCode dijeljenog URL-a.
```bash
opencode import <file>
```
Možete uvesti iz lokalne datoteke ili OpenCode dijeljenog URL-a.
```bash
opencode import session.json
opencode import https://opncd.ai/s/abc123
```
---
### web
Pokrenite OpenCode server bez glave sa web interfejsom.
```bash
opencode web
```
Ovo pokreće HTTP server i otvara web pretraživač za pristup OpenCodeu preko web interfejsa. Postavite `OPENCODE_SERVER_PASSWORD` da omogućite HTTP osnovnu auth (korisničko ime je zadano na `opencode`).
#### Zastave
| Zastava | Opis || ------------ | ------------------------------------------ |
| `--port` | Port za slušanje na |
| `--hostname` | Ime hosta za slušanje |
| `--mdns` | Omogući mDNS otkrivanje |
| `--cors` | Dodatni izvor(a) pretraživača koji dozvoljavaju CORS |
---
### acp
Pokrenite ACP (Agent Client Protocol) server.
```bash
opencode acp
```
Ova komanda pokreće ACP server koji komunicira preko stdin/stdout koristeći nd-JSON.
#### Zastave
| Zastava | Opis || ------------ | --------------------- |
| `--cwd` | Radni imenik |
| `--port` | Port za slušanje na |
| `--hostname` | Slušajte ime hosta |
---
### deinstaliraj
Deinstalirajte OpenCode i uklonite sve povezane datoteke.
```bash
opencode uninstall
```
#### Zastave
| Zastava | Kratko | Opis || --------------- | ----- | ------------------------------------------- |
| `--keep-config` | `-c` | Čuvajte konfiguracijske datoteke |
| `--keep-data` | `-d` | Čuvajte podatke i snimke sesije |
| `--dry-run` | | Pokažite šta bi bilo uklonjeno bez uklanjanja |
| `--force` | `-f` | Preskoči upite za potvrdu |
---
### upgrade
Ažurira opencode na najnoviju verziju ili određenu verziju.
```bash
opencode upgrade [target]
```
Za nadogradnju na najnoviju verziju.
```bash
opencode upgrade
```
Za nadogradnju na određenu verziju.
```bash
opencode upgrade v0.1.48
```
#### Zastave
| Zastava | Kratko | Opis || ---------- | ----- | ------------------------------------------------------------------ |
| `--method` | `-m` | Korišteni način instalacije; curl, npm, pnpm, bun, brew |
---
## Globalne zastave
CLI otvorenog koda uzima sljedeće globalne zastavice.
| Zastava | Kratko | Opis || -------------- | ----- | ------------------------------------ |
| `--help` | `-h` | Prikaži pomoć |
| `--version` | `-v` | Odštampaj broj verzije |
| `--print-logs` | | Ispis zapisnika u stderr |
| `--log-level` | | Nivo dnevnika (DEBUG, INFO, WARN, ERROR) |
---
## Varijable okruženja
OpenCode se može konfigurirati pomoću varijabli okruženja.
| Varijabilna | Vrsta | Opis || ------------------------------------- | ------- | ------------------------------------------------- |
| `OPENCODE_AUTO_SHARE` | boolean | Automatski dijeli sesije |
| `OPENCODE_GIT_BASH_PATH` | string | Putanja do Git Bash izvršne datoteke na Windows |
| `OPENCODE_CONFIG` | string | Put do konfiguracionog fajla |
| `OPENCODE_CONFIG_DIR` | string | Put do konfiguracijskog direktorija |
| `OPENCODE_CONFIG_CONTENT` | string | Inline json konfiguracijski sadržaj |
| `OPENCODE_DISABLE_AUTOUPDATE` | boolean | Onemogući automatske provjere ažuriranja |
| `OPENCODE_DISABLE_PRUNE` | boolean | Onemogući orezivanje starih podataka |
| `OPENCODE_DISABLE_TERMINAL_TITLE` | boolean | Onemogući automatsko ažuriranje naslova terminala |
| `OPENCODE_PERMISSION` | string | Umetnuta json konfiguracija dozvola |
| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | boolean | Onemogući podrazumevane dodatke |
| `OPENCODE_DISABLE_LSP_DOWNLOAD` | boolean | Onemogući automatsko preuzimanje LSP servera |
| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolean | Omogući eksperimentalne modele |
| `OPENCODE_DISABLE_AUTOCOMPACT` | boolean | Onemogući automatsko sažimanje konteksta |
| `OPENCODE_DISABLE_CLAUDE_CODE` | boolean | Onemogući čitanje sa `.claude` (prompt + vještine) |
| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | boolean | Onemogući čitanje `~/.claude/CLAUDE.md` |
| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | boolean | Onemogući učitavanje `.claude/skills` |
| `OPENCODE_DISABLE_MODELS_FETCH` | boolean | Onemogući dohvaćanje modela iz udaljenih izvora |
| `OPENCODE_FAKE_VCS` | string | Lažni VCS provajder za potrebe testiranja |
| `OPENCODE_DISABLE_FILETIME_CHECK` | boolean | Onemogući provjeru vremena datoteke radi optimizacije |
| `OPENCODE_CLIENT` | string | Identifikator klijenta (zadano na `cli`) |
| `OPENCODE_ENABLE_EXA` | boolean | Omogući Exa alate za web pretraživanje |
| `OPENCODE_SERVER_PASSWORD` | string | Omogući osnovnu autorizaciju za `OPENCODE_GIT_BASH_PATH`/`OPENCODE_CONFIG` |
| `OPENCODE_SERVER_USERNAME` | string | Poništi osnovno korisničko ime autentifikacije (zadano `opencode`) |
| `OPENCODE_MODELS_URL` | string | Prilagođeni URL za dohvaćanje konfiguracije modela |
---
### Eksperimentalno
Ove varijable okruženja omogućavaju eksperimentalne karakteristike koje se mogu promijeniti ili ukloniti.
| Varijabilna | Vrsta | Opis || ----------------------------------------------- | ------- | --------------------------------------- |
| `OPENCODE_EXPERIMENTAL` | boolean | Omogući sve eksperimentalne funkcije |
| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | boolean | Omogući otkrivanje ikona |
| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | boolean | Onemogući kopiranje pri odabiru u TUI |
| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | broj | Zadano vremensko ograničenje za bash komande u ms |
| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | broj | Maksimalni izlazni tokeni za LLM odgovore |
| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | boolean | Omogući praćenje datoteka za cijeli dir |
| `OPENCODE_EXPERIMENTAL_OXFMT` | boolean | Omogući oxfmt formatter |
| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | boolean | Omogući eksperimentalni LSP alat |
| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | boolean | Onemogući praćenje datoteka |
| `OPENCODE_EXPERIMENTAL_EXA` | boolean | Omogući eksperimentalne Exa funkcije |
| `OPENCODE_EXPERIMENTAL_LSP_TY` | boolean | Omogući eksperimentalnu provjeru tipa LSP |
| `OPENCODE_EXPERIMENTAL_MARKDOWN` | boolean | Omogući eksperimentalne funkcije smanjenja |
| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | boolean | Omogući režim plana |

View File

@@ -0,0 +1,299 @@
---
title: komandant
description: Kreirajte prilagođene komande za zadatke koji se ponavljaju.
---
Prilagođene komande vam omogućavaju da odredite prompt koji želite da pokrenete kada se ta naredba izvrši u TUI-ju.
```bash frame="none"
/my-command
```
Prilagođene komande su dodatak ugrađenim komandama kao što su `/init`, `/undo`, `/redo`, `/share`, `/help`. [Saznajte više](/docs/tui#commands).
---
## Kreirajte komandne fajlove
Kreirajte mardown fajlove u direktorijumu `commands/` da definišete prilagođene komande.
Kreiraj `.opencode/commands/test.md`:
```md title=".opencode/commands/test.md"
---
description: Run tests with coverage
agent: build
model: anthropic/claude-3-5-sonnet-20241022
---
Run the full test suite with coverage report and show any failures.
Focus on the failing tests and suggest fixes.
```
Frontmatter definira svojstva komande. Sadržaj postaje predložak.
Koristite komandu tako što ćete upisati `/` nakon čega slijedi naziv komande.
```bash frame="none"
"/test"
```
---
## Konfiguriši
Možete dodati prilagođene komande kroz OpenCode konfiguraciju ili kreiranjem markdown datoteka u direktoriju `commands/`.
---
### JSON
Koristite opciju `command` u svom OpenCode [config](/docs/config):
```json title="opencode.jsonc" {4-12}
{
"$schema": "https://opencode.ai/config.json",
"command": {
// This becomes the name of the command
"test": {
// This is the prompt that will be sent to the LLM
"template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.",
// This is shown as the description in the TUI
"description": "Run tests with coverage",
"agent": "build",
"model": "anthropic/claude-3-5-sonnet-20241022"
}
}
}
```
Sada možete pokrenuti ovu naredbu u TUI:
```bash frame="none"
/test
```
---
### Markdown
Također možete definirati komande koristeći mardown datoteke. Stavite ih u:
- Globalno: `~/.config/opencode/commands/`
- Po projektu: `.opencode/commands/
````markdown title="~/.config/opencode/commands/test.md"
---
description: Run tests with coverage
agent: build
model: anthropic/claude-3-5-sonnet-20241022
---
Run the full test suite with coverage report and show any failures.
Focus on the failing tests and suggest fixes.
```
Ime datoteke za označavanje postaje ime naredbe. Na primjer, `test.md` dozvoljava
pokrećeš:
```bash frame="none"
/test
```
---
## Prompt config
Promptovi za prilagođene komande podržavaju nekoliko posebnih čuvara mjesta i sintakse.
---
### Argumenti
Proslijedite argumente naredbama koristeći čuvar mjesta `$ARGUMENTS`.
```md title=".opencode/commands/component.md"
---
description: Create a new component
---
Create a new React component named $ARGUMENTS with TypeScript support.
Include proper typing and basic structure.
```
Pokrenite naredbu s argumentima:
```bash frame="none"
/componentButton
```
I `$ARGUMENTS` će biti zamijenjen sa `Button`.
Također možete pristupiti pojedinačnim argumentima koristeći pozicione parametre:
- `$1` - Prvi argument
- `$2` - Drugi argument
- `$3` - Treći argument
- I tako dalje...
na primjer:
```md title=".opencode/commands/create-file.md"
---
description: Create a new file with content
---
Create a file named $1 in the directory $2
with the following content: $3
```
Pokrenite naredbu:
```bash frame="none"
/create-file config.json src "{ \"key\": \"value\" }"
```
Ovo zamjenjuje:
- `$1` do `config.json`
- `$2` do `src`
- `$3` do `{ "key": "value" }`
---
### Izlaz ljuske
Koristite _!`command`_ da ubacite [bash command](/docs/tui#bash-commands) izlaz u svoj prompt.
Na primjer, da kreirate prilagođenu naredbu koja analizira pokrivenost testom:
```md title=".opencode/commands/analyze-coverage.md"
---
description: Analyze test coverage
---
Here are the current test results:
!`npm test`
Based on these results, suggest improvements to increase coverage.
```
Ili da vidite nedavne promjene:
```md title=".opencode/commands/review-changes.md"
---
opis: Pregledajte nedavne promjene
---
Nedavna git urezivanja:
!`git log --oneline -10`
Pregledajte ove promjene i predložite bilo kakva poboljšanja.
```
Naredbe se pokreću u korijenskom direktoriju vašeg projekta i njihov izlaz postaje dio prompta.
---
### Reference fajlova
Uključite datoteke u svoju naredbu koristeći `@` nakon čega slijedi naziv datoteke.
```md title=".opencode/commands/review-component.md"
---
description: Review component
---
Review the component in @src/components/Button.tsx.
Check for performance issues and suggest improvements.
```
Sadržaj datoteke se automatski uključuje u prompt.
---
## Opcije
Pogledajmo detaljno opcije konfiguracije.
---
### Template
Opcija `template` definira prompt koji će biti poslan LLM-u kada se naredba izvrši.
```json title="opencode.json"
{
"komanda": {
"test": {
"template": "Pokrenite kompletan testni paket sa izvještajem o pokrivenosti i pokažite sve greške.\nFokusirajte se na neuspjele testove i predložite popravke." }
}
}
```
Ovo je **obavezna** opcija konfiguracije.
---
### Opis
Koristite opciju `description` da pružite kratak opis onoga što naredba radi.
```json title="opencode.json"
{
"command": {
"test": {
"description": "Run tests with coverage"
}
}
}
```
Ovo se prikazuje kao opis u TUI-u kada unesete naredbu.
---
### Agent
Koristite `agent` konfiguraciju da opciono odredite koji [agent](/docs/agents) treba da izvrši ovu naredbu.
Ako je ovo [subagent](/docs/agents/#subagents) naredba će po defaultu pokrenuti pozivanje subagenta.
Da onemogućite ovo ponašanje, postavite `subtask` na `false`.
```json title="opencode.json"
{
"komanda": {
"recenzija": {
"agent": "plan" }
}
}
```
Ovo je **opciona** opcija konfiguracije. Ako nije navedeno, podrazumevano je vaš trenutni agent.
---
### Subdatatak
Koristite `subtask` boolean da prisilite naredbu da pokrene [subagent](/docs/agents/#subagents) pozivanje.
Ovo je korisno ako želite da naredba ne zagađuje vaš primarni kontekst i da će **primorati** agenta da djeluje kao subagent,
čak i ako je `mode` postavljeno na `primary` u konfiguraciji [agent](/docs/agents).
```json title="opencode.json"
{
"command": {
"analyze": {
"subtask": true
}
}
}
```
Ovo je **opciona** opcija konfiguracije.
---
### Model
Koristite `model` konfiguraciju da nadjačate zadani model za ovu naredbu.
```json title="opencode.json"
{
"komanda": {
"analizirati": {
"model": "antropski/claude-3-5-sonnet-20241022" }
}
}
```
Ovo je **opciona** opcija konfiguracije.
---
## Embedded
opencode uključuje nekoliko ugrađenih naredbi kao što su `/init`, `/undo`, `/redo`, `/share`, `/help`; [saznaj više](/docs/tui#commands).
:::napomena
Prilagođene komande mogu nadjačati ugrađene komande.
:::
Ako definirate prilagođenu naredbu s istim imenom, ona će nadjačati ugrađenu naredbu.

View File

@@ -0,0 +1,657 @@
---
title: Config
description: Korištenje OpenCode JSON konfiguracije.
---
Možete konfigurirati OpenCode koristeći JSON konfiguracijski fajl.
---
## Format
OpenCode podržava i **JSON** i **JSONC** (JSON sa komentarima) formate.
```jsonc title="opencode.jsonc"
{
"$schema": "https://opencode.ai/config.json",
// Konfiguracija teme
"tema": "otvoreni kod",
"model": "antropski/claude-sonnet-4-5",
"automatsko ažuriranje": istina,}
```
---
## Lokacije
Možete postaviti svoju konfiguraciju na nekoliko različitih lokacija i one imaju a
drugačiji redosled prioriteta.
:::napomena
Konfiguracijski fajlovi su **spojeni zajedno**, a ne zamijenjeni.
:::
Konfiguracijski fajlovi se spajaju, ne zamjenjuju. Kombiniraju se postavke sa sljedećih konfiguracijskih lokacija. Kasnije konfiguracije poništavaju prethodne samo za konfliktne ključeve. Nekonfliktne postavke iz svih konfiguracija su sačuvane.
Na primjer, ako vaša globalna konfiguracija postavlja `theme: "opencode"` i `autoupdate: true`, a vaša projektna konfiguracija postavlja `model: "anthropic/claude-sonnet-4-5"`, konačna konfiguracija će uključivati sve tri postavke.
---
### Redoslijed prioriteta
Izvori konfiguracije se učitavaju ovim redoslijedom (kasniji izvori poništavaju ranije):
1. **Udaljena konfiguracija** (od `.well-known/opencode`) - organizacione postavke
2. **Globalna konfiguracija** (`~/.config/opencode/opencode.json`) - korisničke postavke
3. **Prilagođena konfiguracija** (`OPENCODE_CONFIG` env var) - prilagođena zaobilaženja
4. **Konfiguracija projekta** (`opencode.json` u projektu) - postavke specifične za projekat
5. **`.opencode` direktoriji** - agenti, komande, dodaci
6. **Inline config** (`OPENCODE_CONFIG_CONTENT` env var) - runtime nadjačava
To znači da konfiguracije projekta mogu nadjačati globalne zadane postavke, a globalne konfiguracije mogu nadjačati postavke udaljene organizacije.
:::napomena
Direktoriji `.opencode` i `~/.config/opencode` koriste **imena u množini** za poddirektorije: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/` i `themes/`. Pojedinačna imena (npr. `agent/`) su također podržana za kompatibilnost unatrag.
:::
---
### Daljinski
Organizacije mogu pružiti zadanu konfiguraciju preko `.well-known/opencode` krajnje točke. Ovo se automatski preuzima kada se autentifikujete kod provajdera koji to podržava.
Prvo se učitava udaljena konfiguracija koja služi kao osnovni sloj. Svi ostali izvori konfiguracije (globalni, projektni) mogu nadjačati ove zadane postavke.
Na primjer, ako vaša organizacija nudi MCP servere koji su po defaultu onemogućeni:
```json title="Remote config from .well-known/opencode"
{
"mcp": {
"jira": {
"type": "remote",
"url": "https://jira.example.com/mcp",
"enabled": false
}
}
}
```
Možete omogućiti određene servere u vašoj lokalnoj konfiguraciji:
```json title="opencode.json"
{
"mcp": {
"jira": {
"tip": "daljinski",
"url": "https://jira.example.com/mcp",
"omogućeno": istina }
}
}
```
---
### Global
Postavite svoju globalnu OpenCode konfiguraciju u `~/.config/opencode/opencode.json`. Koristite globalnu konfiguraciju za korisničke preferencije kao što su teme, provajderi ili veze tipki.
Globalna konfiguracija poništava zadane postavke udaljene organizacije.
---
### Nakon projekta
Dodajte `opencode.json` u korijen projekta. Konfiguracija projekta ima najveći prioritet među standardnim konfiguracijskim datotekama - ona nadjačava globalne i udaljene konfiguracije.
::: tip
Postavite specifičnu konfiguraciju projekta u korijen vašeg projekta.
:::
Kada se OpenCode pokrene, traži konfiguracijsku datoteku u trenutnom direktoriju ili prelazi do najbližeg Git direktorija.
Ovo je također sigurno provjeriti u Git i koristi istu shemu kao globalna.
---
### Custom track
Navedite prilagođenu putanju konfiguracijske datoteke koristeći varijablu okruženja `OPENCODE_CONFIG`.
```bash
export OPENCODE_CONFIG=/path/to/my/custom-config.json
opencode run "Hello world"
```
Prilagođena konfiguracija se učitava između globalne i projektne konfiguracije po redoslijedu prioriteta.
---
### Prilagođeni imenik
Navedite prilagođeni konfiguracijski direktorij koristeći `OPENCODE_CONFIG_DIR`
varijabla okruženja. U ovom direktoriju će se tražiti agenti, komande,
modove i dodatke baš kao standardni `.opencode` direktorij, i trebali bi
prate istu strukturu.
```bash
export OPENCODE_CONFIG_DIR=/path/to/my/config-directory
opencode run "Hello world"
```
Prilagođeni direktorij se učitava nakon direktorija globalne konfiguracije i `.opencode`, tako da **može nadjačati** njihove postavke.
---
## Shema
Konfiguracijski fajl ima šemu koja je definirana u [**`opencode.ai/config.json`**](https://opencode.ai/config.json).
Vaš uređivač bi trebao biti u mogućnosti da potvrdi i autodovršava na osnovu šeme.
---
### TUI
Možete konfigurirati postavke specifične za TUI putem opcije `tui`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"tui": {
"scroll_speed": 3,
"scroll_acceleration": {
"enabled": true
},
"diff_style": "auto"
}
}
```
Dostupne opcije:
- `scroll_acceleration.enabled` - Omogući ubrzanje skrolovanja u macOS stilu. **Ima prednost nad `scroll_speed`.**
- `scroll_speed` - Prilagođeni množitelj brzine pomicanja (podrazumevano: `3`, minimalno: `1`). Zanemareno ako je `scroll_acceleration.enabled` `true`.
- `diff_style` - Kontrola prikaza razlike. `"auto"` se prilagođava širini terminala, `"stacked"` uvijek prikazuje jednu kolonu.
[Ovdje saznajte više o korištenju TUI](/docs/tui).
---
### Server
Možete konfigurirati postavke servera za komande `opencode serve` i `opencode web` putem opcije `server`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"server": {
"port": 4096,
"hostname": "0.0.0.0",
"mdns": true,
"mdnsDomain": "myproject.local",
"cors": ["http://localhost:5173"]
}
}
```
Dostupne opcije:
- `port` - Port za slušanje.
- `hostname` - Ime hosta za slušanje. Kada je `mdns` omogućen i nije postavljeno ime hosta, podrazumevano je `0.0.0.0`.
- `mdns` - Omogući otkrivanje mDNS usluge. Ovo omogućava drugim uređajima na mreži da otkriju vaš OpenCode server.
- `mdnsDomain` - Prilagođeno ime domene za mDNS uslugu. Zadano je `opencode.local`. Korisno za pokretanje više instanci na istoj mreži.
- `cors` - Dodatni izvori koji omogućavaju CORS kada koristite HTTP server iz klijenta baziranog na pretraživaču. Vrijednosti moraju biti punog porijekla (šema + host + opcijski port), npr. `https://app.example.com`.
[Saznajte više o serveru](/docs/server) ovdje.
---
### Uvijek
Možete upravljati alatima koje LLM može koristiti putem opcije `tools`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"tools": {
"write": false,
"bash": false
}
}
```
[Saznajte više o alatima](/docs/tools) ovdje.
---
### Model
Možete konfigurirati dobavljače i modele koje želite koristiti u svojoj OpenCode konfiguraciji kroz opcije `provider`, `model` i `small_model`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"provider": {},
"model": "anthropic/claude-sonnet-4-5",
"small_model": "anthropic/claude-haiku-4-5"
}
```
Opcija `small_model` konfigurira poseban model za lagane zadatke poput generiranja naslova. Podrazumevano, OpenCode pokušava da koristi jeftiniji model ako je dostupan od vašeg provajdera, inače se vraća na vaš glavni model.
Opcije provajdera mogu uključivati `timeout` i `setCacheKey`:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"anthropic": {
"options": {
"timeout": 600000,
"setCacheKey": true
}
}
}
}
```
- `timeout` - Vrijeme čekanja zahtjeva u milisekundama (podrazumevano: 300000). Postavite na `false` da onemogućite.
- `setCacheKey` - Osigurajte da je ključ keš memorije uvijek postavljen za određenog provajdera.
Također možete konfigurirati [lokalni modeli](/docs/models#local). [Saznajte više](/docs/models).
---
#### Opcije specifične za provajdere
Neki provajderi podržavaju dodatne opcije konfiguracije osim generičkih postavki `timeout` i `apiKey`.
##### Amazon Bedrock
Amazon Bedrock podržava konfiguraciju specifičnu za AWS:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"amazon-bedrock": {
"options": {
"region": "us-east-1",
"profile": "my-aws-profile",
"endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com"
}
}
}
}
```
- `region` - AWS regija za Bedrock (zadano na `AWS_REGION` env var ili `us-east-1`)
- `profile` - AWS imenovan profil od `~/.aws/credentials` (podrazumevano na `AWS_PROFILE` env var)
- `endpoint` - URL prilagođene krajnje tačke za VPC krajnje tačke. Ovo je pseudonim za generičku opciju `baseURL` koristeći terminologiju specifičnu za AWS. Ako su oba navedena, `endpoint` ima prednost.
:::napomena
Tokeni nosioca (`AWS_BEARER_TOKEN_BEDROCK` ili `/connect`) imaju prednost nad autentifikacijom zasnovanom na profilu. Pogledajte [prednost autentifikacije](/docs/providers#authentication-precedence) za detalje.
:::
[Saznajte više o konfiguraciji Amazon Bedrock](/docs/providers#amazon-bedrock).
---
### Domaći
Možete konfigurirati temu koju želite koristiti u svojoj OpenCode konfiguraciji putem opcije `theme`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"theme": ""
}
```
[Saznajte više ovdje](/docs/themes).
---
### Agenti
Možete konfigurirati specijalizirane agente za određene zadatke putem opcije `agent`.
```jsonc title="opencode.jsonc"
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"code-reviewer": {
"description": "Reviews code for best practices and potential issues",
"model": "anthropic/claude-sonnet-4-5",
"prompt": "You are a code reviewer. Focus on security, performance, and maintainability.",
"tools": {
// Disable file modification tools for review-only agent
"write": false,
"edit": false,
},
},
},
}
```
Također možete definirati agente koristeći mardown datoteke u `~/.config/opencode/agents/` ili `.opencode/agents/`. [Saznajte više ovdje](/docs/agents).
---
### Zadani agent
Možete postaviti zadanog agenta koristeći opciju `default_agent`. Ovo određuje koji se agent koristi kada nijedan nije eksplicitno specificiran.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"default_agent": "plan"
}
```
Zadani agent mora biti primarni agent (ne podagent). Ovo može biti ugrađeni agent kao što je `"build"` ili `"plan"`, ili [prilagođeni agent](/docs/agents) koji ste definirali. Ako navedeni agent ne postoji ili je subagent, OpenCode će se vratiti na `"build"` s upozorenjem.
Ova postavka se primjenjuje na sva sučelja: TUI, CLI (`opencode run`), desktop aplikaciju i GitHub Action.
---
### Dijeljenje
Možete konfigurirati funkciju [share](/docs/share) putem opcije `share`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"share": "manual"
}
```
Ovo traje:
- `"manual"` - Dozvoli ručno dijeljenje putem komandi (podrazumevano)
- `"auto"` - Automatski dijelite nove razgovore
- `"disabled"` - Onemogući dijeljenje u potpunosti
Podrazumevano, dijeljenje je postavljeno na ručni način rada gdje trebate eksplicitno dijeliti razgovore pomoću naredbe `/share`.
---
### komandante
Možete konfigurirati prilagođene komande za ponavljanje zadataka putem opcije `command`.
```jsonc title="opencode.jsonc"
{
"$schema": "https://opencode.ai/config.json",
"command": {
"test": {
"template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.",
"description": "Run tests with coverage",
"agent": "build",
"model": "anthropic/claude-haiku-4-5",
},
"component": {
"template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.",
"description": "Create a new component",
},
},
}
```
Također možete definirati komande koristeći mardown fajlove u `~/.config/opencode/commands/` ili `.opencode/commands/`. [Saznajte više ovdje](/docs/commands).
---
### Keybinds
Možete prilagoditi svoje veze ključeva putem opcije `keybinds`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"keybinds": {}
}
```
[Saznajte više ovdje](/docs/keybinds).
---
### Automatsko ažuriranje
OpenCode će automatski preuzeti sva nova ažuriranja kada se pokrene. Ovo možete onemogućiti opcijom `autoupdate`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"autoupdate": false
}
```
Ako ne želite ažuriranja, ali želite biti obaviješteni kada nova verzija bude dostupna, postavite `autoupdate` na `"notify"`.
Imajte na umu da ovo funkcionira samo ako nije instalirano pomoću upravitelja paketa kao što je Homebrew.
---
### Trenerke
Možete konfigurirati formatere koda putem opcije `formatter`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"formatter": {
"prettier": {
"disabled": true
},
"custom-prettier": {
"command": ["npx", "prettier", "--write", "$FILE"],
"environment": {
"NODE_ENV": "development"
},
"extensions": [".js", ".ts", ".jsx", ".tsx"]
}
}
}
```
[Saznajte više o formatterima](/docs/formatters) ovdje.
---
### Dozvole
Prema zadanim postavkama, opencode **dopušta sve operacije** bez potrebe za eksplicitnim dopuštenjem. Ovo možete promijeniti koristeći opciju `permission`.
Na primjer, da osigurate da alati `edit` i `bash` zahtijevaju odobrenje korisnika:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"edit": "ask",
"bash": "ask"
}
}
```
[Ovdje saznajte više o ](/docs/permissions) dozvolama.
---
### Compaction
Možete kontrolirati ponašanje sažimanja konteksta putem opcije `compaction`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"compaction": {
"auto": true,
"prune": true
}
}
```
- `auto` - Automatski sažimanje sesije kada je kontekst pun (podrazumevano: `true`).
- `prune` - Uklonite stare izlaze alata da sačuvate tokene (podrazumevano: `true`).
---
### Watcher
Možete konfigurirati obrasce ignoriranja promatrača datoteka putem opcije `watcher`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"watcher": {
"ignore": ["node_modules/**", "dist/**", ".git/**"]
}
}
```
Obrasci prate glob sintaksu. Koristite ovo da isključite bučne direktorije iz pregleda datoteka.
---
### MCP serveri
Možete konfigurirati MCP servere koje želite koristiti putem opcije `mcp`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {}
}
```
[Saznajte više ovdje](/docs/mcp-servers).
---
### Extras
[Plugins](/docs/plugins) proširuju OpenCode sa prilagođenim alatima, kukicama i integracijama.
Postavite datoteke dodataka u `.opencode/plugins/` ili `~/.config/opencode/plugins/`. Također možete učitati dodatke iz npm-a preko opcije `plugin`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-helicone-session", "@my-org/custom-plugin"]
}
```
[Saznajte više ovdje](/docs/plugins).
---
### Uputstva
Možete konfigurirati upute za model koji koristite putem opcije `instructions`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"]
}
```
Ovo uzima niz putanja i uzoraka globusa do datoteka instrukcija. [Saznajte više
o pravilima ovdje](/docs/rules).
---
### Onemogućeni provajderi
Možete onemogućiti dobavljače koji se automatski učitavaju preko opcije `disabled_providers`. Ovo je korisno kada želite spriječiti učitavanje određenih provajdera čak i ako su njihovi vjerodajnici dostupni.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"disabled_providers": ["openai", "gemini"]
}
```
:::napomena
`disabled_providers` ima prioritet nad `enabled_providers`.
:::
Opcija `disabled_providers` prihvata niz ID-ova provajdera. Kada je provajder onemogućen:
- Neće se učitati čak i ako su varijable okruženja postavljene.
- Neće se učitati čak i ako su API ključevi konfigurirani putem `/connect` komande.
- Modeli dobavljača se neće pojaviti na listi za odabir modela.
---
### Omogućeni provajderi
Možete odrediti listu dozvoljenih dobavljača putem opcije `enabled_providers`. Kada se podesi, samo navedeni provajderi će biti omogućeni, a svi ostali će biti zanemareni.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"enabled_providers": ["anthropic", "openai"]
}
```
Ovo je korisno kada želite da ograničite OpenCode da koristi samo određene provajdere umesto da ih onemogućavate jednog po jednog.
:::napomena
`disabled_providers` ima prioritet nad `enabled_providers`.
:::
Ako se provajder pojavljuje i u `enabled_providers` i `disabled_providers`, `disabled_providers` ima prioritet za kompatibilnost unatrag.
---
### Eksperimentalno
Ključ `experimental` sadrži opcije koje su u aktivnom razvoju.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"experimental": {}
}
```
:::oprez
Eksperimentalne opcije nisu stabilne. Mogu se promijeniti ili ukloniti bez prethodne najave.
:::
---
## Varijable
Možete koristiti zamjenu varijabli u vašim konfiguracijskim datotekama da biste referencirali varijable okruženja i sadržaj datoteke.
---
### Env vars
Koristite `{env:VARIABLE_NAME}` za zamjenu varijabli okruženja:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"model": "{env:OPENCODE_MODEL}",
"provider": {
"anthropic": {
"models": {},
"options": {
"apiKey": "{env:ANTHROPIC_API_KEY}"
}
}
}
}
```
Ako varijabla okruženja nije postavljena, bit će zamijenjena praznim nizom.
---
### Fajlovi
Koristite `{file:path/to/file}` da zamijenite sadržaj fajla:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"instructions": ["./custom-instructions.md"],
"provider": {
"openai": {
"options": {
"apiKey": "{file:~/.secrets/openai-key}"
}
}
}
}
```
Putanja fajla mogu biti:
- U odnosu na direktorij konfiguracijskih datoteka
- Ili apsolutne staze koje počinju sa `/` ili `~`
Ovo je korisno za:
- Pohranjivanje osjetljivih podataka poput API ključeva u odvojenim datotekama.
- Uključujući velike datoteke instrukcija bez zatrpavanja vaše konfiguracije.
- Dijeljenje zajedničkih isječaka konfiguracije u više konfiguracijskih datoteka.

View File

@@ -0,0 +1,160 @@
---
title: Custom Tools
description: Kreirajte alate koje LLM može pozvati u otvorenom kodu.
---
Prilagođeni alati su funkcije koje kreirate i koje LLM može pozvati tokom razgovora. Oni rade zajedno sa [ugrađenim opencode](/docs/tools) alatima kao što su `read`, `write` i `bash`.
---
## Kreiranje alata
Alati su definisani kao **TypeScript** ili **JavaScript** datoteke. Međutim, definicija alata može pozvati skripte napisane na **bilo kom jeziku** — TypeScript ili JavaScript se koriste samo za samu definiciju alata.
---
### Lokacija
Mogu se definisati:
- Lokalno postavljanjem u `.opencode/tools/` direktorij vašeg projekta.
- Ili globalno, postavljanjem u `~/.config/opencode/tools/`.
---
### Struktura
Najlakši način za kreiranje alata je korištenje pomoćnika `tool()` koji pruža sigurnost tipa i validaciju.
```ts title=".opencode/tools/database.ts" {1}
import { tool } from "@opencode-ai/plugin"
export default tool({
description: "Query the project database",
args: {
query: tool.schema.string().describe("SQL query to execute"),
},
async execute(args) {
// Your database logic here
return `Executed query: ${args.query}`
},
})
```
**ime datoteke** postaje **naziv alata**. Gore navedeno je kreirano pomoću `database` alata.
---
#### Više alata po datoteci
Također možete izvesti više alata iz jedne datoteke. Svaki izvoz postaje **poseban alat** pod nazivom **`<filename>_<exportname>`**:
```ts title=".opencode/tools/math.ts"
import { tool } from "@opencode-ai/plugin"
export const add = tool({
description: "Add two numbers",
args: {
a: tool.schema.number().describe("First number"),
b: tool.schema.number().describe("Second number"),
},
async execute(args) {
return args.a + args.b
},
})
export const multiply = tool({
description: "Multiply two numbers",
args: {
a: tool.schema.number().describe("First number"),
b: tool.schema.number().describe("Second number"),
},
async execute(args) {
return args.a * args.b
},
})
```
Ovo stvara dva alata: `math_add` i `math_multiply`.
---
### Argumenti
Možete koristiti `tool.schema`, što je samo [Zod](https://zod.dev), da definirate tipove argumenata.
```ts "tool.schema"
args: {
query: tool.schema.string().describe("SQL query to execute")
}
```
Također možete direktno uvesti [Zod](https://zod.dev) i vratiti običan objekt:
```ts {6}
import { z } from "zod"
export default {
description: "Tool description",
args: {
param: z.string().describe("Parameter description"),
},
async execute(args, context) {
// Tool implementation
return "result"
},
}
```
---
### Kontekst
Alati primaju kontekst o trenutnoj sesiji:
```ts title=".opencode/tools/project.ts" {8}
import { tool } from "@opencode-ai/plugin"
export default tool({
description: "Get project information",
args: {},
async execute(args, context) {
// Access context information
const { agent, sessionID, messageID, directory, worktree } = context
return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}`
},
})
```
Koristite `context.directory` za radni direktorij sesije.
Koristite `context.worktree` za korijen git radnog stabla.
---
## Primjeri
### Napišite alat u Python-u
Možete pisati svoje alate na bilo kom jeziku koji želite. Evo primjera koji zbraja dva broja koristeći Python.
Prvo kreirajte alat kao Python skriptu:
```python title=".opencode/tools/add.py"
import sys
a = int(sys.argv[1])
b = int(sys.argv[2])
print(a + b)
```
Zatim kreirajte definiciju alata koja ga poziva:
```ts title=".opencode/tools/python-add.ts" {10}
import { tool } from "@opencode-ai/plugin"
import path from "path"
export default tool({
description: "Add two numbers using Python",
args: {
a: tool.schema.number().describe("First number"),
b: tool.schema.number().describe("Second number"),
},
async execute(args, context) {
const script = path.join(context.worktree, ".opencode/tools/add.py")
const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text()
return result.trim()
},
})
```
Ovdje koristimo [`Bun.$`_](https://bun.com/docs/runtime/shell) uslužni program za pokretanje Python skripte.

View File

@@ -0,0 +1,66 @@
---
title: Ekosistem
description: Projekti i integracije izgrađeni uz OpenCode.
---
Kolekcija projekata zajednice izgrađenih na OpenCode-u.
:::napomena
Želite li na ovu listu dodati svoj OpenCode projekat? Pošaljite PR.
:::
Također možete pogledati [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) i [opencode.cafe](https://opencode.cafe), zajednicu koja spaja ekosistem i zajednicu.
---
## Dodaci
| Ime | Opis || --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | Automatski pokrenite OpenCode sesije u izoliranim Daytona sandboxovima uz git sinhronizaciju i preglede uživo |
| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | Automatski ubacite Helicone zaglavlja sesije za grupisanje zahtjeva |
| [opencode-type-iject](https://github.com/nick-vi/opencode-type-inject) | Automatski ubaci TypeScript/Svelte tipove u čitanje datoteka pomoću alata za pretraživanje |
| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | Koristite svoju ChatGPT Plus/Pro pretplatu umjesto API kredita |
| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | Koristite svoj postojeći Gemini plan umjesto API naplate |
| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | Koristite besplatne modele Antigravity umjesto API naplate |
| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | Izolacija devcontainer-a s više grana s plitkim klonovima i automatski dodijeljenim portovima |
| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Google Antigravity OAuth dodatak, s podrškom za Google pretraživanje i robusnijim API rukovanjem |
| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | Optimizirajte korištenje tokena smanjenjem izlaza zastarjelih alata |
| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | Dodajte podršku za izvorno web pretraživanje za podržane provajdere sa stilom utemeljenim na Googleu |
| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | Omogućuje AI agentima da pokreću pozadinske procese u PTY-u, šalju im interaktivni ulaz. |
| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | Upute za neinteraktivne naredbe ljuske - sprječava visi od TTY ovisnih operacija || [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | Pratite upotrebu OpenCodea sa Wakatime |
| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | Očistite tabele umanjenja vrijednosti koje su izradili LLM |
| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | 10x brže uređivanje koda s Morph Fast Apply API-jem i markerima za lijeno uređivanje |
| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | Pozadinski agenti, unapred izgrađeni LSP/AST/MCP alati, kurirani agenti, kompatibilni sa Claude Code |
| [opencode-notificator](https://github.com/panta82/opencode-notificator) | Obavještenja na radnoj površini i zvučna upozorenja za OpenCode sesije |
| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | Obavještenja na radnoj površini i zvučna upozorenja za dozvole, završetak i događaje greške |
| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | Automatsko imenovanje Zellij sesije na bazi OpenCode konteksta |
| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | Dozvolite OpenCode agentima da lijeno učitavaju upite na zahtjev uz otkrivanje vještina i ubrizgavanje |
| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | Trajna memorija kroz sesije koristeći Supermemory |
| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | Interaktivni pregled plana s vizualnim napomenama i privatnim/offline dijeljenjem |
| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | Proširite opencode /komande u moćan sistem orkestracije sa granularnom kontrolom toka |
| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | Planirajte ponavljajuće poslove koristeći launchd (Mac) ili systemd (Linux) sa cron sintaksom || [micode](https://github.com/vtemian/micode) | Strukturirana Brainstorm → Plan → Implementacija toka rada uz kontinuitet sesije |
| [oktobar](https://github.com/vtemian/octto) | Interaktivno korisničko sučelje pretraživača za AI brainstorming sa obrascima za više pitanja |
| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | Pozadinski agenti u stilu Claudea s asinhroniziranim delegiranjem i postojanošću konteksta |
| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | Notifikacije izvornog OS-a za OpenCode znajte kada se zadaci dovrše |
| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | Uvezeni višeagentni orkestracijski pojas 16 komponenti, jedna instalacija |
| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | Git radna stabla bez trenja za OpenCode |
---
## Projekti
| Ime | Opis || ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------- |
| [kimaki](https://github.com/remorses/kimaki) | Discord bot za kontrolu OpenCode sesija, izgrađen na SDK |
| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | Neovim dodatak za upite svjestan uređivača, izgrađen na API |
| [portal](https://github.com/hosenur/portal) | Mobilni korisnički interfejs za OpenCode preko Tailscale/VPN |
| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | Predložak za izgradnju OpenCode dodataka |
| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | Neovim frontend za opencode - terminal baziran AI agent za kodiranje |
| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | Vercel AI SDK dobavljač za korištenje OpenCodea putem @opencode-ai/sdk |
| [OpenChamber](https://github.com/btriapitsyn/openchamber) | Web / Desktop App i VS Code Extension za OpenCode |
| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | Obsidian dodatak koji ugrađuje OpenCode u Obsidian-ov UI |
| [OpenWork](https://github.com/different-ai/openwork) | Alternativa otvorenog koda Claudeu Coworku, pokretana pomoću OpenCode |
| [ocx](https://github.com/kdcokenny/ocx) | OpenCode menadžer ekstenzija sa prenosivim, izolovanim profilima. |
| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | Desktop, Web, Mobile i Remote Client aplikacija za OpenCode |
---
## Agenti
| Ime | Opis || ----------------------------------------------------------------- | ------------------------------------------------------------ |
| [Agentic](https://github.com/Cluster444/agentic) | Modularni AI agenti i komande za strukturirani razvoj |
| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | Konfiguracije, upiti, agenti i dodaci za poboljšane tokove rada |

View File

@@ -0,0 +1,165 @@
---
title: Enterprise
description: Sigurno korištenje OpenCodea u vašoj organizaciji.
---
import config from "../../../../config.mjs"
export const email = `mailto:${config.email}`
OpenCode Enterprise je za organizacije koje žele osigurati da njihov kod i podaci nikada ne napuštaju njihovu infrastrukturu. To omogućava centralizovana konfiguracija koja se integriše s vašim SSO-om i internim AI gateway-om.
:::note
OpenCode ne pohranjuje nijedan vaš kod ili kontekstualne podatke.
:::
Da započnete s OpenCode Enterprise:
1. Uradite interni probni period sa svojim timom.
2. **<a href={email}>Kontaktirajte nas</a>** da razgovaramo o cijenama i opcijama implementacije.
---
## Trial
OpenCode je otvorenog koda i ne pohranjuje vaš kod niti kontekstualne podatke, tako da vaši developeri mogu jednostavno [započeti](/docs/) i provesti probu.
---
### Rukovanje podacima
**OpenCode ne pohranjuje vaš kod ni kontekstualne podatke.** Sva obrada se odvija lokalno ili putem direktnih API poziva vašem AI provajderu.
To znači da, sve dok koristite provajdera kojem vjerujete ili interni AI gateway, OpenCode možete koristiti sigurno.
Jedina iznimka je opcionalna funkcija `/share`.
---
#### Dijeljenje razgovora
Ako korisnik uključi funkciju `/share`, razgovor i povezani podaci šalju se servisu koji koristimo za hosting ovih share stranica na opencode.ai.
Podaci se trenutno serviraju kroz edge mrežu našeg CDN-a i keširaju se blizu korisnika.
Preporučujemo da ovo onemogućite tokom probe.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"share": "disabled"
}
```
[Saznajte više o dijeljenju](/docs/share).
---
### Vlasništvo koda
**Vi posjedujete sav kod koji OpenCode proizvede.** Nema ograničenja licenciranja niti zahtjeva za vlasništvo.
---
## Pricing
Koristimo model naplate po sjedištu za OpenCode Enterprise. Ako imate vlastiti LLM gateway, ne naplaćujemo korištene tokene. Za više detalja o cijenama i opcijama implementacije, **<a href={email}>kontaktirajte nas</a>**.
---
## Deployment
Nakon što završite probni period i spremni ste koristiti OpenCode u svojoj organizaciji, možete **<a href={email}>kontaktirati nas</a>** da razgovaramo o cijenama i opcijama implementacije.
---
### Central Config
Možemo postaviti OpenCode da koristi jednu centralnu konfiguraciju za cijelu organizaciju.
Ta centralizovana konfiguracija može se integrisati s vašim SSO provajderom i osigurava da svi korisnici pristupaju samo vašem internom AI gateway-u.
---
### SSO integracija
Kroz centralnu konfiguraciju, OpenCode se može integrisati sa SSO provajderom vaše organizacije za autentifikaciju.
To omogućava OpenCodeu da dobije vjerodajnice za interni AI gateway kroz vaš postojeći sistem upravljanja identitetom.
---
### Interni AI gateway
Uz centralnu konfiguraciju, OpenCode se može podesiti da koristi samo vaš interni AI gateway.
Također možete onemogućiti sve druge AI provajdere, čime osiguravate da svi zahtjevi prolaze kroz odobrenu infrastrukturu vaše organizacije.
---
### Self-hosting
Iako preporučujemo onemogućavanje share stranica kako biste osigurali da podaci nikada ne napuštaju vašu organizaciju, možemo vam pomoći i da ih samostalno hostujete na vlastitoj infrastrukturi.
Ovo je trenutno na našoj mapi puta. Ako ste zainteresovani, **<a href={email}>javite nam</a>**.
---
## FAQ
<details>
<summary>What is OpenCode Enterprise?</summary>
OpenCode Enterprise je za organizacije koje žele osigurati da njihov kod i podaci nikada ne napuštaju njihovu infrastrukturu. To omogućava centralizovana konfiguracija koja se integriše s vašim SSO-om i internim AI gateway-om.
</details>
<details>
<summary>How do I get started with OpenCode Enterprise?</summary>
Jednostavno započnite internu probu sa svojim timom. OpenCode po defaultu ne pohranjuje vaš kod ni kontekstualne podatke, što olakšava početak.
Zatim **<a href={email}>kontaktirajte nas</a>** da razgovaramo o cijenama i opcijama implementacije.
</details>
<details>
<summary>How does enterprise pricing work?</summary>
Nudimo enterprise cijene po sjedištu. Ako imate vlastiti LLM gateway, ne naplaćujemo korištene tokene. Za više detalja, **<a href={email}>kontaktirajte nas</a>** za prilagođenu ponudu prema potrebama vaše organizacije.
</details>
<details>
<summary>Is my data secure with OpenCode Enterprise?</summary>
Da. OpenCode ne pohranjuje vaš kod niti kontekstualne podatke. Sva obrada se odvija lokalno ili putem direktnih API poziva vašem AI provajderu. Uz centralnu konfiguraciju i SSO integraciju, vaši podaci ostaju sigurni unutar infrastrukture vaše organizacije.
</details>
<details>
<summary>Can we use our own private NPM registry?</summary>
OpenCode podržava privatne npm registre kroz Bunovu izvornu podršku za `.npmrc` datoteku. Ako vaša organizacija koristi privatni registar, kao što je JFrog Artifactory, Nexus ili slično, osigurajte da su developeri autentifikovani prije pokretanja OpenCodea.
Da postavite autentifikaciju s privatnim registrom:
```bash
npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/
```
Ovo kreira `~/.npmrc` s detaljima za autentifikaciju. OpenCode će to automatski prepoznati.
:::caution
Morate biti prijavljeni na privatni registar prije pokretanja OpenCodea.
:::
Alternativno, možete ručno konfigurisati `.npmrc` datoteku:
```bash title="~/.npmrc"
registry=https://your-company.jfrog.io/api/npm/npm-virtual/
//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN}
```
Developeri moraju biti prijavljeni na privatni registar prije pokretanja OpenCodea kako bi se paketi mogli instalirati iz vašeg enterprise registra.
</details>

View File

@@ -0,0 +1,115 @@
---
title: Trenerke
description: OpenCode koristi formatere specifične za jezik.
---
OpenCode automatski formatira datoteke nakon što su napisane ili uređene pomoću formatera specifičnih za jezik. Ovo osigurava da kod koji se generira prati stilove koda vašeg projekta.
---
## Ugrađeno
OpenCode dolazi sa nekoliko ugrađenih formatera za popularne jezike i okvire. Ispod je lista formatera, podržanih ekstenzija datoteka i naredbi ili opcija konfiguracije koje su mu potrebne.
| Formatter | Ekstenzije | Zahtjevi || -------------------- | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| gofmt | .go | `gofmt` komanda dostupna |
| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | `mix` komanda dostupna |
| ljepše | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml i [više](https://prettier.io/docs/en/index.html) | `prettier` zavisnost u `package.json` |
| biom | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml i [više](https://biomejs.dev/) | `biome.json(c)` konfiguracijski fajl |
| zig | .zig, .zon | `zig` komanda dostupna |
| clang-format | .c, .cpp, .h, .hpp, .ino i [više](https://clang.llvm.org/docs/ClangFormat.html) | `.clang-format` konfiguracijski fajl |
| ktlint | .kt, .kts | `ktlint` komanda dostupna |
| ruff | .py, .pyi | `ruff` komanda dostupna sa konfiguracijom |
| rustfmt | .rs | `rustfmt` komanda dostupna |
| cargofmt | .rs | `cargo fmt` komanda dostupna |
| uv | .py, .pyi | `uv` komanda dostupna || rubocop | .rb, .rake, .gemspec, .ru | `rubocop` komanda dostupna |
| standardrb | .rb, .rake, .gemspec, .ru | `standardrb` komanda dostupna |
| htmlbeautifier | .erb, .html.erb | `htmlbeautifier` komanda dostupna |
| zrak | .R | `air` komanda dostupna |
| dart | .dart | `dart` komanda dostupna |
| ocamlformat | .ml, .mli | `ocamlformat` komanda dostupna i `.ocamlformat` konfiguracioni fajl |
| terraform | .tf, .tfvars | `terraform` komanda dostupna |
| sjaj | .bleam | `gleam` komanda dostupna |
| nixfmt | .nix | `nixfmt` komanda dostupna |
| shfmt | .sh, .bash | `shfmt` komanda dostupna |
| pint | .php | `laravel/pint` zavisnost u `composer.json` || oxfmt (Eksperimentalno) | .js, .jsx, .ts, .tsx | `oxfmt` zavisnost u `package.json` i [eksperimentalna env varijabla flag](/docs/cli/#experimental) |
| ormolu | .hs | `ormolu` komanda dostupna |
Dakle, ako vaš projekat ima `prettier` u vašem `package.json`, OpenCode će ga automatski koristiti.
---
## Kako radi
Kada OpenCode piše ili uređuje datoteku, on:
1. Provjerava ekstenziju datoteke prema svim omogućenim formaterima.
2. Pokreće odgovarajuću naredbu za formatiranje na datoteci.
3. Automatski primjenjuje promjene formatiranja.
Ovaj proces se događa u pozadini, osiguravajući da se vaši stilovi koda održavaju bez ikakvih ručnih koraka.
---
## Konfiguriši
Možete prilagoditi formatere kroz `formatter` odjeljak u vašoj OpenCode konfiguraciji.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"formatter": {}
}
```
Svaka konfiguracija formatera podržava sljedeće:
| Nekretnine | Vrsta | Opis || ------------- | -------- | ------------------------------------------------------- |
| `disabled` | boolean | Postavite ovo na `true` da onemogućite formater |
| `command` | string[] | Naredba za pokretanje za formatiranje |
| `environment` | objekt | Varijable okruženja koje treba postaviti prilikom pokretanja formatera |
| `extensions` | string[] | Ekstenzije datoteka koje ovaj formater treba da obrađuje |
Pogledajmo neke primjere.
---
### Onemogućavanje formatera
Da onemogućite **sve** formatere globalno, postavite `formatter` na `false`:
```json title="opencode.json" {3}
{
"$schema": "https://opencode.ai/config.json",
"formatter": false
}
```
Da onemogućite **specifični** formater, postavite `disabled` na `true`:
```json title="opencode.json" {5}
{
"$schema": "https://opencode.ai/config.json",
"formatter": {
"prettier": {
"disabled": true
}
}
}
```
---
### Prilagođeni formateri
Možete nadjačati ugrađene formatere ili dodati nove navođenjem naredbe, varijabli okruženja i ekstenzija datoteke:
```json title="opencode.json" {4-14}
{
"$schema": "https://opencode.ai/config.json",
"formatter": {
"prettier": {
"command": ["npx", "prettier", "--write", "$FILE"],
"environment": {
"NODE_ENV": "development"
},
"extensions": [".js", ".ts", ".jsx", ".tsx"]
},
"custom-markdown-formatter": {
"command": ["deno", "fmt", "$FILE"],
"extensions": [".md"]
}
}
}
```
**`$FILE` čuvar mjesta** u naredbi će biti zamijenjen putanjom do datoteke koja se formatira.

View File

@@ -0,0 +1,305 @@
---
title: GitHub
description: Koristite OpenCode u GitHub problemima i zahtjevima za povlačenjem.
---
OpenCode se integriše sa vašim GitHub tokovom rada. Spomenite `/opencode` ili `/oc` u svom komentaru i OpenCode će izvršiti zadatke unutar vašeg GitHub Actions runnera.
---
## Karakteristike
- **Problemi trijaže**: Zamolite OpenCode da ispita problem i objasni vam ga.
- **Popravi i implementiraj**: Zamolite OpenCode da popravi problem ili implementira funkciju. I radit će u novoj poslovnici i dostavljati PR sa svim promjenama.
- **Secure**: OpenCode se pokreće unutar pokretača vašeg GitHub-a.
---
## Instalacija
Pokrenite sljedeću naredbu u projektu koji se nalazi u GitHub repo:
```bash
opencode github install
```
Ovo će vas provesti kroz instalaciju GitHub aplikacije, kreiranje toka posla i postavljanje tajni.
---
### Ručno podešavanje
Ili ga možete postaviti ručno.
1. **Instalirajte GitHub aplikaciju**
Idite na [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent). Uvjerite se da je instaliran na ciljnom spremištu.
2. **Dodajte radni tok**
Dodajte sljedeći fajl toka posla u `.github/workflows/opencode.yml` u svoj repo. Obavezno postavite odgovarajuće `model` i potrebne API ključeve u `env`.
```yml title=".github/workflows/opencode.yml" {24,26}
name: opencode
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
opencode:
if: |
contains(github.event.comment.body, '/oc') ||
contains(github.event.comment.body, '/opencode')
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 1
persist-credentials: false
- name: Run OpenCode
uses: anomalyco/opencode/github@latest
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
model: anthropic/claude-sonnet-4-20250514
# share: true
# github_token: xxxx
```
3. **Sačuvaj API ključeve u tajne**
U **postavkama** organizacije ili projekta proširite **Tajne i varijable** na lijevoj strani i odaberite **Radnje**. I dodajte potrebne API ključeve.
---
## Konfiguracija
- `model`: Model za korištenje s OpenCodeom. Uzima format `provider/model`. Ovo je **obavezno**.
- `agent`: Agent za korištenje. Mora biti primarni agent. Vraća se na `default_agent` iz konfiguracije ili `"build"` ako nije pronađen.
- `share`: Da li dijeliti OpenCode sesiju. Podrazumevano je **true** za javna spremišta.
- `prompt`: Opcioni prilagođeni upit za nadjačavanje zadanog ponašanja. Koristite ovo da prilagodite kako OpenCode obrađuje zahtjeve.
- `token`: Opcionalni GitHub pristupni token za izvođenje operacija kao što su kreiranje komentara, upisivanje promjena i otvaranje zahtjeva za povlačenjem. OpenCode prema zadanim postavkama koristi token za pristup instalaciji iz aplikacije OpenCode GitHub, tako da se urezivanje, komentari i zahtjevi za povlačenjem pojavljuju kao da dolaze iz aplikacije.
Alternativno, možete koristiti GitHub Action runner [ugrađeni `GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) bez instaliranja OpenCode GitHub aplikacije. Samo se pobrinite da date potrebna odobrenja u svom toku rada:
```yaml
permissions:
id-token: write
contents: write
pull-requests: write
issues: write
```
Također možete koristiti [Personal Access Tokens](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT) ako želite.
---
## Podržani događaji
OpenCode se može pokrenuti sljedećim GitHub događajima:
| Vrsta događaja | Pokrenuo | Detalji || ----------------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `issue_comment` | Komentirajte problem ili PR | Navedite `/opencode` ili `/oc` u svom komentaru. OpenCode čita kontekst i može kreirati grane, otvarati PR-ove ili odgovarati. |
| `pull_request_review_comment` | Komentirajte određene linije koda u PR-u | Navedite `/opencode` ili `/oc` dok pregledavate kod. OpenCode prima putanju datoteke, brojeve redova i kontekst razlike. |
| `issues` | Broj otvoren ili uređen | Automatski pokrenite OpenCode kada se problemi kreiraju ili modificiraju. Zahtijeva `prompt` unos. |
| `pull_request` | PR otvoren ili ažuriran | Automatski pokrenite OpenCode kada se PR-ovi otvore, sinkroniziraju ili ponovo otvore. Korisno za automatske recenzije. |
| `schedule` | Cron baziran raspored | Pokrenite OpenCode prema rasporedu. Zahtijeva `prompt` unos. Izlaz ide u dnevnike i PR-ove (nema problema za komentarisanje). |
| `workflow_dispatch` | Ručni okidač iz GitHub korisničkog sučelja | Aktivirajte OpenCode na zahtjev preko kartice Akcije. Zahtijeva `prompt` unos. Izlaz ide u dnevnike i PR-ove. |
### Primjer rasporeda
Pokrenite OpenCode po rasporedu za obavljanje automatiziranih zadataka:
```yaml title=".github/workflows/opencode-scheduled.yml"
name: Scheduled OpenCode Task
on:
schedule:
- cron: "0 9 * * 1" # Every Monday at 9am UTC
jobs:
opencode:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write
pull-requests: write
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Run OpenCode
uses: anomalyco/opencode/github@latest
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
model: anthropic/claude-sonnet-4-20250514
prompt: |
Review the codebase for any TODO comments and create a summary.
If you find issues worth addressing, open an issue to track them.
```
Za zakazane događaje, unos `prompt` je **potreban** jer nema komentara za izvlačenje instrukcija. Planirani tokovi posla se pokreću bez korisničkog konteksta za provjeru dozvola, tako da tok posla mora odobriti `contents: write` i `pull-requests: write` ako očekujete da će OpenCode kreirati grane ili PR-ove.
---
### Primjer zahtjeva za povlačenjem
Automatski pregledajte PR-ove kada se otvore ili ažuriraju:
```yaml title=".github/workflows/opencode-review.yml"
name: opencode-review
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
jobs:
review:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
pull-requests: read
issues: read
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: anomalyco/opencode/github@latest
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
model: anthropic/claude-sonnet-4-20250514
use_github_token: true
prompt: |
Review this pull request:
- Check for code quality issues
- Look for potential bugs
- Suggest improvements
```
Za `pull_request` događaje, ako nije naveden `prompt`, OpenCode podrazumevano pregledava zahtjev za povlačenjem.
---
### Primjer trijaže problema
Automatski triažirajte nove probleme. Ovaj primjer filtrira na račune starije od 30 dana radi smanjenja neželjene pošte:
```yaml title=".github/workflows/opencode-triage.yml"
name: Issue Triage
on:
issues:
types: [opened]
jobs:
triage:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write
pull-requests: write
issues: write
steps:
- name: Check account age
id: check
uses: actions/github-script@v7
with:
script: |
const user = await github.rest.users.getByUsername({
username: context.payload.issue.user.login
});
const created = new Date(user.data.created_at);
const days = (Date.now() - created) / (1000 * 60 * 60 * 24);
return days >= 30;
result-encoding: string
- uses: actions/checkout@v6
if: steps.check.outputs.result == 'true'
with:
persist-credentials: false
- uses: anomalyco/opencode/github@latest
if: steps.check.outputs.result == 'true'
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
model: anthropic/claude-sonnet-4-20250514
prompt: |
Review this issue. If there's a clear fix or relevant docs:
- Provide documentation links
- Add error handling guidance for code examples
Otherwise, do not comment.
```
Za `issues` događaje, `prompt` unos je **potreban** jer nema komentara za izvlačenje instrukcija.
---
## Prilagođene upite
Zaobiđite zadani prompt da biste prilagodili ponašanje OpenCodea za vaš tok posla.
```yaml title=".github/workflows/opencode.yml"
- uses: anomalyco/opencode/github@latest
with:
model: anthropic/claude-sonnet-4-5
prompt: |
Review this pull request:
- Check for code quality issues
- Look for potential bugs
- Suggest improvements
```
Ovo je korisno za provođenje specifičnih kriterija pregleda, standarda kodiranja ili fokusnih područja relevantnih za vaš projekt.
---
## Primjeri
Evo nekoliko primjera kako možete koristiti OpenCode u GitHubu.
- **Objasnite problem**
Dodajte ovaj komentar u GitHub izdanje.
```
/opencode explain this issue
```
OpenCode će pročitati cijelu temu, uključujući sve komentare, i odgovoriti s jasnim objašnjenjem.
- **Popravi problem**
U izdanju na GitHub-u recite:
```
/opencode fix this
```
I OpenCode će kreirati novu granu, implementirati promjene i otvoriti PR sa promjenama.
- **Pregledajte PR-ove i izvršite izmjene**
Ostavite sljedeći komentar na GitHub PR-u.
```
Delete the attachment from S3 when the note is removed /oc
```
OpenCode će implementirati traženu promjenu i posvetiti je istom PR-u.
- **Pregledajte određene linije koda**
Ostavite komentar direktno na linije koda u PR kartici "Files". OpenCode automatski detektuje datoteku, brojeve redova i kontekst razlike kako bi pružio precizne odgovore.
```
[Comment on specific lines in Files tab]
/oc add error handling here
```
Kada komentarišete određene linije, OpenCode prima:
- Tačan fajl se pregleda
- Specifične linije koda
- Okolni diff kontekst
- Informacije o broju linije
Ovo omogućava više ciljanih zahtjeva bez potrebe za ručno specificiranjem putanja datoteka ili brojeva linija.

View File

@@ -0,0 +1,194 @@
---
title: GitLab
description: Koristite OpenCode u GitLab problemima i zahtjevima za spajanje.
---
OpenCode se integriše sa vašim GitLab radnim tokom kroz vaš GitLab CI/CD cevovod ili sa GitLab Duo.
U oba slučaja, OpenCode će se pokrenuti na vašim GitLab pokretačima.
---
## GitLab CI
OpenCode radi u redovnom GitLab cevovodu. Možete ga ugraditi u cjevovod kao [CI komponenta](https://docs.gitlab.com/ee/ci/components/)
Ovdje koristimo CI/CD komponentu kreiranu u zajednici za OpenCode — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode).
---
### Karakteristike
- **Koristite prilagođenu konfiguraciju po poslu**: Konfigurirajte OpenCode s prilagođenim konfiguracijskim direktorijem, na primjer `./config/#custom-directory` da omogućite ili onemogućite funkcionalnost po OpenCode pozivanju.
- **Minimalno podešavanje**: CI komponenta postavlja OpenCode u pozadini, samo trebate kreirati OpenCode konfiguraciju i početnu prompt.
- **Fleksibilno**: CI komponenta podržava nekoliko ulaza za prilagođavanje njenog ponašanja
---
### Podešavanje
1. Sačuvajte JSON za autentifikaciju OpenCode-a kao CI varijable okruženja tipa datoteke pod **Postavke** > **CI/CD** > **Varijable**. Obavezno ih označite kao "Maskirane i skrivene".
2. Dodajte sljedeće u svoju `.gitlab-ci.yml` datoteku.
```yaml title=".gitlab-ci.yml"
include:
- component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2
inputs:
config_dir: ${CI_PROJECT_DIR}/opencode-config
auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON
command: optional-custom-command
message: "Your prompt here"
```
Za više unosa i slučajeva upotrebe [pogledajte dokumente docs](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) za ovu komponentu.
---
## GitLab Duo
OpenCode se integriše sa vašim GitLab tokovom rada.
Spomenite `@opencode` u komentaru i OpenCode će izvršiti zadatke unutar vašeg GitLab CI cevovoda.
---
### Karakteristike
- **Problemi trijaže**: Zamolite OpenCode da ispita problem i objasni vam ga.
- **Popravi i implementiraj**: Zamolite OpenCode da popravi problem ili implementira funkciju.
To će kreirati novu granu i pokrenuti zahtjev za spajanje s promjenama.
- **Secure**: OpenCode radi na vašim GitLab pokretačima.
---
### Podešavanje
OpenCode radi u vašem GitLab CI/CD cevovodu, evo šta će vam trebati da ga postavite:
:::tip
Pogledajte [**GitLab dokumente**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) za ažurirane upute.
:::
1. Konfigurirajte svoje GitLab okruženje
2. Postavite CI/CD
3. Nabavite API ključ dobavljača AI modela
4. Kreirajte nalog usluge
5. Konfigurirajte CI/CD varijable
6. Kreirajte konfiguracijski fajl toka, evo primjera:
<details>
<summary>Flow configuration</summary>
```yaml
image: node:22-slim
commands:
- echo "Installing opencode"
- npm install --global opencode-ai
- echo "Installing glab"
- export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE
- apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/*
- curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash
- apt-get install --yes glab
- echo "Configuring glab"
- echo $GITLAB_HOST
- echo "Creating OpenCode auth configuration"
- mkdir --parents ~/.local/share/opencode
- |
cat > ~/.local/share/opencode/auth.json << EOF
{
"anthropic": {
"type": "api",
"key": "$ANTHROPIC_API_KEY"
}
}
EOF
- echo "Configuring git"
- git config --global user.email "opencode@gitlab.com"
- git config --global user.name "OpenCode"
- echo "Testing glab"
- glab issue list
- echo "Running OpenCode"
- |
opencode run "
You are an AI assistant helping with GitLab operations.
Context: $AI_FLOW_CONTEXT
Task: $AI_FLOW_INPUT
Event: $AI_FLOW_EVENT
Please execute the requested task using the available GitLab tools.
Be thorough in your analysis and provide clear explanations.
<important>
Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands.
If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it.
You don't need to commit or push up changes, those will be done automatically based on the file changes you make.
</important>
"
- git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF
- echo "Checking for git changes and pushing if any exist"
- |
if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then
echo "Git changes detected, adding and pushing..."
git add .
if git diff --cached --quiet; then
echo "No staged changes to commit"
else
echo "Committing changes to branch: $CI_WORKLOAD_REF"
git commit --message "Codex changes"
echo "Pushing changes up to $CI_WORKLOAD_REF"
git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF
echo "Changes successfully pushed"
fi
else
echo "No git changes detected, skipping push"
fi
variables:
- ANTHROPIC_API_KEY
- GITLAB_TOKEN_OPENCODE
- GITLAB_HOST
```
</details>
Možete vidjeti [GitLab CLI agenti docs](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) za detaljna uputstva.
---
### Primjeri
Evo nekoliko primjera kako možete koristiti OpenCode u GitLabu.
:::tip
Možete konfigurirati da koristite drugu frazu okidača od `@opencode`.
:::
- **Objasnite problem**
Dodajte ovaj komentar u izdanje GitLaba.
```
@opencode explain this issue
```
OpenCode će pročitati problem i odgovoriti jasnim objašnjenjem.
- **Reši problem**
U izdanju GitLaba recite:
```
@opencode fix this
```
OpenCode će kreirati novu granu, implementirati promjene i otvoriti zahtjev za spajanje s promjenama.
- **Pregledajte zahtjeve za pridruživanje**
Ostavite sljedeći komentar na zahtjev za spajanje GitLab-a.
```
@opencode review this merge request
```
OpenCode će pregledati zahtjev za spajanje i dati povratne informacije.

View File

@@ -0,0 +1,41 @@
---
title: IDE
description: Ekstenzija OpenCode za VS Code, Cursor i druge IDE
---
OpenCode se integriše sa VS kodom, kursorom ili bilo kojim IDE-om koji podržava terminal. Samo pokrenite `opencode` u terminalu da započnete.
---
## Upotreba
- **Brzo pokretanje**: Koristite `Cmd+Esc` (Mac) ili `Ctrl+Esc` (Windows/Linux) da otvorite OpenCode u prikazu podijeljenog terminala ili fokusirajte postojeću terminalsku sesiju ako je već pokrenuta.
- **Nova sesija**: Koristite `Cmd+Shift+Esc` (Mac) ili `Ctrl+Shift+Esc` (Windows/Linux) da započnete novu OpenCode terminalsku sesiju, čak i ako je ona već otvorena. Takođe možete kliknuti na dugme OpenCode u korisničkom sučelju.
- **Svijest o kontekstu**: Automatski dijelite svoj trenutni odabir ili karticu s OpenCodeom.
- **Prečice za referencu datoteka**: Koristite `Cmd+Option+K` (Mac) ili `Alt+Ctrl+K` (Linux/Windows) za umetanje referenci datoteka. Na primjer, `@File#L37-42`.
---
## Instalacija
Da biste instalirali OpenCode na VS Code i popularne viljuške kao što su Cursor, Windsurf, VSCodium:
1. Otvorite VS Code
2. Otvorite integrirani terminal
3. Pokrenite `opencode` - ekstenzija se automatski instalira
Ako s druge strane želite da koristite svoj vlastiti IDE kada pokrenete `/editor` ili `/export` iz TUI-ja, morat ćete postaviti `export EDITOR="code --wait"`. [Saznajte više](/docs/tui/#editor-setup).
---
### Ručna instalacija
Potražite **OpenCode** na Extension Marketplaceu i kliknite na **Instaliraj**.
---
### Rješavanje problema
Ako se ekstenzija ne uspije automatski instalirati:
- Uvjerite se da koristite `opencode` u integriranom terminalu.
- Potvrdite da je CLI za vaš IDE instaliran:
- Za VS kod: `code` naredbu
- Za kursor: `cursor` naredba
- Za jedrenje na dasci: `windsurf` komanda
- Za VSCodium: `codium` komanda
- Ako ne, pokrenite `Cmd+Shift+P` (Mac) ili `Ctrl+Shift+P` (Windows/Linux) i potražite "Shell Command: Install 'code' command in PATH" (ili ekvivalent za vaš IDE)
- Osigurajte da VS Code ima dozvolu za instaliranje ekstenzija

View File

@@ -0,0 +1,360 @@
---
title: Intro
description: Započnite s OpenCodeom.
---
import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../../config.mjs"
export const console = config.console
[**OpenCode**](/) je agent za AI kodiranje otvorenog koda. Dostupan je kao interfejs baziran na terminalu, desktop aplikacija ili IDE ekstenzija.
![OpenCode TUI sa temom otvorenog koda](../../../assets/lander/screenshot.png)
Hajde da počnemo.
---
#### Preduvjeti
Da biste koristili OpenCode u svom terminalu, trebat će vam:
1. Moderan emulator terminala kao što su:
- [WezTerm](https://wezterm.org), multi-platforma
- [Alacritty](https://alacritty.org), više platforma
- [Ghostty](https://ghostty.org), Linux i macOS
- [Kitty](https://sw.kovidgoyal.net/kitty/), Linux i macOS
2. API ključevi za LLM provajdere koje želite koristiti.
---
## Instaliraj
Najlakši način za instaliranje OpenCode-a je putem instalacione skripte.
```bash
curl -fsSL https://opencode.ai/install | bash
```
Također ga možete instalirati pomoću sljedećih naredbi:
- **Korišćenje Node.js**
<Tabs>
<TabItem label="npm">
```bash
npm install -g opencode-ai
```
</TabItem>
<TabItem label="Bun">
```bash
bun install -g opencode-ai
```
</TabItem>
<TabItem label="pnpm">
```bash
pnpm install -g opencode-ai
```
</TabItem>
<TabItem label="Yarn">
```bash
yarn global add opencode-ai
```
</TabItem>
</Tabs>
- **Korišćenje Homebrew-a na macOS-u i Linux-u**
```bash
brew install anomalyco/tap/opencode
```
> Preporučujemo korištenje OpenCode tap za najnovija izdanja. Službenu formulu `brew install opencode` održava Homebrew tim i ažurira se rjeđe.
- **Korišćenje Parua na Arch Linuxu**
```bash
paru -S opencode-bin
```
#### Windows
:::tip[Preporučeno: Koristite WSL]
Za najbolje iskustvo na Windows-u preporučujemo korištenje [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). Pruža bolje performanse i potpunu kompatibilnost sa OpenCode karakteristikama.
:::
- **Upotreba čokolade**
```bash
choco install opencode
```
- **Upotreba Scoop-a**
```bash
scoop install opencode
```
- **Upotreba NPM-a**
```bash
npm install -g opencode-ai
```
- **Korišćenje Mise**
```bash
mise use -g github:anomalyco/opencode
```
- **Korišćenje Dockera**
```bash
docker run -it --rm ghcr.io/anomalyco/opencode
```
Podrška za instaliranje OpenCode-a na Windows koristeći Bun je trenutno u toku.
Također možete preuzeti binarnu datoteku iz [Releases](https://github.com/anomalyco/opencode/releases).
---
## Konfiguriši
Uz OpenCode možete koristiti bilo kojeg LLM provajdera tako što ćete konfigurirati njihove API ključeve.
Ako ste tek počeli koristiti LLM provajdere, preporučujemo korištenje [OpenCode Zen](/docs/zen).
To je kurirana lista modela koji su testirani i verifikovani od strane OpenCode-a
tim.
1. Pokrenite naredbu `/connect` u TUI-u, odaberite opencode i idite na [opencode.ai/auth](https://opencode.ai/auth).
```txt
/connect
```
2. Prijavite se, dodajte svoje detalje naplate i kopirajte svoj API ključ.
3. Zalijepite svoj API ključ.
```txt
┌ API key
└ enter
```
Alternativno, možete odabrati jednog od drugih provajdera. [Saznajte više](/docs/providers#directory).
---
## Inicijaliziraj
Sada kada ste konfigurisali provajdera, možete se kretati do projekta koji
na čemu želite da radite.
```bash
cd /path/to/project
```
I pokrenite OpenCode.
```bash
opencode
```
Zatim inicijalizirajte OpenCode za projekat pokretanjem sljedeće naredbe.
```bash frame="none"
/init
```
Ovo će omogućiti OpenCode da analizira vaš projekat i kreira `AGENTS.md` fajl u njemu
korijen projekta.
:::tip
Trebali biste urezati datoteku `AGENTS.md` vašeg projekta u Git.
:::
Ovo pomaže OpenCodeu da razumije strukturu projekta i obrasce kodiranja
korišteno.
---
## Upotreba
Sada ste spremni da koristite OpenCode za rad na svom projektu. Slobodno pitajte
bilo šta!
Ako ste novi u korištenju agenta za AI kodiranje, evo nekoliko primjera koji bi mogli
pomoć.
---
### Postavljajte pitanja
Možete zamoliti OpenCode da vam objasni kodnu bazu.
:::tip
Koristite tipku `@` za nejasnu pretragu datoteka u projektu.
:::
```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```
Ovo je korisno ako postoji dio kodne baze na kojem niste radili.
---
### Dodajte karakteristike
Možete zamoliti OpenCode da vašem projektu doda nove funkcije. Iako preporučujemo da ga prvo zamolite da napravi plan.
1. **Kreirajte plan**
OpenCode ima _Plan mod_ koji onemogućuje njegovu sposobnost da pravi promjene i
umjesto toga predložite _kako_ će implementirati ovu funkciju.
Prebacite se na njega pomoću tipke **Tab**. Vidjet ćete indikator za ovo u donjem desnom uglu.
```bash frame="none" title="Switch to Plan mode"
<TAB>
```
Hajde sada da opišemo šta želimo da uradi.
```txt frame="none"
When a user deletes a note, we'd like to flag it as deleted in the database.
Then create a screen that shows all the recently deleted notes.
From this screen, the user can undelete a note or permanently delete it.
```
Želite da date OpenCode-u dovoljno detalja da razumete šta želite. Pomaže
da razgovarate s njim kao da razgovarate sa mlađim programerom u svom timu.
:::tip
Dajte OpenCodeu dosta konteksta i primjera koji će mu pomoći da razumije šta vi
želim. ::: 2. **Ponovite plan**
Kada vam da plan, možete mu dati povratne informacije ili dodati više detalja.
```txt frame="none"
We'd like to design this new screen using a design I've used before.
[Image #1] Take a look at this image and use it as a reference.
```
:::tip
Prevucite i ispustite slike u terminal da biste ih dodali u prompt. :::
OpenCode može skenirati sve slike koje mu date i dodati ih u prompt. Možeš
učinite to povlačenjem i ispuštanjem slike u terminal. 3. **Izgradite funkciju**
Kada se osjećate ugodno s planom, vratite se na _Build mode_ do
ponovnim pritiskom na taster **Tab**.
```bash frame="none"
<TAB>
```
I tražeći od njega da napravi promjene.
```bash frame="none"
Sounds good! Go ahead and make the changes.
```
---
### Napravite promjene
Za jednostavnije promjene, možete zamoliti OpenCode da ga direktno izgradi
bez potrebe da prvo pregledate plan.
```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```
Želite da budete sigurni da ste pružili dobru količinu detalja kako bi OpenCode bio ispravan
promjene.
---
### Poništi promjene
Recimo da tražite od OpenCodea da izvrši neke promjene.
```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```
Ali shvatate da to nije ono što ste želeli. Možete **poništiti** promjene
koristeći naredbu `/undo`.
```bash frame="none"
/undo
```
OpenCode će sada poništiti promjene koje ste napravili i prikazati vašu originalnu poruku
opet.
```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```
Odavde možete podesiti prompt i zamoliti OpenCode da pokuša ponovo.
:::tip
Možete pokrenuti `/undo` više puta da poništite više promjena.
:::
Ili **možete ponoviti** promjene koristeći naredbu `/redo`.
```bash frame="none"
/redo
```
---
## Dijeli
Razgovore koje imate sa OpenCodeom možete [dijeliti sa vašim
tim](/docs/share).
```bash frame="none"
/share
```
Ovo će kreirati vezu do trenutnog razgovora i kopirati je u međuspremnik.
:::note
Razgovori se ne dijele prema zadanim postavkama.
:::
Evo [primjer razgovora](https://opencode.ai/s/4XP1fce5) sa OpenCodeom.
---
## Prilagodi
I to je to! Sada ste profesionalac u korištenju OpenCodea.
Da biste to učinili svojim, preporučujemo [odabir teme](/docs/themes), [prilagođavanje povezivanja tipki](/docs/keybinds), [konfiguriranje formatera koda](/docs/formatters), [kreiranje prilagođenih komandi](/docs/commands), ili igranje sa [OpenCode config](/docs/config).

View File

@@ -0,0 +1,182 @@
---
title: Keybinds
description: Prilagodite svoje veze dugmadi.
---
OpenCode ima listu veza ključeva koje možete prilagoditi preko OpenCode konfiguracije.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"keybinds": {
"leader": "ctrl+x",
"app_exit": "ctrl+c,ctrl+d,<leader>q",
"editor_open": "<leader>e",
"theme_list": "<leader>t",
"sidebar_toggle": "<leader>b",
"scrollbar_toggle": "none",
"username_toggle": "none",
"status_view": "<leader>s",
"tool_details": "none",
"session_export": "<leader>x",
"session_new": "<leader>n",
"session_list": "<leader>l",
"session_timeline": "<leader>g",
"session_fork": "none",
"session_rename": "none",
"session_share": "none",
"session_unshare": "none",
"session_interrupt": "escape",
"session_compact": "<leader>c",
"session_child_cycle": "<leader>right",
"session_child_cycle_reverse": "<leader>left",
"session_parent": "<leader>up",
"messages_page_up": "pageup,ctrl+alt+b",
"messages_page_down": "pagedown,ctrl+alt+f",
"messages_line_up": "ctrl+alt+y",
"messages_line_down": "ctrl+alt+e",
"messages_half_page_up": "ctrl+alt+u",
"messages_half_page_down": "ctrl+alt+d",
"messages_first": "ctrl+g,home",
"messages_last": "ctrl+alt+g,end",
"messages_next": "none",
"messages_previous": "none",
"messages_copy": "<leader>y",
"messages_undo": "<leader>u",
"messages_redo": "<leader>r",
"messages_last_user": "none",
"messages_toggle_conceal": "<leader>h",
"model_list": "<leader>m",
"model_cycle_recent": "f2",
"model_cycle_recent_reverse": "shift+f2",
"model_cycle_favorite": "none",
"model_cycle_favorite_reverse": "none",
"variant_cycle": "ctrl+t",
"command_list": "ctrl+p",
"agent_list": "<leader>a",
"agent_cycle": "tab",
"agent_cycle_reverse": "shift+tab",
"input_clear": "ctrl+c",
"input_paste": "ctrl+v",
"input_submit": "return",
"input_newline": "shift+return,ctrl+return,alt+return,ctrl+j",
"input_move_left": "left,ctrl+b",
"input_move_right": "right,ctrl+f",
"input_move_up": "up",
"input_move_down": "down",
"input_select_left": "shift+left",
"input_select_right": "shift+right",
"input_select_up": "shift+up",
"input_select_down": "shift+down",
"input_line_home": "ctrl+a",
"input_line_end": "ctrl+e",
"input_select_line_home": "ctrl+shift+a",
"input_select_line_end": "ctrl+shift+e",
"input_visual_line_home": "alt+a",
"input_visual_line_end": "alt+e",
"input_select_visual_line_home": "alt+shift+a",
"input_select_visual_line_end": "alt+shift+e",
"input_buffer_home": "home",
"input_buffer_end": "end",
"input_select_buffer_home": "shift+home",
"input_select_buffer_end": "shift+end",
"input_delete_line": "ctrl+shift+d",
"input_delete_to_line_end": "ctrl+k",
"input_delete_to_line_start": "ctrl+u",
"input_backspace": "backspace,shift+backspace",
"input_delete": "ctrl+d,delete,shift+delete",
"input_undo": "ctrl+-,super+z",
"input_redo": "ctrl+.,super+shift+z",
"input_word_forward": "alt+f,alt+right,ctrl+right",
"input_word_backward": "alt+b,alt+left,ctrl+left",
"input_select_word_forward": "alt+shift+f,alt+shift+right",
"input_select_word_backward": "alt+shift+b,alt+shift+left",
"input_delete_word_forward": "alt+d,alt+delete,ctrl+delete",
"input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace",
"history_previous": "up",
"history_next": "down",
"terminal_suspend": "ctrl+z",
"terminal_title_toggle": "none",
"tips_toggle": "<leader>h",
"display_thinking": "none"
}
}
```
---
## Leader key
OpenCode koristi `leader` ključ za većinu povezivanja tipki. Ovo izbjegava sukobe u vašem terminalu.
Prema zadanim postavkama, `ctrl+x` je vodeći taster i većina radnji zahtijeva da prvo pritisnete vodeći taster, a zatim i prečicu. Na primjer, da biste započeli novu sesiju, prvo pritisnite `ctrl+x`, a zatim pritisnite `n`.
Ne morate koristiti vodeći ključ za svoje veze tipki, ali preporučujemo da to učinite.
---
## Onemogući povezivanje tastera
Možete onemogućiti spajanje tipki dodavanjem ključa u svoju konfiguraciju s vrijednošću "none".
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"keybinds": {
"session_compact": "none"
}
}
```
---
## Prečice za radnu površinu
Unos prompta aplikacije OpenCode za desktop podržava uobičajene prečice u stilu Readline/Emacs za uređivanje teksta. Oni su ugrađeni i trenutno se ne mogu konfigurirati putem `opencode.json`.
| Prečica | Akcija || -------- | ---------------------------------------- |
| `ctrl+a` | Prelazak na početak tekućeg reda |
| `ctrl+e` | Prelazak na kraj trenutnog reda |
| `ctrl+b` | Pomeri kursor za jedan znak unazad |
| `ctrl+f` | Pomicanje kursora naprijed za jedan znak |
| `alt+b` | Pomeri kursor za jednu reč unazad |
| `alt+f` | Pomeri kursor za jednu reč unapred |
| `ctrl+d` | Izbriši znak ispod kursora |
| `ctrl+k` | Ubiti do kraja reda |
| `ctrl+u` | Kill do početka reda |
| `ctrl+w` | Ubiti prethodnu riječ |
| `alt+d` | Ubiti sljedeću riječ |
| `ctrl+t` | Transponirajte znakove |
| `ctrl+g` | Otkaži iskakanje / poništi odgovor na pokretanje |
---
## Shift+Enter
Neki terminali ne šalju modifikatorske tipke sa Enter prema zadanim postavkama. Možda ćete trebati konfigurirati svoj terminal da pošalje `Shift+Enter` kao escape sekvencu.
### Windows terminal
Otvorite svoj `settings.json` na:
```
%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json
```
Dodajte ovo u niz korijenskog nivoa `actions`:
```json
"actions": [
{
"command": {
"action": "sendInput",
"input": "\u001b[13;2u"
},
"id": "User.sendInput.ShiftEnterCustom"
}
]
```
Dodajte ovo u niz korijenskog nivoa `keybindings`:
```json
"keybindings": [
{
"keys": "shift+enter",
"id": "User.sendInput.ShiftEnterCustom"
}
]
```
Sačuvajte datoteku i ponovo pokrenite Windows Terminal ili otvorite novu karticu.

View File

@@ -0,0 +1,160 @@
---
title: LSP serveri
description: OpenCode se integriše sa vašim LSP serverima.
---
OpenCode se integriše sa vašim jezičkim serverskim protokolom (LSP) kako bi pomogao LLM-u u interakciji s vašom bazom koda. Koristi dijagnostiku za pružanje povratnih informacija LLM-u.
---
## Ugrađeno
OpenCode dolazi sa nekoliko ugrađenih LSP servera za popularne jezike:
| LSP server | Ekstenzije | Zahtjevi || ------------------ | ------------------------------------------------------------------- | ------------------------------------------------------------ |
| astro | .astro | Automatske instalacije za Astro projekte |
| bash | .sh, .bash, .zsh, .ksh | Automatski instalira bash-language-server |
| clangd | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++ | Automatske instalacije za C/C++ projekte |
| csharp | .cs | `.NET SDK` instaliran |
| clojure-lsp | .clj, .cljs, .cljc, .edn | `clojure-lsp` komanda dostupna |
| dart | .dart | `dart` komanda dostupna |
| deno | .ts, .tsx, .js, .jsx, .mjs | `deno` komanda dostupna (automatski detektuje deno.json/deno.jsonc) |
| elixir-ls | .ex, .exs | `elixir` komanda dostupna |
| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue | `eslint` ovisnost u projektu |
| fsharp | .fs, .fsi, .fsx, .fsscript | `.NET SDK` instaliran |
| sjaj | .bleam | `gleam` komanda dostupna |
| gopls | .go | `go` komanda dostupna |
| hls | .hs, .lhs | `haskell-language-server-wrapper` komanda dostupna |
| jdtls | .java | `Java SDK (version 21+)` instaliran |
| kotlin-ls | .kt, .kts | Automatske instalacije za Kotlin projekte |
| lua-ls | .lua | Automatske instalacije za Lua projekte |
| nixd | .nix | `nixd` komanda dostupna |
| ocaml-lsp | .ml, .mli | `ocamllsp` komanda dostupna |
| oxlint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | `oxlint` zavisnost u projektu |
| php intelephense | .php | Automatske instalacije za PHP projekte |
| prisma | .prisma | `prisma` komanda dostupna |
| pyright | .py, .pyi | `pyright` ovisnost instalirana |
| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru | `ruby` i `gem` komande dostupne |
| hrđa | .rs | `rust-analyzer` komanda dostupna |
| sourcekit-lsp | .swift, .objc, .objcpp | `swift` instaliran (`xcode` na macOS-u) |
| vitka | .svelte | Automatske instalacije za Svelte projekte |
| terraform | .tf, .tfvars | Automatske instalacije iz GitHub izdanja |
| tinymist | .typ, .typc | Automatske instalacije iz GitHub izdanja |
| strojopis | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | `typescript` zavisnost u projektu |
| vue | .vue | Automatske instalacije za Vue projekte |
| yaml-ls | .yaml, .yml | Automatski instalira Red Hat yaml-language-server |
| zls | .zig, .zon | `zig` komanda dostupna |
LSP serveri su automatski omogućeni kada se otkrije jedna od gore navedenih ekstenzija datoteke i zahtjevi su ispunjeni.
:::napomena
Možete onemogućiti automatska preuzimanja LSP servera tako što ćete postaviti varijablu okruženja `OPENCODE_DISABLE_LSP_DOWNLOAD` na `true`.
:::
---
## Kako radi
Kada opencode otvori fajl, on:
1. Provjerava ekstenziju datoteke u odnosu na sve omogućene LSP servere.
2. Pokreće odgovarajući LSP server ako već nije pokrenut.
---
## Konfiguriši
Možete prilagoditi LSP servere kroz `lsp` odjeljak u vašoj opencode konfiguraciji.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"lsp": {}
}
```
Svaki LSP server podržava sljedeće:
| Nekretnine | Vrsta | Opis || ---------------- | -------- | ------------------------------------------------- |
| `disabled` | boolean | Postavite ovo na `true` da onemogućite LSP server |
| `command` | string[] | Naredba za pokretanje LSP servera |
| `extensions` | string[] | Ekstenzije datoteka koje ovaj LSP server treba da rukuje |
| `env` | objekt | Varijable okruženja koje treba postaviti prilikom pokretanja servera |
| `initialization` | objekt | Opcije inicijalizacije za slanje na LSP server |
Pogledajmo neke primjere.
---
### Varijable okruženja
Koristite svojstvo `env` za postavljanje varijabli okruženja prilikom pokretanja LSP servera:
```json title="opencode.json" {5-7}
{
"$schema": "https://opencode.ai/config.json",
"lsp": {
"rust": {
"env": {
"RUST_LOG": "debug"
}
}
}
}
```
---
### Opcije inicijalizacije
Koristite svojstvo `initialization` da prosledite opcije inicijalizacije na LSP server. Ovo su postavke specifične za server poslane tokom LSP `initialize` zahtjeva:
```json title="opencode.json" {5-9}
{
"$schema": "https://opencode.ai/config.json",
"lsp": {
"typescript": {
"initialization": {
"preferences": {
"importModuleSpecifierPreference": "relative"
}
}
}
}
}
```
:::napomena
Opcije inicijalizacije razlikuju se od LSP servera. Provjerite dokumentaciju vašeg LSP servera za dostupne opcije.
:::
---
### Onemogućavanje LSP servera
Da biste onemogućili **sve** LSP servere globalno, postavite `lsp` na `false`:
```json title="opencode.json" {3}
{
"$schema": "https://opencode.ai/config.json",
"lsp": false
}
```
Da onemogućite **specifičan** LSP server, postavite `disabled` na `true`:
```json title="opencode.json" {5}
{
"$schema": "https://opencode.ai/config.json",
"lsp": {
"typescript": {
"disabled": true
}
}
}
```
---
### Prilagođeni LSP serveri
Možete dodati prilagođene LSP servere navodeći ekstenzije naredbe i datoteke:
```json title="opencode.json" {4-7}
{
"$schema": "https://opencode.ai/config.json",
"lsp": {
"custom-lsp": {
"command": ["custom-lsp-server", "--stdio"],
"extensions": [".custom"]
}
}
}
```
---
## Dodatne informacije
### PHP Intelephense
PHP Intelephense nudi vrhunske funkcije putem licencnog ključa. Možete dati licencni ključ postavljanjem (samo) ključa u tekstualnu datoteku na:
- Na macOS/Linuxu: `$HOME/intelephense/licence.txt`
- Na Windowsima: `%USERPROFILE%/intelephense/licence.txt`
Datoteka treba da sadrži samo licencni ključ bez dodatnog sadržaja.

View File

@@ -0,0 +1,432 @@
---
title: MCP serveri
description: Dodajte lokalne i udaljene MCP alate.
---
Možete dodati vanjske alate u OpenCode koristeći _Model Context Protocol_, ili MCP. OpenCode podržava i lokalne i udaljene servere.
Jednom dodani, MCP alati su automatski dostupni LLM-u zajedno sa ugrađenim alatima.
---
#### Upozorenja
Kada koristite MCP server, on dodaje u kontekst. Ovo se može brzo zbrojiti ako imate puno alata. Stoga preporučujemo da pazite koje MCP servere koristite.
:::tip
MCP serveri dodaju vaš kontekst, tako da želite da budete pažljivi s tim koje ćete omogućiti.
:::
Određeni MCP serveri, poput GitHub MCP servera, imaju tendenciju da dodaju mnogo tokena i lako mogu premašiti ograničenje konteksta.
---
## Omogući
Možete definirati MCP servere u vašoj [OpenCode Config](https://opencode.ai/docs/config/) pod `mcp`. Dodajte svaki MCP sa jedinstvenim imenom. Možete se pozvati na taj MCP po imenu kada tražite LLM.
```jsonc title="opencode.jsonc" {6}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"name-of-mcp-server": {
// ...
"enabled": true,
},
"name-of-other-mcp-server": {
// ...
},
},
}
```
Također možete onemogućiti server postavljanjem `enabled` na `false`. Ovo je korisno ako želite privremeno onemogućiti server bez uklanjanja iz vaše konfiguracije.
---
### Poništavanje daljinskih zadanih postavki
Organizacije mogu obezbijediti zadane MCP servere preko svoje krajnje tačke `.well-known/opencode`. Ovi serveri mogu biti onemogućeni prema zadanim postavkama, omogućavajući korisnicima da se odluče za one koji su im potrebni.
Da omogućite određeni server iz udaljene konfiguracije vaše organizacije, dodajte ga u svoju lokalnu konfiguraciju sa `enabled: true`:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"jira": {
"type": "remote",
"url": "https://jira.example.com/mcp",
"enabled": true
}
}
}
```
Vrijednosti vaše lokalne konfiguracije nadjačavaju udaljene zadane postavke. Pogledajte [config precedence](/docs/config#precedence-order) za više detalja.
---
## Lokalno
Dodajte lokalne MCP servere koristeći `type` u `"local"` unutar MCP objekta.
```jsonc title="opencode.jsonc" {15}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-local-mcp-server": {
"type": "local",
// Or ["bun", "x", "my-mcp-command"]
"command": ["npx", "-y", "my-mcp-command"],
"enabled": true,
"environment": {
"MY_ENV_VAR": "my_env_var_value",
},
},
},
}
```
Naredba je način na koji se pokreće lokalni MCP server. Također možete proslijediti listu varijabli okruženja.
Na primjer, evo kako možete dodati testni [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything) MCP server.
```jsonc title="opencode.jsonc"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"mcp_everything": {
"type": "local",
"command": ["npx", "-y", "@modelcontextprotocol/server-everything"],
},
},
}
```
I da ga koristim mogu dodati `use the mcp_everything tool` u svoje upite.
```txt "mcp_everything"
use the mcp_everything tool to add the number 3 and 4
```
---
#### Opcije
Ovdje su sve opcije za konfiguriranje lokalnog MCP servera.
| Opcija | Vrsta | Obavezno | Opis || ------------- | ------- | -------- | ----------------------------------------------------------------------------------- |
| `type` | String | Y | Tip veze sa MCP serverom, mora biti `"local"`. |
| `command` | Niz | Y | Naredba i argumenti za pokretanje MCP servera. |
| `environment` | Objekt | | Varijable okruženja koje treba postaviti prilikom pokretanja servera. |
| `enabled` | Boolean | | Omogućite ili onemogućite MCP server pri pokretanju. |
| `timeout` | Broj | | Vremensko ograničenje u ms za dohvaćanje alata sa MCP servera. Podrazumevano je 5000 (5 sekundi). |
---
## Daljinski
Dodajte udaljene MCP servere postavljanjem `type` na `"remote"`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-remote-mcp": {
"type": "remote",
"url": "https://my-mcp-server.com",
"enabled": true,
"headers": {
"Authorization": "Bearer MY_API_KEY"
}
}
}
}
```
`url` je URL udaljenog MCP servera i sa opcijom `headers` možete proslijediti listu zaglavlja.
---
#### Opcije
| Opcija | Vrsta | Obavezno | Opis || --------- | ------- | -------- | ----------------------------------------------------------------------------------- |
| `type` | String | Y | Tip veze sa MCP serverom, mora biti `"remote"`. |
| `url` | String | Y | URL udaljenog MCP servera. |
| `enabled` | Boolean | | Omogućite ili onemogućite MCP server pri pokretanju. |
| `headers` | Objekt | | Zaglavlja za slanje uz zahtjev. |
| `oauth` | Objekt | | Konfiguracija OAuth provjere autentičnosti. Pogledajte odjeljak [OAuth](#oauth) ispod. |
| `timeout` | Broj | | Vremensko ograničenje u ms za preuzimanje alata sa MCP servera. Podrazumevano je 5000 (5 sekundi). |
---
## OAuth
OpenCode automatski rukuje OAuth autentifikacijom za udaljene MCP servere. Kada server zahtijeva autentifikaciju, OpenCode će:
1. Otkrijte 401 odgovor i pokrenite OAuth tok
2. Koristite **Dynamic Client Registration (RFC 7591)** ako podržava server
3. Sigurno čuvajte tokene za buduće zahtjeve
---
### Automatski
Za većinu MCP servera sa omogućenim OAuthom nije potrebna posebna konfiguracija. Samo konfigurirajte udaljeni server:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-oauth-server": {
"type": "remote",
"url": "https://mcp.example.com/mcp"
}
}
}
```
Ako server zahtijeva autentifikaciju, OpenCode će od vas zatražiti autentifikaciju kada prvi put pokušate da ga koristite. Ako ne, možete [ručno pokrenuti tok](#authenticating) sa `opencode mcp auth <server-name>`.
---
### Prethodno registrovano
Ako imate klijentske vjerodajnice od dobavljača MCP servera, možete ih konfigurirati:
```json title="opencode.json" {7-11}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-oauth-server": {
"type": "remote",
"url": "https://mcp.example.com/mcp",
"oauth": {
"clientId": "{env:MY_MCP_CLIENT_ID}",
"clientSecret": "{env:MY_MCP_CLIENT_SECRET}",
"scope": "tools:read tools:execute"
}
}
}
}
```
---
### Autentifikacija
Možete ručno pokrenuti autentifikaciju ili upravljati vjerodajnicama.
Autentifikacija sa određenim MCP serverom:
```bash
opencode mcp auth my-oauth-server
```
Navedite sve MCP servere i njihov status autentifikacije:
```bash
opencode mcp list
```
Uklonite pohranjene vjerodajnice:
```bash
opencode mcp logout my-oauth-server
```
Komanda `mcp auth` će otvoriti vaš pretraživač za autorizaciju. Nakon što odobrite, OpenCode će sigurno pohraniti tokene u `~/.local/share/opencode/mcp-auth.json`.
---
#### Onemogućavanje OAuth-a
Ako želite onemogućiti automatski OAuth za server (npr. za servere koji umjesto toga koriste API ključeve), postavite `oauth` na `false`:
```json title="opencode.json" {7}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-api-key-server": {
"type": "remote",
"url": "https://mcp.example.com/mcp",
"oauth": false,
"headers": {
"Authorization": "Bearer {env:MY_API_KEY}"
}
}
}
}
```
---
#### OAuth opcije
| Opcija | Vrsta | Opis || -------------- | --------------- | -------------------------------------------------------------------------------- |
| `oauth` | Objekt \| false | OAuth konfiguracijski objekt, ili `false` da onemogućite automatsko otkrivanje OAuth. |
| `clientId` | String | ID OAuth klijenta. Ako nije navedeno, pokušat će se izvršiti dinamička registracija klijenta. |
| `clientSecret` | String | Tajna OAuth klijenta, ako to zahtijeva autorizacijski server. |
| `scope` | String | OAuth opseg zahtjeva za vrijeme autorizacije. |
#### Otklanjanje grešaka
Ako udaljeni MCP server ne uspije u autentifikaciji, možete dijagnosticirati probleme pomoću:
```bash
# View auth status for all OAuth-capable servers
opencode mcp auth list
# Debug connection and OAuth flow for a specific server
opencode mcp debug my-oauth-server
```
Komanda `mcp debug` pokazuje trenutni status auth, testira HTTP povezanost i pokušava tok otkrivanja OAuth.
---
## Upravljaj
Vaši MCP-ovi su dostupni kao alati u OpenCode-u, zajedno sa ugrađenim alatima. Tako da možete upravljati njima kroz OpenCode konfiguraciju kao i svaki drugi alat.
---
### Global
To znači da ih možete omogućiti ili onemogućiti globalno.
```json title="opencode.json" {14}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-mcp-foo": {
"type": "local",
"command": ["bun", "x", "my-mcp-command-foo"]
},
"my-mcp-bar": {
"type": "local",
"command": ["bun", "x", "my-mcp-command-bar"]
}
},
"tools": {
"my-mcp-foo": false
}
}
```
Također možemo koristiti glob obrazac da onemogućimo sve odgovarajuće MCP-ove.
```json title="opencode.json" {14}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-mcp-foo": {
"type": "local",
"command": ["bun", "x", "my-mcp-command-foo"]
},
"my-mcp-bar": {
"type": "local",
"command": ["bun", "x", "my-mcp-command-bar"]
}
},
"tools": {
"my-mcp*": false
}
}
```
Ovdje koristimo glob obrazac `my-mcp*` da onemogućimo sve MCP-ove.
---
### Po agentu
Ako imate veliki broj MCP servera, možda ćete želeti da ih omogućite samo po agentu i da ih onemogućite globalno. Da biste to učinili:
1. Onemogućite ga kao alat globalno.
2. U vašem [agent config](/docs/agents#tools), omogućite MCP server kao alat.
```json title="opencode.json" {11, 14-18}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-mcp": {
"type": "local",
"command": ["bun", "x", "my-mcp-command"],
"enabled": true
}
},
"tools": {
"my-mcp*": false
},
"agent": {
"my-agent": {
"tools": {
"my-mcp*": true
}
}
}
}
```
---
#### Glob uzorci
Uzorak glob koristi jednostavne šablone globbiranja regularnih izraza:
- `*` odgovara nuli ili više bilo kojeg znaka (npr. `"my-mcp*"` odgovara `my-mcp_search`, `my-mcp_list`, itd.)
- `?` odgovara tačno jednom znaku
- Svi ostali likovi se bukvalno podudaraju
:::napomena
MCP serverski alati se registruju sa imenom servera kao prefiksom, tako da onemogućite sve alate za server jednostavno koristite:
```
"mymcpservername_*": false
```
:::
---
## Primjeri
Ispod su primjeri nekih uobičajenih MCP servera. Možete poslati PR ako želite dokumentirati druge servere.
---
### Stražar
Dodajte [Sentry MCP server](https://mcp.sentry.dev) za interakciju sa vašim Sentry projektima i problemima.
```json title="opencode.json" {4-8}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"sentry": {
"type": "remote",
"url": "https://mcp.sentry.dev/mcp",
"oauth": {}
}
}
}
```
Nakon dodavanja konfiguracije, autentifikujte se sa Sentry:
```bash
opencode mcp auth sentry
```
Ovo će otvoriti prozor pretraživača da završite OAuth tok i povežete OpenCode sa vašim Sentry nalogom.
Nakon provjere autentičnosti, možete koristiti Sentry alate u svojim upitima za upite o problemima, projektima i podacima o greškama.
```txt "use sentry"
Show me the latest unresolved issues in my project. use sentry
```
---
### Kontekst7
Dodajte [Context7 MCP server](https://github.com/upstash/context7) za pretraživanje dokumenata.
```json title="opencode.json" {4-7}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"context7": {
"type": "remote",
"url": "https://mcp.context7.com/mcp"
}
}
}
```
Ako ste se prijavili za besplatni račun, možete koristiti svoj API ključ i dobiti viša ograničenja stope.
```json title="opencode.json" {7-9}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"context7": {
"type": "remote",
"url": "https://mcp.context7.com/mcp",
"headers": {
"CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}"
}
}
}
}
```
Ovdje pretpostavljamo da imate postavljenu varijablu okruženja `CONTEXT7_API_KEY`.
Dodajte `use context7` vašim upitima za korištenje Context7 MCP servera.
```txt "use context7"
Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7
```
Alternativno, možete dodati nešto poput ovoga na svoj [AGENTS.md](/docs/rules/).
```md title="AGENTS.md"
When you need to search docs, use `context7` tools.
```
---
### Grep od Vercela
Dodajte [Grep by Vercel](https://grep.app) MCP server za pretraživanje isječaka koda na GitHubu.
```json title="opencode.json" {4-7}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"gh_grep": {
"type": "remote",
"url": "https://mcp.grep.app"
}
}
}
```
Pošto smo naš MCP server nazvali `gh_grep`, možete dodati `use the gh_grep tool` u svoje upite da natjerate agenta da ga koristi.
```txt "use the gh_grep tool"
What's the right way to set a custom domain in an SST Astro component? use the gh_grep tool
```
Alternativno, možete dodati nešto poput ovoga na svoj [AGENTS.md](/docs/rules/).
```md title="AGENTS.md"
If you are unsure how to do something, use `gh_grep` to search code examples from GitHub.
```

View File

@@ -0,0 +1,186 @@
---
title: Modeli
description: Konfiguriranje LLM provajdera i modela.
---
OpenCode koristi [AI SDK](https://ai-sdk.dev/) i [Models.dev](https://models.dev) za podršku **75+ LLM provajdera** i podržava pokretanje lokalnih modela.
---
## Provajderi
Većina popularnih provajdera su unaprijed učitani prema zadanim postavkama. Ako ste dodali vjerodajnice za provajdera putem naredbe `/connect`, oni će biti dostupni kada pokrenete OpenCode.
Saznajte više o [providers](/docs/providers).
---
## Odaberite model
Nakon što konfigurirate svog provajdera, možete odabrati model koji želite upisivanjem:
```bash frame="none"
/models
```
---
## Preporučeni modeli
Postoji mnogo modela vani, a novi modeli izlaze svake sedmice.
:::tip
Razmislite o korištenju jednog od modela koje preporučujemo.
:::
Međutim, postoji samo nekoliko njih koji su dobri i u generiranju koda i u pozivanju alata.
Evo nekoliko modela koji dobro rade sa OpenCodeom, bez posebnog redosleda. (Ovo nije potpuna lista niti je nužno ažurirana):
- GPT 5.2
- Kodeks GPT 5.1
- Claude Opus 4.5
- Claude Sonet 4.5
- Minimax M2.1
- Gemini 3 Pro
---
## Postavite zadano
Da postavite jedan od ovih kao zadani model, možete postaviti ključ `model` u svom
OpenCode config.
```json title="opencode.json" {3}
{
"$schema": "https://opencode.ai/config.json",
"model": "lmstudio/google/gemma-3n-e4b"
}
```
Ovdje je puni ID `provider_id/model_id`. Na primjer, ako koristite [OpenCode Zen](/docs/zen), koristili biste `opencode/gpt-5.1-codex` za GPT 5.1 Codex.
Ako ste konfigurirali [prilagođenog provajdera](/docs/providers#custom), `provider_id` je ključ iz `provider` dijela vaše konfiguracije, a `model_id` je ključ iz `provider.models`.
---
## Konfigurišite modele
Možete globalno konfigurirati opcije modela kroz config.
```jsonc title="opencode.jsonc" {7-12,19-24}
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"openai": {
"models": {
"gpt-5": {
"options": {
"reasoningEffort": "high",
"textVerbosity": "low",
"reasoningSummary": "auto",
"include": ["reasoning.encrypted_content"],
},
},
},
},
"anthropic": {
"models": {
"claude-sonnet-4-5-20250929": {
"options": {
"thinking": {
"type": "enabled",
"budgetTokens": 16000,
},
},
},
},
},
},
}
```
Ovdje konfiguriramo globalne postavke za dva ugrađena modela: `gpt-5` kada se pristupa preko `openai` provajdera i `claude-sonnet-4-20250514` kada se pristupa preko `anthropic` provajdera.
Ugrađeni dobavljač i nazivi modela mogu se naći na [Models.dev](https://models.dev).
Također možete konfigurirati ove opcije za sve agente koje koristite. Konfiguracija agenta poništava sve globalne opcije ovdje. [Saznajte više](/docs/agents/#additional).
Također možete definirati prilagođene varijante koje proširuju ugrađene. Varijante vam omogućavaju da konfigurirate različite postavke za isti model bez stvaranja duplih unosa:
```jsonc title="opencode.jsonc" {6-21}
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"opencode": {
"models": {
"gpt-5": {
"variants": {
"high": {
"reasoningEffort": "high",
"textVerbosity": "low",
"reasoningSummary": "auto",
},
"low": {
"reasoningEffort": "low",
"textVerbosity": "low",
"reasoningSummary": "auto",
},
},
},
},
},
},
}
```
---
## Varijante
Mnogi modeli podržavaju više varijanti sa različitim konfiguracijama. OpenCode se isporučuje sa ugrađenim podrazumevanim varijantama za popularne provajdere.
### Ugrađene varijante
OpenCode se isporučuje sa zadanim varijantama za mnoge provajdere:
**Antropski**:
- `high` - Visok budžet za razmišljanje (zadano)
- `max` - Maksimalni budžet za razmišljanje
**OpenAI**:
Zavisi od modela, ali otprilike:
- `none` - Bez obrazloženja
- `minimal` - Minimalni napor za rasuđivanje
- `low` - Nizak napor u rasuđivanju
- `medium` - Srednji napor u zaključivanju
- `high` - Veliki napor u rasuđivanju
- `xhigh` - Ekstra visok napor u rasuđivanju
**Google**:
- `low` - Manji trud/budžet tokena
- `high` - Veći budžet za trud/token
:::tip
Ova lista nije sveobuhvatna. Mnogi drugi provajderi također imaju ugrađene zadane postavke.
:::
### Prilagođene varijante
Možete nadjačati postojeće varijante ili dodati svoje:
```jsonc title="opencode.jsonc" {7-18}
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"openai": {
"models": {
"gpt-5": {
"variants": {
"thinking": {
"reasoningEffort": "high",
"textVerbosity": "low",
},
"fast": {
"disabled": true,
},
},
},
},
},
},
}
```
### Varijante ciklusa
Koristite vezu `variant_cycle` za brzo prebacivanje između varijanti. [Saznajte više](/docs/keybinds).
---
## Učitavanje modela
Kada se OpenCode pokrene, on provjerava modele u sljedećem prioritetnom redoslijedu:
1. Oznaka komandne linije `--model` ili `-m`. Format je isti kao u konfiguracijskoj datoteci: `provider_id/model_id`.
2. Lista modela u OpenCode konfiguraciji.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"model": "anthropic/claude-sonnet-4-20250514"
}
```
Format ovdje je `provider/model`.
3. Posljednji korišteni model.
4. Prvi model koji koristi interni prioritet.

View File

@@ -0,0 +1,283 @@
---
title: Načini rada
description: Različiti načini za različite slučajeve upotrebe.
---
:::oprez
Načini se sada konfiguriraju preko opcije `agent` u konfiguraciji otvorenog koda. The
`mode` opcija je sada zastarjela. [Saznajte više](/docs/agents).
:::
Režimi u otvorenom kodu omogućavaju vam da prilagodite ponašanje, alate i upite za različite slučajeve upotrebe.
Dolazi sa dva ugrađena načina rada: **gradite** i **planirajte**. Možete prilagoditi
ove ili konfigurirajte svoje putem opencode config.
Možete se prebacivati između režima tokom sesije ili ih konfigurisati u svom konfiguracionom fajlu.
---
## Ugrađeno
opencode dolazi sa dva ugrađena načina rada.
---
### Build
Izrada je **podrazumevani** režim sa svim omogućenim alatima. Ovo je standardni način rada na razvoju gdje vam je potreban pun pristup operacijama datoteka i sistemskim komandama.
---
### Plan
Ograničeni način rada dizajniran za planiranje i analizu. U načinu plana, sljedeći alati su onemogućeni prema zadanim postavkama:
- `write` - Ne mogu kreirati nove fajlove
- `edit` - Ne mogu modificirati postojeće fajlove, osim fajlova koji se nalaze na `.opencode/plans/*.md` radi detaljiziranja samog plana
- `patch` - Ne mogu primijeniti zakrpe
- `bash` - Ne mogu izvršiti naredbe ljuske
Ovaj način rada je koristan kada želite da AI analizira kod, predlaže promjene ili kreira planove bez ikakvih stvarnih modifikacija u vašoj bazi kodova.
---
## Prebacivanje
Možete se prebacivati između načina rada tokom sesije pomoću tipke _Tab_. Ili vaše konfigurirano `switch_mode` spajanje tipki.
Vidi također: [Formatters](/docs/formatters) za informacije o konfiguraciji formatiranja koda.
---
## Konfiguriši
Možete prilagoditi ugrađene načine rada ili kreirati vlastite kroz konfiguraciju. Modovi se mogu konfigurirati na dva načina:
### JSON konfiguracija
Konfigurirajte načine rada u svom `opencode.json` konfiguracijskom fajlu:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"mode": {
"build": {
"model": "anthropic/claude-sonnet-4-20250514",
"prompt": "{file:./prompts/build.txt}",
"tools": {
"write": true,
"edit": true,
"bash": true
}
},
"plan": {
"model": "anthropic/claude-haiku-4-20250514",
"tools": {
"write": false,
"edit": false,
"bash": false
}
}
}
}
```
### Markdown konfiguracija
Također možete definirati načine rada koristeći mardown datoteke. Postavite ih u:
- Globalno: `~/.config/opencode/modes/`
- Projekat: `.opencode/modes/`
```markdown title="~/.config/opencode/modes/review.md"
---
model: anthropic/claude-sonnet-4-20250514
temperature: 0.1
tools:
write: false
edit: false
bash: false
---
You are in code review mode. Focus on:
- Code quality and best practices
- Potential bugs and edge cases
- Performance implications
- Security considerations
Provide constructive feedback without making direct changes.
```
Naziv datoteke s uštedom postaje naziv načina (npr. `review.md` kreira `review` način rada).
Pogledajmo ove opcije konfiguracije detaljno.
---
### Model
Koristite `model` konfiguraciju da nadjačate zadani model za ovaj način rada. Korisno za korištenje različitih modela optimiziranih za različite zadatke. Na primjer, brži model za planiranje, sposobniji model za implementaciju.
```json title="opencode.json"
{
"mode": {
"plan": {
"model": "anthropic/claude-haiku-4-20250514"
}
}
}
```
---
### Temperatura
Kontrolišite slučajnost i kreativnost odgovora AI pomoću `temperature` konfiguracije. Niže vrijednosti čine odgovore fokusiranijim i determinističkim, dok veće vrijednosti povećavaju kreativnost i varijabilnost.
```json title="opencode.json"
{
"mode": {
"plan": {
"temperature": 0.1
},
"creative": {
"temperature": 0.8
}
}
}
```
Vrijednosti temperature obično se kreću od 0,0 do 1,0:
- **0,0-0,2**: Vrlo fokusirani i deterministički odgovori, idealni za analizu i planiranje koda
- **0,3-0,5**: Uravnoteženi odgovori sa malo kreativnosti, dobro za opšte razvojne zadatke
- **0,6-1,0**: kreativniji i raznovrsniji odgovori, korisni za razmišljanje i istraživanje
```json title="opencode.json"
{
"mode": {
"analyze": {
"temperature": 0.1,
"prompt": "{file:./prompts/analysis.txt}"
},
"build": {
"temperature": 0.3
},
"brainstorm": {
"temperature": 0.7,
"prompt": "{file:./prompts/creative.txt}"
}
}
}
```
Ako temperatura nije navedena, opencode koristi zadane postavke specifične za model (obično 0 za većinu modela, 0,55 za Qwen modele).
---
### Prompt
Navedite prilagođenu sistemsku datoteku prompta za ovaj način rada s konfiguracijom `prompt`. Datoteka s promptom treba da sadrži upute specifične za svrhu načina rada.
```json title="opencode.json"
{
"mode": {
"review": {
"prompt": "{file:./prompts/code-review.txt}"
}
}
}
```
Ova putanja je relativna u odnosu na mjesto gdje se nalazi konfiguracijski fajl. Dakle, ovo radi za
i globalnu konfiguraciju otvorenog koda i konfiguraciju specifične za projekat.
---
### Alati
Kontrolirajte koji su alati dostupni u ovom načinu rada pomoću `tools` konfiguracije. Možete omogućiti ili onemogućiti određene alate tako što ćete ih postaviti na `true` ili `false`.
```json
{
"mode": {
"readonly": {
"tools": {
"write": false,
"edit": false,
"bash": false,
"read": true,
"grep": true,
"glob": true
}
}
}
}
```
Ako nijedan alat nije specificiran, svi alati su omogućeni prema zadanim postavkama.
---
#### Dostupni alati
Ovdje su svi alati koji se mogu kontrolirati kroz konfiguraciju načina rada.
| Alat | Opis || ----------- | ----------------------- |
| `bash` | Izvrši naredbe ljuske |
| `edit` | Izmijenite postojeće datoteke |
| `write` | Kreirajte nove fajlove |
| `read` | Pročitajte sadržaj datoteke |
| `grep` | Pretraži sadržaj datoteke |
| `glob` | Pronađite datoteke po uzorku |
| `list` | Lista sadržaja direktorija |
| `patch` | Primijenite zakrpe na datoteke |
| `todowrite` | Upravljanje listama zadataka |
| `todoread` | Pročitajte liste obaveza |
| `webfetch` | Dohvati web sadržaj |
---
## Prilagođeni načini rada
Možete kreirati vlastite prilagođene modove tako što ćete ih dodati u konfiguraciju. Evo primjera koji koriste oba pristupa:
### Korištenje JSON konfiguracije
```json title="opencode.json" {4-14}
{
"$schema": "https://opencode.ai/config.json",
"mode": {
"docs": {
"prompt": "{file:./prompts/documentation.txt}",
"tools": {
"write": true,
"edit": true,
"bash": false,
"read": true,
"grep": true,
"glob": true
}
}
}
}
```
### Korištenje mardown fajlova
Kreirajte fajlove načina u `.opencode/modes/` za specifične načine rada ili `~/.config/opencode/modes/` za globalne načine:
```markdown title=".opencode/modes/debug.md"
---
temperature: 0.1
tools:
bash: true
read: true
grep: true
write: false
edit: false
---
You are in debug mode. Your primary goal is to help investigate and diagnose issues.
Focus on:
- Understanding the problem through careful analysis
- Using bash commands to inspect system state
- Reading relevant files and logs
- Searching for patterns and anomalies
- Providing clear explanations of findings
Do not make any changes to files. Only investigate and report.
```
```markdown title="~/.config/opencode/modes/refactor.md"
---
model: anthropic/claude-sonnet-4-20250514
temperature: 0.2
tools:
edit: true
read: true
grep: true
glob: true
---
You are in refactoring mode. Focus on improving code quality without changing functionality.
Priorities:
- Improve code readability and maintainability
- Apply consistent naming conventions
- Reduce code duplication
- Optimize performance where appropriate
- Ensure all tests continue to pass
```
---
### Slučajevi upotrebe
Evo nekoliko uobičajenih slučajeva upotrebe za različite načine rada.
- **Način izgradnje**: Potpuni razvojni rad sa svim omogućenim alatima
- **Način planiranja**: Analiza i planiranje bez izmjena
- **Review mode**: Pregled koda sa pristupom samo za čitanje plus alati za dokumentaciju
- **Režim za otklanjanje grešaka**: Fokusiran na istragu sa omogućenim bash i alatima za čitanje
- **Režim dokumenata**: Pisanje dokumentacije sa operacijama datoteka, ali bez sistemskih naredbi
Možda ćete također otkriti da su različiti modeli dobri za različite slučajeve upotrebe.

View File

@@ -0,0 +1,48 @@
---
title: Mreža
description: Konfigurirajte proksije i prilagođene certifikate.
---
OpenCode podržava standardne varijable proxy okruženja i prilagođene sertifikate za mrežna okruženja preduzeća.
---
## Proxy
OpenCode poštuje standardne varijable proxy okruženja.
```bash
# HTTPS proxy (recommended)
export HTTPS_PROXY=https://proxy.example.com:8080
# HTTP proxy (if HTTPS not available)
export HTTP_PROXY=http://proxy.example.com:8080
# Bypass proxy for local server (required)
export NO_PROXY=localhost,127.0.0.1
```
:::oprez
TUI komunicira sa lokalnim HTTP serverom. Morate zaobići proxy za ovu vezu kako biste spriječili petlje usmjeravanja.
:::
Možete konfigurirati port servera i ime hosta koristeći [CLI flags](/docs/cli#run).
---
### Autentikacija
Ako vaš proxy zahtijeva osnovnu autentifikaciju, uključite vjerodajnice u URL.
```bash
export HTTPS_PROXY=http://username:password@proxy.example.com:8080
```
:::oprez
Izbjegavajte tvrdo kodiranje lozinki. Koristite varijable okruženja ili sigurno skladište vjerodajnica.
:::
Za proxy servere koji zahtijevaju naprednu autentifikaciju kao što je NTLM ili Kerberos, razmislite o korištenju LLM Gatewaya koji podržava vašu metodu provjere autentičnosti.
---
## Prilagođeni certifikati
Ako vaše preduzeće koristi prilagođene CA-ove za HTTPS veze, konfigurirajte OpenCode da im vjeruje.
```bash
export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem
```
Ovo radi i za proxy veze i za direktan pristup API-ju.

View File

@@ -0,0 +1,201 @@
---
title: Dozvole
description: Kontrolirajte koje radnje zahtijevaju odobrenje za pokretanje.
---
OpenCode koristi `permission` konfiguraciju da odluči da li će se određena radnja pokrenuti automatski, zatražiti od vas ili biti blokirana.
Od `v1.1.1`, naslijeđena `tools` logička konfiguracija je zastarjela i spojena je u `permission`. Stara `tools` konfiguracija je još uvijek podržana za kompatibilnost unatrag.
---
## Akcije
Svako pravilo dozvole rješava jedno od:
- `"allow"` — pokrenuti bez odobrenja
- `"ask"` — upit za odobrenje
- `"deny"` — blokiraj akciju
---
## Konfiguracija
Dozvole možete postaviti globalno (sa `*`) i nadjačati određene alate.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"*": "ask",
"bash": "allow",
"edit": "deny"
}
}
```
Također možete postaviti sve dozvole odjednom:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": "allow"
}
```
---
## Granularna pravila (sintaksa objekta)
Za većinu dozvola, možete koristiti objekt za primjenu različitih radnji na osnovu unosa alata.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"npm *": "allow",
"rm *": "deny",
"grep *": "allow"
},
"edit": {
"*": "deny",
"packages/web/src/content/docs/*.mdx": "allow"
}
}
}
```
Pravila se procjenjuju na osnovu podudaranja uzorka, pri čemu **pobjeđuje **poslednje odgovarajuće pravilo**. Uobičajeni obrazac je da se prvo pravilo `"*"` stavi sveobuhvatno, a poslije njega konkretnija pravila.
### Zamjenski znakovi
Uzorci dozvola koriste jednostavno podudaranje zamjenskih znakova:
- `*` odgovara nula ili više bilo kojeg znaka
- `?` odgovara tačno jednom znaku
- Svi ostali likovi se bukvalno podudaraju
### Proširenje kućnog imenika
Možete koristiti `~` ili `$HOME` na početku obrasca da referencirate svoj početni direktorij. Ovo je posebno korisno za [`external_directory`](#external-directories) pravila.
- `~/projects/*` -> `/Users/username/projects/*`
- `$HOME/projects/*` -> `/Users/username/projects/*`
- `~` -> `/Users/username`
### Vanjski imenici
Koristite `external_directory` da dozvolite pozive alata koji dodiruju putanje izvan radnog direktorija gdje je OpenCode pokrenut. Ovo se odnosi na bilo koji alat koji uzima putanju kao ulaz (na primjer `read`, `edit`, `list`, `glob`, `grep` i mnoge `bash` komande).
Proširenje kuće (poput `~/...`) utiče samo na način na koji je obrazac napisan. Ne čini vanjsku stazu dijelom trenutnog radnog prostora, tako da staze izvan radnog direktorija i dalje moraju biti dozvoljene preko `external_directory`.
Na primjer, ovo omogućava pristup svemu pod `~/projects/personal/`:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"external_directory": {
"~/projects/personal/**": "allow"
}
}
}
```
Svaki direktorij koji je ovdje dozvoljen nasljeđuje iste zadane postavke kao trenutni radni prostor. Pošto je [`read` zadano na `allow`](#defaults), čitanje je također dozvoljeno za unose pod `external_directory` osim ako se ne poništi. Dodajte eksplicitna pravila kada bi alat trebao biti ograničen na ovim stazama, kao što je blokiranje uređivanja uz zadržavanje čitanja:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"external_directory": {
"~/projects/personal/**": "allow"
},
"edit": {
"~/projects/personal/**": "deny"
}
}
}
```
Neka lista bude fokusirana na pouzdane staze, a dodatni sloj dozvoljava ili odbija pravila prema potrebi za druge alate (na primjer `bash`).
---
## Dostupne dozvole
Dozvole OpenCode-a su označene imenom alata, plus nekoliko sigurnosnih mjera:
- `read` — čitanje datoteke (odgovara putanji datoteke)
- `edit` — sve izmjene fajlova (pokriva `edit`, `write`, `patch`, `multiedit`)
- `glob` — globbiranje fajla (odgovara glob uzorku)
- `grep` — pretraga sadržaja (podudara se sa regularnim izrazom)
- `list` — lista fajlova u direktorijumu (podudara se sa putanjom direktorijuma)
- `bash` — izvođenje komandi ljuske (podudara se s raščlanjenim komandama kao što je `git status --porcelain`)
- `task` — pokretanje subagenta (odgovara tipu podagenta)
- `skill` — učitavanje vještine (odgovara nazivu vještine)
- `lsp` — pokretanje LSP upita (trenutno negranularno)
- `todoread`, `todowrite` — čitanje/ažuriranje liste obaveza
- `webfetch` — dohvaćanje URL-a (odgovara URL-u)
- `websearch`, `codesearch` — pretraživanje weba/koda (odgovara upitu)
- `external_directory` — pokreće se kada alat dodirne staze izvan radnog direktorija projekta
- `doom_loop` — aktivira se kada se isti poziv alata ponovi 3 puta sa identičnim unosom
---
## Defaults
Ako ništa ne navedete, OpenCode počinje od dozvoljenih zadanih vrijednosti:
- Većina dozvola je zadana na `"allow"`.
- `doom_loop` i `external_directory` zadano na `"ask"`.
- `read` je `"allow"`, ali `.env` fajlovi su po defaultu odbijeni:
```json title="opencode.json"
{
"permission": {
"read": {
"*": "allow",
"*.env": "deny",
"*.env.*": "deny",
"*.env.example": "allow"
}
}
}
```
---
## Šta radi “Ask”.
Kada OpenCode zatraži odobrenje, korisničko sučelje nudi tri ishoda:
- `once` — odobri samo ovaj zahtjev
- `always` — odobri buduće zahtjeve koji odgovaraju predloženim obrascima (za ostatak trenutne OpenCode sesije)
- `reject` — odbiti zahtjev
Skup obrazaca koje bi `always` odobrio pruža alat (na primjer, bash odobrenja obično stavljaju na bijelu listu sigurni prefiks komande kao što je `git status*`).
---
## Agenti
Možete nadjačati dozvole po agentu. Dozvole agenta su spojene sa globalnom konfiguracijom, a pravila agenta imaju prednost. [Saznajte više](/docs/agents#permissions) o dozvolama agenta.
:::napomena
Pogledajte gornji odjeljak [Granularna pravila (sintaksa objekata)](#granular-rules-object-syntax) za detaljnije primjere podudaranja uzoraka.
:::
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"git commit *": "deny",
"git push *": "deny",
"grep *": "allow"
}
},
"agent": {
"build": {
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"git commit *": "ask",
"git push *": "deny",
"grep *": "allow"
}
}
}
}
}
```
Također možete konfigurirati dozvole agenta u Markdownu:
```markdown title="~/.config/opencode/agents/review.md"
---
description: Code review without edits
mode: subagent
permission:
edit: deny
bash: ask
webfetch: deny
---
Only analyze code and suggest changes.
```
:::tip
Koristite podudaranje uzoraka za naredbe s argumentima. `"grep *"` dozvoljava `grep pattern file.txt`, dok bi ga samo `"grep"` blokirao. Naredbe poput `git status` rade za zadano ponašanje, ali zahtijevaju eksplicitnu dozvolu (kao `"git status *"`) kada se prosljeđuju argumenti.
:::

View File

@@ -0,0 +1,309 @@
---
title: Plugins
description: Napišite vlastite dodatke za proširenje OpenCode-a.
---
Dodaci vam omogućavaju da proširite OpenCode spajanjem na različite događaje i prilagođavanjem ponašanja. Možete kreirati dodatke za dodavanje novih funkcija, integraciju sa eksternim uslugama ili izmenu zadanog ponašanja OpenCode-a.
Za primjere, pogledajte [plugins](/docs/ecosystem#plugins) kreirane od strane zajednice.
---
## Koristite dodatak
Postoje dva načina za učitavanje dodataka.
---
### Iz lokalnih datoteka
Postavite JavaScript ili TypeScript datoteke u direktorij dodataka.
- `.opencode/plugins/` - Dodaci na nivou projekta
- `~/.config/opencode/plugins/` - Globalni dodaci
Datoteke u ovim direktorijumima se automatski učitavaju pri pokretanju.
---
### Od npm
Navedite npm pakete u vašoj konfiguracijskoj datoteci.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"]
}
```
Podržani su i regularni i npm paketi sa opsegom.
Pregledajte dostupne dodatke u [ecosystem](/docs/ecosystem#plugins).
---
### Kako se instaliraju dodaci
**npm dodaci** se instaliraju automatski pomoću Bun pri pokretanju. Paketi i njihove zavisnosti su keširani u `~/.cache/opencode/node_modules/`.
**Lokalni dodaci** se učitavaju direktno iz direktorija dodataka. Da biste koristili vanjske pakete, morate kreirati `package.json` unutar svog konfiguracijskog direktorija (pogledajte [Zavisnosti](#dependencies)) ili objaviti dodatak na npm i [dodati ga u svoju konfiguraciju](/docs/config#plugins).
---
### Učitaj redoslijed
Dodaci se učitavaju iz svih izvora i svi zakačnjaci rade u nizu. Redoslijed učitavanja je:
1. Globalna konfiguracija (`~/.config/opencode/opencode.json`)
2. Konfiguracija projekta (`opencode.json`)
3. Globalni direktorij dodataka (`~/.config/opencode/plugins/`)
4. Direktorij dodataka projekta (`.opencode/plugins/`)
Duplicirani npm paketi sa istim imenom i verzijom se učitavaju jednom. Međutim, lokalni dodatak i npm dodatak sa sličnim nazivima se učitavaju odvojeno.
---
## Kreirajte dodatak
Dodatak je **JavaScript/TypeScript modul** koji izvozi jedan ili više dodataka
funkcije. Svaka funkcija prima objekt konteksta i vraća hooks objekt.
---
### Zavisnosti
Lokalni dodaci i prilagođeni alati mogu koristiti vanjske npm pakete. Dodajte `package.json` u svoj konfiguracijski direktorij sa zavisnostima koje su vam potrebne.
```json title=".opencode/package.json"
{
"dependencies": {
"shescape": "^2.1.0"
}
}
```
OpenCode pokreće `bun install` pri pokretanju da ih instalira. Vaši dodaci i alati ih zatim mogu uvesti.
```ts title=".opencode/plugins/my-plugin.ts"
import { escape } from "shescape"
export const MyPlugin = async (ctx) => {
return {
"tool.execute.before": async (input, output) => {
if (input.tool === "bash") {
output.args.command = escape(output.args.command)
}
},
}
}
```
---
### Osnovna struktura
```js title=".opencode/plugins/example.js"
export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
console.log("Plugin initialized!")
return {
// Hook implementations go here
}
}
```
Funkcija dodatka prima:
- `project`: Trenutne informacije o projektu.
- `directory`: Trenutni radni direktorij.
- `worktree`: Putanja git radnog stabla.
- `client`: Opencode SDK klijent za interakciju sa AI.
- `$`: Bun's [shell API](https://bun.com/docs/runtime/shell) za izvršavanje naredbi.
---
### Podrška za TypeScript
Za TypeScript dodatke, možete uvesti tipove iz paketa dodataka:
```ts title="my-plugin.ts" {1}
import type { Plugin } from "@opencode-ai/plugin"
export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
return {
// Type-safe hook implementations
}
}
```
---
### Događaji
Dodaci se mogu pretplatiti na događaje kao što je prikazano ispod u odjeljku Primjeri. Evo liste različitih dostupnih događaja.
#### Komandni događaji
- `command.executed`
#### Događaji datoteka
- `file.edited`
- `file.watcher.updated`
#### Instalacijski događaji
- `installation.updated`
#### LSP događaji
- `lsp.client.diagnostics`
- `lsp.updated`
#### Poruka Događaji
- `message.part.removed`
- `message.part.updated`
- `message.removed`
- `message.updated`
#### Događaji dozvole
- `permission.asked`
- `permission.replied`
#### Serverski događaji
- `server.connected`
#### Događaji sesije
- `session.created`
- `session.compacted`
- `session.deleted`
- `session.diff`
- `session.error`
- `session.idle`
- `session.status`
- `session.updated`
#### Todo događaji
- `todo.updated`
#### Shell događaji
- `shell.env`
#### Alat Događaji
- `tool.execute.after`
- `tool.execute.before`
#### TUI događaji
- `tui.prompt.append`
- `tui.command.execute`
- `tui.toast.show`
---
## Primjeri
Evo nekoliko primjera dodataka koje možete koristiti za proširenje otvorenog koda.
---
### Šalji obavještenja
Pošaljite obavještenja kada se dogode određeni događaji:
```js title=".opencode/plugins/notification.js"
export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => {
return {
event: async ({ event }) => {
// Send notification on session completion
if (event.type === "session.idle") {
await $`osascript -e 'display notification "Session completed!" with title "opencode"'`
}
},
}
}
```
Koristimo `osascript` za pokretanje AppleScript-a na macOS-u. Ovdje ga koristimo za slanje obavještenja.
:::napomena
Ako koristite desktop aplikaciju OpenCode, ona može automatski slati sistemske obavijesti kada je odgovor spreman ili kada dođe do greške u sesiji.
:::
---
### .env zaštita
Spriječite opencode da čita `.env` fajlove:
```javascript title=".opencode/plugins/env-protection.js"
export const EnvProtection = async ({ project, client, $, directory, worktree }) => {
return {
"tool.execute.before": async (input, output) => {
if (input.tool === "read" && output.args.filePath.includes(".env")) {
throw new Error("Do not read .env files")
}
},
}
}
```
---
### Ubacite varijable okruženja
Ubacite varijable okruženja u sva izvršavanja ljuske (AI alati i korisnički terminali):
```javascript title=".opencode/plugins/inject-env.js"
export const InjectEnvPlugin = async () => {
return {
"shell.env": async (input, output) => {
output.env.MY_API_KEY = "secret"
output.env.PROJECT_ROOT = input.cwd
},
}
}
```
---
### Prilagođeni alati
Dodaci također mogu dodati prilagođene alate u opencode:
```ts title=".opencode/plugins/custom-tools.ts"
import { type Plugin, tool } from "@opencode-ai/plugin"
export const CustomToolsPlugin: Plugin = async (ctx) => {
return {
tool: {
mytool: tool({
description: "This is a custom tool",
args: {
foo: tool.schema.string(),
},
async execute(args, context) {
const { directory, worktree } = context
return `Hello ${args.foo} from ${directory} (worktree: ${worktree})`
},
}),
},
}
}
```
Pomoćnik `tool` kreira prilagođeni alat koji opencode može pozvati. Uzima funkciju Zod sheme i vraća definiciju alata sa:
- `description`: Šta alat radi
- `args`: Zod šema za argumente alata
- `execute`: Funkcija koja se pokreće kada se pozove alat
Vaši prilagođeni alati će biti dostupni za opencode zajedno sa ugrađenim alatima.
---
### Logging
Koristite `client.app.log()` umjesto `console.log` za strukturirano bilježenje:
```ts title=".opencode/plugins/my-plugin.ts"
export const MyPlugin = async ({ client }) => {
await client.app.log({
body: {
service: "my-plugin",
level: "info",
message: "Plugin initialized",
extra: { foo: "bar" },
},
})
}
```
Nivoi: `debug`, `info`, `warn`, `error`. Pogledajte [SDK dokumentaciju](https://opencode.ai/docs/sdk) za detalje.
---
### Kuke za sabijanje
Prilagodite kontekst uključen kada se sesija zbije:
```ts title=".opencode/plugins/compaction.ts"
import type { Plugin } from "@opencode-ai/plugin"
export const CompactionPlugin: Plugin = async (ctx) => {
return {
"experimental.session.compacting": async (input, output) => {
// Inject additional context into the compaction prompt
output.context.push(`
## Custom Context
Include any state that should persist across compaction:
- Current task status
- Important decisions made
- Files being actively worked on
`)
},
}
}
```
`experimental.session.compacting` kuka se aktivira prije nego što LLM generira sažetak nastavka. Koristite ga za ubacivanje konteksta specifičnog za domenu koji bi zadani prompt za sažimanje propustio.
Također možete u potpunosti zamijeniti prompt za sabijanje postavljanjem `output.prompt`:
```ts title=".opencode/plugins/custom-compaction.ts"
import type { Plugin } from "@opencode-ai/plugin"
export const CustomCompactionPlugin: Plugin = async (ctx) => {
return {
"experimental.session.compacting": async (input, output) => {
// Replace the entire compaction prompt
output.prompt = `
You are generating a continuation prompt for a multi-agent swarm session.
Summarize:
1. The current task and its status
2. Which files are being modified and by whom
3. Any blockers or dependencies between agents
4. The next steps to complete the work
Format as a structured prompt that a new agent can use to resume work.
`
},
}
}
```
Kada je `output.prompt` postavljen, on u potpunosti zamjenjuje zadani prompt za sažimanje. Niz `output.context` se zanemaruje u ovom slučaju.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,180 @@
---
title: Pravila
description: Postavite prilagodena uputstva za opencode.
---
Mozete dodati prilagodena uputstva za opencode tako sto kreirate `AGENTS.md` datoteku. Ovo je slicno pravilima u Cursoru. Sadrzi uputstva koja se ubacuju u LLM kontekst da prilagode ponasanje za vas projekat.
---
## Inicijalizacija
Da kreirate novu `AGENTS.md` datoteku, pokrenite `/init` komandu u opencode.
:::tip
Preporuceno je da `AGENTS.md` iz projekta commitujete u Git.
:::
Ovo skenira projekat i njegov sadrzaj, razumije cemu projekat sluzi i generise `AGENTS.md`. Tako opencode bolje navigira kroz kod.
Ako vec imate `AGENTS.md`, komanda ce pokusati da ga dopuni.
---
## Primjer
Datoteku mozete napraviti i rucno. Evo primjera sta mozete staviti u `AGENTS.md`.
```markdown title="AGENTS.md"
# SST v3 Monorepo Project
This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management.
## Project Structure
- `packages/` - Contains all workspace packages (functions, core, web, etc.)
- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts)
- `sst.config.ts` - Main SST configuration with dynamic imports
## Code Standards
- Use TypeScript with strict mode enabled
- Shared code goes in `packages/core/` with proper exports configuration
- Functions go in `packages/functions/`
- Infrastructure should be split into logical files in `infra/`
## Monorepo Conventions
- Import shared modules using workspace names: `@my-app/core/example`
```
Ovdje dodajete uputstva specificna za projekat koja se dijele sa timom.
---
## Tipovi
opencode podrzava citanje `AGENTS.md` datoteke sa vise lokacija. Svaka lokacija ima drugu svrhu.
### Projekat
Stavite `AGENTS.md` u korijen projekta za pravila specificna za taj projekat. Primjenjuju se samo kada radite u tom direktoriju ili poddirektorijima.
### Globalno
Mozete imati i globalna pravila u `~/.config/opencode/AGENTS.md`. Ona se primjenjuju u svim opencode sesijama.
Posto se ovo ne commituje u Git niti dijeli s timom, najbolje je da ovdje cuvate licna pravila koja LLM treba pratiti.
### Kompatibilnost s Claude Code
Za korisnike koji prelaze sa Claude Code, OpenCode podrzava i Claude konvencije datoteka kao rezervu:
- **Pravila projekta**: `CLAUDE.md` u direktoriju projekta (koristi se ako ne postoji `AGENTS.md`)
- **Globalna pravila**: `~/.claude/CLAUDE.md` (koristi se ako ne postoji `~/.config/opencode/AGENTS.md`)
- **Skills**: `~/.claude/skills/` — pogledajte [Agent Skills](/docs/skills/) za detalje
Da iskljucite kompatibilnost sa Claude Code, postavite jednu od ovih varijabli okruzenja:
```bash
export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support
export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md
export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills
```
---
## Prioritet
Kada se opencode pokrene, trazi datoteke pravila ovim redoslijedom:
1. **Lokalne datoteke** pretrazivanjem prema gore od trenutnog direktorija (`AGENTS.md`, `CLAUDE.md`)
2. **Globalna datoteka** na `~/.config/opencode/AGENTS.md`
3. **Claude Code datoteka** na `~/.claude/CLAUDE.md` (osim ako je iskljucena)
Prva pronadena datoteka pobjeduje u svakoj kategoriji. Na primjer, ako imate i `AGENTS.md` i `CLAUDE.md`, koristi se samo `AGENTS.md`. Isto tako, `~/.config/opencode/AGENTS.md` ima prednost nad `~/.claude/CLAUDE.md`.
---
## Prilagodena uputstva
Mozete navesti prilagodene datoteke uputstava u `opencode.json` ili globalnom `~/.config/opencode/opencode.json`. Tako vi i tim ponovo koristite postojeca pravila bez dupliranja u AGENTS.md.
Primjer:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"]
}
```
Mozete koristiti i udaljene URL-ove za ucitavanje uputstava sa weba.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"]
}
```
Udaljena uputstva se preuzimaju uz timeout od 5 sekundi.
Sve datoteke uputstava se kombinuju sa vasim `AGENTS.md` datotekama.
---
## Referenciranje eksternih datoteka
Iako opencode ne parsira automatski reference datoteka u `AGENTS.md`, slicno ponasanje mozete dobiti na dva nacina:
### Koristenje opencode.json
Preporuceni pristup je da koristite `instructions` polje u `opencode.json`:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"]
}
```
### Rucna uputstva u AGENTS.md
Mozete nauciti opencode da cita eksterne datoteke tako sto cete dati eksplicitna uputstva u `AGENTS.md`. Evo prakticnog primjera:
```markdown title="AGENTS.md"
# TypeScript Project Rules
## External File Loading
CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand.
Instructions:
- Do NOT preemptively load all references - use lazy loading based on actual need
- When loaded, treat content as mandatory instructions that override defaults
- Follow references recursively when needed
## Development Guidelines
For TypeScript code style and best practices: @docs/typescript-guidelines.md
For React component architecture and hooks patterns: @docs/react-patterns.md
For REST API design and error handling: @docs/api-standards.md
For testing strategies and coverage requirements: @test/testing-guidelines.md
## General Guidelines
Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md.
```
Ovaj pristup vam omogucava da:
- Kreirate modularne datoteke pravila koje se mogu ponovo koristiti
- Dijelite pravila izmedu projekata kroz symlinkove ili git submodule
- Drzite AGENTS.md kratkim dok upucujete na detaljne smjernice
- Osigurate da opencode ucitava datoteke samo kad su potrebne za konkretan zadatak
:::tip
Za monorepo projekte ili projekte sa zajednickim standardima, odrzivije je koristiti `opencode.json` sa glob obrascima (npr. `packages/*/AGENTS.md`) nego rucna uputstva.
:::

View File

@@ -0,0 +1,391 @@
---
title: SDK
description: Type-safe JS klijent za opencode server.
---
import config from "../../../../config.mjs"
export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts`
opencode JS/TS SDK pruza type-safe klijent za interakciju sa serverom.
Koristite ga za izradu integracija i programsko upravljanje opencode-om.
[Saznajte vise](/docs/server) kako server radi. Za primjere pogledajte [projects](/docs/ecosystem#projects) koje je napravila zajednica.
---
## Install
Instalirajte SDK sa npm-a:
```bash
npm install @opencode-ai/sdk
```
---
## Create client
Kreirajte instancu opencode-a:
```javascript
import { createOpencode } from "@opencode-ai/sdk"
const { client } = await createOpencode()
```
Ovo pokrece i server i klijent
#### Options
| Opcija | Tip | Opis | Default |
| ---------- | ------------- | ----------------------------- | ----------- |
| `hostname` | `string` | Hostname servera | `127.0.0.1` |
| `port` | `number` | Port servera | `4096` |
| `signal` | `AbortSignal` | Abort signal za otkazivanje | `undefined` |
| `timeout` | `number` | Timeout u ms za start servera | `5000` |
| `config` | `Config` | Konfiguracijski objekat | `{}` |
---
## Config
Mozete proslijediti konfiguracijski objekat za prilagodavanje ponasanja. Instanca i dalje ucitava `opencode.json`, ali konfiguraciju mozete nadjacati ili dodati inline:
```javascript
import { createOpencode } from "@opencode-ai/sdk"
const opencode = await createOpencode({
hostname: "127.0.0.1",
port: 4096,
config: {
model: "anthropic/claude-3-5-sonnet-20241022",
},
})
console.log(`Server running at ${opencode.server.url}`)
opencode.server.close()
```
## Client only
Ako vec imate pokrenutu opencode instancu, mozete napraviti klijentsku instancu i povezati se na nju:
```javascript
import { createOpencodeClient } from "@opencode-ai/sdk"
const client = createOpencodeClient({
baseUrl: "http://localhost:4096",
})
```
#### Options
| Opcija | Tip | Opis | Default |
| --------------- | ---------- | --------------------------------- | ----------------------- |
| `baseUrl` | `string` | URL servera | `http://localhost:4096` |
| `fetch` | `function` | Prilagodena fetch implementacija | `globalThis.fetch` |
| `parseAs` | `string` | Metoda parsiranja odgovora | `auto` |
| `responseStyle` | `string` | Stil povrata: `data` ili `fields` | `fields` |
| `throwOnError` | `boolean` | Baci greske umjesto povrata | `false` |
---
## Types
SDK ukljucuje TypeScript definicije za sve API tipove. Uvezite ih direktno:
```typescript
import type { Session, Message, Part } from "@opencode-ai/sdk"
```
Svi tipovi su generisani iz OpenAPI specifikacije servera i dostupni u <a href={typesUrl}>types datoteci</a>.
---
## Errors
SDK moze baciti greske koje mozete uhvatiti i obraditi:
```typescript
try {
await client.session.get({ path: { id: "invalid-id" } })
} catch (error) {
console.error("Failed to get session:", (error as Error).message)
}
```
---
## APIs
SDK izlaže sve server API-je kroz type-safe klijent.
---
### Global
| Metoda | Opis | Odgovor |
| ----------------- | --------------------------- | ------------------------------------ |
| `global.health()` | Provjera zdravlja i verzije | `{ healthy: true, version: string }` |
---
#### Examples
```javascript
const health = await client.global.health()
console.log(health.data.version)
```
---
### App
| Metoda | Opis | Odgovor |
| -------------- | ----------------------- | ------------------------------------------- |
| `app.log()` | Upis log zapisa | `boolean` |
| `app.agents()` | Lista dostupnih agenata | <a href={typesUrl}><code>Agent[]</code></a> |
---
#### Examples
```javascript
// Write a log entry
await client.app.log({
body: {
service: "my-app",
level: "info",
message: "Operation completed",
},
})
// List available agents
const agents = await client.app.agents()
```
---
### Project
| Metoda | Opis | Odgovor |
| ------------------- | -------------------- | --------------------------------------------- |
| `project.list()` | Lista svih projekata | <a href={typesUrl}><code>Project[]</code></a> |
| `project.current()` | Trenutni projekat | <a href={typesUrl}><code>Project</code></a> |
---
#### Examples
```javascript
// List all projects
const projects = await client.project.list()
// Get current project
const currentProject = await client.project.current()
```
---
### Path
| Metoda | Opis | Odgovor |
| ------------ | ---------------- | ---------------------------------------- |
| `path.get()` | Trenutna putanja | <a href={typesUrl}><code>Path</code></a> |
---
#### Examples
```javascript
// Get current path information
const pathInfo = await client.path.get()
```
---
### Config
| Metoda | Opis | Odgovor |
| -------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `config.get()` | Info o konfiguraciji | <a href={typesUrl}><code>Config</code></a> |
| `config.providers()` | Lista provajdera i default modela | `{ providers: `<a href={typesUrl}><code>Provider[]</code></a>`, default: { [key: string]: string } }` |
---
#### Examples
```javascript
const config = await client.config.get()
const { providers, default: defaults } = await client.config.providers()
```
---
### Sessions
| Method | Description | Notes |
| ---------------------------------------------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `session.list()` | List sessions | Returns <a href={typesUrl}><code>Session[]</code></a> |
| `session.get({ path })` | Get session | Returns <a href={typesUrl}><code>Session</code></a> |
| `session.children({ path })` | List child sessions | Returns <a href={typesUrl}><code>Session[]</code></a> |
| `session.create({ body })` | Create session | Returns <a href={typesUrl}><code>Session</code></a> |
| `session.delete({ path })` | Delete session | Returns `boolean` |
| `session.update({ path, body })` | Update session properties | Returns <a href={typesUrl}><code>Session</code></a> |
| `session.init({ path, body })` | Analyze app and create `AGENTS.md` | Returns `boolean` |
| `session.abort({ path })` | Abort a running session | Returns `boolean` |
| `session.share({ path })` | Share session | Returns <a href={typesUrl}><code>Session</code></a> |
| `session.unshare({ path })` | Unshare session | Returns <a href={typesUrl}><code>Session</code></a> |
| `session.summarize({ path, body })` | Summarize session | Returns `boolean` |
| `session.messages({ path })` | List messages in a session | Returns `{ info: `<a href={typesUrl}><code>Message</code></a>`, parts: `<a href={typesUrl}><code>Part[]</code></a>`}[]` |
| `session.message({ path })` | Get message details | Returns `{ info: `<a href={typesUrl}><code>Message</code></a>`, parts: `<a href={typesUrl}><code>Part[]</code></a>`}` |
| `session.prompt({ path, body })` | Send prompt message | `body.noReply: true` returns UserMessage (context only). Default returns <a href={typesUrl}><code>AssistantMessage</code></a> with AI response |
| `session.command({ path, body })` | Send command to session | Returns `{ info: `<a href={typesUrl}><code>AssistantMessage</code></a>`, parts: `<a href={typesUrl}><code>Part[]</code></a>`}` |
| `session.shell({ path, body })` | Run a shell command | Returns <a href={typesUrl}><code>AssistantMessage</code></a> |
| `session.revert({ path, body })` | Revert a message | Returns <a href={typesUrl}><code>Session</code></a> |
| `session.unrevert({ path })` | Restore reverted messages | Returns <a href={typesUrl}><code>Session</code></a> |
| `postSessionByIdPermissionsByPermissionId({ path, body })` | Respond to a permission request | Returns `boolean` |
---
#### Examples
```javascript
// Create and manage sessions
const session = await client.session.create({
body: { title: "My session" },
})
const sessions = await client.session.list()
// Send a prompt message
const result = await client.session.prompt({
path: { id: session.id },
body: {
model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" },
parts: [{ type: "text", text: "Hello!" }],
},
})
// Inject context without triggering AI response (useful for plugins)
await client.session.prompt({
path: { id: session.id },
body: {
noReply: true,
parts: [{ type: "text", text: "You are a helpful assistant." }],
},
})
```
---
### Files
| Method | Description | Response |
| ------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------- |
| `find.text({ query })` | Search for text in files | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` |
| `find.files({ query })` | Find files and directories by name | `string[]` (paths) |
| `find.symbols({ query })` | Find workspace symbols | <a href={typesUrl}><code>Symbol[]</code></a> |
| `file.read({ query })` | Read a file | `{ type: "raw" \| "patch", content: string }` |
| `file.status({ query? })` | Get status for tracked files | <a href={typesUrl}><code>File[]</code></a> |
`find.files` supports a few optional query fields:
- `type`: `"file"` or `"directory"`
- `directory`: override the project root for the search
- `limit`: max results (1200)
---
#### Examples
```javascript
// Search and read files
const textResults = await client.find.text({
query: { pattern: "function.*opencode" },
})
const files = await client.find.files({
query: { query: "*.ts", type: "file" },
})
const directories = await client.find.files({
query: { query: "packages", type: "directory", limit: 20 },
})
const content = await client.file.read({
query: { path: "src/index.ts" },
})
```
---
### TUI
| Method | Description | Response |
| ------------------------------ | ------------------------- | --------- |
| `tui.appendPrompt({ body })` | Append text to the prompt | `boolean` |
| `tui.openHelp()` | Open the help dialog | `boolean` |
| `tui.openSessions()` | Open the session selector | `boolean` |
| `tui.openThemes()` | Open the theme selector | `boolean` |
| `tui.openModels()` | Open the model selector | `boolean` |
| `tui.submitPrompt()` | Submit the current prompt | `boolean` |
| `tui.clearPrompt()` | Clear the prompt | `boolean` |
| `tui.executeCommand({ body })` | Execute a command | `boolean` |
| `tui.showToast({ body })` | Show toast notification | `boolean` |
---
#### Examples
```javascript
// Control TUI interface
await client.tui.appendPrompt({
body: { text: "Add this to prompt" },
})
await client.tui.showToast({
body: { message: "Task completed", variant: "success" },
})
```
---
### Auth
| Method | Description | Response |
| ------------------- | ------------------------------ | --------- |
| `auth.set({ ... })` | Set authentication credentials | `boolean` |
---
#### Examples
```javascript
await client.auth.set({
path: { id: "anthropic" },
body: { type: "api", key: "your-api-key" },
})
```
---
### Events
| Method | Description | Response |
| ------------------- | ------------------------- | ------------------------- |
| `event.subscribe()` | Server-sent events stream | Server-sent events stream |
---
#### Examples
```javascript
// Listen to real-time events
const events = await client.event.subscribe()
for await (const event of events.stream) {
console.log("Event:", event.type, event.properties)
}
```

View File

@@ -0,0 +1,284 @@
---
title: Server
description: Komunicirajte s opencode serverom preko HTTP-a.
---
import config from "../../../../config.mjs"
export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts`
Komanda `opencode serve` pokrece headless HTTP server koji izlaže OpenAPI endpoint koji opencode klijent moze koristiti.
---
### Usage
```bash
opencode serve [--port <number>] [--hostname <string>] [--cors <origin>]
```
#### Options
| Zastava | Opis | Default |
| --------------- | ----------------------------------- | ---------------- |
| `--port` | Port na kojem slusa | `4096` |
| `--hostname` | Hostname na kojem slusa | `127.0.0.1` |
| `--mdns` | Ukljuci mDNS otkrivanje | `false` |
| `--mdns-domain` | Prilagodeni domen za mDNS servis | `opencode.local` |
| `--cors` | Dodatni browser origin-i koje dozv. | `[]` |
`--cors` mozete navesti vise puta:
```bash
opencode serve --cors http://localhost:5173 --cors https://app.example.com
```
---
### Authentication
Postavite `OPENCODE_SERVER_PASSWORD` da zastitite server HTTP basic auth mehanizmom. Korisnicko ime je po defaultu `opencode`, ili postavite `OPENCODE_SERVER_USERNAME` za nadjacavanje. Ovo vazi i za `opencode serve` i za `opencode web`.
```bash
OPENCODE_SERVER_PASSWORD=your-password opencode serve
```
---
### How it works
Kada pokrenete `opencode`, pokrecu se TUI i server. TUI je klijent koji komunicira sa serverom. Server izlaže OpenAPI 3.1 spec endpoint koji se koristi i za generisanje [SDK-a](/docs/sdk).
:::tip
Koristite opencode server za programsku interakciju sa opencode-om.
:::
Ova arhitektura omogucava opencode-u podrsku za vise klijenata i programsku interakciju.
Mozete pokrenuti `opencode serve` da startate standalone server. Ako je opencode TUI vec pokrenut, `opencode serve` ce pokrenuti novi server.
---
#### Connect to an existing server
Kada pokrenete TUI, port i hostname se nasumicno dodijele. Umjesto toga, mozete zadati `--hostname` i `--port` [zastave](/docs/cli), pa se povezati na taj server.
Endpoint [`/tui`](#tui) mozete koristiti za upravljanje TUI-jem kroz server. Na primjer, mozete unaprijed popuniti ili pokrenuti prompt. Ovaj setup koriste OpenCode [IDE](/docs/ide) pluginovi.
---
## Spec
Server objavljuje OpenAPI 3.1 specifikaciju koju mozete vidjeti na:
```
http://<hostname>:<port>/doc
```
Na primjer, `http://localhost:4096/doc`. Koristite specifikaciju da generisete klijente ili pregledate tipove zahtjeva i odgovora. Mozete je otvoriti i u Swagger exploreru.
---
## APIs
opencode server izlaže sljedece API-je.
---
### Global
| Method | Path | Description | Response |
| ------ | ---------------- | ------------------------------ | ------------------------------------ |
| `GET` | `/global/health` | Get server health and version | `{ healthy: true, version: string }` |
| `GET` | `/global/event` | Get global events (SSE stream) | Event stream |
---
### Project
| Method | Path | Description | Response |
| ------ | ------------------ | ----------------------- | --------------------------------------------- |
| `GET` | `/project` | List all projects | <a href={typesUrl}><code>Project[]</code></a> |
| `GET` | `/project/current` | Get the current project | <a href={typesUrl}><code>Project</code></a> |
---
### Path & VCS
| Method | Path | Description | Response |
| ------ | ------- | ------------------------------------ | ------------------------------------------- |
| `GET` | `/path` | Get the current path | <a href={typesUrl}><code>Path</code></a> |
| `GET` | `/vcs` | Get VCS info for the current project | <a href={typesUrl}><code>VcsInfo</code></a> |
---
### Instance
| Method | Path | Description | Response |
| ------ | ------------------- | ---------------------------- | --------- |
| `POST` | `/instance/dispose` | Dispose the current instance | `boolean` |
---
### Config
| Method | Path | Description | Response |
| ------- | ------------------- | --------------------------------- | ---------------------------------------------------------------------------------------- |
| `GET` | `/config` | Get config info | <a href={typesUrl}><code>Config</code></a> |
| `PATCH` | `/config` | Update config | <a href={typesUrl}><code>Config</code></a> |
| `GET` | `/config/providers` | List providers and default models | `{ providers: `<a href={typesUrl}>Provider[]</a>`, default: { [key: string]: string } }` |
---
### Provider
| Method | Path | Description | Response |
| ------ | -------------------------------- | ------------------------------------ | ----------------------------------------------------------------------------------- |
| `GET` | `/provider` | List all providers | `{ all: `<a href={typesUrl}>Provider[]</a>`, default: {...}, connected: string[] }` |
| `GET` | `/provider/auth` | Get provider authentication methods | `{ [providerID: string]: `<a href={typesUrl}>ProviderAuthMethod[]</a>` }` |
| `POST` | `/provider/{id}/oauth/authorize` | Authorize a provider using OAuth | <a href={typesUrl}><code>ProviderAuthAuthorization</code></a> |
| `POST` | `/provider/{id}/oauth/callback` | Handle OAuth callback for a provider | `boolean` |
---
### Sessions
| Method | Path | Description | Notes |
| -------- | ---------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------- |
| `GET` | `/session` | List all sessions | Returns <a href={typesUrl}><code>Session[]</code></a> |
| `POST` | `/session` | Create a new session | body: `{ parentID?, title? }`, returns <a href={typesUrl}><code>Session</code></a> |
| `GET` | `/session/status` | Get session status for all sessions | Returns `{ [sessionID: string]: `<a href={typesUrl}>SessionStatus</a>` }` |
| `GET` | `/session/:id` | Get session details | Returns <a href={typesUrl}><code>Session</code></a> |
| `DELETE` | `/session/:id` | Delete a session and all its data | Returns `boolean` |
| `PATCH` | `/session/:id` | Update session properties | body: `{ title? }`, returns <a href={typesUrl}><code>Session</code></a> |
| `GET` | `/session/:id/children` | Get a session's child sessions | Returns <a href={typesUrl}><code>Session[]</code></a> |
| `GET` | `/session/:id/todo` | Get the todo list for a session | Returns <a href={typesUrl}><code>Todo[]</code></a> |
| `POST` | `/session/:id/init` | Analyze app and create `AGENTS.md` | body: `{ messageID, providerID, modelID }`, returns `boolean` |
| `POST` | `/session/:id/fork` | Fork an existing session at a message | body: `{ messageID? }`, returns <a href={typesUrl}><code>Session</code></a> |
| `POST` | `/session/:id/abort` | Abort a running session | Returns `boolean` |
| `POST` | `/session/:id/share` | Share a session | Returns <a href={typesUrl}><code>Session</code></a> |
| `DELETE` | `/session/:id/share` | Unshare a session | Returns <a href={typesUrl}><code>Session</code></a> |
| `GET` | `/session/:id/diff` | Get the diff for this session | query: `messageID?`, returns <a href={typesUrl}><code>FileDiff[]</code></a> |
| `POST` | `/session/:id/summarize` | Summarize the session | body: `{ providerID, modelID }`, returns `boolean` |
| `POST` | `/session/:id/revert` | Revert a message | body: `{ messageID, partID? }`, returns `boolean` |
| `POST` | `/session/:id/unrevert` | Restore all reverted messages | Returns `boolean` |
| `POST` | `/session/:id/permissions/:permissionID` | Respond to a permission request | body: `{ response, remember? }`, returns `boolean` |
---
### Messages
| Method | Path | Description | Notes |
| ------ | --------------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET` | `/session/:id/message` | List messages in a session | query: `limit?`, returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}[]` |
| `POST` | `/session/:id/message` | Send a message and wait for response | body: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}` |
| `GET` | `/session/:id/message/:messageID` | Get message details | Returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}` |
| `POST` | `/session/:id/prompt_async` | Send a message asynchronously (no wait) | body: same as `/session/:id/message`, returns `204 No Content` |
| `POST` | `/session/:id/command` | Execute a slash command | body: `{ messageID?, agent?, model?, command, arguments }`, returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}` |
| `POST` | `/session/:id/shell` | Run a shell command | body: `{ agent, model?, command }`, returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}` |
---
### Commands
| Method | Path | Description | Response |
| ------ | ---------- | ----------------- | --------------------------------------------- |
| `GET` | `/command` | List all commands | <a href={typesUrl}><code>Command[]</code></a> |
---
### Files
| Method | Path | Description | Response |
| ------ | ------------------------ | ---------------------------------- | ------------------------------------------------------------------------------------------- |
| `GET` | `/find?pattern=<pat>` | Search for text in files | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` |
| `GET` | `/find/file?query=<q>` | Find files and directories by name | `string[]` (paths) |
| `GET` | `/find/symbol?query=<q>` | Find workspace symbols | <a href={typesUrl}><code>Symbol[]</code></a> |
| `GET` | `/file?path=<path>` | List files and directories | <a href={typesUrl}><code>FileNode[]</code></a> |
| `GET` | `/file/content?path=<p>` | Read a file | <a href={typesUrl}><code>FileContent</code></a> |
| `GET` | `/file/status` | Get status for tracked files | <a href={typesUrl}><code>File[]</code></a> |
#### `/find/file` query parameters
- `query` (required) — search string (fuzzy match)
- `type` (optional) — limit results to `"file"` or `"directory"`
- `directory` (optional) — override the project root for the search
- `limit` (optional) — max results (1200)
- `dirs` (optional) — legacy flag (`"false"` returns only files)
---
### Tools (Experimental)
| Method | Path | Description | Response |
| ------ | ------------------------------------------- | ---------------------------------------- | -------------------------------------------- |
| `GET` | `/experimental/tool/ids` | List all tool IDs | <a href={typesUrl}><code>ToolIDs</code></a> |
| `GET` | `/experimental/tool?provider=<p>&model=<m>` | List tools with JSON schemas for a model | <a href={typesUrl}><code>ToolList</code></a> |
---
### LSP, Formatters & MCP
| Method | Path | Description | Response |
| ------ | ------------ | -------------------------- | -------------------------------------------------------- |
| `GET` | `/lsp` | Get LSP server status | <a href={typesUrl}><code>LSPStatus[]</code></a> |
| `GET` | `/formatter` | Get formatter status | <a href={typesUrl}><code>FormatterStatus[]</code></a> |
| `GET` | `/mcp` | Get MCP server status | `{ [name: string]: `<a href={typesUrl}>MCPStatus</a>` }` |
| `POST` | `/mcp` | Add MCP server dynamically | body: `{ name, config }`, returns MCP status object |
---
### Agents
| Method | Path | Description | Response |
| ------ | -------- | ------------------------- | ------------------------------------------- |
| `GET` | `/agent` | List all available agents | <a href={typesUrl}><code>Agent[]</code></a> |
---
### Logging
| Method | Path | Description | Response |
| ------ | ------ | ------------------------------------------------------------ | --------- |
| `POST` | `/log` | Write log entry. Body: `{ service, level, message, extra? }` | `boolean` |
---
### TUI
| Method | Path | Description | Response |
| ------ | ----------------------- | ------------------------------------------- | ---------------------- |
| `POST` | `/tui/append-prompt` | Append text to the prompt | `boolean` |
| `POST` | `/tui/open-help` | Open the help dialog | `boolean` |
| `POST` | `/tui/open-sessions` | Open the session selector | `boolean` |
| `POST` | `/tui/open-themes` | Open the theme selector | `boolean` |
| `POST` | `/tui/open-models` | Open the model selector | `boolean` |
| `POST` | `/tui/submit-prompt` | Submit the current prompt | `boolean` |
| `POST` | `/tui/clear-prompt` | Clear the prompt | `boolean` |
| `POST` | `/tui/execute-command` | Execute a command (`{ command }`) | `boolean` |
| `POST` | `/tui/show-toast` | Show toast (`{ title?, message, variant }`) | `boolean` |
| `GET` | `/tui/control/next` | Wait for the next control request | Control request object |
| `POST` | `/tui/control/response` | Respond to a control request (`{ body }`) | `boolean` |
---
### Auth
| Method | Path | Description | Response |
| ------ | ----------- | --------------------------------------------------------------- | --------- |
| `PUT` | `/auth/:id` | Set authentication credentials. Body must match provider schema | `boolean` |
---
### Events
| Method | Path | Description | Response |
| ------ | -------- | ----------------------------------------------------------------------------- | ------------------------- |
| `GET` | `/event` | Server-sent events stream. First event is `server.connected`, then bus events | Server-sent events stream |
---
### Docs
| Method | Path | Description | Response |
| ------ | ------ | ------------------------- | --------------------------- |
| `GET` | `/doc` | OpenAPI 3.1 specification | HTML page with OpenAPI spec |

Some files were not shown because too many files have changed in this diff Show More