lazyopencode 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. lazyopencode-0.1.0/.github/release-drafter.yml +13 -0
  2. lazyopencode-0.1.0/.github/workflows/ci.yml +24 -0
  3. lazyopencode-0.1.0/.github/workflows/publish.yml +23 -0
  4. lazyopencode-0.1.0/.github/workflows/release-drafter.yml +16 -0
  5. lazyopencode-0.1.0/.gitignore +73 -0
  6. lazyopencode-0.1.0/.opencode/command/commit.md +36 -0
  7. lazyopencode-0.1.0/.opencode/command/run-quality-gates.md +6 -0
  8. lazyopencode-0.1.0/.opencode/plugin/compaction.ts +21 -0
  9. lazyopencode-0.1.0/.opencode/plugin/custom-tools.ts +31 -0
  10. lazyopencode-0.1.0/.opencode/plugin/env-protection.ts +21 -0
  11. lazyopencode-0.1.0/.opencode/plugin/notification.ts +24 -0
  12. lazyopencode-0.1.0/.opencode/skill/quality-gates/SKILL.md +42 -0
  13. lazyopencode-0.1.0/.opencode/tool/database.ts +12 -0
  14. lazyopencode-0.1.0/.opencode/tool/math.ts +39 -0
  15. lazyopencode-0.1.0/.opencode/tool/project-info.ts +11 -0
  16. lazyopencode-0.1.0/.opencode/tool/python-runner.ts +17 -0
  17. lazyopencode-0.1.0/.pre-commit-config.yaml +16 -0
  18. lazyopencode-0.1.0/AGENTS.md +173 -0
  19. lazyopencode-0.1.0/LICENSE +21 -0
  20. lazyopencode-0.1.0/PKG-INFO +118 -0
  21. lazyopencode-0.1.0/README.md +86 -0
  22. lazyopencode-0.1.0/artifacts/lazyclaude-reference.png +0 -0
  23. lazyopencode-0.1.0/opencode.json +33 -0
  24. lazyopencode-0.1.0/pyproject.toml +112 -0
  25. lazyopencode-0.1.0/reference-customizations/.opencode/agent/researcher.md +12 -0
  26. lazyopencode-0.1.0/reference-customizations/.opencode/command/verify.md +11 -0
  27. lazyopencode-0.1.0/reference-customizations/.opencode/plugin/compaction.ts +21 -0
  28. lazyopencode-0.1.0/reference-customizations/.opencode/plugin/custom-tools.ts +31 -0
  29. lazyopencode-0.1.0/reference-customizations/.opencode/plugin/env-protection.ts +21 -0
  30. lazyopencode-0.1.0/reference-customizations/.opencode/plugin/notification.ts +24 -0
  31. lazyopencode-0.1.0/reference-customizations/.opencode/skill/architecture-audit/SKILL.md +15 -0
  32. lazyopencode-0.1.0/reference-customizations/.opencode/skill/architecture-audit/references/patterns.md +10 -0
  33. lazyopencode-0.1.0/reference-customizations/.opencode/skill/simple-formatter/SKILL.md +10 -0
  34. lazyopencode-0.1.0/reference-customizations/.opencode/tool/database.ts +12 -0
  35. lazyopencode-0.1.0/reference-customizations/.opencode/tool/math.ts +39 -0
  36. lazyopencode-0.1.0/reference-customizations/.opencode/tool/project-info.ts +11 -0
  37. lazyopencode-0.1.0/reference-customizations/.opencode/tool/python-runner.ts +17 -0
  38. lazyopencode-0.1.0/reference-customizations/AGENTS.md +12 -0
  39. lazyopencode-0.1.0/reference-customizations/TODO.md +10 -0
  40. lazyopencode-0.1.0/reference-customizations/docs/api-standards.md +82 -0
  41. lazyopencode-0.1.0/reference-customizations/docs/testing-guidelines.md +70 -0
  42. lazyopencode-0.1.0/reference-customizations/docs/typescript-guidelines.md +56 -0
  43. lazyopencode-0.1.0/reference-customizations/opencode.json +68 -0
  44. lazyopencode-0.1.0/reference-customizations/prompts/security-audit.txt +8 -0
  45. lazyopencode-0.1.0/reference-customizations/scripts/fake-lint.sh +4 -0
  46. lazyopencode-0.1.0/scripts/check_quality.sh +82 -0
  47. lazyopencode-0.1.0/src/lazyopencode/__init__.py +48 -0
  48. lazyopencode-0.1.0/src/lazyopencode/__main__.py +6 -0
  49. lazyopencode-0.1.0/src/lazyopencode/_version.py +34 -0
  50. lazyopencode-0.1.0/src/lazyopencode/app.py +310 -0
  51. lazyopencode-0.1.0/src/lazyopencode/bindings.py +27 -0
  52. lazyopencode-0.1.0/src/lazyopencode/mixins/filtering.py +33 -0
  53. lazyopencode-0.1.0/src/lazyopencode/mixins/help.py +74 -0
  54. lazyopencode-0.1.0/src/lazyopencode/mixins/navigation.py +184 -0
  55. lazyopencode-0.1.0/src/lazyopencode/models/__init__.py +17 -0
  56. lazyopencode-0.1.0/src/lazyopencode/models/customization.py +120 -0
  57. lazyopencode-0.1.0/src/lazyopencode/services/__init__.py +7 -0
  58. lazyopencode-0.1.0/src/lazyopencode/services/discovery.py +350 -0
  59. lazyopencode-0.1.0/src/lazyopencode/services/gitignore_filter.py +123 -0
  60. lazyopencode-0.1.0/src/lazyopencode/services/parsers/__init__.py +152 -0
  61. lazyopencode-0.1.0/src/lazyopencode/services/parsers/agent.py +93 -0
  62. lazyopencode-0.1.0/src/lazyopencode/services/parsers/command.py +94 -0
  63. lazyopencode-0.1.0/src/lazyopencode/services/parsers/mcp.py +67 -0
  64. lazyopencode-0.1.0/src/lazyopencode/services/parsers/plugin.py +127 -0
  65. lazyopencode-0.1.0/src/lazyopencode/services/parsers/rules.py +65 -0
  66. lazyopencode-0.1.0/src/lazyopencode/services/parsers/skill.py +138 -0
  67. lazyopencode-0.1.0/src/lazyopencode/services/parsers/tool.py +67 -0
  68. lazyopencode-0.1.0/src/lazyopencode/styles/app.tcss +173 -0
  69. lazyopencode-0.1.0/src/lazyopencode/themes.py +30 -0
  70. lazyopencode-0.1.0/src/lazyopencode/widgets/__init__.py +17 -0
  71. lazyopencode-0.1.0/src/lazyopencode/widgets/app_footer.py +71 -0
  72. lazyopencode-0.1.0/src/lazyopencode/widgets/combined_panel.py +345 -0
  73. lazyopencode-0.1.0/src/lazyopencode/widgets/detail_pane.py +338 -0
  74. lazyopencode-0.1.0/src/lazyopencode/widgets/filter_input.py +88 -0
  75. lazyopencode-0.1.0/src/lazyopencode/widgets/helpers/__init__.py +5 -0
  76. lazyopencode-0.1.0/src/lazyopencode/widgets/helpers/rendering.py +17 -0
  77. lazyopencode-0.1.0/src/lazyopencode/widgets/status_panel.py +70 -0
  78. lazyopencode-0.1.0/src/lazyopencode/widgets/type_panel.py +501 -0
  79. lazyopencode-0.1.0/tests/AGENTS.md +308 -0
  80. lazyopencode-0.1.0/tests/conftest.py +164 -0
  81. lazyopencode-0.1.0/tests/integration/__init__.py +1 -0
  82. lazyopencode-0.1.0/tests/integration/discovery/__init__.py +1 -0
  83. lazyopencode-0.1.0/tests/integration/discovery/test_agents.py +126 -0
  84. lazyopencode-0.1.0/tests/integration/discovery/test_commands.py +103 -0
  85. lazyopencode-0.1.0/tests/integration/discovery/test_full_discovery.py +209 -0
  86. lazyopencode-0.1.0/tests/integration/discovery/test_mcps.py +121 -0
  87. lazyopencode-0.1.0/tests/integration/discovery/test_rules.py +192 -0
  88. lazyopencode-0.1.0/tests/integration/discovery/test_skills.py +172 -0
  89. lazyopencode-0.1.0/tests/integration/fixtures/agent/explorer.md +9 -0
  90. lazyopencode-0.1.0/tests/integration/fixtures/command/greet.md +8 -0
  91. lazyopencode-0.1.0/tests/integration/fixtures/mcp/project-opencode.json +9 -0
  92. lazyopencode-0.1.0/tests/integration/fixtures/mcp/user-opencode.json +8 -0
  93. lazyopencode-0.1.0/tests/integration/fixtures/memory/AGENTS.md +6 -0
  94. lazyopencode-0.1.0/tests/integration/fixtures/project/AGENTS.md +6 -0
  95. lazyopencode-0.1.0/tests/integration/fixtures/project/agent/reviewer.md +9 -0
  96. lazyopencode-0.1.0/tests/integration/fixtures/project/command/project-cmd.md +6 -0
  97. lazyopencode-0.1.0/tests/integration/fixtures/project/docs/guidelines.md +21 -0
  98. lazyopencode-0.1.0/tests/integration/fixtures/project/skill/project-skill/SKILL.md +7 -0
  99. lazyopencode-0.1.0/tests/integration/fixtures/project/skill/project-skill/src/helper.py +6 -0
  100. lazyopencode-0.1.0/tests/integration/fixtures/skill/task-tracker/SKILL.md +7 -0
  101. lazyopencode-0.1.0/tests/integration/fixtures/skill/task-tracker/reference.md +11 -0
  102. lazyopencode-0.1.0/tests/integration/fixtures/skill/task-tracker/scripts/run.sh +6 -0
  103. lazyopencode-0.1.0/tests/test_inline.py +261 -0
  104. lazyopencode-0.1.0/tests/test_version.py +5 -0
  105. lazyopencode-0.1.0/tests/unit/__init__.py +1 -0
  106. lazyopencode-0.1.0/uv.lock +647 -0
@@ -0,0 +1,13 @@
1
+ name-template: "$RESOLVED_VERSION"
2
+ tag-template: "$RESOLVED_VERSION"
3
+ change-template: "- $TITLE by @$AUTHOR (#$NUMBER)"
4
+ no-changes-template: "- No changes"
5
+
6
+ template: |
7
+ ## Changes
8
+
9
+ $CHANGES
10
+
11
+ ## Contributors
12
+
13
+ $CONTRIBUTORS
@@ -0,0 +1,24 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: astral-sh/setup-uv@v4
15
+ - name: Install dependencies
16
+ run: uv sync --all-extras
17
+ - name: Lint
18
+ run: uv run ruff check src tests
19
+ - name: Format check
20
+ run: uv run ruff format --check src tests
21
+ - name: Type check
22
+ run: uv run mypy src
23
+ - name: Test
24
+ run: uv run pytest
@@ -0,0 +1,23 @@
1
+ name: Publish
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish:
9
+ name: Build and publish to PyPI
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ with:
14
+ fetch-depth: 0 # Important for hatch-vcs versioning
15
+ - uses: astral-sh/setup-uv@v4
16
+ with:
17
+ enable-cache: true
18
+ - name: Build
19
+ run: uv build
20
+ - name: Publish to PyPI
21
+ run: uv publish
22
+ env:
23
+ UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_KEY }}
@@ -0,0 +1,16 @@
1
+ name: Release Drafter
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ update_release_draft:
10
+ permissions:
11
+ contents: write
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: release-drafter/release-drafter@v6
15
+ env:
16
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,73 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+
23
+ # Virtual environments
24
+ .venv/
25
+ venv/
26
+ ENV/
27
+ env/
28
+
29
+ # uv
30
+ .uv/
31
+
32
+ # IDE
33
+ .idea/
34
+ .vscode/
35
+ *.swp
36
+ *.swo
37
+ *~
38
+
39
+ # Testing
40
+ .pytest_cache/
41
+ .coverage
42
+ htmlcov/
43
+ .tox/
44
+ .nox/
45
+
46
+ # Type checking
47
+ .mypy_cache/
48
+ .dmypy.json
49
+ dmypy.json
50
+
51
+ # OS
52
+ .DS_Store
53
+ Thumbs.db
54
+
55
+ # Environment
56
+ .env
57
+ .env.local
58
+ *.env
59
+
60
+ # Logs
61
+ *.log
62
+
63
+ # Textual snapshots (keep in repo but ignore local changes during dev)
64
+ # tests/snapshots/*.svg
65
+
66
+ # backlog.md special folder
67
+ backlog
68
+
69
+ # Plans folder (keep in filesystem, don't track)
70
+ _plans/
71
+
72
+ # hatch-vcs generated version file
73
+ src/lazyopencode/_version.py
@@ -0,0 +1,36 @@
1
+ ---
2
+ description: Create a git commit
3
+ ---
4
+ Create a git commit $ARGUMENTS.
5
+
6
+ Process:
7
+ 1. Check for staged changes (!`git status`)
8
+ 2. If no staged changes, review and stage appropriate files
9
+ 3. Run pre-commit checks (unless --no-verify is in $ARGUMENTS)
10
+ 4. Analyze changes to determine commit type
11
+ 5. Generate descriptive commit message
12
+ 6. Include scope if applicable: `type(scope): description`
13
+ 7. Add body for complex changes explaining why
14
+ 8. NOTE: Exclude Claude co-authorship footer from commits
15
+ 9. Execute commit
16
+
17
+ Commit Types:
18
+ - ✨ feat: New features
19
+ - 🐛 fix: Bug fixes
20
+ - 📝 docs: Documentation changes
21
+ - ♻️ refactor: Code restructuring without changing functionality
22
+ - 🎨 style: Code formatting, missing semicolons, etc.
23
+ - ⚡️ perf: Performance improvements
24
+ - ✅ test: Adding or correcting tests
25
+ - 🧑‍💻 chore: Tooling, configuration, maintenance
26
+ - 🚧 wip: Work in progress
27
+ - 🔥 remove: Removing code or files
28
+ - 🚑 hotfix: Critical fixes
29
+ - 🔒 security: Security improvements
30
+
31
+ Best Practices:
32
+ - Keep commits atomic and focused
33
+ - Write in imperative mood ("Add feature" not "Added feature")
34
+ - Explain why, not just what
35
+ - Reference issues/PRs when relevant
36
+ - Split unrelated changes into separate commits
@@ -0,0 +1,6 @@
1
+ ---
2
+ allowed-tools: Skill(quality-gates)
3
+ description: Run code quality checks (lint, format, type check, tests)
4
+ ---
5
+
6
+ Invoke the `quality-gates` skill to run linting, formatting, type checking, and tests.
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Compaction Plugin - customizes context during session compaction.
3
+ *
4
+ * This plugin demonstrates using the 'experimental.session.compacting' hook
5
+ * to inject additional context when a session is compacted.
6
+ */
7
+ import type { Plugin } from "@opencode-ai/plugin"
8
+
9
+ export const CompactionPlugin: Plugin = async (ctx) => {
10
+ return {
11
+ "experimental.session.compacting": async (input, output) => {
12
+ // Inject additional context into the compaction prompt
13
+ output.context.push(`## Custom Context
14
+
15
+ Include any state that should persist across compaction:
16
+ - Current task status
17
+ - Important decisions made
18
+ - Files being actively worked on`)
19
+ },
20
+ }
21
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Custom Tools Plugin - demonstrates adding custom tools via plugin.
3
+ *
4
+ * Plugins can define their own tools that OpenCode can call,
5
+ * alongside the built-in tools.
6
+ */
7
+ import { type Plugin, tool } from "@opencode-ai/plugin"
8
+
9
+ export const CustomToolsPlugin: Plugin = async (ctx) => {
10
+ return {
11
+ tool: {
12
+ greet: tool({
13
+ description: "Greets a user by name",
14
+ args: {
15
+ name: tool.schema.string(),
16
+ },
17
+ async execute(args, ctx) {
18
+ return `Hello ${args.name}! Welcome to OpenCode.`
19
+ },
20
+ }),
21
+
22
+ timestamp: tool({
23
+ description: "Returns the current timestamp",
24
+ args: {},
25
+ async execute(args, ctx) {
26
+ return new Date().toISOString()
27
+ },
28
+ }),
29
+ },
30
+ }
31
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Environment Protection Plugin - prevents reading .env files.
3
+ *
4
+ * This plugin demonstrates using the 'tool.execute.before' hook
5
+ * to intercept and block certain tool operations.
6
+ */
7
+ export const EnvProtection = async ({
8
+ project,
9
+ client,
10
+ $,
11
+ directory,
12
+ worktree,
13
+ }) => {
14
+ return {
15
+ "tool.execute.before": async (input, output) => {
16
+ if (input.tool === "read" && output.args.filePath.includes(".env")) {
17
+ throw new Error("Do not read .env files")
18
+ }
19
+ },
20
+ }
21
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Notification Plugin - sends system notifications on session events.
3
+ *
4
+ * This plugin demonstrates using the 'event' handler to respond
5
+ * to OpenCode events like session.idle.
6
+ */
7
+ export const NotificationPlugin = async ({
8
+ project,
9
+ client,
10
+ $,
11
+ directory,
12
+ worktree,
13
+ }) => {
14
+ console.log("NotificationPlugin initialized!")
15
+
16
+ return {
17
+ event: async ({ event }) => {
18
+ // Send notification on session completion
19
+ if (event.type === "session.idle") {
20
+ await $`osascript -e 'display notification "Session completed!" with title "opencode"'`
21
+ }
22
+ },
23
+ }
24
+ }
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: quality-gates
3
+ description: This skill should be used when the user wants to run code quality checks (linting, formatting, type checking, tests) on the lazyopencode project. Use this skill when asked to "run quality gates", "check the code", "run tests", "lint the code", or verify code quality before committing.
4
+ ---
5
+
6
+ # Quality Gates
7
+
8
+ Run code quality checks for the lazyopencode project. This skill executes the same checks used in pre-commit hooks plus tests.
9
+
10
+ ## Quality Checks
11
+
12
+ The following checks are run in order:
13
+
14
+ | Check | Command | Purpose |
15
+ |-------|---------|---------|
16
+ | **Ruff Lint** | `uv run ruff check src tests --fix` | Lint code and auto-fix issues |
17
+ | **Ruff Format** | `uv run ruff format src tests` | Format code consistently |
18
+ | **Mypy** | `uv run mypy src` | Static type checking |
19
+ | **Pytest** | `uv run pytest tests/ -q` | Run test suite |
20
+
21
+ ## Usage
22
+
23
+ To run all quality gates:
24
+
25
+ ```bash
26
+ scripts/check_quality.sh
27
+ ```
28
+
29
+ Or run individual checks as needed using the commands above.
30
+
31
+ ## Workflow
32
+
33
+ 1. Run the `scripts/check_quality.sh` script from the project root
34
+ 2. Review any failures and fix issues
35
+ 3. Re-run until all checks pass
36
+ 4. Present user with concise summary of results in markdown table format
37
+
38
+ ## Common Issues
39
+
40
+ - **Ruff lint failures**: Usually auto-fixed. If not, check the error message for manual fixes needed.
41
+ - **Mypy errors**: Type annotation issues. Add or fix type hints as indicated.
42
+ - **Test failures**: Review test output, fix failing tests or underlying code.
@@ -0,0 +1,12 @@
1
+ import { tool } from "@opencode-ai/plugin"
2
+
3
+ export default tool({
4
+ description: "Query the project database",
5
+ args: {
6
+ query: tool.schema.string().describe("SQL query to execute"),
7
+ },
8
+ async execute(args) {
9
+ // Your database logic here
10
+ return `Executed query: ${args.query}`
11
+ },
12
+ })
@@ -0,0 +1,39 @@
1
+ import { tool } from "@opencode-ai/plugin"
2
+
3
+ // Multiple exports create separate tools: math_add, math_multiply, math_divide
4
+
5
+ export const add = tool({
6
+ description: "Add two numbers",
7
+ args: {
8
+ a: tool.schema.number().describe("First number"),
9
+ b: tool.schema.number().describe("Second number"),
10
+ },
11
+ async execute(args) {
12
+ return args.a + args.b
13
+ },
14
+ })
15
+
16
+ export const multiply = tool({
17
+ description: "Multiply two numbers",
18
+ args: {
19
+ a: tool.schema.number().describe("First number"),
20
+ b: tool.schema.number().describe("Second number"),
21
+ },
22
+ async execute(args) {
23
+ return args.a * args.b
24
+ },
25
+ })
26
+
27
+ export const divide = tool({
28
+ description: "Divide two numbers",
29
+ args: {
30
+ a: tool.schema.number().describe("Dividend"),
31
+ b: tool.schema.number().describe("Divisor"),
32
+ },
33
+ async execute(args) {
34
+ if (args.b === 0) {
35
+ throw new Error("Cannot divide by zero")
36
+ }
37
+ return args.a / args.b
38
+ },
39
+ })
@@ -0,0 +1,11 @@
1
+ import { tool } from "@opencode-ai/plugin"
2
+
3
+ export default tool({
4
+ description: "Get project information from context",
5
+ args: {},
6
+ async execute(args, context) {
7
+ // Access context information
8
+ const { agent, sessionID, messageID } = context
9
+ return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}`
10
+ },
11
+ })
@@ -0,0 +1,17 @@
1
+ import { tool } from "@opencode-ai/plugin"
2
+
3
+ // Example: Tool that invokes a Python script
4
+ // The tool definition is TypeScript, but execution can use any language
5
+
6
+ export default tool({
7
+ description: "Run a Python script with arguments",
8
+ args: {
9
+ script: tool.schema.string().describe("Path to Python script"),
10
+ args: tool.schema.array(tool.schema.string()).describe("Arguments to pass"),
11
+ },
12
+ async execute(args) {
13
+ const scriptArgs = args.args.join(" ")
14
+ const result = await Bun.$`python3 ${args.script} ${scriptArgs}`.text()
15
+ return result.trim()
16
+ },
17
+ })
@@ -0,0 +1,16 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.8.6
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
8
+
9
+ - repo: local
10
+ hooks:
11
+ - id: mypy
12
+ name: mypy
13
+ entry: uv run mypy src
14
+ language: system
15
+ types: [python]
16
+ pass_filenames: false
@@ -0,0 +1,173 @@
1
+ # LazyOpenCode
2
+
3
+ A keyboard-driven TUI for visualizing and managing OpenCode customizations.
4
+
5
+ ## Environment Rules
6
+ - **OS**: Windows (Git Bash). Use forward slashes `/` and `/c/` prefix for absolute paths.
7
+ - **Search**: `rg` and `fd` are installed. Use them for fast searching.
8
+ - **Quality Gates**: Always run quality gates before asking the user to commit changes. Use the `quality-gates` skill by calling the Skill tool. Do NOT run `uv run ruff`, `uv run mypy`, or other individual linting tools directly - always use the skill instead.
9
+ - **TUI Verification**: Do NOT run `uv run lazyopencode` to verify the application. It is a TUI and output cannot be captured effectively. Use unit tests or static analysis instead.
10
+
11
+ ## Project Overview
12
+
13
+ - **Language**: Python 3.11+
14
+ - **Framework**: Textual (TUI), Rich (terminal formatting)
15
+ - **Package Manager**: uv
16
+ - **Architecture**: Mixin-based Textual app with service layer
17
+ - **Inspired by**: LazyClaude, Lazygit
18
+
19
+ ## Implementation Status (Phases 0-5 Completed)
20
+
21
+ - [x] **Foundation**: Project structure, dependencies, CLI entry point
22
+ - [x] **Models**: Customization types, data classes
23
+ - [x] **Widgets**: Type panels, combined panel, detail pane, status bar, footer
24
+ - [x] **Parsers**: Full support for Commands, Agents, Skills, Rules, MCPs, Tools, Plugins
25
+ - [x] **Navigation**: Vim-like navigation (j/k), tab switching, number shortcuts
26
+ - [x] **Filtering**: Filter by Global/Project, Search overlay
27
+ - [x] **Theme**: Gruvbox theme (default) matching LazyClaude style
28
+ - [ ] **Polish**: Settings persistence, comprehensive tests (In Progress)
29
+
30
+ ## Quick Start
31
+
32
+ ```bash
33
+ # Run the application
34
+ uv run lazyopencode
35
+
36
+ # Run tests
37
+ uv run pytest
38
+
39
+ # Run quality gates (linting, formatting, type checking, tests)
40
+ bash scripts/check_quality.sh
41
+ ```
42
+
43
+ ## Directory Structure
44
+
45
+ ```
46
+ src/lazyopencode/
47
+ ├── app.py # Main Textual application
48
+ ├── bindings.py # Keyboard bindings
49
+ ├── themes.py # Theme definitions
50
+ ├── models/ # Data models (Customization, ConfigLevel, etc.)
51
+ ├── services/ # Business logic
52
+ │ ├── discovery.py # Finds customizations on disk
53
+ │ ├── filter.py # Filters by level/query
54
+ │ └── parsers/ # Type-specific parsers
55
+ ├── widgets/ # Textual UI components
56
+ ├── mixins/ # App functionality mixins
57
+ └── styles/ # TCSS stylesheets
58
+ ```
59
+
60
+ ## Code Standards
61
+
62
+ ### Python Style
63
+ - Use type hints for all function parameters and return values
64
+ - Use `dataclasses` for data models
65
+ - Follow PEP 8 naming conventions
66
+ - Maximum line length: 88 characters (ruff default)
67
+
68
+ ### Textual Patterns
69
+ - Use `reactive` for state that should trigger UI updates
70
+ - Use `Message` classes for widget communication
71
+ - Use mixins to organize app functionality
72
+ - Keep widgets focused and single-purpose
73
+
74
+ ### Imports
75
+ - Group imports: stdlib, third-party, local
76
+ - Use absolute imports within the package
77
+ - Re-export public APIs from `__init__.py`
78
+
79
+ ## OpenCode Configuration Paths
80
+
81
+ The application discovers customizations from these locations:
82
+
83
+ | Type | Global Path | Project Path |
84
+ |------|-------------|--------------|
85
+ | Commands | `~/.config/opencode/command/*.md` | `.opencode/command/*.md` |
86
+ | Agents | `~/.config/opencode/agent/*.md` | `.opencode/agent/*.md` |
87
+ | Skills | `~/.config/opencode/skill/*/SKILL.md` | `.opencode/skill/*/SKILL.md` |
88
+ | Rules | `~/.config/opencode/AGENTS.md` | `AGENTS.md` |
89
+ | MCPs | `~/.config/opencode/opencode.json` | `opencode.json` |
90
+ | Tools | `~/.config/opencode/tool/*.ts` | `.opencode/tool/*.ts` |
91
+ | Plugins | `~/.config/opencode/plugin/` | `.opencode/plugin/` |
92
+
93
+ ## Key Components
94
+
95
+ ### Models (`models/customization.py`)
96
+ - `Customization` - Core data object for any customization
97
+ - `ConfigLevel` - Enum: GLOBAL, PROJECT
98
+ - `CustomizationType` - Enum: COMMAND, AGENT, SKILL, RULES, MCP, TOOL, PLUGIN
99
+
100
+ ### Services
101
+ - `ConfigDiscoveryService` - Scans filesystem, uses parsers
102
+ - `FilterService` - Filters by level and search query
103
+ - `ICustomizationParser` - Protocol for type-specific parsers
104
+
105
+ ### Widgets
106
+ - `TypePanel` - List panel with selection
107
+ - `CombinedPanel` - Tabbed panel for multiple types
108
+ - `DetailPane` - Content display with syntax highlighting
109
+ - `StatusPanel` - Shows current path and filter
110
+ - `AppFooter` - Keyboard shortcuts
111
+
112
+ ### Mixins
113
+ - `NavigationMixin` - Panel focus, cursor movement
114
+ - `FilterMixin` - Level filters, search
115
+ - `HelpMixin` - Help overlay
116
+
117
+ ## Testing
118
+
119
+ ```bash
120
+ # Run all tests
121
+ uv run pytest
122
+
123
+ # Run with coverage
124
+ uv run pytest --cov=lazyopencode
125
+
126
+ # Run specific test file
127
+ uv run pytest tests/unit/test_parsers.py
128
+ ```
129
+
130
+ ### Test Structure
131
+ - `tests/unit/` - Unit tests for models, services, parsers
132
+ - `tests/integration/` - App integration tests
133
+ - `tests/conftest.py` - Shared fixtures
134
+
135
+ ## Dependencies
136
+
137
+ ### Runtime
138
+ - `textual>=0.89.0` - TUI framework
139
+ - `rich>=13.0.0` - Terminal formatting
140
+ - `pyyaml>=6.0` - YAML/frontmatter parsing
141
+
142
+ ### Development
143
+ - `pytest` - Testing
144
+ - `pytest-asyncio` - Async test support
145
+ - `ruff` - Linting and formatting
146
+
147
+ ## Adding New Features
148
+
149
+ ### Adding a new customization type
150
+ 1. Add enum value to `CustomizationType`
151
+ 2. Create parser in `services/parsers/`
152
+ 3. Register parser in `ConfigDiscoveryService`
153
+ 4. Add panel or tab in widgets
154
+
155
+ ### Adding a new keybinding
156
+ 1. Add binding to `bindings.py`
157
+ 2. Implement `action_*` method in appropriate mixin
158
+ 3. Update help text
159
+
160
+ ### Adding a new widget
161
+ 1. Create widget in `widgets/`
162
+ 2. Add styles to `styles/app.tcss`
163
+ 3. Compose in `app.py`
164
+
165
+ ## Planning Documents
166
+
167
+ See `_plans/` directory for detailed specifications:
168
+ - `00-overview.md` - Project overview
169
+ - `01-architecture.md` - Architecture decisions
170
+ - `02-customization-types.md` - OpenCode customization mapping
171
+ - `03-implementation-phases.md` - Implementation plan
172
+ - `04-file-structure.md` - File structure
173
+ - `05-agents-md-template.md` - This template
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 nikiforovall
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.